Skip to content

Commit 93480f7

Browse files
tbunggpanderszeertzjq
authored
feat(term): trigger TermRequest for APC (neovim#32407)
Co-authored-by: Gregory Anders <[email protected]> Co-authored-by: zeertzjq <[email protected]>
1 parent e4c6e73 commit 93480f7

File tree

7 files changed

+67
-16
lines changed

7 files changed

+67
-16
lines changed

runtime/doc/autocmd.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,8 +1004,8 @@ TermClose When a |terminal| job ends.
10041004
Sets these |v:event| keys:
10051005
status
10061006
*TermRequest*
1007-
TermRequest When a |:terminal| child process emits an OSC
1008-
or DCS sequence. Sets |v:termrequest|. The
1007+
TermRequest When a |:terminal| child process emits an OSC,
1008+
DCS or APC sequence. Sets |v:termrequest|. The
10091009
|event-data| is the request string.
10101010
*TermResponse*
10111011
TermResponse When Nvim receives an OSC or DCS response from

runtime/doc/news.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,8 @@ TERMINAL
372372
• The |terminal| has experimental support for the Kitty keyboard protocol
373373
(sometimes called "CSI u" key encoding). Only the "Disambiguate escape
374374
codes" mode is currently supported.
375+
• The |terminal| emits a |TermRequest| autocommand event when the child process
376+
emits an APC control sequence.
375377

376378
TREESITTER
377379

runtime/doc/vvars.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ v:t_string Value of |String| type. Read-only. See: |type()|
663663

664664
*v:termrequest* *termrequest-variable*
665665
v:termrequest
666-
The value of the most recent OSC or DCS control sequence
666+
The value of the most recent OSC, DCS or APC control sequence
667667
sent from a process running in the embedded |terminal|.
668668
This can be read in a |TermRequest| event handler to respond
669669
to queries from embedded applications.

runtime/lua/vim/_meta/vvars.lua

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/nvim/terminal.c

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,10 @@ struct terminal {
183183

184184
bool color_set[16];
185185

186-
char *selection_buffer; /// libvterm selection buffer
187-
StringBuilder selection; /// Growable array containing full selection data
186+
char *selection_buffer; ///< libvterm selection buffer
187+
StringBuilder selection; ///< Growable array containing full selection data
188+
189+
StringBuilder termrequest_buffer; ///< Growable array containing unfinished request payload
188190

189191
size_t refcount; // reference count
190192
};
@@ -307,26 +309,61 @@ static int on_osc(int command, VTermStringFragment frag, void *user)
307309
return 1;
308310
}
309311

310-
StringBuilder request = KV_INITIAL_VALUE;
311-
kv_printf(request, "\x1b]%d;", command);
312-
kv_concat_len(request, frag.str, frag.len);
313-
schedule_termrequest(term, request.items, request.size);
312+
if (frag.initial) {
313+
kv_size(term->termrequest_buffer) = 0;
314+
kv_printf(term->termrequest_buffer, "\x1b]%d;", command);
315+
}
316+
kv_concat_len(term->termrequest_buffer, frag.str, frag.len);
317+
if (frag.final) {
318+
char *payload = xmemdup(term->termrequest_buffer.items, term->termrequest_buffer.size);
319+
schedule_termrequest(user, payload, term->termrequest_buffer.size);
320+
}
314321
return 1;
315322
}
316323

317324
static int on_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user)
318325
{
326+
Terminal *term = user;
327+
319328
if (command == NULL || frag.str == NULL) {
320329
return 0;
321330
}
322331
if (!has_event(EVENT_TERMREQUEST)) {
323332
return 1;
324333
}
325334

326-
StringBuilder request = KV_INITIAL_VALUE;
327-
kv_printf(request, "\x1bP%*s", (int)commandlen, command);
328-
kv_concat_len(request, frag.str, frag.len);
329-
schedule_termrequest(user, request.items, request.size);
335+
if (frag.initial) {
336+
kv_size(term->termrequest_buffer) = 0;
337+
kv_printf(term->termrequest_buffer, "\x1bP%*s", (int)commandlen, command);
338+
}
339+
kv_concat_len(term->termrequest_buffer, frag.str, frag.len);
340+
if (frag.final) {
341+
char *payload = xmemdup(term->termrequest_buffer.items, term->termrequest_buffer.size);
342+
schedule_termrequest(user, payload, term->termrequest_buffer.size);
343+
}
344+
return 1;
345+
}
346+
347+
static int on_apc(VTermStringFragment frag, void *user)
348+
{
349+
Terminal *term = user;
350+
if (frag.str == NULL || frag.len == 0) {
351+
return 0;
352+
}
353+
354+
if (!has_event(EVENT_TERMREQUEST)) {
355+
return 1;
356+
}
357+
358+
if (frag.initial) {
359+
kv_size(term->termrequest_buffer) = 0;
360+
kv_printf(term->termrequest_buffer, "\x1b_");
361+
}
362+
kv_concat_len(term->termrequest_buffer, frag.str, frag.len);
363+
if (frag.final) {
364+
char *payload = xmemdup(term->termrequest_buffer.items, term->termrequest_buffer.size);
365+
schedule_termrequest(user, payload, term->termrequest_buffer.size);
366+
}
330367
return 1;
331368
}
332369

@@ -335,7 +372,7 @@ static VTermStateFallbacks vterm_fallbacks = {
335372
.csi = NULL,
336373
.osc = on_osc,
337374
.dcs = on_dcs,
338-
.apc = NULL,
375+
.apc = on_apc,
339376
.pm = NULL,
340377
.sos = NULL,
341378
};
@@ -924,6 +961,7 @@ void terminal_destroy(Terminal **termpp)
924961
xfree(term->title);
925962
xfree(term->selection_buffer);
926963
kv_destroy(term->selection);
964+
kv_destroy(term->termrequest_buffer);
927965
vterm_free(term->vt);
928966
xfree(term);
929967
*termpp = NULL; // coverity[dead-store]

src/nvim/vvars.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ M.vars = {
799799
termrequest = {
800800
type = 'string',
801801
desc = [=[
802-
The value of the most recent OSC or DCS control sequence
802+
The value of the most recent OSC, DCS or APC control sequence
803803
sent from a process running in the embedded |terminal|.
804804
This can be read in a |TermRequest| event handler to respond
805805
to queries from embedded applications.

test/functional/terminal/buffer_spec.lua

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,17 @@ describe(':terminal buffer', function()
350350
eq(termbuf, eval('g:termbuf'))
351351
end)
352352

353+
it('emits TermRequest events for APC', function()
354+
local term = api.nvim_open_term(0, {})
355+
356+
-- cwd will be inserted in a file URI, which cannot contain backs
357+
local cwd = t.fix_slashes(fn.getcwd())
358+
local parent = cwd:match('^(.+/)')
359+
local expected = '\027_Gfile://host' .. parent
360+
api.nvim_chan_send(term, string.format('%s\027\\', expected))
361+
eq(expected, eval('v:termrequest'))
362+
end)
363+
353364
it('TermRequest synchronization #27572', function()
354365
command('autocmd! nvim.terminal TermRequest')
355366
local term = exec_lua([[

0 commit comments

Comments
 (0)