1 /* search.c - code for non-incremental searching in emacs and vi modes. */
3 /* Copyright (C) 1992-2013 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 int _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));
77 static int noninc_dosearch
PARAMS((char *, 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 int _rl_nsearch_cleanup
PARAMS((_rl_search_cxt
*, int));
84 static void _rl_nsearch_abort
PARAMS((_rl_search_cxt
*));
85 static int _rl_nsearch_dispatch
PARAMS((_rl_search_cxt
*, int));
87 /* Make the data from the history entry ENTRY be the contents of the
88 current line. This doesn't do anything with rl_point; the caller
91 make_history_line_current (entry
)
94 _rl_replace_text (entry
->line
, 0, rl_end
);
97 if (rl_editing_mode
== vi_mode
)
98 /* POSIX.2 says that the `U' command doesn't affect the copy of any
99 command lines to the edit line. We're going to implement that by
100 making the undo list start after the matching line is copied to the
101 current editing buffer. */
102 rl_free_undo_list ();
105 if (_rl_saved_line_for_history
)
106 _rl_free_history_entry (_rl_saved_line_for_history
);
107 _rl_saved_line_for_history
= (HIST_ENTRY
*)NULL
;
110 /* Search the history list for STRING starting at absolute history position
111 POS. If STRING begins with `^', the search must match STRING at the
112 beginning of a history line, otherwise a full substring match is performed
113 for STRING. DIR < 0 means to search backwards through the history list,
114 DIR >= 0 means to search forward. */
116 noninc_search_from_pos (string
, pos
, dir
)
125 old
= where_history ();
126 if (history_set_pos (pos
) == 0)
129 RL_SETSTATE(RL_STATE_SEARCH
);
131 ret
= history_search_prefix (string
+ 1, dir
);
133 ret
= history_search (string
, dir
);
134 RL_UNSETSTATE(RL_STATE_SEARCH
);
137 ret
= where_history ();
139 history_set_pos (old
);
143 /* Search for a line in the history containing STRING. If DIR is < 0, the
144 search is backwards through previous entries, else through subsequent
145 entries. Returns 1 if the search was successful, 0 otherwise. */
147 noninc_dosearch (string
, dir
)
154 if (string
== 0 || *string
== '\0' || noninc_history_pos
< 0)
160 pos
= noninc_search_from_pos (string
, noninc_history_pos
+ dir
, dir
);
163 /* Search failed, current history position unchanged. */
164 rl_maybe_unsave_line ();
171 noninc_history_pos
= pos
;
173 oldpos
= where_history ();
174 history_set_pos (noninc_history_pos
);
175 entry
= current_history (); /* will never be NULL after successful search */
177 #if defined (VI_MODE)
178 if (rl_editing_mode
!= vi_mode
)
180 history_set_pos (oldpos
);
182 make_history_line_current (entry
);
191 static _rl_search_cxt
*
192 _rl_nsearch_init (dir
, pchar
)
198 cxt
= _rl_scxt_alloc (RL_SEARCH_NSEARCH
, 0);
200 cxt
->sflags
|= SF_REVERSE
; /* not strictly needed */
202 cxt
->direction
= dir
;
203 cxt
->history_pos
= cxt
->save_line
;
205 rl_maybe_save_line ();
207 /* Clear the undo list, since reading the search string should create its
208 own undo list, and the whole list will end up being freed when we
209 finish reading the search string. */
212 /* Use the line buffer to read the search string. */
213 rl_line_buffer
[0] = 0;
214 rl_end
= rl_point
= 0;
216 p
= _rl_make_prompt_for_search (pchar
? pchar
: ':');
217 rl_message ("%s", p
);
220 RL_SETSTATE(RL_STATE_NSEARCH
);
228 _rl_nsearch_cleanup (cxt
, r
)
232 _rl_scxt_dispose (cxt
, 0);
235 RL_UNSETSTATE(RL_STATE_NSEARCH
);
241 _rl_nsearch_abort (cxt
)
244 rl_maybe_unsave_line ();
246 rl_point
= cxt
->save_point
;
247 rl_mark
= cxt
->save_mark
;
248 rl_restore_prompt ();
250 RL_UNSETSTATE (RL_STATE_NSEARCH
);
253 /* Process just-read character C according to search context CXT. Return -1
254 if the caller should abort the search, 0 if we should break out of the
255 loop, and 1 if we should continue to read characters. */
257 _rl_nsearch_dispatch (cxt
, c
)
264 rl_unix_word_rubout (1, c
);
268 rl_unix_line_discard (1, c
);
279 _rl_nsearch_abort (cxt
);
282 _rl_rubout_char (1, c
);
288 _rl_nsearch_abort (cxt
);
292 #if defined (HANDLE_MULTIBYTE)
293 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
294 rl_insert_text (cxt
->mb
);
297 _rl_insert_char (1, c
);
301 (*rl_redisplay_function
) ();
305 /* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
306 -1 if the search should be aborted, any other value means to clean up
307 using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
310 _rl_nsearch_dosearch (cxt
)
313 rl_mark
= cxt
->save_mark
;
315 /* If rl_point == 0, we want to re-use the previous search string and
316 start from the saved history position. If there's no previous search
320 if (noninc_search_string
== 0)
323 rl_restore_prompt ();
324 RL_UNSETSTATE (RL_STATE_NSEARCH
);
330 /* We want to start the search from the current history position. */
331 noninc_history_pos
= cxt
->save_line
;
332 FREE (noninc_search_string
);
333 noninc_search_string
= savestring (rl_line_buffer
);
335 /* If we don't want the subsequent undo list generated by the search
336 matching a history line to include the contents of the search string,
337 we need to clear rl_line_buffer here. For now, we just clear the
338 undo list generated by reading the search string. (If the search
339 fails, the old undo list will be restored by rl_maybe_unsave_line.) */
340 rl_free_undo_list ();
343 rl_restore_prompt ();
344 return (noninc_dosearch (noninc_search_string
, cxt
->direction
));
347 /* Search non-interactively through the history list. DIR < 0 means to
348 search backwards through the history of previous commands; otherwise
349 the search is for commands subsequent to the current position in the
350 history list. PCHAR is the character to use for prompting when reading
351 the search string; if not specified (0), it defaults to `:'. */
353 noninc_search (dir
, pchar
)
360 cxt
= _rl_nsearch_init (dir
, pchar
);
362 if (RL_ISSTATE (RL_STATE_CALLBACK
))
365 /* Read the search string. */
369 c
= _rl_search_getchar (cxt
);
374 r
= _rl_nsearch_dispatch (cxt
, c
);
381 r
= _rl_nsearch_dosearch (cxt
);
382 return ((r
>= 0) ? _rl_nsearch_cleanup (cxt
, r
) : (r
!= 1));
385 /* Search forward through the history list for a string. If the vi-mode
386 code calls this, KEY will be `?'. */
388 rl_noninc_forward_search (count
, key
)
391 return noninc_search (1, (key
== '?') ? '?' : 0);
394 /* Reverse search the history list for a string. If the vi-mode code
395 calls this, KEY will be `/'. */
397 rl_noninc_reverse_search (count
, key
)
400 return noninc_search (-1, (key
== '/') ? '/' : 0);
403 /* Search forward through the history list for the last string searched
404 for. If there is no saved search string, abort. */
406 rl_noninc_forward_search_again (count
, key
)
411 if (!noninc_search_string
)
416 r
= noninc_dosearch (noninc_search_string
, 1);
420 /* Reverse search in the history list for the last string searched
421 for. If there is no saved search string, abort. */
423 rl_noninc_reverse_search_again (count
, key
)
428 if (!noninc_search_string
)
433 r
= noninc_dosearch (noninc_search_string
, -1);
437 #if defined (READLINE_CALLBACKS)
439 _rl_nsearch_callback (cxt
)
444 c
= _rl_search_getchar (cxt
);
445 r
= _rl_nsearch_dispatch (cxt
, c
);
449 r
= _rl_nsearch_dosearch (cxt
);
450 return ((r
>= 0) ? _rl_nsearch_cleanup (cxt
, r
) : (r
!= 1));
455 rl_history_search_internal (count
, dir
)
462 rl_maybe_save_line ();
463 temp
= (HIST_ENTRY
*)NULL
;
465 /* Search COUNT times through the history for a line matching
466 history_search_string. If history_search_string[0] == '^', the
467 line must match from the start; otherwise any substring can match.
468 When this loop finishes, TEMP, if non-null, is the history line to
469 copy into the line buffer. */
473 ret
= noninc_search_from_pos (history_search_string
, rl_history_search_pos
+ dir
, dir
);
477 /* Get the history entry we found. */
478 rl_history_search_pos
= ret
;
479 oldpos
= where_history ();
480 history_set_pos (rl_history_search_pos
);
481 temp
= current_history (); /* will never be NULL after successful search */
482 history_set_pos (oldpos
);
484 /* Don't find multiple instances of the same line. */
485 if (prev_line_found
&& STREQ (prev_line_found
, temp
->line
))
487 prev_line_found
= temp
->line
;
491 /* If we didn't find anything at all, return. */
494 rl_maybe_unsave_line ();
496 /* If you don't want the saved history line (last match) to show up
497 in the line buffer after the search fails, change the #if 0 to
500 if (rl_point
> rl_history_search_len
)
502 rl_point
= rl_end
= rl_history_search_len
;
503 rl_line_buffer
[rl_end
] = '\0';
507 rl_point
= rl_history_search_len
; /* rl_maybe_unsave_line changes it */
513 /* Copy the line we found into the current line buffer. */
514 make_history_line_current (temp
);
516 if (rl_history_search_flags
& ANCHORED_SEARCH
)
517 rl_point
= rl_history_search_len
; /* easy case */
520 t
= strstr (rl_line_buffer
, history_search_string
);
521 rl_point
= t
? (int)(t
- rl_line_buffer
) + rl_history_search_len
: rl_end
;
529 rl_history_search_reinit (flags
)
534 rl_history_search_pos
= where_history ();
535 rl_history_search_len
= rl_point
;
536 rl_history_search_flags
= flags
;
538 prev_line_found
= (char *)NULL
;
541 /* Allocate enough space for anchored and non-anchored searches */
542 if (rl_history_search_len
>= history_string_size
- 2)
544 history_string_size
= rl_history_search_len
+ 2;
545 history_search_string
= (char *)xrealloc (history_search_string
, history_string_size
);
548 if (flags
& ANCHORED_SEARCH
)
549 history_search_string
[sind
++] = '^';
550 strncpy (history_search_string
+ sind
, rl_line_buffer
, rl_point
);
551 history_search_string
[rl_point
+ sind
] = '\0';
553 _rl_free_saved_history_line ();
556 /* Search forward in the history for the string of characters
557 from the start of the line to rl_point. This is a non-incremental
558 search. The search is anchored to the beginning of the history line. */
560 rl_history_search_forward (count
, ignore
)
566 if (rl_last_func
!= rl_history_search_forward
&&
567 rl_last_func
!= rl_history_search_backward
)
568 rl_history_search_reinit (ANCHORED_SEARCH
);
570 if (rl_history_search_len
== 0)
571 return (rl_get_next_history (count
, ignore
));
572 return (rl_history_search_internal (abs (count
), (count
> 0) ? 1 : -1));
575 /* Search backward through the history for the string of characters
576 from the start of the line to rl_point. This is a non-incremental
579 rl_history_search_backward (count
, ignore
)
585 if (rl_last_func
!= rl_history_search_forward
&&
586 rl_last_func
!= rl_history_search_backward
)
587 rl_history_search_reinit (ANCHORED_SEARCH
);
589 if (rl_history_search_len
== 0)
590 return (rl_get_previous_history (count
, ignore
));
591 return (rl_history_search_internal (abs (count
), (count
> 0) ? -1 : 1));
594 /* Search forward in the history for the string of characters
595 from the start of the line to rl_point. This is a non-incremental
596 search. The search succeeds if the search string is present anywhere
597 in the history line. */
599 rl_history_substr_search_forward (count
, ignore
)
605 if (rl_last_func
!= rl_history_substr_search_forward
&&
606 rl_last_func
!= rl_history_substr_search_backward
)
607 rl_history_search_reinit (NON_ANCHORED_SEARCH
);
609 if (rl_history_search_len
== 0)
610 return (rl_get_next_history (count
, ignore
));
611 return (rl_history_search_internal (abs (count
), (count
> 0) ? 1 : -1));
614 /* Search backward through the history for the string of characters
615 from the start of the line to rl_point. This is a non-incremental
618 rl_history_substr_search_backward (count
, ignore
)
624 if (rl_last_func
!= rl_history_substr_search_forward
&&
625 rl_last_func
!= rl_history_substr_search_backward
)
626 rl_history_search_reinit (NON_ANCHORED_SEARCH
);
628 if (rl_history_search_len
== 0)
629 return (rl_get_previous_history (count
, ignore
));
630 return (rl_history_search_internal (abs (count
), (count
> 0) ? -1 : 1));