2323** is a C1 control in its UTF-8 form: running `printf '\e[31m'` once must
2424** not repaint every later prompt. */
2525
26- /* True when `s` holds nothing a terminal would interpret. 0x7f is DEL; the
27- pair 0xC2 0x80..0x9F is U+0080..U+009F, which some terminals read as a
28- control sequence introducer. */
29- static bool sg_clean (const unsigned char * s )
26+ /* The newest of the last sg_max entries that starts with the first `n`
27+ bytes of the line, is longer than it and is clean (rl_suggest_scan). */
28+ static char * sg_scan (t_shell * state , t_rl * l )
3029{
31- size_t i ;
30+ ssize_t i ;
3231
33- i = 0 ;
34- while (s [i ])
35- {
36- if (s [i ] < 0x20 || s [i ] == 0x7f )
37- return (false);
38- if (s [i ] == 0xc2 && s [i + 1 ] >= 0x80 && s [i + 1 ] < 0xa0 )
39- return (false);
40- i ++ ;
41- }
42- return (true);
32+ i = rl_suggest_scan (state , l , state -> hist .hist_cmds .len );
33+ if (i < 0 )
34+ return (NULL );
35+ return (((char * * )state -> hist .hist_cmds .ctx )[i ]);
4336}
4437
45- /* The newest of the last sg_max entries that starts with the first `n`
46- bytes of the line, is longer than it and is clean. A bounded look keeps
47- a huge history from slowing a keystroke down. */
48- static char * sg_scan (t_shell * state , t_rl * l , size_t n )
38+ /* True when the last scan still answers for the line: the line extends the
39+ one it was for and the entry still matches (or there was none). */
40+ static bool sg_cached (t_rl * l , size_t n )
4941{
50- char * * a ;
51- size_t i ;
52- size_t seen ;
42+ size_t p ;
5343
54- a = (char * * )state -> hist .hist_cmds .ctx ;
55- i = state -> hist .hist_cmds .len ;
56- seen = 0 ;
57- while (i > 0 && seen ++ < (size_t )l -> sg_max )
58- {
59- i -- ;
60- if (a [i ] && !ft_strncmp (a [i ], rl_line_buffer , n )
61- && ft_strlen (a [i ]) > n && sg_clean ((unsigned char * )a [i ]))
62- return (a [i ]);
63- }
64- return (NULL );
44+ if (!l -> sg_known )
45+ return (false);
46+ p = ft_strlen (l -> sg_prev );
47+ return (p <= n && !ft_strncmp (rl_line_buffer , l -> sg_prev , p )
48+ && (!l -> sg_ent || (ft_strlen (l -> sg_ent ) > n
49+ && !ft_strncmp (l -> sg_ent , rl_line_buffer , n ))));
6550}
6651
6752/* The entry to suggest for the line, or NULL.
@@ -75,26 +60,20 @@ static char *sg_scan(t_shell *state, t_rl *l, size_t n)
7560** it: it only grows between reads, and the cache is dropped per read. */
7661char * rl_suggest_find (t_shell * state , t_rl * l )
7762{
78- size_t n ;
79- size_t p ;
8063 char * e ;
8164
82- n = (size_t )rl_end ;
83- p = 0 ;
84- if (l -> sg_known )
85- p = ft_strlen (l -> sg_prev );
86- if (l -> sg_known && p <= n && !ft_strncmp (rl_line_buffer , l -> sg_prev , p )
87- && (!l -> sg_ent || (ft_strlen (l -> sg_ent ) > n
88- && !ft_strncmp (l -> sg_ent , rl_line_buffer , n ))))
65+ rl_suggest_cyc_sync (state , l );
66+ if (sg_cached (l , (size_t )rl_end ))
8967 return (l -> sg_ent );
9068 xfree (l -> sg_prev );
9169 xfree (l -> sg_ent );
92- e = sg_scan (state , l , n );
70+ e = sg_scan (state , l );
9371 l -> sg_ent = NULL ;
9472 if (e )
9573 l -> sg_ent = ft_strdup (e );
9674 l -> sg_prev = ft_strdup (rl_line_buffer );
9775 l -> sg_known = true;
76+ l -> sg_hn = state -> hist .hist_cmds .len ;
9877 return (l -> sg_ent );
9978}
10079
0 commit comments