1 /* isearch.c - incremental searching */
3 /* **************************************************************** */
5 /* I-Search and Searching */
7 /* **************************************************************** */
9 /* Copyright (C) 1987-2012 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 *));
69 static int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int));
71 /* Last line found by the current incremental search, so we don't `find'
72 identical lines many times in a row. Now part of isearch context. */
73 /* static char *prev_line_found; */
75 /* Last search string and its length. */
76 static char *last_isearch_string;
77 static int last_isearch_string_len;
79 static char * const default_isearch_terminators = "\033\012";
82 _rl_scxt_alloc (type, flags)
87 cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt));
92 cxt->search_string = 0;
93 cxt->search_string_size = cxt->search_string_index = 0;
96 cxt->allocated_line = 0;
97 cxt->hlen = cxt->hindex = 0;
99 cxt->save_point = rl_point;
100 cxt->save_mark = rl_mark;
101 cxt->save_line = where_history ();
102 cxt->last_found_line = cxt->save_line;
103 cxt->prev_line_found = 0;
105 cxt->save_undo_list = 0;
107 cxt->keymap = _rl_keymap;
108 cxt->okeymap = _rl_keymap;
110 cxt->history_pos = 0;
113 cxt->prevc = cxt->lastc = 0;
116 cxt->sline_len = cxt->sline_index = 0;
118 cxt->search_terminators = 0;
124 _rl_scxt_dispose (cxt, flags)
128 FREE (cxt->search_string);
129 FREE (cxt->allocated_line);
135 /* Search backwards through the history looking for a string which is typed
136 interactively. Start with the current line. */
138 rl_reverse_search_history (sign, key)
141 return (rl_search_history (-sign, key));
144 /* Search forwards through the history looking for a string which is typed
145 interactively. Start with the current line. */
147 rl_forward_search_history (sign, key)
150 return (rl_search_history (sign, key));
153 /* Display the current state of the search in the echo-area.
154 SEARCH_STRING contains the string that is being searched for,
155 DIRECTION is zero for forward, or non-zero for reverse,
156 WHERE is the history list number of the current line. If it is
157 -1, then this line is the starting one. */
159 rl_display_search (search_string, flags, where)
164 int msglen, searchlen;
166 searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
168 message = (char *)xmalloc (searchlen + 64);
174 sprintf (message, "[%d]", where + history_base);
175 msglen = strlen (message);
179 message[msglen++] = '(';
181 if (flags & SF_FAILED)
183 strcpy (message + msglen, "failed ");
187 if (flags & SF_REVERSE)
189 strcpy (message + msglen, "reverse-");
193 strcpy (message + msglen, "i-search)`");
198 strcpy (message + msglen, search_string);
202 strcpy (message + msglen, "': ");
204 rl_message ("%s", message);
206 (*rl_redisplay_function) ();
209 static _rl_search_cxt *
210 _rl_isearch_init (direction)
217 cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
219 cxt->sflags |= SF_REVERSE;
221 cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
222 : default_isearch_terminators;
224 /* Create an array of pointers to the lines that we want to search. */
225 hlist = history_list ();
226 rl_maybe_replace_line ();
229 for (i = 0; hlist[i]; i++);
231 /* Allocate space for this many lines, +1 for the current input line,
232 and remember those lines. */
233 cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *));
234 for (i = 0; i < cxt->hlen; i++)
235 cxt->lines[i] = hlist[i]->line;
237 if (_rl_saved_line_for_history)
238 cxt->lines[i] = _rl_saved_line_for_history->line;
241 /* Keep track of this so we can free it. */
242 cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
243 strcpy (cxt->allocated_line, &rl_line_buffer[0]);
244 cxt->lines[i] = cxt->allocated_line;
249 /* The line where we start the search. */
250 cxt->history_pos = cxt->save_line;
254 /* Initialize search parameters. */
255 cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128);
256 cxt->search_string[cxt->search_string_index = 0] = '\0';
258 /* Normalize DIRECTION into 1 or -1. */
259 cxt->direction = (direction >= 0) ? 1 : -1;
261 cxt->sline = rl_line_buffer;
262 cxt->sline_len = strlen (cxt->sline);
263 cxt->sline_index = rl_point;
265 _rl_iscxt = cxt; /* save globally */
271 _rl_isearch_fini (cxt)
274 /* First put back the original state. */
275 strcpy (rl_line_buffer, cxt->lines[cxt->save_line]);
277 rl_restore_prompt ();
279 /* Save the search string for possible later use. */
280 FREE (last_isearch_string);
281 last_isearch_string = cxt->search_string;
282 last_isearch_string_len = cxt->search_string_index;
283 cxt->search_string = 0;
285 if (cxt->last_found_line < cxt->save_line)
286 rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0);
288 rl_get_next_history (cxt->last_found_line - cxt->save_line, 0);
290 /* If the string was not found, put point at the end of the last matching
291 line. If last_found_line == orig_line, we didn't find any matching
292 history lines at all, so put point back in its original position. */
293 if (cxt->sline_index < 0)
295 if (cxt->last_found_line == cxt->save_line)
296 cxt->sline_index = cxt->save_point;
298 cxt->sline_index = strlen (rl_line_buffer);
299 rl_mark = cxt->save_mark;
302 rl_point = cxt->sline_index;
303 /* Don't worry about where to put the mark here; rl_get_previous_history
304 and rl_get_next_history take care of it. */
310 _rl_search_getchar (cxt)
315 /* Read a key and decide how to proceed. */
316 RL_SETSTATE(RL_STATE_MOREINPUT);
317 c = cxt->lastc = rl_read_key ();
318 RL_UNSETSTATE(RL_STATE_MOREINPUT);
320 #if defined (HANDLE_MULTIBYTE)
321 /* This ends up with C (and LASTC) being set to the last byte of the
322 multibyte character. In most cases c == lastc == mb[0] */
323 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
324 c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
331 #define ENDSRCH_CHAR(c) \
332 ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
334 /* Process just-read character C according to isearch context CXT. Return
335 -1 if the caller should just free the context and return, 0 if we should
336 break out of the loop, and 1 if we should continue to read characters. */
338 _rl_isearch_dispatch (cxt, c)
342 int n, wstart, wlen, limit, cval;
343 rl_command_func_t *f;
345 f = (rl_command_func_t *)NULL;
349 cxt->sflags |= SF_FAILED;
350 cxt->history_pos = cxt->last_found_line;
354 /* If we are moving into a new keymap, modify cxt->keymap and go on.
355 This can be a problem if c == ESC and we want to terminate the
356 incremental search, so we check */
357 if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
359 /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
360 takes microseconds, so multiply by 1000. If we don't get any
361 additional input and this keymap shadows another function, process
362 that key as if it was all we read. */
363 if (_rl_keyseq_timeout > 0 &&
364 RL_ISSTATE (RL_STATE_CALLBACK) == 0 &&
365 RL_ISSTATE (RL_STATE_INPUTPENDING) == 0 &&
366 _rl_pushed_input_available () == 0 &&
367 ((Keymap)(cxt->keymap[c].function))[ANYOTHERKEY].function &&
368 _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
371 cxt->okeymap = cxt->keymap;
372 cxt->keymap = FUNCTION_TO_KEYMAP (cxt->keymap, c);
373 cxt->sflags |= SF_CHGKMAP;
374 /* XXX - we should probably save this sequence, so we can do
375 something useful if this doesn't end up mapping to a command we
376 interpret here. Right now we just save the most recent character
377 that caused the index into a new keymap. */
379 #if defined (HANDLE_MULTIBYTE)
380 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
384 cxt->pmb[0] = c; /* XXX should be == cxt->mb[0] */
388 memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
396 /* Translate the keys we do something with to opcodes. */
397 if (c >= 0 && cxt->keymap[c].type == ISFUNC)
399 f = cxt->keymap[c].function;
401 if (f == rl_reverse_search_history)
402 cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
403 else if (f == rl_forward_search_history)
404 cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1;
405 else if (f == rl_rubout)
407 else if (c == CTRL ('G') || f == rl_abort)
409 else if (c == CTRL ('W') || f == rl_unix_word_rubout) /* XXX */
411 else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
415 /* If we changed the keymap earlier while translating a key sequence into
416 a command, restore it now that we've succeeded. */
417 if (cxt->sflags & SF_CHGKMAP)
419 cxt->keymap = cxt->okeymap;
420 cxt->sflags &= ~SF_CHGKMAP;
421 /* If we indexed into a new keymap, but didn't map to a command that
422 affects the search (lastc > 0), and the character that mapped to a
423 new keymap would have ended the search (ENDSRCH_CHAR(cxt->prevc)),
424 handle that now as if the previous char would have ended the search
425 and we would have read the current character. */
426 /* XXX - should we check cxt->mb? */
427 if (cxt->lastc > 0 && ENDSRCH_CHAR (cxt->prevc))
429 rl_stuff_char (cxt->lastc);
430 rl_execute_next (cxt->prevc);
431 /* XXX - do we insert everything in cxt->pmb? */
434 /* Otherwise, if the current character is mapped to self-insert or
435 nothing (i.e., not an editing command), and the previous character
436 was a keymap index, then we need to insert both the previous
437 character and the current character into the search string. */
438 else if (cxt->lastc > 0 && cxt->prevc > 0 &&
439 cxt->keymap[cxt->prevc].type == ISKMAP &&
440 (f == 0 || f == rl_insert))
442 /* Make lastc be the next character read */
443 /* XXX - do we insert everything in cxt->mb? */
444 rl_execute_next (cxt->lastc);
445 /* Dispatch on the previous character (insert into search string) */
446 cxt->lastc = cxt->prevc;
447 #if defined (HANDLE_MULTIBYTE)
448 /* Have to overwrite cxt->mb here because dispatch uses it below */
449 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
451 if (cxt->pmb[1] == 0)
453 cxt->mb[0] = cxt->lastc; /* == cxt->prevc */
457 memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
462 else if (cxt->lastc > 0 && cxt->prevc > 0 && f && f != rl_insert)
464 rl_stuff_char (cxt->lastc);
465 rl_execute_next (cxt->prevc);
466 /* XXX - do we insert everything in cxt->pmb? */
471 /* The characters in isearch_terminators (set from the user-settable
472 variable isearch-terminators) are used to terminate the search but
473 not subsequently execute the character as a command. The default
474 value is "\033\012" (ESC and C-J). */
475 if (cxt->lastc > 0 && strchr (cxt->search_terminators, cxt->lastc))
477 /* ESC still terminates the search, but if there is pending
478 input or if input arrives within 0.1 seconds (on systems
479 with select(2)) it is used as a prefix character
480 with rl_execute_next. WATCH OUT FOR THIS! This is intended
481 to allow the arrow keys to be used like ^F and ^B are used
482 to terminate the search and execute the movement command.
483 XXX - since _rl_input_available depends on the application-
484 settable keyboard timeout value, this could alternatively
485 use _rl_input_queued(100000) */
486 if (cxt->lastc == ESC && (_rl_pushed_input_available () || _rl_input_available ()))
487 rl_execute_next (ESC);
491 #if defined (HANDLE_MULTIBYTE)
492 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
494 if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc))
496 /* This sets rl_pending_input to LASTC; it will be picked up the next
497 time rl_read_key is called. */
498 rl_execute_next (cxt->lastc);
504 if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc))
506 /* This sets rl_pending_input to LASTC; it will be picked up the next
507 time rl_read_key is called. */
508 rl_execute_next (cxt->lastc);
512 /* Now dispatch on the character. `Opcodes' affect the search string or
513 state. Other characters are added to the string. */
518 if (cxt->search_string_index == 0)
520 if (last_isearch_string)
522 cxt->search_string_size = 64 + last_isearch_string_len;
523 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
524 strcpy (cxt->search_string, last_isearch_string);
525 cxt->search_string_index = last_isearch_string_len;
526 rl_display_search (cxt->search_string, cxt->sflags, -1);
531 else if (cxt->sflags & SF_REVERSE)
533 else if (cxt->sline_index != cxt->sline_len)
539 /* switch directions */
541 cxt->direction = -cxt->direction;
542 if (cxt->direction < 0)
543 cxt->sflags |= SF_REVERSE;
545 cxt->sflags &= ~SF_REVERSE;
548 /* delete character from search string. */
549 case -3: /* C-H, DEL */
550 /* This is tricky. To do this right, we need to keep a
551 stack of search positions for the current search, with
552 sentinels marking the beginning and end. But this will
553 do until we have a real isearch-undo. */
554 if (cxt->search_string_index == 0)
557 cxt->search_string[--cxt->search_string_index] = '\0';
560 case -4: /* C-G, abort */
561 rl_replace_line (cxt->lines[cxt->save_line], 0);
562 rl_point = cxt->save_point;
563 rl_mark = cxt->save_mark;
570 /* skip over portion of line we already matched and yank word */
571 wstart = rl_point + cxt->search_string_index;
572 if (wstart >= rl_end)
578 /* if not in a word, move to one. */
579 cval = _rl_char_value (rl_line_buffer, wstart);
580 if (_rl_walphabetic (cval) == 0)
585 n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);;
588 cval = _rl_char_value (rl_line_buffer, n);
589 if (_rl_walphabetic (cval) == 0)
591 n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);;
593 wlen = n - wstart + 1;
594 if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
596 cxt->search_string_size += wlen + 1;
597 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
599 for (; wstart < n; wstart++)
600 cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart];
601 cxt->search_string[cxt->search_string_index] = '\0';
605 /* skip over portion of line we already matched and yank rest */
606 wstart = rl_point + cxt->search_string_index;
607 if (wstart >= rl_end)
612 n = rl_end - wstart + 1;
613 if (cxt->search_string_index + n + 1 >= cxt->search_string_size)
615 cxt->search_string_size += n + 1;
616 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
618 for (n = wstart; n < rl_end; n++)
619 cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n];
620 cxt->search_string[cxt->search_string_index] = '\0';
623 /* Add character to search string and continue search. */
625 if (cxt->search_string_index + 2 >= cxt->search_string_size)
627 cxt->search_string_size += 128;
628 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
630 #if defined (HANDLE_MULTIBYTE)
631 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
635 if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
636 cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
638 for (j = 0, l = RL_STRLEN (cxt->mb); j < l; )
639 cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
643 cxt->search_string[cxt->search_string_index++] = cxt->lastc; /* XXX - was c instead of lastc */
644 cxt->search_string[cxt->search_string_index] = '\0';
648 for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
650 limit = cxt->sline_len - cxt->search_string_index + 1;
652 /* Search the current line. */
653 while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
655 if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
657 cxt->sflags |= SF_FOUND;
661 cxt->sline_index += cxt->direction;
663 if (cxt->sflags & SF_FOUND)
666 /* Move to the next line, but skip new copies of the line
667 we just found and lines shorter than the string we're
671 /* Move to the next line. */
672 cxt->history_pos += cxt->direction;
674 /* At limit for direction? */
675 if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
677 cxt->sflags |= SF_FAILED;
681 /* We will need these later. */
682 cxt->sline = cxt->lines[cxt->history_pos];
683 cxt->sline_len = strlen (cxt->sline);
685 while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
686 (cxt->search_string_index > cxt->sline_len));
688 if (cxt->sflags & SF_FAILED)
691 /* Now set up the line for searching... */
692 cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
695 if (cxt->sflags & SF_FAILED)
697 /* We cannot find the search string. Ding the bell. */
699 cxt->history_pos = cxt->last_found_line;
700 rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
704 /* We have found the search string. Just display it. But don't
705 actually move there in the history list until the user accepts
707 if (cxt->sflags & SF_FOUND)
709 cxt->prev_line_found = cxt->lines[cxt->history_pos];
710 rl_replace_line (cxt->lines[cxt->history_pos], 0);
711 rl_point = cxt->sline_index;
712 cxt->last_found_line = cxt->history_pos;
713 rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
720 _rl_isearch_cleanup (cxt, r)
725 _rl_isearch_fini (cxt);
726 _rl_scxt_dispose (cxt, 0);
729 RL_UNSETSTATE(RL_STATE_ISEARCH);
734 /* Search through the history looking for an interactively typed string.
735 This is analogous to i-search. We start the search in the current line.
736 DIRECTION is which direction to search; >= 0 means forward, < 0 means
739 rl_search_history (direction, invoking_key)
740 int direction, invoking_key;
742 _rl_search_cxt *cxt; /* local for now, but saved globally */
745 RL_SETSTATE(RL_STATE_ISEARCH);
746 cxt = _rl_isearch_init (direction);
748 rl_display_search (cxt->search_string, cxt->sflags, -1);
750 /* If we are using the callback interface, all we do is set up here and
751 return. The key is that we leave RL_STATE_ISEARCH set. */
752 if (RL_ISSTATE (RL_STATE_CALLBACK))
758 c = _rl_search_getchar (cxt);
759 /* We might want to handle EOF here (c == 0) */
760 r = _rl_isearch_dispatch (cxt, cxt->lastc);
765 /* The searching is over. The user may have found the string that she
766 was looking for, or else she may have exited a failing search. If
767 LINE_INDEX is -1, then that shows that the string searched for was
768 not found. We use this to determine where to place rl_point. */
769 return (_rl_isearch_cleanup (cxt, r));
772 #if defined (READLINE_CALLBACKS)
773 /* Called from the callback functions when we are ready to read a key. The
774 callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH).
775 If _rl_isearch_dispatch finishes searching, this function is responsible
776 for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */
778 _rl_isearch_callback (cxt)
783 c = _rl_search_getchar (cxt);
784 /* We might want to handle EOF here */
785 r = _rl_isearch_dispatch (cxt, cxt->lastc);
787 return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0;