aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/api.txt15
-rw-r--r--runtime/doc/autocmd.txt25
-rw-r--r--runtime/doc/eval.txt16
-rw-r--r--runtime/doc/news.txt3
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--runtime/lua/vim/_meta/api.lua11
-rw-r--r--src/nvim/api/ui.c27
-rw-r--r--src/nvim/tui/input.c26
8 files changed, 107 insertions, 18 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 4430d97fc7..edf683473f 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -3591,6 +3591,21 @@ nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
Attributes: ~
|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()*
TODO: Documentation
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 4b36a7d4ec..6b698b0868 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -987,12 +987,25 @@ TermClose When a |terminal| job ends.
Sets these |v:event| keys:
status
*TermResponse*
-TermResponse After the response to t_RV is received from
- the terminal. The value of |v:termresponse|
- can be used to do things depending on the
- terminal version. May be triggered halfway
- through another event (file I/O, a shell
- command, or anything else that takes time).
+TermResponse When Nvim receives a OSC 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
+ (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 After a change was made to the text in the
current buffer in Normal mode. That is after
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 4cb29205a5..2223829548 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -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:termresponse* *termresponse-variable*
-v:termresponse The escape sequence returned by the terminal for the DA
- (request primary device attributes) control sequence. It is
- set when Vim receives an escape sequence that starts with ESC
- [ or CSI and ends in a 'c', with only digits, ';' and '.' in
- 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: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:testing* *testing-variable*
v:testing Must be set before using `test_garbagecollect_now()`.
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index e32e1aadb6..fa77e8d086 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -205,6 +205,9 @@ The following new APIs and features were added.
• Added |vim.base64.encode()| and |vim.base64.decode()| for encoding and decoding
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*
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 8249179187..efebf46d85 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -567,6 +567,8 @@ Working directory (Vim implemented some of these after Nvim):
Autocommands:
- Fixed inconsistent behavior in execution of nested autocommands:
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*
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index 691da62f4f..0bee27970d 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -2059,6 +2059,17 @@ 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.
+--- 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 height integer
function vim.api.nvim_ui_try_resize(width, height) end
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;