mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 03:05:11 -07:00
feat(tui): use TermResponse event for OSC responses (#25868)
When the terminal emulator sends an OSC sequence to Nvim (as a response to another OSC sequence that was first sent by Nvim), populate the OSC sequence in the v:termresponse variable and fire the TermResponse event. The escape sequence is also included in the "data" field of the autocommand callback when the autocommand is defined in Lua. This makes use of the already documented but unimplemented TermResponse event. This event exists in Vim but is only fired when Vim receives a primary device attributes response. Fixes: https://github.com/neovim/neovim/issues/25856
This commit is contained in:
parent
f9416470b1
commit
56627ca242
@ -3591,6 +3591,21 @@ nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
|
|||||||
Attributes: ~
|
Attributes: ~
|
||||||
|RPC| only
|
|RPC| only
|
||||||
|
|
||||||
|
nvim_ui_term_event({event}, {value}) *nvim_ui_term_event()*
|
||||||
|
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.
|
||||||
|
|
||||||
|
Attributes: ~
|
||||||
|
|RPC| only
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
• {event} Event name
|
||||||
|
• {payload} Event payload
|
||||||
|
|
||||||
nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()*
|
nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()*
|
||||||
TODO: Documentation
|
TODO: Documentation
|
||||||
|
|
||||||
|
@ -987,12 +987,25 @@ TermClose When a |terminal| job ends.
|
|||||||
Sets these |v:event| keys:
|
Sets these |v:event| keys:
|
||||||
status
|
status
|
||||||
*TermResponse*
|
*TermResponse*
|
||||||
TermResponse After the response to t_RV is received from
|
TermResponse When Nvim receives a OSC response from the
|
||||||
the terminal. The value of |v:termresponse|
|
terminal. Sets |v:termresponse|. When used
|
||||||
can be used to do things depending on the
|
from Lua, the response string is included in
|
||||||
terminal version. May be triggered halfway
|
the "data" field of the autocommand callback.
|
||||||
through another event (file I/O, a shell
|
May be triggered halfway through another event
|
||||||
command, or anything else that takes time).
|
(file I/O, a shell command, or anything else
|
||||||
|
that takes time). Example: >lua
|
||||||
|
|
||||||
|
-- Query the terminal palette for the RGB value of color 1
|
||||||
|
-- (red) using OSC 4
|
||||||
|
vim.api.nvim_create_autocmd('TermResponse', {
|
||||||
|
once = true,
|
||||||
|
callback = function(args)
|
||||||
|
local resp = args.data
|
||||||
|
local r, g, b = resp:match("\x1b%]4;1;rgb:(%w+)/(%w+)/(%w+)")
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
io.stdout:write("\x1b]4;1;?\x1b\\")
|
||||||
|
<
|
||||||
*TextChanged*
|
*TextChanged*
|
||||||
TextChanged After a change was made to the text in the
|
TextChanged After a change was made to the text in the
|
||||||
current buffer in Normal mode. That is after
|
current buffer in Normal mode. That is after
|
||||||
|
@ -2318,18 +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:t_blob Value of |Blob| type. Read-only. See: |type()|
|
||||||
|
|
||||||
*v:termresponse* *termresponse-variable*
|
*v:termresponse* *termresponse-variable*
|
||||||
v:termresponse The escape sequence returned by the terminal for the DA
|
v:termresponse The value of the most recent OSC escape sequence received by
|
||||||
(request primary device attributes) control sequence. It is
|
Nvim from the terminal. This can be read in a |TermResponse|
|
||||||
set when Vim receives an escape sequence that starts with ESC
|
event handler after querying the terminal using another escape
|
||||||
[ or CSI and ends in a 'c', with only digits, ';' and '.' in
|
sequence.
|
||||||
between.
|
|
||||||
When this option is set, the TermResponse autocommand event is
|
|
||||||
fired, so that you can react to the response from the
|
|
||||||
terminal.
|
|
||||||
The response from a new xterm is: "<Esc>[ Pp ; Pv ; Pc c". Pp
|
|
||||||
is the terminal type: 0 for vt100 and 1 for vt220. Pv is the
|
|
||||||
patch level (since this was introduced in patch 95, it's
|
|
||||||
always 95 or bigger). Pc is always zero.
|
|
||||||
|
|
||||||
*v:testing* *testing-variable*
|
*v:testing* *testing-variable*
|
||||||
v:testing Must be set before using `test_garbagecollect_now()`.
|
v:testing Must be set before using `test_garbagecollect_now()`.
|
||||||
|
@ -205,6 +205,9 @@ The following new APIs and features were added.
|
|||||||
• Added |vim.base64.encode()| and |vim.base64.decode()| for encoding and decoding
|
• Added |vim.base64.encode()| and |vim.base64.decode()| for encoding and decoding
|
||||||
strings using Base64 encoding.
|
strings using Base64 encoding.
|
||||||
|
|
||||||
|
• The |TermResponse| autocommand event can be used with |v:termresponse| to
|
||||||
|
read escape sequence responses from the terminal.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
CHANGED FEATURES *news-changed*
|
CHANGED FEATURES *news-changed*
|
||||||
|
|
||||||
|
@ -567,6 +567,8 @@ Working directory (Vim implemented some of these after Nvim):
|
|||||||
Autocommands:
|
Autocommands:
|
||||||
- Fixed inconsistent behavior in execution of nested autocommands:
|
- Fixed inconsistent behavior in execution of nested autocommands:
|
||||||
https://github.com/neovim/neovim/issues/23368
|
https://github.com/neovim/neovim/issues/23368
|
||||||
|
- |TermResponse| is fired for any OSC sequence received from the terminal,
|
||||||
|
instead of the Primary Device Attributes response. |v:termresponse|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
Missing features *nvim-missing*
|
Missing features *nvim-missing*
|
||||||
|
11
runtime/lua/vim/_meta/api.lua
generated
11
runtime/lua/vim/_meta/api.lua
generated
@ -2059,6 +2059,17 @@ function vim.api.nvim_ui_set_focus(gained) end
|
|||||||
--- @param value any
|
--- @param value any
|
||||||
function vim.api.nvim_ui_set_option(name, value) end
|
function vim.api.nvim_ui_set_option(name, value) end
|
||||||
|
|
||||||
|
--- 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 event string Event name
|
||||||
|
--- @param value any
|
||||||
|
function vim.api.nvim_ui_term_event(event, value) end
|
||||||
|
|
||||||
--- @param width integer
|
--- @param width integer
|
||||||
--- @param height integer
|
--- @param height integer
|
||||||
function vim.api.nvim_ui_try_resize(width, height) end
|
function vim.api.nvim_ui_try_resize(width, height) end
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "nvim/api/ui.h"
|
#include "nvim/api/ui.h"
|
||||||
#include "nvim/autocmd.h"
|
#include "nvim/autocmd.h"
|
||||||
#include "nvim/channel.h"
|
#include "nvim/channel.h"
|
||||||
|
#include "nvim/eval.h"
|
||||||
#include "nvim/event/loop.h"
|
#include "nvim/event/loop.h"
|
||||||
#include "nvim/event/wstream.h"
|
#include "nvim/event/wstream.h"
|
||||||
#include "nvim/globals.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;
|
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)
|
static void flush_event(UIData *data)
|
||||||
{
|
{
|
||||||
if (data->cur_event) {
|
if (data->cur_event) {
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "nvim/api/private/helpers.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/charset.h"
|
#include "nvim/charset.h"
|
||||||
|
#include "nvim/eval.h"
|
||||||
#include "nvim/event/defs.h"
|
#include "nvim/event/defs.h"
|
||||||
#include "nvim/log.h"
|
#include "nvim/log.h"
|
||||||
#include "nvim/macros.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;
|
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)
|
static void handle_raw_buffer(TermInput *input, bool force)
|
||||||
{
|
{
|
||||||
HandleState is_paste = kNotApplicable;
|
HandleState is_paste = kNotApplicable;
|
||||||
|
Loading…
Reference in New Issue
Block a user