1 /* search.c - code for non-incremental searching in emacs and vi modes. */
3 /* Copyright (C) 1992-2009 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"
47 #include "rlprivate.h"
53 #define abs(x) (((x) >= 0) ? (x) : -(x))
55 _rl_search_cxt
*_rl_nscxt
= 0;
57 extern HIST_ENTRY
*_rl_saved_line_for_history
;
59 /* Functions imported from the rest of the library. */
60 extern int _rl_free_history_entry
PARAMS((HIST_ENTRY
*));
62 static char *noninc_search_string
= (char *) NULL
;
63 static int noninc_history_pos
;
65 static char *prev_line_found
= (char *) NULL
;
67 static int rl_history_search_len
;
68 static int rl_history_search_pos
;
69 static char *history_search_string
;
70 static int history_string_size
;
72 static void make_history_line_current
PARAMS((HIST_ENTRY
*));
73 static int noninc_search_from_pos
PARAMS((char *, int, int));
74 static int noninc_dosearch
PARAMS((char *, int));
75 static int noninc_search
PARAMS((int, int));
76 static int rl_history_search_internal
PARAMS((int, int));
77 static void rl_history_search_reinit
PARAMS((void));
79 static _rl_search_cxt
*_rl_nsearch_init
PARAMS((int, int));
80 static int _rl_nsearch_cleanup
PARAMS((_rl_search_cxt
*, int));
81 static void _rl_nsearch_abort
PARAMS((_rl_search_cxt
*));
82 static int _rl_nsearch_dispatch
PARAMS((_rl_search_cxt
*, int));
84 /* Make the data from the history entry ENTRY be the contents of the
85 current line. This doesn't do anything with rl_point; the caller
88 make_history_line_current (entry
)
91 _rl_replace_text (entry
->line
, 0, rl_end
);
94 if (rl_editing_mode
== vi_mode
)
95 /* POSIX.2 says that the `U' command doesn't affect the copy of any
96 command lines to the edit line. We're going to implement that by
97 making the undo list start after the matching line is copied to the
98 current editing buffer. */
102 if (_rl_saved_line_for_history
)
103 _rl_free_history_entry (_rl_saved_line_for_history
);
104 _rl_saved_line_for_history
= (HIST_ENTRY
*)NULL
;
107 /* Search the history list for STRING starting at absolute history position
108 POS. If STRING begins with `^', the search must match STRING at the
109 beginning of a history line, otherwise a full substring match is performed
110 for STRING. DIR < 0 means to search backwards through the history list,
111 DIR >= 0 means to search forward. */
113 noninc_search_from_pos (string
, pos
, dir
)
122 old
= where_history ();
123 if (history_set_pos (pos
) == 0)
126 RL_SETSTATE(RL_STATE_SEARCH
);
128 ret
= history_search_prefix (string
+ 1, dir
);
130 ret
= history_search (string
, dir
);
131 RL_UNSETSTATE(RL_STATE_SEARCH
);
134 ret
= where_history ();
136 history_set_pos (old
);
140 /* Search for a line in the history containing STRING. If DIR is < 0, the
141 search is backwards through previous entries, else through subsequent
142 entries. Returns 1 if the search was successful, 0 otherwise. */
144 noninc_dosearch (string
, dir
)
151 if (string
== 0 || *string
== '\0' || noninc_history_pos
< 0)
157 pos
= noninc_search_from_pos (string
, noninc_history_pos
+ dir
, dir
);
160 /* Search failed, current history position unchanged. */
161 rl_maybe_unsave_line ();
168 noninc_history_pos
= pos
;
170 oldpos
= where_history ();
171 history_set_pos (noninc_history_pos
);
172 entry
= current_history ();
173 #if defined (VI_MODE)
174 if (rl_editing_mode
!= vi_mode
)
176 history_set_pos (oldpos
);
178 make_history_line_current (entry
);
187 static _rl_search_cxt
*
188 _rl_nsearch_init (dir
, pchar
)
194 cxt
= _rl_scxt_alloc (RL_SEARCH_NSEARCH
, 0);
196 cxt
->sflags
|= SF_REVERSE
; /* not strictly needed */
198 cxt
->direction
= dir
;
199 cxt
->history_pos
= cxt
->save_line
;
201 rl_maybe_save_line ();
203 /* Clear the undo list, since reading the search string should create its
204 own undo list, and the whole list will end up being freed when we
205 finish reading the search string. */
208 /* Use the line buffer to read the search string. */
209 rl_line_buffer
[0] = 0;
210 rl_end
= rl_point
= 0;
212 p
= _rl_make_prompt_for_search (pchar
? pchar
: ':');
213 rl_message ("%s", p
);
216 RL_SETSTATE(RL_STATE_NSEARCH
);
224 _rl_nsearch_cleanup (cxt
, r
)
228 _rl_scxt_dispose (cxt
, 0);
231 RL_UNSETSTATE(RL_STATE_NSEARCH
);
237 _rl_nsearch_abort (cxt
)
240 rl_maybe_unsave_line ();
242 rl_point
= cxt
->save_point
;
243 rl_mark
= cxt
->save_mark
;
244 rl_restore_prompt ();
246 RL_UNSETSTATE (RL_STATE_NSEARCH
);
249 /* Process just-read character C according to search context CXT. Return -1
250 if the caller should abort the search, 0 if we should break out of the
251 loop, and 1 if we should continue to read characters. */
253 _rl_nsearch_dispatch (cxt
, c
)
260 rl_unix_word_rubout (1, c
);
264 rl_unix_line_discard (1, c
);
275 _rl_nsearch_abort (cxt
);
278 _rl_rubout_char (1, c
);
284 _rl_nsearch_abort (cxt
);
288 #if defined (HANDLE_MULTIBYTE)
289 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
290 rl_insert_text (cxt
->mb
);
293 _rl_insert_char (1, c
);
297 (*rl_redisplay_function
) ();
301 /* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
302 -1 if the search should be aborted, any other value means to clean up
303 using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
306 _rl_nsearch_dosearch (cxt
)
309 rl_mark
= cxt
->save_mark
;
311 /* If rl_point == 0, we want to re-use the previous search string and
312 start from the saved history position. If there's no previous search
316 if (noninc_search_string
== 0)
319 rl_restore_prompt ();
320 RL_UNSETSTATE (RL_STATE_NSEARCH
);
326 /* We want to start the search from the current history position. */
327 noninc_history_pos
= cxt
->save_line
;
328 FREE (noninc_search_string
);
329 noninc_search_string
= savestring (rl_line_buffer
);
331 /* If we don't want the subsequent undo list generated by the search
332 matching a history line to include the contents of the search string,
333 we need to clear rl_line_buffer here. For now, we just clear the
334 undo list generated by reading the search string. (If the search
335 fails, the old undo list will be restored by rl_maybe_unsave_line.) */
336 rl_free_undo_list ();
339 rl_restore_prompt ();
340 return (noninc_dosearch (noninc_search_string
, cxt
->direction
));
343 /* Search non-interactively through the history list. DIR < 0 means to
344 search backwards through the history of previous commands; otherwise
345 the search is for commands subsequent to the current position in the
346 history list. PCHAR is the character to use for prompting when reading
347 the search string; if not specified (0), it defaults to `:'. */
349 noninc_search (dir
, pchar
)
356 cxt
= _rl_nsearch_init (dir
, pchar
);
358 if (RL_ISSTATE (RL_STATE_CALLBACK
))
361 /* Read the search string. */
365 c
= _rl_search_getchar (cxt
);
370 r
= _rl_nsearch_dispatch (cxt
, c
);
377 r
= _rl_nsearch_dosearch (cxt
);
378 return ((r
>= 0) ? _rl_nsearch_cleanup (cxt
, r
) : (r
!= 1));
381 /* Search forward through the history list for a string. If the vi-mode
382 code calls this, KEY will be `?'. */
384 rl_noninc_forward_search (count
, key
)
387 return noninc_search (1, (key
== '?') ? '?' : 0);
390 /* Reverse search the history list for a string. If the vi-mode code
391 calls this, KEY will be `/'. */
393 rl_noninc_reverse_search (count
, key
)
396 return noninc_search (-1, (key
== '/') ? '/' : 0);
399 /* Search forward through the history list for the last string searched
400 for. If there is no saved search string, abort. */
402 rl_noninc_forward_search_again (count
, key
)
407 if (!noninc_search_string
)
412 r
= noninc_dosearch (noninc_search_string
, 1);
416 /* Reverse search in the history list for the last string searched
417 for. If there is no saved search string, abort. */
419 rl_noninc_reverse_search_again (count
, key
)
424 if (!noninc_search_string
)
429 r
= noninc_dosearch (noninc_search_string
, -1);
433 #if defined (READLINE_CALLBACKS)
435 _rl_nsearch_callback (cxt
)
440 c
= _rl_search_getchar (cxt
);
441 r
= _rl_nsearch_dispatch (cxt
, c
);
445 r
= _rl_nsearch_dosearch (cxt
);
446 return ((r
>= 0) ? _rl_nsearch_cleanup (cxt
, r
) : (r
!= 1));
451 rl_history_search_internal (count
, dir
)
457 rl_maybe_save_line ();
458 temp
= (HIST_ENTRY
*)NULL
;
460 /* Search COUNT times through the history for a line whose prefix
461 matches history_search_string. When this loop finishes, TEMP,
462 if non-null, is the history line to copy into the line buffer. */
465 ret
= noninc_search_from_pos (history_search_string
, rl_history_search_pos
+ dir
, dir
);
469 /* Get the history entry we found. */
470 rl_history_search_pos
= ret
;
471 oldpos
= where_history ();
472 history_set_pos (rl_history_search_pos
);
473 temp
= current_history ();
474 history_set_pos (oldpos
);
476 /* Don't find multiple instances of the same line. */
477 if (prev_line_found
&& STREQ (prev_line_found
, temp
->line
))
479 prev_line_found
= temp
->line
;
483 /* If we didn't find anything at all, return. */
486 rl_maybe_unsave_line ();
488 /* If you don't want the saved history line (last match) to show up
489 in the line buffer after the search fails, change the #if 0 to
492 if (rl_point
> rl_history_search_len
)
494 rl_point
= rl_end
= rl_history_search_len
;
495 rl_line_buffer
[rl_end
] = '\0';
499 rl_point
= rl_history_search_len
; /* rl_maybe_unsave_line changes it */
505 /* Copy the line we found into the current line buffer. */
506 make_history_line_current (temp
);
508 rl_point
= rl_history_search_len
;
515 rl_history_search_reinit ()
517 rl_history_search_pos
= where_history ();
518 rl_history_search_len
= rl_point
;
519 prev_line_found
= (char *)NULL
;
522 if (rl_history_search_len
>= history_string_size
- 2)
524 history_string_size
= rl_history_search_len
+ 2;
525 history_search_string
= (char *)xrealloc (history_search_string
, history_string_size
);
527 history_search_string
[0] = '^';
528 strncpy (history_search_string
+ 1, rl_line_buffer
, rl_point
);
529 history_search_string
[rl_point
+ 1] = '\0';
531 _rl_free_saved_history_line ();
534 /* Search forward in the history for the string of characters
535 from the start of the line to rl_point. This is a non-incremental
538 rl_history_search_forward (count
, ignore
)
544 if (rl_last_func
!= rl_history_search_forward
&&
545 rl_last_func
!= rl_history_search_backward
)
546 rl_history_search_reinit ();
548 if (rl_history_search_len
== 0)
549 return (rl_get_next_history (count
, ignore
));
550 return (rl_history_search_internal (abs (count
), (count
> 0) ? 1 : -1));
553 /* Search backward through the history for the string of characters
554 from the start of the line to rl_point. This is a non-incremental
557 rl_history_search_backward (count
, ignore
)
563 if (rl_last_func
!= rl_history_search_forward
&&
564 rl_last_func
!= rl_history_search_backward
)
565 rl_history_search_reinit ();
567 if (rl_history_search_len
== 0)
568 return (rl_get_previous_history (count
, ignore
));
569 return (rl_history_search_internal (abs (count
), (count
> 0) ? -1 : 1));