1 /* search.c - code for non-incremental searching in emacs and vi modes. */
3 /* Copyright (C) 1992 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"
46 #include "rlprivate.h"
52 #define abs(x) (((x) >= 0) ? (x) : -(x))
54 extern HIST_ENTRY *_rl_saved_line_for_history;
56 /* Functions imported from the rest of the library. */
57 extern int _rl_free_history_entry __P((HIST_ENTRY *));
59 static char *noninc_search_string = (char *) NULL;
60 static int noninc_history_pos;
62 static char *prev_line_found = (char *) NULL;
64 static int rl_history_search_len;
65 static int rl_history_search_pos;
66 static char *history_search_string;
67 static int history_string_size;
69 /* Make the data from the history entry ENTRY be the contents of the
70 current line. This doesn't do anything with rl_point; the caller
73 make_history_line_current (entry)
78 line_len = strlen (entry->line);
79 if (line_len >= rl_line_buffer_len)
80 rl_extend_line_buffer (line_len);
81 strcpy (rl_line_buffer, entry->line);
83 rl_undo_list = (UNDO_LIST *)entry->data;
86 if (_rl_saved_line_for_history)
87 _rl_free_history_entry (_rl_saved_line_for_history);
88 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
91 /* Search the history list for STRING starting at absolute history position
92 POS. If STRING begins with `^', the search must match STRING at the
93 beginning of a history line, otherwise a full substring match is performed
94 for STRING. DIR < 0 means to search backwards through the history list,
95 DIR >= 0 means to search forward. */
97 noninc_search_from_pos (string, pos, dir)
106 old = where_history ();
107 if (history_set_pos (pos) == 0)
110 RL_SETSTATE(RL_STATE_SEARCH);
112 ret = history_search_prefix (string + 1, dir);
114 ret = history_search (string, dir);
115 RL_UNSETSTATE(RL_STATE_SEARCH);
118 ret = where_history ();
120 history_set_pos (old);
124 /* Search for a line in the history containing STRING. If DIR is < 0, the
125 search is backwards through previous entries, else through subsequent
128 noninc_dosearch (string, dir)
135 if (string == 0 || *string == '\0' || noninc_history_pos < 0)
141 pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
144 /* Search failed, current history position unchanged. */
145 rl_maybe_unsave_line ();
152 noninc_history_pos = pos;
154 oldpos = where_history ();
155 history_set_pos (noninc_history_pos);
156 entry = current_history ();
157 #if defined (VI_MODE)
158 if (rl_editing_mode != vi_mode)
160 history_set_pos (oldpos);
162 make_history_line_current (entry);
168 /* Search non-interactively through the history list. DIR < 0 means to
169 search backwards through the history of previous commands; otherwise
170 the search is for commands subsequent to the current position in the
171 history list. PCHAR is the character to use for prompting when reading
172 the search string; if not specified (0), it defaults to `:'. */
174 noninc_search (dir, pchar)
181 rl_maybe_save_line ();
182 saved_point = rl_point;
184 /* Use the line buffer to read the search string. */
185 rl_line_buffer[0] = 0;
186 rl_end = rl_point = 0;
188 p = _rl_make_prompt_for_search (pchar ? pchar : ':');
189 rl_message (p, 0, 0);
192 #define SEARCH_RETURN rl_restore_prompt (); RL_UNSETSTATE(RL_STATE_NSEARCH); return
194 RL_SETSTATE(RL_STATE_NSEARCH);
195 /* Read the search string. */
198 RL_SETSTATE(RL_STATE_MOREINPUT);
200 RL_UNSETSTATE(RL_STATE_MOREINPUT);
211 rl_maybe_unsave_line ();
213 rl_point = saved_point;
220 rl_unix_word_rubout (1, c);
224 rl_unix_line_discard (1, c);
235 rl_maybe_unsave_line ();
237 rl_point = saved_point;
245 (*rl_redisplay_function) ();
249 /* If rl_point == 0, we want to re-use the previous search string and
250 start from the saved history position. If there's no previous search
254 if (!noninc_search_string)
262 /* We want to start the search from the current history position. */
263 noninc_history_pos = where_history ();
264 FREE (noninc_search_string);
265 noninc_search_string = savestring (rl_line_buffer);
268 rl_restore_prompt ();
269 noninc_dosearch (noninc_search_string, dir);
270 RL_UNSETSTATE(RL_STATE_NSEARCH);
273 /* Search forward through the history list for a string. If the vi-mode
274 code calls this, KEY will be `?'. */
276 rl_noninc_forward_search (count, key)
279 noninc_search (1, (key == '?') ? '?' : 0);
283 /* Reverse search the history list for a string. If the vi-mode code
284 calls this, KEY will be `/'. */
286 rl_noninc_reverse_search (count, key)
289 noninc_search (-1, (key == '/') ? '/' : 0);
293 /* Search forward through the history list for the last string searched
294 for. If there is no saved search string, abort. */
296 rl_noninc_forward_search_again (count, key)
299 if (!noninc_search_string)
304 noninc_dosearch (noninc_search_string, 1);
308 /* Reverse search in the history list for the last string searched
309 for. If there is no saved search string, abort. */
311 rl_noninc_reverse_search_again (count, key)
314 if (!noninc_search_string)
319 noninc_dosearch (noninc_search_string, -1);
324 rl_history_search_internal (count, dir)
330 rl_maybe_save_line ();
331 temp = (HIST_ENTRY *)NULL;
333 /* Search COUNT times through the history for a line whose prefix
334 matches history_search_string. When this loop finishes, TEMP,
335 if non-null, is the history line to copy into the line buffer. */
338 ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
342 /* Get the history entry we found. */
343 rl_history_search_pos = ret;
344 oldpos = where_history ();
345 history_set_pos (rl_history_search_pos);
346 temp = current_history ();
347 history_set_pos (oldpos);
349 /* Don't find multiple instances of the same line. */
350 if (prev_line_found && STREQ (prev_line_found, temp->line))
352 prev_line_found = temp->line;
356 /* If we didn't find anything at all, return. */
359 rl_maybe_unsave_line ();
361 /* If you don't want the saved history line (last match) to show up
362 in the line buffer after the search fails, change the #if 0 to
365 if (rl_point > rl_history_search_len)
367 rl_point = rl_end = rl_history_search_len;
368 rl_line_buffer[rl_end] = '\0';
371 rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
376 /* Copy the line we found into the current line buffer. */
377 make_history_line_current (temp);
379 rl_point = rl_history_search_len;
384 rl_history_search_reinit ()
386 rl_history_search_pos = where_history ();
387 rl_history_search_len = rl_point;
388 prev_line_found = (char *)NULL;
391 if (rl_history_search_len >= history_string_size - 2)
393 history_string_size = rl_history_search_len + 2;
394 history_search_string = xrealloc (history_search_string, history_string_size);
396 history_search_string[0] = '^';
397 strncpy (history_search_string + 1, rl_line_buffer, rl_point);
398 history_search_string[rl_point + 1] = '\0';
400 _rl_free_saved_history_line ();
403 /* Search forward in the history for the string of characters
404 from the start of the line to rl_point. This is a non-incremental
407 rl_history_search_forward (count, ignore)
413 if (rl_last_func != rl_history_search_forward &&
414 rl_last_func != rl_history_search_backward)
415 rl_history_search_reinit ();
417 if (rl_history_search_len == 0)
418 return (rl_get_next_history (count, ignore));
419 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
422 /* Search backward through the history for the string of characters
423 from the start of the line to rl_point. This is a non-incremental
426 rl_history_search_backward (count, ignore)
432 if (rl_last_func != rl_history_search_forward &&
433 rl_last_func != rl_history_search_backward)
434 rl_history_search_reinit ();
436 if (rl_history_search_len == 0)
437 return (rl_get_previous_history (count, ignore));
438 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));