From c5b07f520379614e183285cd437763bf4146ab2a Mon Sep 17 00:00:00 2001 From: fang Date: Fri, 1 Apr 2022 22:15:34 +0200 Subject: [PATCH] term: batch simple input events into a single %txt By accumulating %txt events until we reach a more complex event or reach the end of the input buffer, we can significantly reduce the "overhead" of pasting text into the terminal. Instead of an event for each character, we now inject up to a buffer's worth of characters (currently, 123 bytes) at a time. This makes pasting process much faster. Incidentally, the behavior for pasting text with syntax errors into the dojo may be a little bit surprising: after every buffer boundary, the dojo will complain about the syntax error, moving the cursor to its location, and causing the remainder of the text to be inserted in that position. This may result in garbled-looking input in some cases. This ux problem should be resolved on dojo's end, perhaps by highlighting syntax errors with color, instead of the cursor. Alleviates most of the need for #5687. --- pkg/urbit/include/vere/vere.h | 9 ++++--- pkg/urbit/vere/io/term.c | 47 +++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index 023635f35c..3d7c0b0308 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -158,10 +158,11 @@ c3_y col_y; // column coordinate } esc; - struct { - c3_y syb_y[5]; // utf8 code buffer - c3_w len_w; // present length - c3_w wid_w; // total width + struct { // input buffering + c3_y syb_y[5]; // utf8 code buffer + c3_w len_w; // present length + c3_w wid_w; // total width + u3_noun imp; // %txt input buffer } fut; struct { diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index 387e939ea8..f4039bf8b3 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -147,6 +147,7 @@ u3_term_log_init(void) uty_u->tat_u.fut.len_w = 0; uty_u->tat_u.fut.wid_w = 0; + uty_u->tat_u.fut.imp = u3_nul; } // default size @@ -636,9 +637,28 @@ _term_io_belt(u3_utty* uty_u, u3_noun blb) } } -/* _term_io_suck_char(): process a single character. +/* _term_io_spit(): input the buffer (if any), then input the belt (if any) */ static void +_term_io_spit(u3_utty* uty_u, u3_noun bet) { + u3_utat* tat_u = &uty_u->tat_u; + if (u3_nul != tat_u->fut.imp) { + _term_io_belt(uty_u, u3nc(c3__txt, u3kb_flop(tat_u->fut.imp))); + tat_u->fut.imp = u3_nul; + } + if (u3_none != bet) { + _term_io_belt(uty_u, bet); + } +} + +/* _term_io_suck_char(): process a single character. + * + * Note that this accumulates simple inputs in a buffer, and is not + * guaranteed to flush it fully. After a call (or sequence of calls) + * to this function, please call _term_io_spit(uty_u, u3_none) to + * flush any remainder. + */ +static void _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) { u3_utat* tat_u = &uty_u->tat_u; @@ -652,10 +672,10 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); break; } - case 'A': _term_io_belt(uty_u, u3nc(c3__aro, 'u')); break; - case 'B': _term_io_belt(uty_u, u3nc(c3__aro, 'd')); break; - case 'C': _term_io_belt(uty_u, u3nc(c3__aro, 'r')); break; - case 'D': _term_io_belt(uty_u, u3nc(c3__aro, 'l')); break; + case 'A': _term_io_spit(uty_u, u3nc(c3__aro, 'u')); break; + case 'B': _term_io_spit(uty_u, u3nc(c3__aro, 'd')); break; + case 'C': _term_io_spit(uty_u, u3nc(c3__aro, 'r')); break; + case 'D': _term_io_spit(uty_u, u3nc(c3__aro, 'l')); break; // case 'M': tat_u->esc.mou = c3y; break; } @@ -667,13 +687,13 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) // XX for backwards compatibility, check kelvin version // and fallback to [%met @c] // - _term_io_belt(uty_u, u3nt(c3__mod, c3__met, cay_y)); + _term_io_spit(uty_u, u3nt(c3__mod, c3__met, cay_y)); } else if ( 8 == cay_y || 127 == cay_y ) { tat_u->esc.ape = c3n; // XX backwards compatibility [%met @c] // - _term_io_belt(uty_u, u3nq(c3__mod, c3__met, c3__bac, u3_nul)); + _term_io_spit(uty_u, u3nq(c3__mod, c3__met, c3__bac, u3_nul)); } else if ( ('[' == cay_y) || ('O' == cay_y) ) { tat_u->esc.bra = c3y; @@ -698,7 +718,7 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) c3_y row_y = cay_y - 32; // only acknowledge button 1 presses within our window if ( 1 != tat_u->esc.ton_y && row_y <= tat_u->siz.row_l ) { - _term_io_belt(uty_u, u3nt(c3__hit, + _term_io_spit(uty_u, u3nt(c3__hit, tat_u->esc.col_y - 1, tat_u->siz.row_l - row_y)); } @@ -720,28 +740,28 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) wug = u3do("taft", huv); tat_u->fut.len_w = tat_u->fut.wid_w = 0; - _term_io_belt(uty_u, u3nt(c3__txt, wug, u3_nul)); + tat_u->fut.imp = u3nc(wug, tat_u->fut.imp); } } // individual characters // else { if ( (cay_y >= 32) && (cay_y < 127) ) { // visual ascii - _term_io_belt(uty_u, u3nt(c3__txt, cay_y, u3_nul)); + tat_u->fut.imp = u3nc(cay_y, tat_u->fut.imp); } else if ( 0 == cay_y ) { // null _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); } else if ( 8 == cay_y || 127 == cay_y ) { // backspace & delete - _term_io_belt(uty_u, u3nc(c3__bac, u3_nul)); + _term_io_spit(uty_u, u3nc(c3__bac, u3_nul)); } else if ( 10 == cay_y || 13 == cay_y ) { // newline & carriage return - _term_io_belt(uty_u, u3nc(c3__ret, u3_nul)); + _term_io_spit(uty_u, u3nc(c3__ret, u3_nul)); } else if ( cay_y <= 26 ) { // XX backwards compatibility [%ctl @c] // - _term_io_belt(uty_u, u3nt(c3__mod, c3__ctl, ('a' + (cay_y - 1)))); + _term_io_spit(uty_u, u3nt(c3__mod, c3__ctl, ('a' + (cay_y - 1)))); } else if ( 27 == cay_y ) { tat_u->esc.ape = c3y; @@ -799,6 +819,7 @@ _term_suck(u3_utty* uty_u, const c3_y* buf, ssize_t siz_i) for ( i=0; i < siz_i; i++ ) { _term_io_suck_char(uty_u, buf[i]); } + _term_io_spit(uty_u, u3_none); } } }