aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/README.md35
-rw-r--r--src/nvim/option.c11
-rw-r--r--src/nvim/tui/terminfo.c87
-rw-r--r--src/nvim/tui/tui.c21
-rw-r--r--src/nvim/ui_bridge.c3
5 files changed, 147 insertions, 10 deletions
diff --git a/src/nvim/README.md b/src/nvim/README.md
index 0caf71e2c5..da87a0208e 100644
--- a/src/nvim/README.md
+++ b/src/nvim/README.md
@@ -32,6 +32,39 @@ The source files use extensions to hint about their purpose.
- `*.h.generated.h` - exported 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
--------------
@@ -39,7 +72,7 @@ Following describes how Nvim processes input.
Consider a typical Vim-like editing session:
-01. Vim dispays the welcome screen
+01. Vim displays the welcome screen
02. User types: `:`
03. Vim enters command-line mode
04. User types: `edit README.txt<CR>`
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 913d27d508..37c4233142 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -4906,15 +4906,14 @@ showoptions (
vimoption_T **items = xmalloc(sizeof(vimoption_T *) * PARAM_COUNT);
- /* Highlight title */
- if (all == 2)
- MSG_PUTS_TITLE(_("\n--- Terminal codes ---"));
- else if (opt_flags & OPT_GLOBAL)
+ // Highlight title
+ if (opt_flags & OPT_GLOBAL) {
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 ---"));
- else
+ } else {
MSG_PUTS_TITLE(_("\n--- Options ---"));
+ }
/*
* do the loop two times:
diff --git a/src/nvim/tui/terminfo.c b/src/nvim/tui/terminfo.c
index fdc33f0a77..492c1c5e9c 100644
--- a/src/nvim/tui/terminfo.c
+++ b/src/nvim/tui/terminfo.c
@@ -9,7 +9,10 @@
#include <unibilium.h>
#include "nvim/log.h"
+#include "nvim/globals.h"
#include "nvim/memory.h"
+#include "nvim/message.h"
+#include "nvim/option.h"
#include "nvim/tui/terminfo.h"
#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);
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);
+}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 2436295ad4..739f3d18d2 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -354,10 +354,12 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
tui_terminal_start(ui);
data->stop = false;
- // allow the main thread to continue, we are ready to start handling UI
- // callbacks
+ // 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));
+
while (!data->stop) {
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);
}
+/// 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
static void suspend_event(void **argv)
{
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index 5585886612..7573fa1653 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -82,6 +82,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
abort();
}
+ // Suspend the main thread until CONTINUE is called by the UI thread.
while (!rv->ready) {
uv_cond_wait(&rv->cond, &rv->mutex);
}
@@ -149,7 +150,7 @@ static void ui_bridge_suspend(UI *b)
uv_mutex_lock(&data->mutex);
UI_BRIDGE_CALL(b, suspend, 1, b);
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) {
uv_cond_wait(&data->cond, &data->mutex);
}