]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/search.c
bash-4.3-rc1 overlay
[thirdparty/bash.git] / lib / readline / search.c
CommitLineData
726f6388
JA
1/* search.c - code for non-incremental searching in emacs and vi modes. */
2
8581f42d 3/* Copyright (C) 1992-2013 Free Software Foundation, Inc.
726f6388 4
2e4498b3
CR
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.
726f6388 7
2e4498b3 8 Readline is free software: you can redistribute it and/or modify
726f6388 9 it under the terms of the GNU General Public License as published by
2e4498b3
CR
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
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.
17
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/>.
20*/
21
726f6388
JA
22#define READLINE_LIBRARY
23
ccc6cda3
JA
24#if defined (HAVE_CONFIG_H)
25# include <config.h>
26#endif
27
726f6388
JA
28#include <sys/types.h>
29#include <stdio.h>
30
31#if defined (HAVE_UNISTD_H)
32# include <unistd.h>
33#endif
34
d166f048
JA
35#if defined (HAVE_STDLIB_H)
36# include <stdlib.h>
37#else
38# include "ansi_stdlib.h"
39#endif
40
726f6388 41#include "rldefs.h"
7117c2d2
JA
42#include "rlmbutil.h"
43
726f6388
JA
44#include "readline.h"
45#include "history.h"
276cb932 46#include "histlib.h"
726f6388 47
bb70624e
JA
48#include "rlprivate.h"
49#include "xmalloc.h"
50
d166f048
JA
51#ifdef abs
52# undef abs
53#endif
54#define abs(x) (((x) >= 0) ? (x) : -(x))
726f6388 55
798a67db
CR
56_rl_search_cxt *_rl_nscxt = 0;
57
28ef6c31 58extern HIST_ENTRY *_rl_saved_line_for_history;
726f6388
JA
59
60/* Functions imported from the rest of the library. */
f73dda09 61extern int _rl_free_history_entry PARAMS((HIST_ENTRY *));
726f6388
JA
62
63static char *noninc_search_string = (char *) NULL;
ccc6cda3 64static int noninc_history_pos;
bb70624e 65
726f6388
JA
66static char *prev_line_found = (char *) NULL;
67
bb70624e
JA
68static int rl_history_search_len;
69static int rl_history_search_pos;
276cb932
CR
70static int rl_history_search_flags;
71
bb70624e
JA
72static char *history_search_string;
73static int history_string_size;
74
f73dda09
JA
75static void make_history_line_current PARAMS((HIST_ENTRY *));
76static int noninc_search_from_pos PARAMS((char *, int, int));
798a67db
CR
77static int noninc_dosearch PARAMS((char *, int));
78static int noninc_search PARAMS((int, int));
f73dda09 79static int rl_history_search_internal PARAMS((int, int));
276cb932 80static void rl_history_search_reinit PARAMS((int));
f73dda09 81
798a67db
CR
82static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
83static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int));
84static void _rl_nsearch_abort PARAMS((_rl_search_cxt *));
85static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int));
86
bb70624e
JA
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
89 must set it. */
90static void
91make_history_line_current (entry)
92 HIST_ENTRY *entry;
93{
d3a24ed2
CR
94 _rl_replace_text (entry->line, 0, rl_end);
95 _rl_fix_point (1);
ff247e74
CR
96#if defined (VI_MODE)
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 ();
d3a24ed2 103#endif
bb70624e 104
28ef6c31
JA
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;
bb70624e
JA
108}
109
726f6388
JA
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. */
115static int
116noninc_search_from_pos (string, pos, dir)
117 char *string;
118 int pos, dir;
119{
120 int ret, old;
121
28ef6c31
JA
122 if (pos < 0)
123 return -1;
124
726f6388 125 old = where_history ();
28ef6c31
JA
126 if (history_set_pos (pos) == 0)
127 return -1;
726f6388 128
28ef6c31 129 RL_SETSTATE(RL_STATE_SEARCH);
726f6388
JA
130 if (*string == '^')
131 ret = history_search_prefix (string + 1, dir);
132 else
133 ret = history_search (string, dir);
28ef6c31 134 RL_UNSETSTATE(RL_STATE_SEARCH);
726f6388
JA
135
136 if (ret != -1)
137 ret = where_history ();
138
139 history_set_pos (old);
140 return (ret);
141}
142
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
798a67db
CR
145 entries. Returns 1 if the search was successful, 0 otherwise. */
146static int
726f6388
JA
147noninc_dosearch (string, dir)
148 char *string;
149 int dir;
150{
bb70624e 151 int oldpos, pos;
726f6388
JA
152 HIST_ENTRY *entry;
153
154 if (string == 0 || *string == '\0' || noninc_history_pos < 0)
155 {
28ef6c31 156 rl_ding ();
798a67db 157 return 0;
726f6388
JA
158 }
159
160 pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
161 if (pos == -1)
162 {
163 /* Search failed, current history position unchanged. */
28ef6c31 164 rl_maybe_unsave_line ();
726f6388
JA
165 rl_clear_message ();
166 rl_point = 0;
28ef6c31 167 rl_ding ();
798a67db 168 return 0;
726f6388
JA
169 }
170
171 noninc_history_pos = pos;
172
173 oldpos = where_history ();
174 history_set_pos (noninc_history_pos);
175 entry = current_history ();
176#if defined (VI_MODE)
177 if (rl_editing_mode != vi_mode)
178#endif
798a67db 179 history_set_pos (oldpos);
726f6388 180
bb70624e 181 make_history_line_current (entry);
726f6388 182
726f6388 183 rl_point = 0;
7117c2d2
JA
184 rl_mark = rl_end;
185
726f6388 186 rl_clear_message ();
798a67db 187 return 1;
726f6388
JA
188}
189
798a67db
CR
190static _rl_search_cxt *
191_rl_nsearch_init (dir, pchar)
192 int dir, pchar;
726f6388 193{
798a67db 194 _rl_search_cxt *cxt;
726f6388 195 char *p;
798a67db
CR
196
197 cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
198 if (dir < 0)
199 cxt->sflags |= SF_REVERSE; /* not strictly needed */
200
201 cxt->direction = dir;
202 cxt->history_pos = cxt->save_line;
726f6388 203
28ef6c31 204 rl_maybe_save_line ();
726f6388 205
d3a24ed2
CR
206 /* Clear the undo list, since reading the search string should create its
207 own undo list, and the whole list will end up being freed when we
208 finish reading the search string. */
209 rl_undo_list = 0;
210
726f6388
JA
211 /* Use the line buffer to read the search string. */
212 rl_line_buffer[0] = 0;
213 rl_end = rl_point = 0;
214
ccc6cda3 215 p = _rl_make_prompt_for_search (pchar ? pchar : ':');
8581f42d 216 rl_message ("%s", p);
9ec5ed66 217 xfree (p);
726f6388 218
28ef6c31 219 RL_SETSTATE(RL_STATE_NSEARCH);
798a67db
CR
220
221 _rl_nscxt = cxt;
222
223 return cxt;
224}
225
226static int
227_rl_nsearch_cleanup (cxt, r)
228 _rl_search_cxt *cxt;
229 int r;
230{
231 _rl_scxt_dispose (cxt, 0);
232 _rl_nscxt = 0;
233
234 RL_UNSETSTATE(RL_STATE_NSEARCH);
235
236 return (r != 1);
237}
238
239static void
240_rl_nsearch_abort (cxt)
241 _rl_search_cxt *cxt;
242{
243 rl_maybe_unsave_line ();
244 rl_clear_message ();
245 rl_point = cxt->save_point;
246 rl_mark = cxt->save_mark;
247 rl_restore_prompt ();
248
249 RL_UNSETSTATE (RL_STATE_NSEARCH);
250}
251
252/* Process just-read character C according to search context CXT. Return -1
253 if the caller should abort the search, 0 if we should break out of the
254 loop, and 1 if we should continue to read characters. */
255static int
256_rl_nsearch_dispatch (cxt, c)
257 _rl_search_cxt *cxt;
258 int c;
259{
260 switch (c)
726f6388 261 {
798a67db
CR
262 case CTRL('W'):
263 rl_unix_word_rubout (1, c);
264 break;
28ef6c31 265
798a67db
CR
266 case CTRL('U'):
267 rl_unix_line_discard (1, c);
268 break;
7117c2d2 269
798a67db
CR
270 case RETURN:
271 case NEWLINE:
272 return 0;
28ef6c31 273
798a67db
CR
274 case CTRL('H'):
275 case RUBOUT:
276 if (rl_point == 0)
726f6388 277 {
798a67db
CR
278 _rl_nsearch_abort (cxt);
279 return -1;
280 }
281 _rl_rubout_char (1, c);
282 break;
726f6388 283
798a67db
CR
284 case CTRL('C'):
285 case CTRL('G'):
286 rl_ding ();
287 _rl_nsearch_abort (cxt);
288 return -1;
289
290 default:
7117c2d2 291#if defined (HANDLE_MULTIBYTE)
798a67db
CR
292 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
293 rl_insert_text (cxt->mb);
294 else
7117c2d2 295#endif
798a67db
CR
296 _rl_insert_char (1, c);
297 break;
726f6388
JA
298 }
299
798a67db
CR
300 (*rl_redisplay_function) ();
301 return 1;
302}
303
304/* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
305 -1 if the search should be aborted, any other value means to clean up
306 using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
307 0 otherwise. */
308static int
309_rl_nsearch_dosearch (cxt)
310 _rl_search_cxt *cxt;
311{
312 rl_mark = cxt->save_mark;
7117c2d2 313
726f6388
JA
314 /* If rl_point == 0, we want to re-use the previous search string and
315 start from the saved history position. If there's no previous search
316 string, punt. */
317 if (rl_point == 0)
318 {
798a67db 319 if (noninc_search_string == 0)
726f6388 320 {
28ef6c31 321 rl_ding ();
798a67db
CR
322 rl_restore_prompt ();
323 RL_UNSETSTATE (RL_STATE_NSEARCH);
324 return -1;
726f6388
JA
325 }
326 }
327 else
328 {
329 /* We want to start the search from the current history position. */
798a67db 330 noninc_history_pos = cxt->save_line;
bb70624e 331 FREE (noninc_search_string);
726f6388 332 noninc_search_string = savestring (rl_line_buffer);
ff247e74
CR
333
334 /* If we don't want the subsequent undo list generated by the search
335 matching a history line to include the contents of the search string,
336 we need to clear rl_line_buffer here. For now, we just clear the
337 undo list generated by reading the search string. (If the search
338 fails, the old undo list will be restored by rl_maybe_unsave_line.) */
339 rl_free_undo_list ();
726f6388
JA
340 }
341
b72432fd 342 rl_restore_prompt ();
798a67db
CR
343 return (noninc_dosearch (noninc_search_string, cxt->direction));
344}
345
346/* Search non-interactively through the history list. DIR < 0 means to
347 search backwards through the history of previous commands; otherwise
348 the search is for commands subsequent to the current position in the
349 history list. PCHAR is the character to use for prompting when reading
350 the search string; if not specified (0), it defaults to `:'. */
351static int
352noninc_search (dir, pchar)
353 int dir;
354 int pchar;
355{
356 _rl_search_cxt *cxt;
357 int c, r;
358
359 cxt = _rl_nsearch_init (dir, pchar);
360
361 if (RL_ISSTATE (RL_STATE_CALLBACK))
362 return (0);
363
364 /* Read the search string. */
365 r = 0;
366 while (1)
367 {
368 c = _rl_search_getchar (cxt);
369
370 if (c == 0)
371 break;
372
373 r = _rl_nsearch_dispatch (cxt, c);
374 if (r < 0)
375 return 1;
376 else if (r == 0)
377 break;
378 }
379
380 r = _rl_nsearch_dosearch (cxt);
381 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
726f6388
JA
382}
383
384/* Search forward through the history list for a string. If the vi-mode
385 code calls this, KEY will be `?'. */
ccc6cda3 386int
726f6388
JA
387rl_noninc_forward_search (count, key)
388 int count, key;
389{
798a67db 390 return noninc_search (1, (key == '?') ? '?' : 0);
726f6388
JA
391}
392
393/* Reverse search the history list for a string. If the vi-mode code
394 calls this, KEY will be `/'. */
ccc6cda3 395int
726f6388
JA
396rl_noninc_reverse_search (count, key)
397 int count, key;
398{
798a67db 399 return noninc_search (-1, (key == '/') ? '/' : 0);
726f6388
JA
400}
401
402/* Search forward through the history list for the last string searched
403 for. If there is no saved search string, abort. */
ccc6cda3 404int
726f6388
JA
405rl_noninc_forward_search_again (count, key)
406 int count, key;
407{
798a67db
CR
408 int r;
409
726f6388
JA
410 if (!noninc_search_string)
411 {
28ef6c31 412 rl_ding ();
726f6388
JA
413 return (-1);
414 }
798a67db
CR
415 r = noninc_dosearch (noninc_search_string, 1);
416 return (r != 1);
726f6388
JA
417}
418
419/* Reverse search in the history list for the last string searched
420 for. If there is no saved search string, abort. */
ccc6cda3 421int
726f6388
JA
422rl_noninc_reverse_search_again (count, key)
423 int count, key;
424{
798a67db
CR
425 int r;
426
726f6388
JA
427 if (!noninc_search_string)
428 {
28ef6c31 429 rl_ding ();
726f6388
JA
430 return (-1);
431 }
798a67db
CR
432 r = noninc_dosearch (noninc_search_string, -1);
433 return (r != 1);
726f6388
JA
434}
435
19e1dd93 436#if defined (READLINE_CALLBACKS)
798a67db
CR
437int
438_rl_nsearch_callback (cxt)
439 _rl_search_cxt *cxt;
440{
441 int c, r;
442
443 c = _rl_search_getchar (cxt);
444 r = _rl_nsearch_dispatch (cxt, c);
445 if (r != 0)
446 return 1;
447
448 r = _rl_nsearch_dosearch (cxt);
449 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
450}
19e1dd93 451#endif
798a67db 452
726f6388 453static int
bb70624e
JA
454rl_history_search_internal (count, dir)
455 int count, dir;
726f6388 456{
bb70624e
JA
457 HIST_ENTRY *temp;
458 int ret, oldpos;
276cb932 459 char *t;
726f6388 460
28ef6c31 461 rl_maybe_save_line ();
bb70624e 462 temp = (HIST_ENTRY *)NULL;
726f6388 463
276cb932
CR
464 /* Search COUNT times through the history for a line matching
465 history_search_string. If history_search_string[0] == '^', the
466 line must match from the start; otherwise any substring can match.
467 When this loop finishes, TEMP, if non-null, is the history line to
468 copy into the line buffer. */
726f6388
JA
469 while (count)
470 {
83509ab7 471 RL_CHECK_SIGNALS ();
bb70624e
JA
472 ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
473 if (ret == -1)
474 break;
475
476 /* Get the history entry we found. */
477 rl_history_search_pos = ret;
478 oldpos = where_history ();
479 history_set_pos (rl_history_search_pos);
480 temp = current_history ();
481 history_set_pos (oldpos);
482
483 /* Don't find multiple instances of the same line. */
484 if (prev_line_found && STREQ (prev_line_found, temp->line))
485 continue;
486 prev_line_found = temp->line;
487 count--;
726f6388
JA
488 }
489
bb70624e 490 /* If we didn't find anything at all, return. */
ccc6cda3 491 if (temp == 0)
726f6388 492 {
28ef6c31
JA
493 rl_maybe_unsave_line ();
494 rl_ding ();
bb70624e
JA
495 /* If you don't want the saved history line (last match) to show up
496 in the line buffer after the search fails, change the #if 0 to
497 #if 1 */
498#if 0
499 if (rl_point > rl_history_search_len)
500 {
501 rl_point = rl_end = rl_history_search_len;
502 rl_line_buffer[rl_end] = '\0';
7117c2d2 503 rl_mark = 0;
bb70624e
JA
504 }
505#else
28ef6c31 506 rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
7117c2d2 507 rl_mark = rl_end;
bb70624e
JA
508#endif
509 return 1;
726f6388
JA
510 }
511
bb70624e
JA
512 /* Copy the line we found into the current line buffer. */
513 make_history_line_current (temp);
514
276cb932
CR
515 if (rl_history_search_flags & ANCHORED_SEARCH)
516 rl_point = rl_history_search_len; /* easy case */
517 else
518 {
519 t = strstr (rl_line_buffer, history_search_string);
520 rl_point = t ? (int)(t - rl_line_buffer) + rl_history_search_len : rl_end;
521 }
7117c2d2
JA
522 rl_mark = rl_end;
523
726f6388
JA
524 return 0;
525}
526
bb70624e 527static void
276cb932
CR
528rl_history_search_reinit (flags)
529 int flags;
bb70624e 530{
276cb932
CR
531 int sind;
532
bb70624e
JA
533 rl_history_search_pos = where_history ();
534 rl_history_search_len = rl_point;
276cb932
CR
535 rl_history_search_flags = flags;
536
bb70624e
JA
537 prev_line_found = (char *)NULL;
538 if (rl_point)
539 {
276cb932 540 /* Allocate enough space for anchored and non-anchored searches */
bb70624e
JA
541 if (rl_history_search_len >= history_string_size - 2)
542 {
543 history_string_size = rl_history_search_len + 2;
f73dda09 544 history_search_string = (char *)xrealloc (history_search_string, history_string_size);
bb70624e 545 }
276cb932
CR
546 sind = 0;
547 if (flags & ANCHORED_SEARCH)
548 history_search_string[sind++] = '^';
549 strncpy (history_search_string + sind, rl_line_buffer, rl_point);
550 history_search_string[rl_point + sind] = '\0';
bb70624e 551 }
28ef6c31 552 _rl_free_saved_history_line ();
bb70624e
JA
553}
554
726f6388
JA
555/* Search forward in the history for the string of characters
556 from the start of the line to rl_point. This is a non-incremental
276cb932 557 search. The search is anchored to the beginning of the history line. */
726f6388
JA
558int
559rl_history_search_forward (count, ignore)
560 int count, ignore;
561{
562 if (count == 0)
563 return (0);
bb70624e
JA
564
565 if (rl_last_func != rl_history_search_forward &&
566 rl_last_func != rl_history_search_backward)
276cb932 567 rl_history_search_reinit (ANCHORED_SEARCH);
bb70624e
JA
568
569 if (rl_history_search_len == 0)
570 return (rl_get_next_history (count, ignore));
726f6388
JA
571 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
572}
573
574/* Search backward through the history for the string of characters
575 from the start of the line to rl_point. This is a non-incremental
576 search. */
577int
578rl_history_search_backward (count, ignore)
579 int count, ignore;
580{
581 if (count == 0)
582 return (0);
bb70624e
JA
583
584 if (rl_last_func != rl_history_search_forward &&
585 rl_last_func != rl_history_search_backward)
276cb932
CR
586 rl_history_search_reinit (ANCHORED_SEARCH);
587
588 if (rl_history_search_len == 0)
589 return (rl_get_previous_history (count, ignore));
590 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
591}
592
593/* Search forward in the history for the string of characters
594 from the start of the line to rl_point. This is a non-incremental
595 search. The search succeeds if the search string is present anywhere
596 in the history line. */
597int
598rl_history_substr_search_forward (count, ignore)
599 int count, ignore;
600{
601 if (count == 0)
602 return (0);
603
604 if (rl_last_func != rl_history_substr_search_forward &&
605 rl_last_func != rl_history_substr_search_backward)
606 rl_history_search_reinit (NON_ANCHORED_SEARCH);
607
608 if (rl_history_search_len == 0)
609 return (rl_get_next_history (count, ignore));
610 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
611}
612
613/* Search backward through the history for the string of characters
614 from the start of the line to rl_point. This is a non-incremental
615 search. */
616int
617rl_history_substr_search_backward (count, ignore)
618 int count, ignore;
619{
620 if (count == 0)
621 return (0);
622
623 if (rl_last_func != rl_history_substr_search_forward &&
624 rl_last_func != rl_history_substr_search_backward)
625 rl_history_search_reinit (NON_ANCHORED_SEARCH);
bb70624e
JA
626
627 if (rl_history_search_len == 0)
628 return (rl_get_previous_history (count, ignore));
726f6388
JA
629 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
630}