1 /* search.c - code for non-incremental searching in emacs and vi modes. */
3 /* Copyright (C) 1992-2020 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
)
162 int oldpos
, pos
, ind
;
165 if (string
== 0 || *string
== '\0' || noninc_history_pos
< 0)
171 pos
= noninc_search_from_pos (string
, noninc_history_pos
+ dir
, dir
, flags
, &ind
);
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
);
195 if (_rl_enable_active_region
&& ((flags
& SF_PATTERN
) == 0) && ind
> 0 && ind
< rl_end
)
198 rl_mark
= ind
+ strlen (string
);
199 if (rl_mark
> rl_end
)
200 rl_mark
= rl_end
; /* can't happen? */
213 static _rl_search_cxt
*
214 _rl_nsearch_init (int dir
, int pchar
)
219 cxt
= _rl_scxt_alloc (RL_SEARCH_NSEARCH
, 0);
221 cxt
->sflags
|= SF_REVERSE
; /* not strictly needed */
222 #if defined (VI_MODE)
223 if (VI_COMMAND_MODE() && (pchar
== '?' || pchar
== '/'))
224 cxt
->sflags
|= SF_PATTERN
;
227 cxt
->direction
= dir
;
228 cxt
->history_pos
= cxt
->save_line
;
230 rl_maybe_save_line ();
232 /* Clear the undo list, since reading the search string should create its
233 own undo list, and the whole list will end up being freed when we
234 finish reading the search string. */
237 /* Use the line buffer to read the search string. */
238 rl_line_buffer
[0] = 0;
239 rl_end
= rl_point
= 0;
241 p
= _rl_make_prompt_for_search (pchar
? pchar
: ':');
242 rl_message ("%s", p
);
245 RL_SETSTATE(RL_STATE_NSEARCH
);
253 _rl_nsearch_cleanup (_rl_search_cxt
*cxt
, int r
)
255 _rl_scxt_dispose (cxt
, 0);
258 RL_UNSETSTATE(RL_STATE_NSEARCH
);
264 _rl_nsearch_abort (_rl_search_cxt
*cxt
)
266 rl_maybe_unsave_line ();
268 rl_point
= cxt
->save_point
;
269 rl_mark
= cxt
->save_mark
;
271 rl_restore_prompt ();
273 RL_UNSETSTATE (RL_STATE_NSEARCH
);
276 /* Process just-read character C according to search context CXT. Return -1
277 if the caller should abort the search, 0 if we should break out of the
278 loop, and 1 if we should continue to read characters. */
280 _rl_nsearch_dispatch (_rl_search_cxt
*cxt
, int c
)
290 rl_unix_word_rubout (1, c
);
294 rl_unix_line_discard (1, c
);
305 _rl_nsearch_abort (cxt
);
308 _rl_rubout_char (1, c
);
314 _rl_nsearch_abort (cxt
);
318 /* XXX - experimental code to allow users to bracketed-paste into the
319 search string. Similar code is in isearch.c:_rl_isearch_dispatch().
320 The difference here is that the bracketed paste sometimes doesn't
321 paste everything, so checking for the prefix and the suffix in the
322 input queue doesn't work well. We just have to check to see if the
323 number of chars in the input queue is enough for the bracketed paste
324 prefix and hope for the best. */
325 if (_rl_enable_bracketed_paste
&& ((n
= _rl_nchars_available ()) >= (BRACK_PASTE_SLEN
-1)))
327 if (_rl_read_bracketed_paste_prefix (c
) == 1)
328 rl_bracketed_paste_begin (1, c
);
331 c
= rl_read_key (); /* get the ESC that got pushed back */
332 _rl_insert_char (1, c
);
336 _rl_insert_char (1, c
);
340 #if defined (HANDLE_MULTIBYTE)
341 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
342 rl_insert_text (cxt
->mb
);
345 _rl_insert_char (1, c
);
349 (*rl_redisplay_function
) ();
350 rl_deactivate_mark ();
354 /* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
355 -1 if the search should be aborted, any other value means to clean up
356 using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
359 _rl_nsearch_dosearch (_rl_search_cxt
*cxt
)
361 rl_mark
= cxt
->save_mark
;
363 /* If rl_point == 0, we want to re-use the previous search string and
364 start from the saved history position. If there's no previous search
368 if (noninc_search_string
== 0)
371 rl_restore_prompt ();
372 RL_UNSETSTATE (RL_STATE_NSEARCH
);
378 /* We want to start the search from the current history position. */
379 noninc_history_pos
= cxt
->save_line
;
380 FREE (noninc_search_string
);
381 noninc_search_string
= savestring (rl_line_buffer
);
383 /* If we don't want the subsequent undo list generated by the search
384 matching a history line to include the contents of the search string,
385 we need to clear rl_line_buffer here. For now, we just clear the
386 undo list generated by reading the search string. (If the search
387 fails, the old undo list will be restored by rl_maybe_unsave_line.) */
388 rl_free_undo_list ();
391 rl_restore_prompt ();
392 return (noninc_dosearch (noninc_search_string
, cxt
->direction
, cxt
->sflags
&SF_PATTERN
));
395 /* Search non-interactively through the history list. DIR < 0 means to
396 search backwards through the history of previous commands; otherwise
397 the search is for commands subsequent to the current position in the
398 history list. PCHAR is the character to use for prompting when reading
399 the search string; if not specified (0), it defaults to `:'. */
401 noninc_search (int dir
, int pchar
)
406 cxt
= _rl_nsearch_init (dir
, pchar
);
408 if (RL_ISSTATE (RL_STATE_CALLBACK
))
411 /* Read the search string. */
415 c
= _rl_search_getchar (cxt
);
419 _rl_nsearch_abort (cxt
);
426 r
= _rl_nsearch_dispatch (cxt
, c
);
433 r
= _rl_nsearch_dosearch (cxt
);
434 return ((r
>= 0) ? _rl_nsearch_cleanup (cxt
, r
) : (r
!= 1));
437 /* Search forward through the history list for a string. If the vi-mode
438 code calls this, KEY will be `?'. */
440 rl_noninc_forward_search (int count
, int key
)
442 return noninc_search (1, (key
== '?') ? '?' : 0);
445 /* Reverse search the history list for a string. If the vi-mode code
446 calls this, KEY will be `/'. */
448 rl_noninc_reverse_search (int count
, int key
)
450 return noninc_search (-1, (key
== '/') ? '/' : 0);
453 /* Search forward through the history list for the last string searched
454 for. If there is no saved search string, abort. If the vi-mode code
455 calls this, KEY will be `N'. */
457 rl_noninc_forward_search_again (int count
, int key
)
461 if (!noninc_search_string
)
466 #if defined (VI_MODE)
467 if (VI_COMMAND_MODE() && key
== 'N')
468 r
= noninc_dosearch (noninc_search_string
, 1, SF_PATTERN
);
471 r
= noninc_dosearch (noninc_search_string
, 1, 0);
475 /* Reverse search in the history list for the last string searched
476 for. If there is no saved search string, abort. If the vi-mode code
477 calls this, KEY will be `n'. */
479 rl_noninc_reverse_search_again (int count
, int key
)
483 if (!noninc_search_string
)
488 #if defined (VI_MODE)
489 if (VI_COMMAND_MODE() && key
== 'n')
490 r
= noninc_dosearch (noninc_search_string
, -1, SF_PATTERN
);
493 r
= noninc_dosearch (noninc_search_string
, -1, 0);
497 #if defined (READLINE_CALLBACKS)
499 _rl_nsearch_callback (_rl_search_cxt
*cxt
)
503 c
= _rl_search_getchar (cxt
);
507 _rl_nsearch_abort (cxt
);
510 r
= _rl_nsearch_dispatch (cxt
, c
);
514 r
= _rl_nsearch_dosearch (cxt
);
515 return ((r
>= 0) ? _rl_nsearch_cleanup (cxt
, r
) : (r
!= 1));
520 rl_history_search_internal (int count
, int dir
)
523 int ret
, oldpos
, newcol
;
526 rl_maybe_save_line ();
527 temp
= (HIST_ENTRY
*)NULL
;
529 /* Search COUNT times through the history for a line matching
530 history_search_string. If history_search_string[0] == '^', the
531 line must match from the start; otherwise any substring can match.
532 When this loop finishes, TEMP, if non-null, is the history line to
533 copy into the line buffer. */
537 ret
= noninc_search_from_pos (history_search_string
, rl_history_search_pos
+ dir
, dir
, 0, &newcol
);
541 /* Get the history entry we found. */
542 rl_history_search_pos
= ret
;
543 oldpos
= where_history ();
544 history_set_pos (rl_history_search_pos
);
545 temp
= current_history (); /* will never be NULL after successful search */
546 history_set_pos (oldpos
);
548 /* Don't find multiple instances of the same line. */
549 if (prev_line_found
&& STREQ (prev_line_found
, temp
->line
))
551 prev_line_found
= temp
->line
;
555 /* If we didn't find anything at all, return. */
558 rl_maybe_unsave_line ();
560 /* If you don't want the saved history line (last match) to show up
561 in the line buffer after the search fails, change the #if 0 to
564 if (rl_point
> rl_history_search_len
)
566 rl_point
= rl_end
= rl_history_search_len
;
567 rl_line_buffer
[rl_end
] = '\0';
571 rl_point
= rl_history_search_len
; /* rl_maybe_unsave_line changes it */
577 /* Copy the line we found into the current line buffer. */
578 make_history_line_current (temp
);
580 /* decide where to put rl_point -- need to change this for pattern search */
581 if (rl_history_search_flags
& ANCHORED_SEARCH
)
582 rl_point
= rl_history_search_len
; /* easy case */
586 t
= strstr (rl_line_buffer
, history_search_string
); /* XXX */
587 rl_point
= t
? (int)(t
- rl_line_buffer
) + rl_history_search_len
: rl_end
;
589 rl_point
= (newcol
>= 0) ? newcol
: rl_end
;
598 rl_history_search_reinit (int flags
)
602 rl_history_search_pos
= where_history ();
603 rl_history_search_len
= rl_point
;
604 rl_history_search_flags
= flags
;
606 prev_line_found
= (char *)NULL
;
609 /* Allocate enough space for anchored and non-anchored searches */
610 if (rl_history_search_len
>= history_string_size
- 2)
612 history_string_size
= rl_history_search_len
+ 2;
613 history_search_string
= (char *)xrealloc (history_search_string
, history_string_size
);
616 if (flags
& ANCHORED_SEARCH
)
617 history_search_string
[sind
++] = '^';
618 strncpy (history_search_string
+ sind
, rl_line_buffer
, rl_point
);
619 history_search_string
[rl_point
+ sind
] = '\0';
621 _rl_free_saved_history_line ();
624 /* Search forward in the history for the string of characters
625 from the start of the line to rl_point. This is a non-incremental
626 search. The search is anchored to the beginning of the history line. */
628 rl_history_search_forward (int count
, int ignore
)
633 if (rl_last_func
!= rl_history_search_forward
&&
634 rl_last_func
!= rl_history_search_backward
)
635 rl_history_search_reinit (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_search_backward (int count
, int ignore
)
651 if (rl_last_func
!= rl_history_search_forward
&&
652 rl_last_func
!= rl_history_search_backward
)
653 rl_history_search_reinit (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));
660 /* Search forward in the history for the string of characters
661 from the start of the line to rl_point. This is a non-incremental
662 search. The search succeeds if the search string is present anywhere
663 in the history line. */
665 rl_history_substr_search_forward (int count
, int ignore
)
670 if (rl_last_func
!= rl_history_substr_search_forward
&&
671 rl_last_func
!= rl_history_substr_search_backward
)
672 rl_history_search_reinit (NON_ANCHORED_SEARCH
);
674 if (rl_history_search_len
== 0)
675 return (rl_get_next_history (count
, ignore
));
676 return (rl_history_search_internal (abs (count
), (count
> 0) ? 1 : -1));
679 /* Search backward through the history for the string of characters
680 from the start of the line to rl_point. This is a non-incremental
683 rl_history_substr_search_backward (int count
, int ignore
)
688 if (rl_last_func
!= rl_history_substr_search_forward
&&
689 rl_last_func
!= rl_history_substr_search_backward
)
690 rl_history_search_reinit (NON_ANCHORED_SEARCH
);
692 if (rl_history_search_len
== 0)
693 return (rl_get_previous_history (count
, ignore
));
694 return (rl_history_search_internal (abs (count
), (count
> 0) ? -1 : 1));