1 /* search.c - code for non-incremental searching in emacs and vi modes. */
3 /* Copyright (C) 1992-2005 Free Software Foundation, Inc.
5 This file is part of the Readline Library (the Library), a set of
6 routines for providing Emacs style line input to programs that ask
9 The Library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 The Library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 The GNU General Public License is often shipped with GNU software, and
20 is generally kept in a file called COPYING or LICENSE. If you do not
21 have a copy of the license, write to the Free Software Foundation,
22 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23 #define READLINE_LIBRARY
25 #if defined (HAVE_CONFIG_H)
29 #include <sys/types.h>
32 #if defined (HAVE_UNISTD_H)
36 #if defined (HAVE_STDLIB_H)
39 # 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 char *history_search_string
;
71 static int history_string_size
;
73 static UNDO_LIST
*noninc_saved_undo_list
;
74 static void make_history_line_current
PARAMS((HIST_ENTRY
*));
75 static int noninc_search_from_pos
PARAMS((char *, int, int));
76 static int noninc_dosearch
PARAMS((char *, int));
77 static int noninc_search
PARAMS((int, int));
78 static int rl_history_search_internal
PARAMS((int, int));
79 static void rl_history_search_reinit
PARAMS((void));
81 static _rl_search_cxt
*_rl_nsearch_init
PARAMS((int, int));
82 static int _rl_nsearch_cleanup
PARAMS((_rl_search_cxt
*, 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 (entry
)
93 _rl_replace_text (entry
->line
, 0, rl_end
);
96 if (rl_editing_mode
== vi_mode
)
97 /* POSIX.2 says that the `U' command doesn't affect the copy of any
98 command lines to the edit line. We're going to implement that by
99 making the undo list start after the matching line is copied to the
100 current editing buffer. */
101 rl_free_undo_list ();
104 if (_rl_saved_line_for_history
)
105 _rl_free_history_entry (_rl_saved_line_for_history
);
106 _rl_saved_line_for_history
= (HIST_ENTRY
*)NULL
;
109 /* Search the history list for STRING starting at absolute history position
110 POS. If STRING begins with `^', the search must match STRING at the
111 beginning of a history line, otherwise a full substring match is performed
112 for STRING. DIR < 0 means to search backwards through the history list,
113 DIR >= 0 means to search forward. */
115 noninc_search_from_pos (string
, pos
, dir
)
124 old
= where_history ();
125 if (history_set_pos (pos
) == 0)
128 RL_SETSTATE(RL_STATE_SEARCH
);
130 ret
= history_search_prefix (string
+ 1, dir
);
132 ret
= history_search (string
, dir
);
133 RL_UNSETSTATE(RL_STATE_SEARCH
);
136 ret
= where_history ();
138 history_set_pos (old
);
142 /* Search for a line in the history containing STRING. If DIR is < 0, the
143 search is backwards through previous entries, else through subsequent
144 entries. Returns 1 if the search was successful, 0 otherwise. */
146 noninc_dosearch (string
, dir
)
153 if (string
== 0 || *string
== '\0' || noninc_history_pos
< 0)
159 pos
= noninc_search_from_pos (string
, noninc_history_pos
+ dir
, dir
);
162 /* Search failed, current history position unchanged. */
163 rl_maybe_unsave_line ();
170 noninc_history_pos
= pos
;
172 oldpos
= where_history ();
173 history_set_pos (noninc_history_pos
);
174 entry
= current_history ();
175 #if defined (VI_MODE)
176 if (rl_editing_mode
!= vi_mode
)
178 history_set_pos (oldpos
);
180 make_history_line_current (entry
);
189 static _rl_search_cxt
*
190 _rl_nsearch_init (dir
, pchar
)
196 cxt
= _rl_scxt_alloc (RL_SEARCH_NSEARCH
, 0);
198 cxt
->sflags
|= SF_REVERSE
; /* not strictly needed */
200 cxt
->direction
= dir
;
201 cxt
->history_pos
= cxt
->save_line
;
203 rl_maybe_save_line ();
205 /* Clear the undo list, since reading the search string should create its
206 own undo list, and the whole list will end up being freed when we
207 finish reading the search string. */
210 /* Use the line buffer to read the search string. */
211 rl_line_buffer
[0] = 0;
212 rl_end
= rl_point
= 0;
214 p
= _rl_make_prompt_for_search (pchar
? pchar
: ':');
215 rl_message (p
, 0, 0);
218 RL_SETSTATE(RL_STATE_NSEARCH
);
226 _rl_nsearch_cleanup (cxt
, r
)
230 _rl_scxt_dispose (cxt
, 0);
233 RL_UNSETSTATE(RL_STATE_NSEARCH
);
239 _rl_nsearch_abort (cxt
)
242 rl_maybe_unsave_line ();
244 rl_point
= cxt
->save_point
;
245 rl_mark
= cxt
->save_mark
;
246 rl_restore_prompt ();
248 RL_UNSETSTATE (RL_STATE_NSEARCH
);
251 /* Process just-read character C according to search context CXT. Return -1
252 if the caller should abort the search, 0 if we should break out of the
253 loop, and 1 if we should continue to read characters. */
255 _rl_nsearch_dispatch (cxt
, c
)
262 rl_unix_word_rubout (1, c
);
266 rl_unix_line_discard (1, c
);
277 _rl_nsearch_abort (cxt
);
280 _rl_rubout_char (1, c
);
286 _rl_nsearch_abort (cxt
);
290 #if defined (HANDLE_MULTIBYTE)
291 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
292 rl_insert_text (cxt
->mb
);
295 _rl_insert_char (1, c
);
299 (*rl_redisplay_function
) ();
303 /* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
304 -1 if the search should be aborted, any other value means to clean up
305 using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
308 _rl_nsearch_dosearch (cxt
)
311 rl_mark
= cxt
->save_mark
;
313 /* If rl_point == 0, we want to re-use the previous search string and
314 start from the saved history position. If there's no previous search
318 if (noninc_search_string
== 0)
321 rl_restore_prompt ();
322 RL_UNSETSTATE (RL_STATE_NSEARCH
);
328 /* We want to start the search from the current history position. */
329 noninc_history_pos
= cxt
->save_line
;
330 FREE (noninc_search_string
);
331 noninc_search_string
= savestring (rl_line_buffer
);
333 /* If we don't want the subsequent undo list generated by the search
334 matching a history line to include the contents of the search string,
335 we need to clear rl_line_buffer here. For now, we just clear the
336 undo list generated by reading the search string. (If the search
337 fails, the old undo list will be restored by rl_maybe_unsave_line.) */
338 rl_free_undo_list ();
341 rl_restore_prompt ();
342 return (noninc_dosearch (noninc_search_string
, cxt
->direction
));
345 /* Search non-interactively through the history list. DIR < 0 means to
346 search backwards through the history of previous commands; otherwise
347 the search is for commands subsequent to the current position in the
348 history list. PCHAR is the character to use for prompting when reading
349 the search string; if not specified (0), it defaults to `:'. */
351 noninc_search (dir
, pchar
)
358 cxt
= _rl_nsearch_init (dir
, pchar
);
360 if (RL_ISSTATE (RL_STATE_CALLBACK
))
363 /* Read the search string. */
367 c
= _rl_search_getchar (cxt
);
372 r
= _rl_nsearch_dispatch (cxt
, c
);
379 r
= _rl_nsearch_dosearch (cxt
);
380 return ((r
>= 0) ? _rl_nsearch_cleanup (cxt
, r
) : (r
!= 1));
383 /* Search forward through the history list for a string. If the vi-mode
384 code calls this, KEY will be `?'. */
386 rl_noninc_forward_search (count
, key
)
389 return noninc_search (1, (key
== '?') ? '?' : 0);
392 /* Reverse search the history list for a string. If the vi-mode code
393 calls this, KEY will be `/'. */
395 rl_noninc_reverse_search (count
, key
)
398 return noninc_search (-1, (key
== '/') ? '/' : 0);
401 /* Search forward through the history list for the last string searched
402 for. If there is no saved search string, abort. */
404 rl_noninc_forward_search_again (count
, key
)
409 if (!noninc_search_string
)
414 r
= noninc_dosearch (noninc_search_string
, 1);
418 /* Reverse search in the history list for the last string searched
419 for. If there is no saved search string, abort. */
421 rl_noninc_reverse_search_again (count
, key
)
426 if (!noninc_search_string
)
431 r
= noninc_dosearch (noninc_search_string
, -1);
435 #if defined (READLINE_CALLBACKS)
437 _rl_nsearch_callback (cxt
)
442 c
= _rl_search_getchar (cxt
);
443 r
= _rl_nsearch_dispatch (cxt
, c
);
447 r
= _rl_nsearch_dosearch (cxt
);
448 return ((r
>= 0) ? _rl_nsearch_cleanup (cxt
, r
) : (r
!= 1));
453 rl_history_search_internal (count
, dir
)
459 rl_maybe_save_line ();
460 temp
= (HIST_ENTRY
*)NULL
;
462 /* Search COUNT times through the history for a line whose prefix
463 matches history_search_string. When this loop finishes, TEMP,
464 if non-null, is the history line to copy into the line buffer. */
467 ret
= noninc_search_from_pos (history_search_string
, rl_history_search_pos
+ dir
, dir
);
471 /* Get the history entry we found. */
472 rl_history_search_pos
= ret
;
473 oldpos
= where_history ();
474 history_set_pos (rl_history_search_pos
);
475 temp
= current_history ();
476 history_set_pos (oldpos
);
478 /* Don't find multiple instances of the same line. */
479 if (prev_line_found
&& STREQ (prev_line_found
, temp
->line
))
481 prev_line_found
= temp
->line
;
485 /* If we didn't find anything at all, return. */
488 rl_maybe_unsave_line ();
490 /* If you don't want the saved history line (last match) to show up
491 in the line buffer after the search fails, change the #if 0 to
494 if (rl_point
> rl_history_search_len
)
496 rl_point
= rl_end
= rl_history_search_len
;
497 rl_line_buffer
[rl_end
] = '\0';
501 rl_point
= rl_history_search_len
; /* rl_maybe_unsave_line changes it */
507 /* Copy the line we found into the current line buffer. */
508 make_history_line_current (temp
);
510 rl_point
= rl_history_search_len
;
517 rl_history_search_reinit ()
519 rl_history_search_pos
= where_history ();
520 rl_history_search_len
= rl_point
;
521 prev_line_found
= (char *)NULL
;
524 if (rl_history_search_len
>= history_string_size
- 2)
526 history_string_size
= rl_history_search_len
+ 2;
527 history_search_string
= (char *)xrealloc (history_search_string
, history_string_size
);
529 history_search_string
[0] = '^';
530 strncpy (history_search_string
+ 1, rl_line_buffer
, rl_point
);
531 history_search_string
[rl_point
+ 1] = '\0';
533 _rl_free_saved_history_line ();
536 /* Search forward in the history for the string of characters
537 from the start of the line to rl_point. This is a non-incremental
540 rl_history_search_forward (count
, ignore
)
546 if (rl_last_func
!= rl_history_search_forward
&&
547 rl_last_func
!= rl_history_search_backward
)
548 rl_history_search_reinit ();
550 if (rl_history_search_len
== 0)
551 return (rl_get_next_history (count
, ignore
));
552 return (rl_history_search_internal (abs (count
), (count
> 0) ? 1 : -1));
555 /* Search backward through the history for the string of characters
556 from the start of the line to rl_point. This is a non-incremental
559 rl_history_search_backward (count
, ignore
)
565 if (rl_last_func
!= rl_history_search_forward
&&
566 rl_last_func
!= rl_history_search_backward
)
567 rl_history_search_reinit ();
569 if (rl_history_search_len
== 0)
570 return (rl_get_previous_history (count
, ignore
));
571 return (rl_history_search_internal (abs (count
), (count
> 0) ? -1 : 1));