1 /* search.c - code for non-incremental searching in emacs and vi modes. */
3 /* Copyright (C) 1992-2017 Free Software Foundation, Inc.
5 This file is part of the GNU Readline Library (Readline), a library
6 for reading lines of text with interactive input and history editing.
8 Readline is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 Readline is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Readline. If not, see <http://www.gnu.org/licenses/>.
22 #define READLINE_LIBRARY
24 #if defined (HAVE_CONFIG_H)
28 #include <sys/types.h>
31 #if defined (HAVE_UNISTD_H)
35 #if defined (HAVE_STDLIB_H)
38 # include "ansi_stdlib.h"
48 #include "rlprivate.h"
54 #define abs(x) (((x) >= 0) ? (x) : -(x))
56 _rl_search_cxt *_rl_nscxt = 0;
58 extern HIST_ENTRY *_rl_saved_line_for_history;
60 /* Functions imported from the rest of the library. */
61 extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
63 static char *noninc_search_string = (char *) NULL;
64 static int noninc_history_pos;
66 static char *prev_line_found = (char *) NULL;
68 static int rl_history_search_len;
69 static int rl_history_search_pos;
70 static int rl_history_search_flags;
72 static char *history_search_string;
73 static int history_string_size;
75 static void make_history_line_current PARAMS((HIST_ENTRY *));
76 static int noninc_search_from_pos PARAMS((char *, int, int, int, int *));
77 static int noninc_dosearch PARAMS((char *, int, int));
78 static int noninc_search PARAMS((int, int));
79 static int rl_history_search_internal PARAMS((int, int));
80 static void rl_history_search_reinit PARAMS((int));
82 static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
83 static void _rl_nsearch_abort PARAMS((_rl_search_cxt *));
84 static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int));
86 /* Make the data from the history entry ENTRY be the contents of the
87 current line. This doesn't do anything with rl_point; the caller
90 make_history_line_current (HIST_ENTRY *entry)
92 _rl_replace_text (entry->line, 0, rl_end);
95 if (rl_editing_mode == vi_mode)
96 /* POSIX.2 says that the `U' command doesn't affect the copy of any
97 command lines to the edit line. We're going to implement that by
98 making the undo list start after the matching line is copied to the
99 current editing buffer. */
100 rl_free_undo_list ();
103 if (_rl_saved_line_for_history)
104 _rl_free_history_entry (_rl_saved_line_for_history);
105 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
108 /* Search the history list for STRING starting at absolute history position
109 POS. If STRING begins with `^', the search must match STRING at the
110 beginning of a history line, otherwise a full substring match is performed
111 for STRING. DIR < 0 means to search backwards through the history list,
112 DIR >= 0 means to search forward. */
114 noninc_search_from_pos (char *string, int pos, int dir, int flags, int *ncp)
116 int ret, old, sflags;
122 old = where_history ();
123 if (history_set_pos (pos) == 0)
126 RL_SETSTATE(RL_STATE_SEARCH);
127 /* These functions return the match offset in the line; history_offset gives
128 the matching line in the history list */
129 if (flags & SF_PATTERN)
132 sflags = 0; /* Non-anchored search */
135 sflags |= ANCHORED_SEARCH;
138 ret = _hs_history_patsearch (s, dir, sflags);
140 else if (*string == '^')
141 ret = history_search_prefix (string + 1, dir);
143 ret = history_search (string, dir);
144 RL_UNSETSTATE(RL_STATE_SEARCH);
147 *ncp = ret; /* caller will catch -1 to indicate no-op */
150 ret = where_history ();
152 history_set_pos (old);
156 /* Search for a line in the history containing STRING. If DIR is < 0, the
157 search is backwards through previous entries, else through subsequent
158 entries. Returns 1 if the search was successful, 0 otherwise. */
160 noninc_dosearch (char *string, int dir, int flags)
165 if (string == 0 || *string == '\0' || noninc_history_pos < 0)
171 pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, (int *)0);
174 /* Search failed, current history position unchanged. */
175 rl_maybe_unsave_line ();
182 noninc_history_pos = pos;
184 oldpos = where_history ();
185 history_set_pos (noninc_history_pos);
186 entry = current_history (); /* will never be NULL after successful search */
188 #if defined (VI_MODE)
189 if (rl_editing_mode != vi_mode)
191 history_set_pos (oldpos);
193 make_history_line_current (entry);
202 static _rl_search_cxt *
203 _rl_nsearch_init (int dir, int pchar)
208 cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
210 cxt->sflags |= SF_REVERSE; /* not strictly needed */
211 #if defined (VI_MODE)
212 if (VI_COMMAND_MODE() && (pchar == '?' || pchar == '/'))
213 cxt->sflags |= SF_PATTERN;
216 cxt->direction = dir;
217 cxt->history_pos = cxt->save_line;
219 rl_maybe_save_line ();
221 /* Clear the undo list, since reading the search string should create its
222 own undo list, and the whole list will end up being freed when we
223 finish reading the search string. */
226 /* Use the line buffer to read the search string. */
227 rl_line_buffer[0] = 0;
228 rl_end = rl_point = 0;
230 p = _rl_make_prompt_for_search (pchar ? pchar : ':');
231 rl_message ("%s", p);
234 RL_SETSTATE(RL_STATE_NSEARCH);
242 _rl_nsearch_cleanup (_rl_search_cxt *cxt, int r)
244 _rl_scxt_dispose (cxt, 0);
247 RL_UNSETSTATE(RL_STATE_NSEARCH);
253 _rl_nsearch_abort (_rl_search_cxt *cxt)
255 rl_maybe_unsave_line ();
257 rl_point = cxt->save_point;
258 rl_mark = cxt->save_mark;
259 rl_restore_prompt ();
261 RL_UNSETSTATE (RL_STATE_NSEARCH);
264 /* Process just-read character C according to search context CXT. Return -1
265 if the caller should abort the search, 0 if we should break out of the
266 loop, and 1 if we should continue to read characters. */
268 _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c)
276 rl_unix_word_rubout (1, c);
280 rl_unix_line_discard (1, c);
291 _rl_nsearch_abort (cxt);
294 _rl_rubout_char (1, c);
300 _rl_nsearch_abort (cxt);
304 #if defined (HANDLE_MULTIBYTE)
305 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
306 rl_insert_text (cxt->mb);
309 _rl_insert_char (1, c);
313 (*rl_redisplay_function) ();
317 /* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
318 -1 if the search should be aborted, any other value means to clean up
319 using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
322 _rl_nsearch_dosearch (_rl_search_cxt *cxt)
324 rl_mark = cxt->save_mark;
326 /* If rl_point == 0, we want to re-use the previous search string and
327 start from the saved history position. If there's no previous search
331 if (noninc_search_string == 0)
334 rl_restore_prompt ();
335 RL_UNSETSTATE (RL_STATE_NSEARCH);
341 /* We want to start the search from the current history position. */
342 noninc_history_pos = cxt->save_line;
343 FREE (noninc_search_string);
344 noninc_search_string = savestring (rl_line_buffer);
346 /* If we don't want the subsequent undo list generated by the search
347 matching a history line to include the contents of the search string,
348 we need to clear rl_line_buffer here. For now, we just clear the
349 undo list generated by reading the search string. (If the search
350 fails, the old undo list will be restored by rl_maybe_unsave_line.) */
351 rl_free_undo_list ();
354 rl_restore_prompt ();
355 return (noninc_dosearch (noninc_search_string, cxt->direction, cxt->sflags&SF_PATTERN));
358 /* Search non-interactively through the history list. DIR < 0 means to
359 search backwards through the history of previous commands; otherwise
360 the search is for commands subsequent to the current position in the
361 history list. PCHAR is the character to use for prompting when reading
362 the search string; if not specified (0), it defaults to `:'. */
364 noninc_search (int dir, int pchar)
369 cxt = _rl_nsearch_init (dir, pchar);
371 if (RL_ISSTATE (RL_STATE_CALLBACK))
374 /* Read the search string. */
378 c = _rl_search_getchar (cxt);
382 _rl_nsearch_abort (cxt);
389 r = _rl_nsearch_dispatch (cxt, c);
396 r = _rl_nsearch_dosearch (cxt);
397 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
400 /* Search forward through the history list for a string. If the vi-mode
401 code calls this, KEY will be `?'. */
403 rl_noninc_forward_search (int count, int key)
405 return noninc_search (1, (key == '?') ? '?' : 0);
408 /* Reverse search the history list for a string. If the vi-mode code
409 calls this, KEY will be `/'. */
411 rl_noninc_reverse_search (int count, int key)
413 return noninc_search (-1, (key == '/') ? '/' : 0);
416 /* Search forward through the history list for the last string searched
417 for. If there is no saved search string, abort. If the vi-mode code
418 calls this, KEY will be `N'. */
420 rl_noninc_forward_search_again (int count, int key)
424 if (!noninc_search_string)
429 #if defined (VI_MODE)
430 if (VI_COMMAND_MODE() && key == 'N')
431 r = noninc_dosearch (noninc_search_string, 1, SF_PATTERN);
434 r = noninc_dosearch (noninc_search_string, 1, 0);
438 /* Reverse search in the history list for the last string searched
439 for. If there is no saved search string, abort. If the vi-mode code
440 calls this, KEY will be `n'. */
442 rl_noninc_reverse_search_again (int count, int key)
446 if (!noninc_search_string)
451 #if defined (VI_MODE)
452 if (VI_COMMAND_MODE() && key == 'n')
453 r = noninc_dosearch (noninc_search_string, -1, SF_PATTERN);
456 r = noninc_dosearch (noninc_search_string, -1, 0);
460 #if defined (READLINE_CALLBACKS)
462 _rl_nsearch_callback (_rl_search_cxt *cxt)
466 c = _rl_search_getchar (cxt);
470 _rl_nsearch_abort (cxt);
473 r = _rl_nsearch_dispatch (cxt, c);
477 r = _rl_nsearch_dosearch (cxt);
478 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
483 rl_history_search_internal (int count, int dir)
486 int ret, oldpos, newcol;
489 rl_maybe_save_line ();
490 temp = (HIST_ENTRY *)NULL;
492 /* Search COUNT times through the history for a line matching
493 history_search_string. If history_search_string[0] == '^', the
494 line must match from the start; otherwise any substring can match.
495 When this loop finishes, TEMP, if non-null, is the history line to
496 copy into the line buffer. */
500 ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir, 0, &newcol);
504 /* Get the history entry we found. */
505 rl_history_search_pos = ret;
506 oldpos = where_history ();
507 history_set_pos (rl_history_search_pos);
508 temp = current_history (); /* will never be NULL after successful search */
509 history_set_pos (oldpos);
511 /* Don't find multiple instances of the same line. */
512 if (prev_line_found && STREQ (prev_line_found, temp->line))
514 prev_line_found = temp->line;
518 /* If we didn't find anything at all, return. */
521 rl_maybe_unsave_line ();
523 /* If you don't want the saved history line (last match) to show up
524 in the line buffer after the search fails, change the #if 0 to
527 if (rl_point > rl_history_search_len)
529 rl_point = rl_end = rl_history_search_len;
530 rl_line_buffer[rl_end] = '\0';
534 rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
540 /* Copy the line we found into the current line buffer. */
541 make_history_line_current (temp);
543 /* decide where to put rl_point -- need to change this for pattern search */
544 if (rl_history_search_flags & ANCHORED_SEARCH)
545 rl_point = rl_history_search_len; /* easy case */
549 t = strstr (rl_line_buffer, history_search_string); /* XXX */
550 rl_point = t ? (int)(t - rl_line_buffer) + rl_history_search_len : rl_end;
552 rl_point = (newcol >= 0) ? newcol : rl_end;
561 rl_history_search_reinit (int flags)
565 rl_history_search_pos = where_history ();
566 rl_history_search_len = rl_point;
567 rl_history_search_flags = flags;
569 prev_line_found = (char *)NULL;
572 /* Allocate enough space for anchored and non-anchored searches */
573 if (rl_history_search_len >= history_string_size - 2)
575 history_string_size = rl_history_search_len + 2;
576 history_search_string = (char *)xrealloc (history_search_string, history_string_size);
579 if (flags & ANCHORED_SEARCH)
580 history_search_string[sind++] = '^';
581 strncpy (history_search_string + sind, rl_line_buffer, rl_point);
582 history_search_string[rl_point + sind] = '\0';
584 _rl_free_saved_history_line ();
587 /* Search forward in the history for the string of characters
588 from the start of the line to rl_point. This is a non-incremental
589 search. The search is anchored to the beginning of the history line. */
591 rl_history_search_forward (int count, int ignore)
596 if (rl_last_func != rl_history_search_forward &&
597 rl_last_func != rl_history_search_backward)
598 rl_history_search_reinit (ANCHORED_SEARCH);
600 if (rl_history_search_len == 0)
601 return (rl_get_next_history (count, ignore));
602 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
605 /* Search backward through the history for the string of characters
606 from the start of the line to rl_point. This is a non-incremental
609 rl_history_search_backward (int count, int ignore)
614 if (rl_last_func != rl_history_search_forward &&
615 rl_last_func != rl_history_search_backward)
616 rl_history_search_reinit (ANCHORED_SEARCH);
618 if (rl_history_search_len == 0)
619 return (rl_get_previous_history (count, ignore));
620 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
623 /* Search forward in the history for the string of characters
624 from the start of the line to rl_point. This is a non-incremental
625 search. The search succeeds if the search string is present anywhere
626 in the history line. */
628 rl_history_substr_search_forward (int count, int ignore)
633 if (rl_last_func != rl_history_substr_search_forward &&
634 rl_last_func != rl_history_substr_search_backward)
635 rl_history_search_reinit (NON_ANCHORED_SEARCH);
637 if (rl_history_search_len == 0)
638 return (rl_get_next_history (count, ignore));
639 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
642 /* Search backward through the history for the string of characters
643 from the start of the line to rl_point. This is a non-incremental
646 rl_history_substr_search_backward (int count, int ignore)
651 if (rl_last_func != rl_history_substr_search_forward &&
652 rl_last_func != rl_history_substr_search_backward)
653 rl_history_search_reinit (NON_ANCHORED_SEARCH);
655 if (rl_history_search_len == 0)
656 return (rl_get_previous_history (count, ignore));
657 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));