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));