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 void make_history_line_current PARAMS((HIST_ENTRY *));
74 static int noninc_search_from_pos PARAMS((char *, int, int));
75 static int noninc_dosearch PARAMS((char *, int));
76 static int noninc_search PARAMS((int, int));
77 static int rl_history_search_internal PARAMS((int, int));
78 static void rl_history_search_reinit PARAMS((void));
80 static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
81 static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int));
82 static void _rl_nsearch_abort PARAMS((_rl_search_cxt *));
83 static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int));
85 /* Make the data from the history entry ENTRY be the contents of the
86 current line. This doesn't do anything with rl_point; the caller
89 make_history_line_current (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 (string, pos, dir)
123 old = where_history ();
124 if (history_set_pos (pos) == 0)
127 RL_SETSTATE(RL_STATE_SEARCH);
129 ret = history_search_prefix (string + 1, dir);
131 ret = history_search (string, dir);
132 RL_UNSETSTATE(RL_STATE_SEARCH);
135 ret = where_history ();
137 history_set_pos (old);
141 /* Search for a line in the history containing STRING. If DIR is < 0, the
142 search is backwards through previous entries, else through subsequent
143 entries. Returns 1 if the search was successful, 0 otherwise. */
145 noninc_dosearch (string, dir)
152 if (string == 0 || *string == '\0' || noninc_history_pos < 0)
158 pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
161 /* Search failed, current history position unchanged. */
162 rl_maybe_unsave_line ();
169 noninc_history_pos = pos;
171 oldpos = where_history ();
172 history_set_pos (noninc_history_pos);
173 entry = current_history ();
174 #if defined (VI_MODE)
175 if (rl_editing_mode != vi_mode)
177 history_set_pos (oldpos);
179 make_history_line_current (entry);
188 static _rl_search_cxt *
189 _rl_nsearch_init (dir, pchar)
195 cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
197 cxt->sflags |= SF_REVERSE; /* not strictly needed */
199 cxt->direction = dir;
200 cxt->history_pos = cxt->save_line;
202 rl_maybe_save_line ();
204 /* Clear the undo list, since reading the search string should create its
205 own undo list, and the whole list will end up being freed when we
206 finish reading the search string. */
209 /* Use the line buffer to read the search string. */
210 rl_line_buffer[0] = 0;
211 rl_end = rl_point = 0;
213 p = _rl_make_prompt_for_search (pchar ? pchar : ':');
214 rl_message ("%s", p, 0);
217 RL_SETSTATE(RL_STATE_NSEARCH);
225 _rl_nsearch_cleanup (cxt, r)
229 _rl_scxt_dispose (cxt, 0);
232 RL_UNSETSTATE(RL_STATE_NSEARCH);
238 _rl_nsearch_abort (cxt)
241 rl_maybe_unsave_line ();
243 rl_point = cxt->save_point;
244 rl_mark = cxt->save_mark;
245 rl_restore_prompt ();
247 RL_UNSETSTATE (RL_STATE_NSEARCH);
250 /* Process just-read character C according to search context CXT. Return -1
251 if the caller should abort the search, 0 if we should break out of the
252 loop, and 1 if we should continue to read characters. */
254 _rl_nsearch_dispatch (cxt, c)
261 rl_unix_word_rubout (1, c);
265 rl_unix_line_discard (1, c);
276 _rl_nsearch_abort (cxt);
279 _rl_rubout_char (1, c);
285 _rl_nsearch_abort (cxt);
289 #if defined (HANDLE_MULTIBYTE)
290 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
291 rl_insert_text (cxt->mb);
294 _rl_insert_char (1, c);
298 (*rl_redisplay_function) ();
302 /* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
303 -1 if the search should be aborted, any other value means to clean up
304 using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
307 _rl_nsearch_dosearch (cxt)
310 rl_mark = cxt->save_mark;
312 /* If rl_point == 0, we want to re-use the previous search string and
313 start from the saved history position. If there's no previous search
317 if (noninc_search_string == 0)
320 rl_restore_prompt ();
321 RL_UNSETSTATE (RL_STATE_NSEARCH);
327 /* We want to start the search from the current history position. */
328 noninc_history_pos = cxt->save_line;
329 FREE (noninc_search_string);
330 noninc_search_string = savestring (rl_line_buffer);
332 /* If we don't want the subsequent undo list generated by the search
333 matching a history line to include the contents of the search string,
334 we need to clear rl_line_buffer here. For now, we just clear the
335 undo list generated by reading the search string. (If the search
336 fails, the old undo list will be restored by rl_maybe_unsave_line.) */
337 rl_free_undo_list ();
340 rl_restore_prompt ();
341 return (noninc_dosearch (noninc_search_string, cxt->direction));
344 /* Search non-interactively through the history list. DIR < 0 means to
345 search backwards through the history of previous commands; otherwise
346 the search is for commands subsequent to the current position in the
347 history list. PCHAR is the character to use for prompting when reading
348 the search string; if not specified (0), it defaults to `:'. */
350 noninc_search (dir, pchar)
357 cxt = _rl_nsearch_init (dir, pchar);
359 if (RL_ISSTATE (RL_STATE_CALLBACK))
362 /* Read the search string. */
366 c = _rl_search_getchar (cxt);
371 r = _rl_nsearch_dispatch (cxt, c);
378 r = _rl_nsearch_dosearch (cxt);
379 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
382 /* Search forward through the history list for a string. If the vi-mode
383 code calls this, KEY will be `?'. */
385 rl_noninc_forward_search (count, key)
388 return noninc_search (1, (key == '?') ? '?' : 0);
391 /* Reverse search the history list for a string. If the vi-mode code
392 calls this, KEY will be `/'. */
394 rl_noninc_reverse_search (count, key)
397 return noninc_search (-1, (key == '/') ? '/' : 0);
400 /* Search forward through the history list for the last string searched
401 for. If there is no saved search string, abort. */
403 rl_noninc_forward_search_again (count, key)
408 if (!noninc_search_string)
413 r = noninc_dosearch (noninc_search_string, 1);
417 /* Reverse search in the history list for the last string searched
418 for. If there is no saved search string, abort. */
420 rl_noninc_reverse_search_again (count, key)
425 if (!noninc_search_string)
430 r = noninc_dosearch (noninc_search_string, -1);
434 #if defined (READLINE_CALLBACKS)
436 _rl_nsearch_callback (cxt)
441 c = _rl_search_getchar (cxt);
442 r = _rl_nsearch_dispatch (cxt, c);
446 r = _rl_nsearch_dosearch (cxt);
447 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
452 rl_history_search_internal (count, dir)
458 rl_maybe_save_line ();
459 temp = (HIST_ENTRY *)NULL;
461 /* Search COUNT times through the history for a line whose prefix
462 matches history_search_string. When this loop finishes, TEMP,
463 if non-null, is the history line to copy into the line buffer. */
466 ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
470 /* Get the history entry we found. */
471 rl_history_search_pos = ret;
472 oldpos = where_history ();
473 history_set_pos (rl_history_search_pos);
474 temp = current_history ();
475 history_set_pos (oldpos);
477 /* Don't find multiple instances of the same line. */
478 if (prev_line_found && STREQ (prev_line_found, temp->line))
480 prev_line_found = temp->line;
484 /* If we didn't find anything at all, return. */
487 rl_maybe_unsave_line ();
489 /* If you don't want the saved history line (last match) to show up
490 in the line buffer after the search fails, change the #if 0 to
493 if (rl_point > rl_history_search_len)
495 rl_point = rl_end = rl_history_search_len;
496 rl_line_buffer[rl_end] = '\0';
500 rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
506 /* Copy the line we found into the current line buffer. */
507 make_history_line_current (temp);
509 rl_point = rl_history_search_len;
516 rl_history_search_reinit ()
518 rl_history_search_pos = where_history ();
519 rl_history_search_len = rl_point;
520 prev_line_found = (char *)NULL;
523 if (rl_history_search_len >= history_string_size - 2)
525 history_string_size = rl_history_search_len + 2;
526 history_search_string = (char *)xrealloc (history_search_string, history_string_size);
528 history_search_string[0] = '^';
529 strncpy (history_search_string + 1, rl_line_buffer, rl_point);
530 history_search_string[rl_point + 1] = '\0';
532 _rl_free_saved_history_line ();
535 /* Search forward in the history for the string of characters
536 from the start of the line to rl_point. This is a non-incremental
539 rl_history_search_forward (count, ignore)
545 if (rl_last_func != rl_history_search_forward &&
546 rl_last_func != rl_history_search_backward)
547 rl_history_search_reinit ();
549 if (rl_history_search_len == 0)
550 return (rl_get_next_history (count, ignore));
551 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
554 /* Search backward through the history for the string of characters
555 from the start of the line to rl_point. This is a non-incremental
558 rl_history_search_backward (count, ignore)
564 if (rl_last_func != rl_history_search_forward &&
565 rl_last_func != rl_history_search_backward)
566 rl_history_search_reinit ();
568 if (rl_history_search_len == 0)
569 return (rl_get_previous_history (count, ignore));
570 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));