mirror of
https://github.com/neovim/neovim.git
synced 2025-09-29 22:48:34 +00:00
tui: dump termcap info if -V3 ('verbose' >= 3)
Get terminal debugging info by starting Nvim with 'verbose' level 3: nvim -V3log This is like Vim's `:set termcap`, which was removed in Nvim (and would be very awkward to restore because of the decoupled UI).
This commit is contained in:
@@ -8889,11 +8889,6 @@ This does NOT work: >
|
|||||||
value and the global value are changed.
|
value and the global value are changed.
|
||||||
Example: >
|
Example: >
|
||||||
:let &path = &path . ',/usr/local/include'
|
:let &path = &path . ',/usr/local/include'
|
||||||
< This also works for terminal codes in the form t_xx.
|
|
||||||
But only for alphanumerical names. Example: >
|
|
||||||
:let &t_k1 = "\<Esc>[234;"
|
|
||||||
< When the code does not exist yet it will be created as
|
|
||||||
a terminal key code, there is no error.
|
|
||||||
|
|
||||||
:let &{option-name} .= {expr1}
|
:let &{option-name} .= {expr1}
|
||||||
For a string option: Append {expr1} to the value.
|
For a string option: Append {expr1} to the value.
|
||||||
|
@@ -6424,6 +6424,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
Currently, these messages are given:
|
Currently, these messages are given:
|
||||||
>= 1 When the shada file is read or written.
|
>= 1 When the shada file is read or written.
|
||||||
>= 2 When a file is ":source"'ed.
|
>= 2 When a file is ":source"'ed.
|
||||||
|
>= 3 UI info, terminal capabilities
|
||||||
>= 5 Every searched tags file and include file.
|
>= 5 Every searched tags file and include file.
|
||||||
>= 8 Files for which a group of autocommands is executed.
|
>= 8 Files for which a group of autocommands is executed.
|
||||||
>= 9 Every executed autocommand.
|
>= 9 Every executed autocommand.
|
||||||
|
@@ -249,14 +249,14 @@ argument.
|
|||||||
for reading or writing a ShaDa file. Can be used to find
|
for reading or writing a ShaDa file. Can be used to find
|
||||||
out what is happening upon startup and exit.
|
out what is happening upon startup and exit.
|
||||||
Example: >
|
Example: >
|
||||||
vim -V8 foobar
|
nvim -V8
|
||||||
|
|
||||||
-V[N]{filename}
|
-V[N]{filename}
|
||||||
Like -V and set 'verbosefile' to {filename}. The result is
|
Like -V and set 'verbosefile' to {filename}. Messages are not
|
||||||
that messages are not displayed but written to the file
|
displayed; instead they are written to the file {filename}.
|
||||||
{filename}. {filename} must not start with a digit.
|
{filename} must not start with a digit.
|
||||||
Example: >
|
Example: >
|
||||||
vim -V20vimlog foobar
|
nvim -V20vimlog
|
||||||
<
|
<
|
||||||
*-D*
|
*-D*
|
||||||
-D Debugging. Go to debugging mode when executing the first
|
-D Debugging. Go to debugging mode when executing the first
|
||||||
|
@@ -327,22 +327,26 @@ Ed-compatible mode:
|
|||||||
":set noedcompatible" is ignored
|
":set noedcompatible" is ignored
|
||||||
":set edcompatible" is an error
|
":set edcompatible" is an error
|
||||||
|
|
||||||
*t_xx* *:set-termcap* *termcap-options* *t_AB* *t_Sb* *t_vb* *t_SI*
|
*t_xx* *termcap-options* *t_AB* *t_Sb* *t_vb* *t_SI*
|
||||||
Nvim does not have special `t_XX` options nor <t_XX> keycodes to configure
|
Nvim does not have special `t_XX` options nor <t_XX> keycodes to configure
|
||||||
terminal capabilities. Instead Nvim treats the terminal as any other UI. For
|
terminal capabilities. Instead Nvim treats the terminal as any other UI. For
|
||||||
example, 'guicursor' sets the terminal cursor style if possible.
|
example, 'guicursor' sets the terminal cursor style if possible.
|
||||||
|
|
||||||
*'term'* *E529* *E530* *E531*
|
*:set-termcap*
|
||||||
|
Start Nvim with 'verbose' level 3 to see the terminal capabilities. >
|
||||||
|
nvim -V3
|
||||||
|
<
|
||||||
|
*'term'* *E529* *E530* *E531*
|
||||||
'term' reflects the terminal type derived from |$TERM| and other environment
|
'term' reflects the terminal type derived from |$TERM| and other environment
|
||||||
checks. For debugging only; not reliable during startup. >
|
checks. For debugging only; not reliable during startup. >
|
||||||
:echo &term
|
:echo &term
|
||||||
"builtin_x" means one of the |builtin-terms| was chosen, because the expected
|
"builtin_x" means one of the |builtin-terms| was chosen, because the expected
|
||||||
terminfo file was not found on the system.
|
terminfo file was not found on the system.
|
||||||
|
|
||||||
*termcap*
|
*termcap*
|
||||||
Nvim never uses the termcap database, only |terminfo| and |builtin-terms|.
|
Nvim never uses the termcap database, only |terminfo| and |builtin-terms|.
|
||||||
|
|
||||||
*xterm-8bit* *xterm-8-bit*
|
*xterm-8bit* *xterm-8-bit*
|
||||||
Xterm can be run in a mode where it uses true 8-bit CSI. Supporting this
|
Xterm can be run in a mode where it uses true 8-bit CSI. Supporting this
|
||||||
requires autodetection of whether the terminal is in UTF-8 mode or non-UTF-8
|
requires autodetection of whether the terminal is in UTF-8 mode or non-UTF-8
|
||||||
mode, as the 8-bit CSI character has to be written differently in each case.
|
mode, as the 8-bit CSI character has to be written differently in each case.
|
||||||
|
@@ -32,6 +32,39 @@ The source files use extensions to hint about their purpose.
|
|||||||
- `*.h.generated.h` - exported functions’ declarations.
|
- `*.h.generated.h` - exported functions’ declarations.
|
||||||
- `*.c.generated.h` - static functions’ declarations.
|
- `*.c.generated.h` - static functions’ declarations.
|
||||||
|
|
||||||
|
TUI debugging
|
||||||
|
-------------
|
||||||
|
|
||||||
|
### TUI troubleshoot
|
||||||
|
|
||||||
|
Nvim logs its internal terminfo state at 'verbose' level 3. This makes it
|
||||||
|
possible to see exactly what terminfo values Nvim is using on any system.
|
||||||
|
|
||||||
|
nvim -V3log
|
||||||
|
|
||||||
|
### TUI trace
|
||||||
|
|
||||||
|
The ancient `script` command is still the "state of the art" for tracing
|
||||||
|
terminal behavior. The libvterm `vterm-dump` utility formats the result for
|
||||||
|
human-readability.
|
||||||
|
|
||||||
|
Record a Nvim terminal session and format it with `vterm-dump`:
|
||||||
|
|
||||||
|
script foo
|
||||||
|
./build/bin/nvim -u NONE
|
||||||
|
# Exit the script session with CTRL-d
|
||||||
|
|
||||||
|
# Use `vterm-dump` utility to format the result.
|
||||||
|
./.deps/usr/bin/vterm-dump foo > bar
|
||||||
|
|
||||||
|
Then you can compare `bar` with another session, to debug TUI behavior.
|
||||||
|
|
||||||
|
### Terminal reference
|
||||||
|
|
||||||
|
- `man terminfo`
|
||||||
|
- http://bazaar.launchpad.net/~libvterm/libvterm/trunk/view/head:/doc/seqs.txt
|
||||||
|
- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||||
|
|
||||||
Nvim lifecycle
|
Nvim lifecycle
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@@ -39,7 +72,7 @@ Following describes how Nvim processes input.
|
|||||||
|
|
||||||
Consider a typical Vim-like editing session:
|
Consider a typical Vim-like editing session:
|
||||||
|
|
||||||
01. Vim dispays the welcome screen
|
01. Vim displays the welcome screen
|
||||||
02. User types: `:`
|
02. User types: `:`
|
||||||
03. Vim enters command-line mode
|
03. Vim enters command-line mode
|
||||||
04. User types: `edit README.txt<CR>`
|
04. User types: `edit README.txt<CR>`
|
||||||
|
@@ -4906,15 +4906,14 @@ showoptions (
|
|||||||
|
|
||||||
vimoption_T **items = xmalloc(sizeof(vimoption_T *) * PARAM_COUNT);
|
vimoption_T **items = xmalloc(sizeof(vimoption_T *) * PARAM_COUNT);
|
||||||
|
|
||||||
/* Highlight title */
|
// Highlight title
|
||||||
if (all == 2)
|
if (opt_flags & OPT_GLOBAL) {
|
||||||
MSG_PUTS_TITLE(_("\n--- Terminal codes ---"));
|
|
||||||
else if (opt_flags & OPT_GLOBAL)
|
|
||||||
MSG_PUTS_TITLE(_("\n--- Global option values ---"));
|
MSG_PUTS_TITLE(_("\n--- Global option values ---"));
|
||||||
else if (opt_flags & OPT_LOCAL)
|
} else if (opt_flags & OPT_LOCAL) {
|
||||||
MSG_PUTS_TITLE(_("\n--- Local option values ---"));
|
MSG_PUTS_TITLE(_("\n--- Local option values ---"));
|
||||||
else
|
} else {
|
||||||
MSG_PUTS_TITLE(_("\n--- Options ---"));
|
MSG_PUTS_TITLE(_("\n--- Options ---"));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do the loop two times:
|
* do the loop two times:
|
||||||
|
@@ -9,7 +9,10 @@
|
|||||||
#include <unibilium.h>
|
#include <unibilium.h>
|
||||||
|
|
||||||
#include "nvim/log.h"
|
#include "nvim/log.h"
|
||||||
|
#include "nvim/globals.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
|
#include "nvim/message.h"
|
||||||
|
#include "nvim/option.h"
|
||||||
#include "nvim/tui/terminfo.h"
|
#include "nvim/tui/terminfo.h"
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
@@ -166,3 +169,87 @@ unibi_term *terminfo_from_builtin(const char *term, char **termname)
|
|||||||
unibi_set_bool(ut, unibi_back_color_erase, false);
|
unibi_set_bool(ut, unibi_back_color_erase, false);
|
||||||
return ut;
|
return ut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dumps termcap info to the messages area.
|
||||||
|
/// 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)
|
||||||
|
{
|
||||||
|
if (exiting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
msg_puts_title("\n\n--- Terminal info --- {{{\n");
|
||||||
|
|
||||||
|
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));
|
||||||
|
const char **a = unibi_get_aliases(ut);
|
||||||
|
if (*a) {
|
||||||
|
msg_puts("Aliases: ");
|
||||||
|
do {
|
||||||
|
msg_printf_attr(0, "%s%s\n", *a, a[1] ? " | " : "");
|
||||||
|
a++;
|
||||||
|
} while (*a);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_puts("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");
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_puts("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 = %hd\n", unibi_name_num(i),
|
||||||
|
unibi_short_name_num(i), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_puts("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));
|
||||||
|
// Most of these strings will contain escape sequences.
|
||||||
|
msg_outtrans_special((char_u *)s, false);
|
||||||
|
msg_putchar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unibi_count_ext_bool(ut)) {
|
||||||
|
msg_puts("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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unibi_count_ext_num(ut)) {
|
||||||
|
msg_puts("Extended numeric capabilities:\n");
|
||||||
|
for (size_t i = 0; i < unibi_count_ext_num(ut); i++) {
|
||||||
|
msg_printf_attr(0, " %-25s = %hd\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");
|
||||||
|
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((char_u *)unibi_get_ext_str(ut, i), false);
|
||||||
|
msg_putchar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_puts("}}}\n");
|
||||||
|
xfree(term);
|
||||||
|
}
|
||||||
|
@@ -354,10 +354,12 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
|
|||||||
tui_terminal_start(ui);
|
tui_terminal_start(ui);
|
||||||
data->stop = false;
|
data->stop = false;
|
||||||
|
|
||||||
// allow the main thread to continue, we are ready to start handling UI
|
// Allow main thread to continue, we are ready to handle UI callbacks.
|
||||||
// callbacks
|
|
||||||
CONTINUE(bridge);
|
CONTINUE(bridge);
|
||||||
|
|
||||||
|
loop_schedule_deferred(&main_loop,
|
||||||
|
event_create(show_termcap_event, 1, data->ut));
|
||||||
|
|
||||||
while (!data->stop) {
|
while (!data->stop) {
|
||||||
loop_poll_events(&tui_loop, -1); // tui_loop.events is never processed
|
loop_poll_events(&tui_loop, -1); // tui_loop.events is never processed
|
||||||
}
|
}
|
||||||
@@ -1061,6 +1063,21 @@ static void tui_flush(UI *ui)
|
|||||||
flush_buf(ui, true);
|
flush_buf(ui, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dumps termcap info to the messages area, if 'verbose' >= 3.
|
||||||
|
static void show_termcap_event(void **argv)
|
||||||
|
{
|
||||||
|
if (p_verbose < 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const unibi_term *const ut = argv[0];
|
||||||
|
if (!ut) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
// XXX: (future) if unibi_term is modified (e.g. after a terminal
|
||||||
|
// query-response) this is a race condition.
|
||||||
|
terminfo_info_msg(ut);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
static void suspend_event(void **argv)
|
static void suspend_event(void **argv)
|
||||||
{
|
{
|
||||||
|
@@ -82,6 +82,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Suspend the main thread until CONTINUE is called by the UI thread.
|
||||||
while (!rv->ready) {
|
while (!rv->ready) {
|
||||||
uv_cond_wait(&rv->cond, &rv->mutex);
|
uv_cond_wait(&rv->cond, &rv->mutex);
|
||||||
}
|
}
|
||||||
@@ -149,7 +150,7 @@ static void ui_bridge_suspend(UI *b)
|
|||||||
uv_mutex_lock(&data->mutex);
|
uv_mutex_lock(&data->mutex);
|
||||||
UI_BRIDGE_CALL(b, suspend, 1, b);
|
UI_BRIDGE_CALL(b, suspend, 1, b);
|
||||||
data->ready = false;
|
data->ready = false;
|
||||||
// suspend the main thread until CONTINUE is called by the UI thread
|
// Suspend the main thread until CONTINUE is called by the UI thread.
|
||||||
while (!data->ready) {
|
while (!data->ready) {
|
||||||
uv_cond_wait(&data->cond, &data->mutex);
|
uv_cond_wait(&data->cond, &data->mutex);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user