diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/ui.c | 27 | ||||
-rw-r--r-- | src/nvim/tui/input.c | 26 |
2 files changed, 53 insertions, 0 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index b508a3ee94..99215f7b4f 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -16,6 +16,7 @@ #include "nvim/api/ui.h" #include "nvim/autocmd.h" #include "nvim/channel.h" +#include "nvim/eval.h" #include "nvim/event/loop.h" #include "nvim/event/wstream.h" #include "nvim/globals.h" @@ -524,6 +525,32 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Floa ui->pum_pos = true; } +/// Tells Nvim when a terminal event has occurred. +/// +/// The following terminal events are supported: +/// +/// - "osc_response": The terminal sent a OSC response sequence to Nvim. The +/// payload is the received OSC sequence. +/// +/// @param channel_id +/// @param event Event name +/// @param payload Event payload +/// @param[out] err Error details, if any. +void nvim_ui_term_event(uint64_t channel_id, String event, Object value, Error *err) + FUNC_API_SINCE(12) FUNC_API_REMOTE_ONLY +{ + if (strequal("osc_response", event.data)) { + if (value.type != kObjectTypeString) { + api_set_error(err, kErrorTypeValidation, "osc_response must be a string"); + return; + } + + const String osc_response = value.data.string; + set_vim_var_string(VV_TERMRESPONSE, osc_response.data, (ptrdiff_t)osc_response.size); + apply_autocmds_group(EVENT_TERMRESPONSE, NULL, NULL, false, AUGROUP_ALL, NULL, NULL, &value); + } +} + static void flush_event(UIData *data) { if (data->cur_event) { diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 487f8b010e..1f659264c5 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -11,6 +11,7 @@ #include "nvim/api/private/helpers.h" #include "nvim/ascii.h" #include "nvim/charset.h" +#include "nvim/eval.h" #include "nvim/event/defs.h" #include "nvim/log.h" #include "nvim/macros.h" @@ -479,6 +480,8 @@ static void tk_getkeys(TermInput *input, bool force) } } } + } else if (key.type == TERMKEY_TYPE_OSC) { + handle_osc_event(input, &key); } } @@ -684,6 +687,29 @@ HandleState handle_background_color(TermInput *input) return kComplete; } +static void handle_osc_event(TermInput *input, const TermKeyKey *key) +{ + assert(input); + + const char *str = NULL; + if (termkey_interpret_string(input->tk, key, &str) == TERMKEY_RES_KEY) { + assert(str != NULL); + + // Send an event to nvim core. This will update the v:termresponse variable and fire the + // TermResponse event + MAXSIZE_TEMP_ARRAY(args, 2); + ADD_C(args, STATIC_CSTR_AS_OBJ("osc_response")); + + // libtermkey strips the OSC bytes from the response. We add it back in so that downstream + // consumers of v:termresponse can differentiate between OSC and CSI events. + StringBuilder response = KV_INITIAL_VALUE; + kv_printf(response, "\x1b]%s", str); + ADD_C(args, STRING_OBJ(cbuf_as_string(response.items, response.size))); + rpc_send_event(ui_client_channel_id, "nvim_ui_term_event", args); + kv_destroy(response); + } +} + static void handle_raw_buffer(TermInput *input, bool force) { HandleState is_paste = kNotApplicable; |