]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/readline/search.c
bash-4.3-rc2 overlay
[thirdparty/bash.git] / lib / readline / search.c
1 /* search.c - code for non-incremental searching in emacs and vi modes. */
2
3 /* Copyright (C) 1992-2013 Free Software Foundation, Inc.
4
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.
7
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.
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
22 #define READLINE_LIBRARY
23
24 #if defined (HAVE_CONFIG_H)
25 # include <config.h>
26 #endif
27
28 #include <sys/types.h>
29 #include <stdio.h>
30
31 #if defined (HAVE_UNISTD_H)
32 # include <unistd.h>
33 #endif
34
35 #if defined (HAVE_STDLIB_H)
36 # include <stdlib.h>
37 #else
38 # include "ansi_stdlib.h"
39 #endif
40
41 #include "rldefs.h"
42 #include "rlmbutil.h"
43
44 #include "readline.h"
45 #include "history.h"
46 #include "histlib.h"
47
48 #include "rlprivate.h"
49 #include "xmalloc.h"
50
51 #ifdef abs
52 # undef abs
53 #endif
54 #define abs(x) (((x) >= 0) ? (x) : -(x))
55
56 _rl_search_cxt *_rl_nscxt = 0;
57
58 extern HIST_ENTRY *_rl_saved_line_for_history;
59
60 /* Functions imported from the rest of the library. */
61 extern int _rl_free_history_entry PARAMS((HIST_ENTRY *));
62
63 static char *noninc_search_string = (char *) NULL;
64 static int noninc_history_pos;
65
66 static char *prev_line_found = (char *) NULL;
67
68 static int rl_history_search_len;
69 static int rl_history_search_pos;
70 static int rl_history_search_flags;
71
72 static char *history_search_string;
73 static int history_string_size;
74
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));
81
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));
86
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. */
90 static void
91 make_history_line_current (entry)
92 HIST_ENTRY *entry;
93 {
94 _rl_replace_text (entry->line, 0, rl_end);
95 _rl_fix_point (1);
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 ();
103 #endif
104
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;
108 }
109
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. */
115 static int
116 noninc_search_from_pos (string, pos, dir)
117 char *string;
118 int pos, dir;
119 {
120 int ret, old;
121
122 if (pos < 0)
123 return -1;
124
125 old = where_history ();
126 if (history_set_pos (pos) == 0)
127 return -1;
128
129 RL_SETSTATE(RL_STATE_SEARCH);
130 if (*string == '^')
131 ret = history_search_prefix (string + 1, dir);
132 else
133 ret = history_search (string, dir);
134 RL_UNSETSTATE(RL_STATE_SEARCH);
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
145 entries. Returns 1 if the search was successful, 0 otherwise. */
146 static int
147 noninc_dosearch (string, dir)
148 char *string;
149 int dir;
150 {
151 int oldpos, pos;
152 HIST_ENTRY *entry;
153
154 if (string == 0 || *string == '\0' || noninc_history_pos < 0)
155 {
156 rl_ding ();
157 return 0;
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. */
164 rl_maybe_unsave_line ();
165 rl_clear_message ();
166 rl_point = 0;
167 rl_ding ();
168 return 0;
169 }
170
171 noninc_history_pos = pos;
172
173 oldpos = where_history ();
174 history_set_pos (noninc_history_pos);
175 entry = current_history (); /* will never be NULL after successful search */
176
177 #if defined (VI_MODE)
178 if (rl_editing_mode != vi_mode)
179 #endif
180 history_set_pos (oldpos);
181
182 make_history_line_current (entry);
183
184 rl_point = 0;
185 rl_mark = rl_end;
186
187 rl_clear_message ();
188 return 1;
189 }
190
191 static _rl_search_cxt *
192 _rl_nsearch_init (dir, pchar)
193 int dir, pchar;
194 {
195 _rl_search_cxt *cxt;
196 char *p;
197
198 cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
199 if (dir < 0)
200 cxt->sflags |= SF_REVERSE; /* not strictly needed */
201
202 cxt->direction = dir;
203 cxt->history_pos = cxt->save_line;
204
205 rl_maybe_save_line ();
206
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. */
210 rl_undo_list = 0;
211
212 /* Use the line buffer to read the search string. */
213 rl_line_buffer[0] = 0;
214 rl_end = rl_point = 0;
215
216 p = _rl_make_prompt_for_search (pchar ? pchar : ':');
217 rl_message ("%s", p);
218 xfree (p);
219
220 RL_SETSTATE(RL_STATE_NSEARCH);
221
222 _rl_nscxt = cxt;
223
224 return cxt;
225 }
226
227 static int
228 _rl_nsearch_cleanup (cxt, r)
229 _rl_search_cxt *cxt;
230 int r;
231 {
232 _rl_scxt_dispose (cxt, 0);
233 _rl_nscxt = 0;
234
235 RL_UNSETSTATE(RL_STATE_NSEARCH);
236
237 return (r != 1);
238 }
239
240 static void
241 _rl_nsearch_abort (cxt)
242 _rl_search_cxt *cxt;
243 {
244 rl_maybe_unsave_line ();
245 rl_clear_message ();
246 rl_point = cxt->save_point;
247 rl_mark = cxt->save_mark;
248 rl_restore_prompt ();
249
250 RL_UNSETSTATE (RL_STATE_NSEARCH);
251 }
252
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. */
256 static int
257 _rl_nsearch_dispatch (cxt, c)
258 _rl_search_cxt *cxt;
259 int c;
260 {
261 switch (c)
262 {
263 case CTRL('W'):
264 rl_unix_word_rubout (1, c);
265 break;
266
267 case CTRL('U'):
268 rl_unix_line_discard (1, c);
269 break;
270
271 case RETURN:
272 case NEWLINE:
273 return 0;
274
275 case CTRL('H'):
276 case RUBOUT:
277 if (rl_point == 0)
278 {
279 _rl_nsearch_abort (cxt);
280 return -1;
281 }
282 _rl_rubout_char (1, c);
283 break;
284
285 case CTRL('C'):
286 case CTRL('G'):
287 rl_ding ();
288 _rl_nsearch_abort (cxt);
289 return -1;
290
291 default:
292 #if defined (HANDLE_MULTIBYTE)
293 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
294 rl_insert_text (cxt->mb);
295 else
296 #endif
297 _rl_insert_char (1, c);
298 break;
299 }
300
301 (*rl_redisplay_function) ();
302 return 1;
303 }
304
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,
308 0 otherwise. */
309 static int
310 _rl_nsearch_dosearch (cxt)
311 _rl_search_cxt *cxt;
312 {
313 rl_mark = cxt->save_mark;
314
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
317 string, punt. */
318 if (rl_point == 0)
319 {
320 if (noninc_search_string == 0)
321 {
322 rl_ding ();
323 rl_restore_prompt ();
324 RL_UNSETSTATE (RL_STATE_NSEARCH);
325 return -1;
326 }
327 }
328 else
329 {
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);
334
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 ();
341 }
342
343 rl_restore_prompt ();
344 return (noninc_dosearch (noninc_search_string, cxt->direction));
345 }
346
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 `:'. */
352 static int
353 noninc_search (dir, pchar)
354 int dir;
355 int pchar;
356 {
357 _rl_search_cxt *cxt;
358 int c, r;
359
360 cxt = _rl_nsearch_init (dir, pchar);
361
362 if (RL_ISSTATE (RL_STATE_CALLBACK))
363 return (0);
364
365 /* Read the search string. */
366 r = 0;
367 while (1)
368 {
369 c = _rl_search_getchar (cxt);
370
371 if (c == 0)
372 break;
373
374 r = _rl_nsearch_dispatch (cxt, c);
375 if (r < 0)
376 return 1;
377 else if (r == 0)
378 break;
379 }
380
381 r = _rl_nsearch_dosearch (cxt);
382 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
383 }
384
385 /* Search forward through the history list for a string. If the vi-mode
386 code calls this, KEY will be `?'. */
387 int
388 rl_noninc_forward_search (count, key)
389 int count, key;
390 {
391 return noninc_search (1, (key == '?') ? '?' : 0);
392 }
393
394 /* Reverse search the history list for a string. If the vi-mode code
395 calls this, KEY will be `/'. */
396 int
397 rl_noninc_reverse_search (count, key)
398 int count, key;
399 {
400 return noninc_search (-1, (key == '/') ? '/' : 0);
401 }
402
403 /* Search forward through the history list for the last string searched
404 for. If there is no saved search string, abort. */
405 int
406 rl_noninc_forward_search_again (count, key)
407 int count, key;
408 {
409 int r;
410
411 if (!noninc_search_string)
412 {
413 rl_ding ();
414 return (-1);
415 }
416 r = noninc_dosearch (noninc_search_string, 1);
417 return (r != 1);
418 }
419
420 /* Reverse search in the history list for the last string searched
421 for. If there is no saved search string, abort. */
422 int
423 rl_noninc_reverse_search_again (count, key)
424 int count, key;
425 {
426 int r;
427
428 if (!noninc_search_string)
429 {
430 rl_ding ();
431 return (-1);
432 }
433 r = noninc_dosearch (noninc_search_string, -1);
434 return (r != 1);
435 }
436
437 #if defined (READLINE_CALLBACKS)
438 int
439 _rl_nsearch_callback (cxt)
440 _rl_search_cxt *cxt;
441 {
442 int c, r;
443
444 c = _rl_search_getchar (cxt);
445 r = _rl_nsearch_dispatch (cxt, c);
446 if (r != 0)
447 return 1;
448
449 r = _rl_nsearch_dosearch (cxt);
450 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
451 }
452 #endif
453
454 static int
455 rl_history_search_internal (count, dir)
456 int count, dir;
457 {
458 HIST_ENTRY *temp;
459 int ret, oldpos;
460 char *t;
461
462 rl_maybe_save_line ();
463 temp = (HIST_ENTRY *)NULL;
464
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. */
470 while (count)
471 {
472 RL_CHECK_SIGNALS ();
473 ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
474 if (ret == -1)
475 break;
476
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);
483
484 /* Don't find multiple instances of the same line. */
485 if (prev_line_found && STREQ (prev_line_found, temp->line))
486 continue;
487 prev_line_found = temp->line;
488 count--;
489 }
490
491 /* If we didn't find anything at all, return. */
492 if (temp == 0)
493 {
494 rl_maybe_unsave_line ();
495 rl_ding ();
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
498 #if 1 */
499 #if 0
500 if (rl_point > rl_history_search_len)
501 {
502 rl_point = rl_end = rl_history_search_len;
503 rl_line_buffer[rl_end] = '\0';
504 rl_mark = 0;
505 }
506 #else
507 rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
508 rl_mark = rl_end;
509 #endif
510 return 1;
511 }
512
513 /* Copy the line we found into the current line buffer. */
514 make_history_line_current (temp);
515
516 if (rl_history_search_flags & ANCHORED_SEARCH)
517 rl_point = rl_history_search_len; /* easy case */
518 else
519 {
520 t = strstr (rl_line_buffer, history_search_string);
521 rl_point = t ? (int)(t - rl_line_buffer) + rl_history_search_len : rl_end;
522 }
523 rl_mark = rl_end;
524
525 return 0;
526 }
527
528 static void
529 rl_history_search_reinit (flags)
530 int flags;
531 {
532 int sind;
533
534 rl_history_search_pos = where_history ();
535 rl_history_search_len = rl_point;
536 rl_history_search_flags = flags;
537
538 prev_line_found = (char *)NULL;
539 if (rl_point)
540 {
541 /* Allocate enough space for anchored and non-anchored searches */
542 if (rl_history_search_len >= history_string_size - 2)
543 {
544 history_string_size = rl_history_search_len + 2;
545 history_search_string = (char *)xrealloc (history_search_string, history_string_size);
546 }
547 sind = 0;
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';
552 }
553 _rl_free_saved_history_line ();
554 }
555
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. */
559 int
560 rl_history_search_forward (count, ignore)
561 int count, ignore;
562 {
563 if (count == 0)
564 return (0);
565
566 if (rl_last_func != rl_history_search_forward &&
567 rl_last_func != rl_history_search_backward)
568 rl_history_search_reinit (ANCHORED_SEARCH);
569
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));
573 }
574
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
577 search. */
578 int
579 rl_history_search_backward (count, ignore)
580 int count, ignore;
581 {
582 if (count == 0)
583 return (0);
584
585 if (rl_last_func != rl_history_search_forward &&
586 rl_last_func != rl_history_search_backward)
587 rl_history_search_reinit (ANCHORED_SEARCH);
588
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));
592 }
593
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. */
598 int
599 rl_history_substr_search_forward (count, ignore)
600 int count, ignore;
601 {
602 if (count == 0)
603 return (0);
604
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);
608
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));
612 }
613
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
616 search. */
617 int
618 rl_history_substr_search_backward (count, ignore)
619 int count, ignore;
620 {
621 if (count == 0)
622 return (0);
623
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);
627
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));
631 }