feat(tui): support DCS responses in TermResponse event (#26061)

This commit is contained in:
Gregory Anders 2023-11-16 11:12:42 -06:00 committed by GitHub
parent dc3f84bf4f
commit b4b7ca2d54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 29 deletions

View File

@ -3598,13 +3598,13 @@ nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
|RPC| only
nvim_ui_term_event({event}, {value}) *nvim_ui_term_event()*
Tells Nvim when a terminal event has occurred: sets |v:termresponse| and
fires |TermResponse|.
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.
• "termresponse": The terminal sent an OSC or DCS response sequence to
Nvim. The payload is the received response. Sets |v:termresponse| and
fires |TermResponse|.
Attributes: ~
|RPC| only

View File

@ -987,8 +987,8 @@ TermClose When a |terminal| job ends.
Sets these |v:event| keys:
status
*TermResponse*
TermResponse When Nvim receives a OSC response from the
terminal. Sets |v:termresponse|. When used
TermResponse When Nvim receives an OSC or DCS response from
the terminal. Sets |v:termresponse|. When used
from Lua, the response string is included in
the "data" field of the autocommand callback.
May be triggered halfway through another event

View File

@ -2318,10 +2318,10 @@ v:t_string Value of |String| type. Read-only. See: |type()|
v:t_blob Value of |Blob| type. Read-only. See: |type()|
*v:termresponse* *termresponse-variable*
v:termresponse The value of the most recent OSC escape sequence received by
Nvim from the terminal. This can be read in a |TermResponse|
event handler after querying the terminal using another escape
sequence.
v:termresponse The value of the most recent OSC or DCS escape sequence
received by Nvim from the terminal. This can be read in a
|TermResponse| event handler after querying the terminal using
another escape sequence.
*v:testing* *testing-variable*
v:testing Must be set before using `test_garbagecollect_now()`.

View File

@ -2065,11 +2065,12 @@ function vim.api.nvim_ui_set_focus(gained) end
--- @param value any
function vim.api.nvim_ui_set_option(name, value) end
--- Tells Nvim when a terminal event has occurred.
--- 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.
--- • "termresponse": The terminal sent an OSC or DCS response sequence to
--- Nvim. The payload is the received response. Sets `v:termresponse` and
--- fires `TermResponse`.
---
---
--- @param event string Event name

View File

@ -513,12 +513,13 @@ 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: sets |v:termresponse| and fires |TermResponse|.
/// 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.
/// - "termresponse": The terminal sent an OSC or DCS response sequence to
/// Nvim. The payload is the received response. Sets
/// |v:termresponse| and fires |TermResponse|.
///
/// @param channel_id
/// @param event Event name
@ -527,14 +528,14 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Floa
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 (strequal("termresponse", event.data)) {
if (value.type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation, "osc_response must be a string");
api_set_error(err, kErrorTypeValidation, "termresponse 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);
const String termresponse = value.data.string;
set_vim_var_string(VV_TERMRESPONSE, termresponse.data, (ptrdiff_t)termresponse.size);
apply_autocmds_group(EVENT_TERMRESPONSE, NULL, NULL, false, AUGROUP_ALL, NULL, NULL, &value);
}
}

View File

@ -476,8 +476,8 @@ static void tk_getkeys(TermInput *input, bool force)
}
}
}
} else if (key.type == TERMKEY_TYPE_OSC) {
handle_osc_event(input, &key);
} else if (key.type == TERMKEY_TYPE_OSC || key.type == TERMKEY_TYPE_DCS) {
handle_term_response(input, &key);
} else if (key.type == TERMKEY_TYPE_MODEREPORT) {
handle_modereport(input, &key);
}
@ -578,22 +578,34 @@ static HandleState handle_bracketed_paste(TermInput *input)
return kNotApplicable;
}
static void handle_osc_event(TermInput *input, const TermKeyKey *key)
static void handle_term_response(TermInput *input, const TermKeyKey *key)
FUNC_ATTR_NONNULL_ALL
{
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
// 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"));
ADD_C(args, STATIC_CSTR_AS_OBJ("termresponse"));
// 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.
// libtermkey strips the OSC/DCS bytes from the response. We add it back in
// so that downstream consumers of v:termresponse can differentiate between
// the two.
StringBuilder response = KV_INITIAL_VALUE;
kv_printf(response, "\x1b]%s", str);
switch (key->type) {
case TERMKEY_TYPE_OSC:
kv_printf(response, "\x1b]%s", str);
break;
case TERMKEY_TYPE_DCS:
kv_printf(response, "\x1bP%s", str);
break;
default:
// Key type already checked for OSC/DCS in termkey_interpret_string
UNREACHABLE;
}
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);