aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/terminal.c
diff options
context:
space:
mode:
authorGhjuvan Lacambre <code@lacamb.re>2024-01-09 15:27:56 +0100
committerGitHub <noreply@github.com>2024-01-09 08:27:56 -0600
commitbeca827212b106114c371f8bb61aa1a50810062f (patch)
tree8c48282193fef8f58768a03663df94bf00b8aa29 /src/nvim/terminal.c
parentf40df63bdca33d343cada6ceaafbc8b765ed7cc6 (diff)
downloadrneovim-beca827212b106114c371f8bb61aa1a50810062f.tar.gz
rneovim-beca827212b106114c371f8bb61aa1a50810062f.tar.bz2
rneovim-beca827212b106114c371f8bb61aa1a50810062f.zip
feat(terminal): trigger TermRequest autocommand events (#22159)
This commit implements a new TermRequest autocommand event and has Neovim emit this event when children of terminal buffers emit an OSC or DCS sequence libvterm does not handle. The TermRequest autocommand event has additional data in the v:termrequest variable. Co-authored-by: Gregory Anders <greg@gpanders.com>
Diffstat (limited to 'src/nvim/terminal.c')
-rw-r--r--src/nvim/terminal.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index c6a2cb3354..ee482f7104 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -169,6 +169,54 @@ static VTermScreenCallbacks vterm_screen_callbacks = {
static Set(ptr_t) invalidated_terminals = SET_INIT;
+static void emit_term_request(void **argv)
+{
+ char *payload = argv[0];
+ size_t payload_length = (size_t)argv[1];
+
+ String termrequest = { .data = payload, .size = payload_length };
+ Object data = STRING_OBJ(termrequest);
+ set_vim_var_string(VV_TERMREQUEST, payload, (ptrdiff_t)payload_length);
+ apply_autocmds_group(EVENT_TERMREQUEST, NULL, NULL, false, AUGROUP_ALL, curbuf, NULL, &data);
+ xfree(payload);
+}
+
+static int on_osc(int command, VTermStringFragment frag, void *user)
+{
+ if (frag.str == NULL) {
+ return 0;
+ }
+
+ StringBuilder request = KV_INITIAL_VALUE;
+ kv_printf(request, "\x1b]%d;", command);
+ kv_concat_len(request, frag.str, frag.len);
+ multiqueue_put(main_loop.events, emit_term_request, request.items, (void *)request.size);
+ return 1;
+}
+
+static int on_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user)
+{
+ if ((command == NULL) || (frag.str == NULL)) {
+ return 0;
+ }
+
+ StringBuilder request = KV_INITIAL_VALUE;
+ kv_printf(request, "\x1bP%*s", (int)commandlen, command);
+ kv_concat_len(request, frag.str, frag.len);
+ multiqueue_put(main_loop.events, emit_term_request, request.items, (void *)request.size);
+ return 1;
+}
+
+static VTermStateFallbacks vterm_fallbacks = {
+ .control = NULL,
+ .csi = NULL,
+ .osc = on_osc,
+ .dcs = on_dcs,
+ .apc = NULL,
+ .pm = NULL,
+ .sos = NULL,
+};
+
void terminal_init(void)
{
time_watcher_init(&main_loop, &refresh_timer, NULL);
@@ -222,6 +270,7 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
vterm_screen_enable_reflow(rv->vts, true);
// delete empty lines at the end of the buffer
vterm_screen_set_callbacks(rv->vts, &vterm_screen_callbacks, rv);
+ vterm_screen_set_unrecognised_fallbacks(rv->vts, &vterm_fallbacks, rv);
vterm_screen_set_damage_merge(rv->vts, VTERM_DAMAGE_SCROLL);
vterm_screen_reset(rv->vts, 1);
vterm_output_set_callback(rv->vt, term_output_callback, rv);