On 5/21/15 5:44 AM, Ole Laursen wrote:
> I've been thinking about batching the input as it seems like an easier
> fix compared to rewriting update_display. So I inserted a log into
> insert_text:
>
> FILE *inserttextlog = fopen("inserttext.log", "a");
> fprintf(inserttextlog, "%i\n", l);
> fclose(inserttextlog);
>
> And it looks like each character is indeed inserted one-by-one since
> readline is reading them one-by-one from the input stream. There's a
> _rl_insert_typein called from _rl_insert_char which looks like it's
> actually taking care of a similar case of a series of rl_insert
> characters, but only for stuffed characters and not for multibyte
> cases.
Yes, readline doesn't try to read more than one character ahead. It
should not grab input that is intended to go to another process, and
it needs to process each character to see whether or not it is an
editing command, a character to be inserted, or the end of input.
Multibyte characters are handled by a loop in _rl_insert_char; characters
are still read one at a time, but this suppresses redisplay until an
entire multibyte character is consumed.
> I suppose one could try to generalize the _rl_insert_char code to grab
> any rl_insert characters waiting in the input stream. Or just always
> stuff everything waiting in the input stream.
The first is a reasonable approach, but _rl_insert_char is the wrong place
to do it. The second is totally wrong.
> Or decouple the display update from the line buffer modifications. The
> update could then e.g. be driven from the input stream reader.
It's already decoupled, as I explained in a previous message. You just
want it to be called less often.
> Or rewrite the call chain leading to _rl_insert_char so that it can
> take a string and not just a single byte.
I did a couple of things. I added an inline _rl_wcwidth function that
returns 1 for all printable ASCII characters and calls the system wcwidth
for the rest. That should help, though it doesn't do anything for
characters between 128 and 256.
The second thing is this experimental patch to text.c that uses the
heuristic you suggested: it assumes that a call to rl_insert will be
followed by other calls to rl_insert and tries to read ahead in the
input stream as long as the character read maps to self-insert. I've
attached that for folks to experiment with.
Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRU [email protected] http://cnswww.cns.cwru.edu/~chet/
*** ../bash-20150501/lib/readline/text.c 2015-01-23 20:32:30.000000000 -0500
--- lib/readline/text.c 2015-05-24 16:57:28.000000000 -0400
***************
*** 72,75 ****
--- 72,77 ----
#define TEXT_COUNT_MAX 1024
+ int _rl_optimize_typeahead = 1; /* rl_insert tries to read typeahead */
+
/* **************************************************************** */
/* */
***************
*** 891,896 ****
int count, c;
{
! return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
! : _rl_overwrite_char (count, c));
}
--- 893,932 ----
int count, c;
{
! int r, n, x;
!
! r = (rl_insert_mode == RL_IM_INSERT) ? _rl_insert_char (count, c) : _rl_overwrite_char (count, c);
!
! /* XXX -- attempt to batch-insert pending input that maps to self-insert */
! x = 0;
! n = (unsigned short)-2;
! while (_rl_optimize_typeahead &&
! (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
! _rl_pushed_input_available () == 0 &&
! _rl_input_queued (0) &&
! (n = rl_read_key ()) > 0 &&
! _rl_keymap[(unsigned char)n].type == ISFUNC &&
! _rl_keymap[(unsigned char)n].function == rl_insert)
! {
! r = (rl_insert_mode == RL_IM_INSERT) ? _rl_insert_char (1, n) : _rl_overwrite_char (1, n);
! /* _rl_insert_char keeps its own set of pending characters to compose a
! complete multibyte character, and only returns 1 if it sees a character
! that's part of a multibyte character but too short to complete one. We
! can try to read another character in the hopes that we will get the
! next one or just punt. Right now we try to read another character.
! We don't want to call rl_insert_next if _rl_insert_char has already
! stored the character in the pending_bytes array because that will
! result in doubled input. */
! n = (unsigned short)-2;
! x++; /* count of bytes of typeahead read, currently unused */
! if (r == 1) /* read partial multibyte character */
! continue;
! if (rl_done || r != 0)
! break;
! }
!
! if (n != (unsigned short)-2) /* -2 = sentinel value for having inserted N */
! r = rl_execute_next (n);
!
! return r;
}
_______________________________________________
Bug-readline mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-readline