1 /* isearch.c - incremental searching */
3 /* **************************************************************** */
5 /* I-Search and Searching */
7 /* **************************************************************** */
9 /* Copyright (C) 1987-2017 Free Software Foundation, Inc.
11 This file is part of the GNU Readline Library (Readline), a library
12 for reading lines of text with interactive input and history editing.
14 Readline is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
19 Readline is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with Readline. If not, see <http://www.gnu.org/licenses/>.
28 #define READLINE_LIBRARY
30 #if defined (HAVE_CONFIG_H)
34 #include <sys/types.h>
38 #if defined (HAVE_UNISTD_H)
42 #if defined (HAVE_STDLIB_H)
45 # include "ansi_stdlib.h"
54 #include "rlprivate.h"
57 /* Variables exported to other files in the readline library. */
58 char *_rl_isearch_terminators = (char *)NULL;
60 _rl_search_cxt *_rl_iscxt = 0;
62 /* Variables imported from other files in the readline library. */
63 extern HIST_ENTRY *_rl_saved_line_for_history;
65 static int rl_search_history PARAMS((int, int));
67 static _rl_search_cxt *_rl_isearch_init PARAMS((int));
68 static void _rl_isearch_fini PARAMS((_rl_search_cxt *));
70 /* Last line found by the current incremental search, so we don't `find'
71 identical lines many times in a row. Now part of isearch context. */
72 /* static char *prev_line_found; */
74 /* Last search string and its length. */
75 static char *last_isearch_string;
76 static int last_isearch_string_len;
78 static char * const default_isearch_terminators = "\033\012";
81 _rl_scxt_alloc (int type, int flags)
85 cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt));
90 cxt->search_string = 0;
91 cxt->search_string_size = cxt->search_string_index = 0;
94 cxt->allocated_line = 0;
95 cxt->hlen = cxt->hindex = 0;
97 cxt->save_point = rl_point;
98 cxt->save_mark = rl_mark;
99 cxt->save_line = where_history ();
100 cxt->last_found_line = cxt->save_line;
101 cxt->prev_line_found = 0;
103 cxt->save_undo_list = 0;
105 cxt->keymap = _rl_keymap;
106 cxt->okeymap = _rl_keymap;
108 cxt->history_pos = 0;
111 cxt->prevc = cxt->lastc = 0;
114 cxt->sline_len = cxt->sline_index = 0;
116 cxt->search_terminators = 0;
122 _rl_scxt_dispose (_rl_search_cxt *cxt, int flags)
124 FREE (cxt->search_string);
125 FREE (cxt->allocated_line);
131 /* Search backwards through the history looking for a string which is typed
132 interactively. Start with the current line. */
134 rl_reverse_search_history (int sign, int key)
136 return (rl_search_history (-sign, key));
139 /* Search forwards through the history looking for a string which is typed
140 interactively. Start with the current line. */
142 rl_forward_search_history (int sign, int key)
144 return (rl_search_history (sign, key));
147 /* Display the current state of the search in the echo-area.
148 SEARCH_STRING contains the string that is being searched for,
149 DIRECTION is zero for forward, or non-zero for reverse,
150 WHERE is the history list number of the current line. If it is
151 -1, then this line is the starting one. */
153 rl_display_search (char *search_string, int flags, int where)
156 int msglen, searchlen;
158 searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
160 message = (char *)xmalloc (searchlen + 64);
166 sprintf (message, "[%d]", where + history_base);
167 msglen = strlen (message);
171 message[msglen++] = '(';
173 if (flags & SF_FAILED)
175 strcpy (message + msglen, "failed ");
179 if (flags & SF_REVERSE)
181 strcpy (message + msglen, "reverse-");
185 strcpy (message + msglen, "i-search)`");
190 strcpy (message + msglen, search_string);
194 strcpy (message + msglen, "': ");
196 rl_message ("%s", message);
198 (*rl_redisplay_function) ();
201 static _rl_search_cxt *
202 _rl_isearch_init (int direction)
208 cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
210 cxt->sflags |= SF_REVERSE;
212 cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
213 : default_isearch_terminators;
215 /* Create an array of pointers to the lines that we want to search. */
216 hlist = history_list ();
217 rl_maybe_replace_line ();
220 for (i = 0; hlist[i]; i++);
222 /* Allocate space for this many lines, +1 for the current input line,
223 and remember those lines. */
224 cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *));
225 for (i = 0; i < cxt->hlen; i++)
226 cxt->lines[i] = hlist[i]->line;
228 if (_rl_saved_line_for_history)
229 cxt->lines[i] = _rl_saved_line_for_history->line;
232 /* Keep track of this so we can free it. */
233 cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
234 strcpy (cxt->allocated_line, &rl_line_buffer[0]);
235 cxt->lines[i] = cxt->allocated_line;
240 /* The line where we start the search. */
241 cxt->history_pos = cxt->save_line;
245 /* Initialize search parameters. */
246 cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128);
247 cxt->search_string[cxt->search_string_index = 0] = '\0';
249 /* Normalize DIRECTION into 1 or -1. */
250 cxt->direction = (direction >= 0) ? 1 : -1;
252 cxt->sline = rl_line_buffer;
253 cxt->sline_len = strlen (cxt->sline);
254 cxt->sline_index = rl_point;
256 _rl_iscxt = cxt; /* save globally */
262 _rl_isearch_fini (_rl_search_cxt *cxt)
264 /* First put back the original state. */
265 rl_replace_line (cxt->lines[cxt->save_line], 0);
267 rl_restore_prompt ();
269 /* Save the search string for possible later use. */
270 FREE (last_isearch_string);
271 last_isearch_string = cxt->search_string;
272 last_isearch_string_len = cxt->search_string_index;
273 cxt->search_string = 0;
275 if (cxt->last_found_line < cxt->save_line)
276 rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0);
278 rl_get_next_history (cxt->last_found_line - cxt->save_line, 0);
280 /* If the string was not found, put point at the end of the last matching
281 line. If last_found_line == orig_line, we didn't find any matching
282 history lines at all, so put point back in its original position. */
283 if (cxt->sline_index < 0)
285 if (cxt->last_found_line == cxt->save_line)
286 cxt->sline_index = cxt->save_point;
288 cxt->sline_index = strlen (rl_line_buffer);
289 rl_mark = cxt->save_mark;
292 rl_point = cxt->sline_index;
293 /* Don't worry about where to put the mark here; rl_get_previous_history
294 and rl_get_next_history take care of it. */
301 _rl_search_getchar (_rl_search_cxt *cxt)
305 /* Read a key and decide how to proceed. */
306 RL_SETSTATE(RL_STATE_MOREINPUT);
307 c = cxt->lastc = rl_read_key ();
308 RL_UNSETSTATE(RL_STATE_MOREINPUT);
310 #if defined (HANDLE_MULTIBYTE)
311 /* This ends up with C (and LASTC) being set to the last byte of the
312 multibyte character. In most cases c == lastc == mb[0] */
313 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
314 c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
321 #define ENDSRCH_CHAR(c) \
322 ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
324 /* Process just-read character C according to isearch context CXT. Return
325 -1 if the caller should just free the context and return, 0 if we should
326 break out of the loop, and 1 if we should continue to read characters. */
328 _rl_isearch_dispatch (_rl_search_cxt *cxt, int c)
330 int n, wstart, wlen, limit, cval, incr;
334 rl_command_func_t *f;
336 f = (rl_command_func_t *)NULL;
340 cxt->sflags |= SF_FAILED;
341 cxt->history_pos = cxt->last_found_line;
345 /* If we are moving into a new keymap, modify cxt->keymap and go on.
346 This can be a problem if c == ESC and we want to terminate the
347 incremental search, so we check */
348 if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
350 /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
351 takes microseconds, so multiply by 1000. If we don't get any
352 additional input and this keymap shadows another function, process
353 that key as if it was all we read. */
354 if (_rl_keyseq_timeout > 0 &&
355 RL_ISSTATE (RL_STATE_CALLBACK) == 0 &&
356 RL_ISSTATE (RL_STATE_INPUTPENDING) == 0 &&
357 _rl_pushed_input_available () == 0 &&
358 ((Keymap)(cxt->keymap[c].function))[ANYOTHERKEY].function &&
359 _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
362 cxt->okeymap = cxt->keymap;
363 cxt->keymap = FUNCTION_TO_KEYMAP (cxt->keymap, c);
364 cxt->sflags |= SF_CHGKMAP;
365 /* XXX - we should probably save this sequence, so we can do
366 something useful if this doesn't end up mapping to a command we
367 interpret here. Right now we just save the most recent character
368 that caused the index into a new keymap. */
370 #if defined (HANDLE_MULTIBYTE)
371 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
375 cxt->pmb[0] = c; /* XXX should be == cxt->mb[0] */
379 memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
387 /* Translate the keys we do something with to opcodes. */
388 if (c >= 0 && cxt->keymap[c].type == ISFUNC)
390 f = cxt->keymap[c].function;
392 if (f == rl_reverse_search_history)
393 cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
394 else if (f == rl_forward_search_history)
395 cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1;
396 else if (f == rl_rubout)
398 else if (c == CTRL ('G') || f == rl_abort)
400 else if (c == CTRL ('W') || f == rl_unix_word_rubout) /* XXX */
402 else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
404 else if (f == rl_bracketed_paste_begin)
408 /* If we changed the keymap earlier while translating a key sequence into
409 a command, restore it now that we've succeeded. */
410 if (cxt->sflags & SF_CHGKMAP)
412 cxt->keymap = cxt->okeymap;
413 cxt->sflags &= ~SF_CHGKMAP;
414 /* If we indexed into a new keymap, but didn't map to a command that
415 affects the search (lastc > 0), and the character that mapped to a
416 new keymap would have ended the search (ENDSRCH_CHAR(cxt->prevc)),
417 handle that now as if the previous char would have ended the search
418 and we would have read the current character. */
419 /* XXX - should we check cxt->mb? */
420 if (cxt->lastc > 0 && ENDSRCH_CHAR (cxt->prevc))
422 rl_stuff_char (cxt->lastc);
423 rl_execute_next (cxt->prevc);
424 /* XXX - do we insert everything in cxt->pmb? */
427 /* Otherwise, if the current character is mapped to self-insert or
428 nothing (i.e., not an editing command), and the previous character
429 was a keymap index, then we need to insert both the previous
430 character and the current character into the search string. */
431 else if (cxt->lastc > 0 && cxt->prevc > 0 &&
432 cxt->keymap[cxt->prevc].type == ISKMAP &&
433 (f == 0 || f == rl_insert))
435 /* Make lastc be the next character read */
436 /* XXX - do we insert everything in cxt->mb? */
437 rl_execute_next (cxt->lastc);
438 /* Dispatch on the previous character (insert into search string) */
439 cxt->lastc = cxt->prevc;
440 #if defined (HANDLE_MULTIBYTE)
441 /* Have to overwrite cxt->mb here because dispatch uses it below */
442 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
444 if (cxt->pmb[1] == 0)
446 cxt->mb[0] = cxt->lastc; /* == cxt->prevc */
450 memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
455 else if (cxt->lastc > 0 && cxt->prevc > 0 && f && f != rl_insert)
457 rl_stuff_char (cxt->lastc);
458 rl_execute_next (cxt->prevc);
459 /* XXX - do we insert everything in cxt->pmb? */
464 /* The characters in isearch_terminators (set from the user-settable
465 variable isearch-terminators) are used to terminate the search but
466 not subsequently execute the character as a command. The default
467 value is "\033\012" (ESC and C-J). */
468 if (cxt->lastc > 0 && strchr (cxt->search_terminators, cxt->lastc))
470 /* ESC still terminates the search, but if there is pending
471 input or if input arrives within 0.1 seconds (on systems
472 with select(2)) it is used as a prefix character
473 with rl_execute_next. WATCH OUT FOR THIS! This is intended
474 to allow the arrow keys to be used like ^F and ^B are used
475 to terminate the search and execute the movement command.
476 XXX - since _rl_input_available depends on the application-
477 settable keyboard timeout value, this could alternatively
478 use _rl_input_queued(100000) */
479 if (cxt->lastc == ESC && (_rl_pushed_input_available () || _rl_input_available ()))
480 rl_execute_next (ESC);
484 #if defined (HANDLE_MULTIBYTE)
485 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
487 if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc))
489 /* This sets rl_pending_input to LASTC; it will be picked up the next
490 time rl_read_key is called. */
491 rl_execute_next (cxt->lastc);
497 if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc))
499 /* This sets rl_pending_input to LASTC; it will be picked up the next
500 time rl_read_key is called. */
501 rl_execute_next (cxt->lastc);
505 /* Now dispatch on the character. `Opcodes' affect the search string or
506 state. Other characters are added to the string. */
511 if (cxt->search_string_index == 0)
513 if (last_isearch_string)
515 cxt->search_string_size = 64 + last_isearch_string_len;
516 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
517 strcpy (cxt->search_string, last_isearch_string);
518 cxt->search_string_index = last_isearch_string_len;
519 rl_display_search (cxt->search_string, cxt->sflags, -1);
524 else if ((cxt->sflags & SF_REVERSE) && cxt->sline_index >= 0)
526 else if (cxt->sline_index != cxt->sline_len)
532 /* switch directions */
534 cxt->direction = -cxt->direction;
535 if (cxt->direction < 0)
536 cxt->sflags |= SF_REVERSE;
538 cxt->sflags &= ~SF_REVERSE;
541 /* delete character from search string. */
542 case -3: /* C-H, DEL */
543 /* This is tricky. To do this right, we need to keep a
544 stack of search positions for the current search, with
545 sentinels marking the beginning and end. But this will
546 do until we have a real isearch-undo. */
547 if (cxt->search_string_index == 0)
549 else if (MB_CUR_MAX == 1 || rl_byte_oriented)
550 cxt->search_string[--cxt->search_string_index] = '\0';
553 wstart = _rl_find_prev_mbchar (cxt->search_string, cxt->search_string_index, MB_FIND_NONZERO);
555 cxt->search_string[cxt->search_string_index = wstart] = '\0';
557 cxt->search_string[cxt->search_string_index = 0] = '\0';
560 if (cxt->search_string_index == 0)
565 case -4: /* C-G, abort */
566 rl_replace_line (cxt->lines[cxt->save_line], 0);
567 rl_point = cxt->save_point;
568 rl_mark = cxt->save_mark;
575 /* skip over portion of line we already matched and yank word */
576 wstart = rl_point + cxt->search_string_index;
577 if (wstart >= rl_end)
583 /* if not in a word, move to one. */
584 cval = _rl_char_value (rl_line_buffer, wstart);
585 if (_rl_walphabetic (cval) == 0)
590 n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);;
593 cval = _rl_char_value (rl_line_buffer, n);
594 if (_rl_walphabetic (cval) == 0)
596 n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);;
598 wlen = n - wstart + 1;
599 if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
601 cxt->search_string_size += wlen + 1;
602 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
604 for (; wstart < n; wstart++)
605 cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart];
606 cxt->search_string[cxt->search_string_index] = '\0';
610 /* skip over portion of line we already matched and yank rest */
611 wstart = rl_point + cxt->search_string_index;
612 if (wstart >= rl_end)
617 n = rl_end - wstart + 1;
618 if (cxt->search_string_index + n + 1 >= cxt->search_string_size)
620 cxt->search_string_size += n + 1;
621 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
623 for (n = wstart; n < rl_end; n++)
624 cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n];
625 cxt->search_string[cxt->search_string_index] = '\0';
628 case -7: /* bracketed paste */
629 paste = _rl_bracketed_text (&pastelen);
630 if (paste == 0 || *paste == 0)
635 if (cxt->search_string_index + pastelen + 1 >= cxt->search_string_size)
637 cxt->search_string_size += pastelen + 2;
638 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
640 strcpy (cxt->search_string + cxt->search_string_index, paste);
641 cxt->search_string_index += pastelen;
645 /* Add character to search string and continue search. */
647 #if defined (HANDLE_MULTIBYTE)
648 wlen = (cxt->mb[0] == 0 || cxt->mb[1] == 0) ? 1 : RL_STRLEN (cxt->mb);
652 if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
654 cxt->search_string_size += 128; /* 128 much greater than MB_CUR_MAX */
655 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
657 #if defined (HANDLE_MULTIBYTE)
658 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
662 if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
663 cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
665 for (j = 0; j < wlen; )
666 cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
670 cxt->search_string[cxt->search_string_index++] = cxt->lastc; /* XXX - was c instead of lastc */
671 cxt->search_string[cxt->search_string_index] = '\0';
675 for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
677 if (cxt->search_string_index == 0)
679 cxt->sflags |= SF_FAILED;
683 limit = cxt->sline_len - cxt->search_string_index + 1;
685 /* Search the current line. */
686 while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
688 if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
690 cxt->sflags |= SF_FOUND;
694 cxt->sline_index += cxt->direction;
696 if (cxt->sline_index < 0)
698 cxt->sline_index = 0;
702 if (cxt->sflags & SF_FOUND)
705 /* Move to the next line, but skip new copies of the line
706 we just found and lines shorter than the string we're
710 /* Move to the next line. */
711 cxt->history_pos += cxt->direction;
713 /* At limit for direction? */
714 if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
716 cxt->sflags |= SF_FAILED;
720 /* We will need these later. */
721 cxt->sline = cxt->lines[cxt->history_pos];
722 cxt->sline_len = strlen (cxt->sline);
724 while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
725 (cxt->search_string_index > cxt->sline_len));
727 if (cxt->sflags & SF_FAILED)
729 /* XXX - reset sline_index if < 0 */
730 if (cxt->sline_index < 0)
731 cxt->sline_index = 0;
735 /* Now set up the line for searching... */
736 cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
739 if (cxt->sflags & SF_FAILED)
741 /* We cannot find the search string. Ding the bell. */
743 cxt->history_pos = cxt->last_found_line;
744 rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
748 /* We have found the search string. Just display it. But don't
749 actually move there in the history list until the user accepts
751 if (cxt->sflags & SF_FOUND)
753 cxt->prev_line_found = cxt->lines[cxt->history_pos];
754 rl_replace_line (cxt->lines[cxt->history_pos], 0);
755 rl_point = cxt->sline_index;
756 cxt->last_found_line = cxt->history_pos;
757 rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
764 _rl_isearch_cleanup (_rl_search_cxt *cxt, int r)
767 _rl_isearch_fini (cxt);
768 _rl_scxt_dispose (cxt, 0);
771 RL_UNSETSTATE(RL_STATE_ISEARCH);
776 /* Search through the history looking for an interactively typed string.
777 This is analogous to i-search. We start the search in the current line.
778 DIRECTION is which direction to search; >= 0 means forward, < 0 means
781 rl_search_history (int direction, int invoking_key)
783 _rl_search_cxt *cxt; /* local for now, but saved globally */
786 RL_SETSTATE(RL_STATE_ISEARCH);
787 cxt = _rl_isearch_init (direction);
789 rl_display_search (cxt->search_string, cxt->sflags, -1);
791 /* If we are using the callback interface, all we do is set up here and
792 return. The key is that we leave RL_STATE_ISEARCH set. */
793 if (RL_ISSTATE (RL_STATE_CALLBACK))
799 c = _rl_search_getchar (cxt);
800 /* We might want to handle EOF here (c == 0) */
801 r = _rl_isearch_dispatch (cxt, cxt->lastc);
806 /* The searching is over. The user may have found the string that she
807 was looking for, or else she may have exited a failing search. If
808 LINE_INDEX is -1, then that shows that the string searched for was
809 not found. We use this to determine where to place rl_point. */
810 return (_rl_isearch_cleanup (cxt, r));
813 #if defined (READLINE_CALLBACKS)
814 /* Called from the callback functions when we are ready to read a key. The
815 callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH).
816 If _rl_isearch_dispatch finishes searching, this function is responsible
817 for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */
819 _rl_isearch_callback (_rl_search_cxt *cxt)
823 c = _rl_search_getchar (cxt);
824 /* We might want to handle EOF here */
825 r = _rl_isearch_dispatch (cxt, cxt->lastc);
827 return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0;