]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/search.c
Imported from ../bash-3.2.tar.gz.
[thirdparty/bash.git] / lib / readline / search.c
CommitLineData
726f6388
JA
1/* search.c - code for non-incremental searching in emacs and vi modes. */
2
95732b49 3/* Copyright (C) 1992-2005 Free Software Foundation, Inc.
726f6388
JA
4
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
7 for it.
8
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
bb70624e 11 the Free Software Foundation; either version 2, or (at your option)
726f6388
JA
12 any later version.
13
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.
18
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,
bb70624e 22 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
726f6388
JA
23#define READLINE_LIBRARY
24
ccc6cda3
JA
25#if defined (HAVE_CONFIG_H)
26# include <config.h>
27#endif
28
726f6388
JA
29#include <sys/types.h>
30#include <stdio.h>
31
32#if defined (HAVE_UNISTD_H)
33# include <unistd.h>
34#endif
35
d166f048
JA
36#if defined (HAVE_STDLIB_H)
37# include <stdlib.h>
38#else
39# include "ansi_stdlib.h"
40#endif
41
726f6388 42#include "rldefs.h"
7117c2d2
JA
43#include "rlmbutil.h"
44
726f6388
JA
45#include "readline.h"
46#include "history.h"
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
95732b49
JA
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;
70static char *history_search_string;
71static int history_string_size;
72
f73dda09
JA
73static void make_history_line_current PARAMS((HIST_ENTRY *));
74static int noninc_search_from_pos PARAMS((char *, int, int));
95732b49
JA
75static int noninc_dosearch PARAMS((char *, int));
76static int noninc_search PARAMS((int, int));
f73dda09
JA
77static int rl_history_search_internal PARAMS((int, int));
78static void rl_history_search_reinit PARAMS((void));
79
95732b49
JA
80static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
81static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int));
82static void _rl_nsearch_abort PARAMS((_rl_search_cxt *));
83static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int));
84
bb70624e
JA
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
87 must set it. */
88static void
89make_history_line_current (entry)
90 HIST_ENTRY *entry;
91{
b80f6443
JA
92 _rl_replace_text (entry->line, 0, rl_end);
93 _rl_fix_point (1);
95732b49
JA
94#if defined (VI_MODE)
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 ();
b80f6443 101#endif
bb70624e 102
28ef6c31
JA
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;
bb70624e
JA
106}
107
726f6388
JA
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. */
113static int
114noninc_search_from_pos (string, pos, dir)
115 char *string;
116 int pos, dir;
117{
118 int ret, old;
119
28ef6c31
JA
120 if (pos < 0)
121 return -1;
122
726f6388 123 old = where_history ();
28ef6c31
JA
124 if (history_set_pos (pos) == 0)
125 return -1;
726f6388 126
28ef6c31 127 RL_SETSTATE(RL_STATE_SEARCH);
726f6388
JA
128 if (*string == '^')
129 ret = history_search_prefix (string + 1, dir);
130 else
131 ret = history_search (string, dir);
28ef6c31 132 RL_UNSETSTATE(RL_STATE_SEARCH);
726f6388
JA
133
134 if (ret != -1)
135 ret = where_history ();
136
137 history_set_pos (old);
138 return (ret);
139}
140
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
95732b49
JA
143 entries. Returns 1 if the search was successful, 0 otherwise. */
144static int
726f6388
JA
145noninc_dosearch (string, dir)
146 char *string;
147 int dir;
148{
bb70624e 149 int oldpos, pos;
726f6388
JA
150 HIST_ENTRY *entry;
151
152 if (string == 0 || *string == '\0' || noninc_history_pos < 0)
153 {
28ef6c31 154 rl_ding ();
95732b49 155 return 0;
726f6388
JA
156 }
157
158 pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
159 if (pos == -1)
160 {
161 /* Search failed, current history position unchanged. */
28ef6c31 162 rl_maybe_unsave_line ();
726f6388
JA
163 rl_clear_message ();
164 rl_point = 0;
28ef6c31 165 rl_ding ();
95732b49 166 return 0;
726f6388
JA
167 }
168
169 noninc_history_pos = pos;
170
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)
176#endif
95732b49 177 history_set_pos (oldpos);
726f6388 178
bb70624e 179 make_history_line_current (entry);
726f6388 180
726f6388 181 rl_point = 0;
7117c2d2
JA
182 rl_mark = rl_end;
183
726f6388 184 rl_clear_message ();
95732b49 185 return 1;
726f6388
JA
186}
187
95732b49
JA
188static _rl_search_cxt *
189_rl_nsearch_init (dir, pchar)
190 int dir, pchar;
726f6388 191{
95732b49 192 _rl_search_cxt *cxt;
726f6388 193 char *p;
95732b49
JA
194
195 cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
196 if (dir < 0)
197 cxt->sflags |= SF_REVERSE; /* not strictly needed */
198
199 cxt->direction = dir;
200 cxt->history_pos = cxt->save_line;
726f6388 201
28ef6c31 202 rl_maybe_save_line ();
726f6388 203
b80f6443
JA
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. */
207 rl_undo_list = 0;
208
726f6388
JA
209 /* Use the line buffer to read the search string. */
210 rl_line_buffer[0] = 0;
211 rl_end = rl_point = 0;
212
ccc6cda3 213 p = _rl_make_prompt_for_search (pchar ? pchar : ':');
0628567a 214 rl_message ("%s", p, 0);
726f6388
JA
215 free (p);
216
28ef6c31 217 RL_SETSTATE(RL_STATE_NSEARCH);
95732b49
JA
218
219 _rl_nscxt = cxt;
220
221 return cxt;
222}
223
224static int
225_rl_nsearch_cleanup (cxt, r)
226 _rl_search_cxt *cxt;
227 int r;
228{
229 _rl_scxt_dispose (cxt, 0);
230 _rl_nscxt = 0;
231
232 RL_UNSETSTATE(RL_STATE_NSEARCH);
233
234 return (r != 1);
235}
236
237static void
238_rl_nsearch_abort (cxt)
239 _rl_search_cxt *cxt;
240{
241 rl_maybe_unsave_line ();
242 rl_clear_message ();
243 rl_point = cxt->save_point;
244 rl_mark = cxt->save_mark;
245 rl_restore_prompt ();
246
247 RL_UNSETSTATE (RL_STATE_NSEARCH);
248}
249
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. */
253static int
254_rl_nsearch_dispatch (cxt, c)
255 _rl_search_cxt *cxt;
256 int c;
257{
258 switch (c)
726f6388 259 {
95732b49
JA
260 case CTRL('W'):
261 rl_unix_word_rubout (1, c);
262 break;
28ef6c31 263
95732b49
JA
264 case CTRL('U'):
265 rl_unix_line_discard (1, c);
266 break;
7117c2d2 267
95732b49
JA
268 case RETURN:
269 case NEWLINE:
270 return 0;
28ef6c31 271
95732b49
JA
272 case CTRL('H'):
273 case RUBOUT:
274 if (rl_point == 0)
726f6388 275 {
95732b49
JA
276 _rl_nsearch_abort (cxt);
277 return -1;
278 }
279 _rl_rubout_char (1, c);
280 break;
726f6388 281
95732b49
JA
282 case CTRL('C'):
283 case CTRL('G'):
284 rl_ding ();
285 _rl_nsearch_abort (cxt);
286 return -1;
287
288 default:
7117c2d2 289#if defined (HANDLE_MULTIBYTE)
95732b49
JA
290 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
291 rl_insert_text (cxt->mb);
292 else
7117c2d2 293#endif
95732b49
JA
294 _rl_insert_char (1, c);
295 break;
726f6388
JA
296 }
297
95732b49
JA
298 (*rl_redisplay_function) ();
299 return 1;
300}
301
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,
305 0 otherwise. */
306static int
307_rl_nsearch_dosearch (cxt)
308 _rl_search_cxt *cxt;
309{
310 rl_mark = cxt->save_mark;
7117c2d2 311
726f6388
JA
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
314 string, punt. */
315 if (rl_point == 0)
316 {
95732b49 317 if (noninc_search_string == 0)
726f6388 318 {
28ef6c31 319 rl_ding ();
95732b49
JA
320 rl_restore_prompt ();
321 RL_UNSETSTATE (RL_STATE_NSEARCH);
322 return -1;
726f6388
JA
323 }
324 }
325 else
326 {
327 /* We want to start the search from the current history position. */
95732b49 328 noninc_history_pos = cxt->save_line;
bb70624e 329 FREE (noninc_search_string);
726f6388 330 noninc_search_string = savestring (rl_line_buffer);
95732b49
JA
331
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 ();
726f6388
JA
338 }
339
b72432fd 340 rl_restore_prompt ();
95732b49
JA
341 return (noninc_dosearch (noninc_search_string, cxt->direction));
342}
343
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 `:'. */
349static int
350noninc_search (dir, pchar)
351 int dir;
352 int pchar;
353{
354 _rl_search_cxt *cxt;
355 int c, r;
356
357 cxt = _rl_nsearch_init (dir, pchar);
358
359 if (RL_ISSTATE (RL_STATE_CALLBACK))
360 return (0);
361
362 /* Read the search string. */
363 r = 0;
364 while (1)
365 {
366 c = _rl_search_getchar (cxt);
367
368 if (c == 0)
369 break;
370
371 r = _rl_nsearch_dispatch (cxt, c);
372 if (r < 0)
373 return 1;
374 else if (r == 0)
375 break;
376 }
377
378 r = _rl_nsearch_dosearch (cxt);
379 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
726f6388
JA
380}
381
382/* Search forward through the history list for a string. If the vi-mode
383 code calls this, KEY will be `?'. */
ccc6cda3 384int
726f6388
JA
385rl_noninc_forward_search (count, key)
386 int count, key;
387{
95732b49 388 return noninc_search (1, (key == '?') ? '?' : 0);
726f6388
JA
389}
390
391/* Reverse search the history list for a string. If the vi-mode code
392 calls this, KEY will be `/'. */
ccc6cda3 393int
726f6388
JA
394rl_noninc_reverse_search (count, key)
395 int count, key;
396{
95732b49 397 return noninc_search (-1, (key == '/') ? '/' : 0);
726f6388
JA
398}
399
400/* Search forward through the history list for the last string searched
401 for. If there is no saved search string, abort. */
ccc6cda3 402int
726f6388
JA
403rl_noninc_forward_search_again (count, key)
404 int count, key;
405{
95732b49
JA
406 int r;
407
726f6388
JA
408 if (!noninc_search_string)
409 {
28ef6c31 410 rl_ding ();
726f6388
JA
411 return (-1);
412 }
95732b49
JA
413 r = noninc_dosearch (noninc_search_string, 1);
414 return (r != 1);
726f6388
JA
415}
416
417/* Reverse search in the history list for the last string searched
418 for. If there is no saved search string, abort. */
ccc6cda3 419int
726f6388
JA
420rl_noninc_reverse_search_again (count, key)
421 int count, key;
422{
95732b49
JA
423 int r;
424
726f6388
JA
425 if (!noninc_search_string)
426 {
28ef6c31 427 rl_ding ();
726f6388
JA
428 return (-1);
429 }
95732b49
JA
430 r = noninc_dosearch (noninc_search_string, -1);
431 return (r != 1);
726f6388
JA
432}
433
95732b49
JA
434#if defined (READLINE_CALLBACKS)
435int
436_rl_nsearch_callback (cxt)
437 _rl_search_cxt *cxt;
438{
439 int c, r;
440
441 c = _rl_search_getchar (cxt);
442 r = _rl_nsearch_dispatch (cxt, c);
443 if (r != 0)
444 return 1;
445
446 r = _rl_nsearch_dosearch (cxt);
447 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
448}
449#endif
450
726f6388 451static int
bb70624e
JA
452rl_history_search_internal (count, dir)
453 int count, dir;
726f6388 454{
bb70624e
JA
455 HIST_ENTRY *temp;
456 int ret, oldpos;
726f6388 457
28ef6c31 458 rl_maybe_save_line ();
bb70624e 459 temp = (HIST_ENTRY *)NULL;
726f6388 460
bb70624e
JA
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. */
726f6388
JA
464 while (count)
465 {
bb70624e
JA
466 ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
467 if (ret == -1)
468 break;
469
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);
476
477 /* Don't find multiple instances of the same line. */
478 if (prev_line_found && STREQ (prev_line_found, temp->line))
479 continue;
480 prev_line_found = temp->line;
481 count--;
726f6388
JA
482 }
483
bb70624e 484 /* If we didn't find anything at all, return. */
ccc6cda3 485 if (temp == 0)
726f6388 486 {
28ef6c31
JA
487 rl_maybe_unsave_line ();
488 rl_ding ();
bb70624e
JA
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
491 #if 1 */
492#if 0
493 if (rl_point > rl_history_search_len)
494 {
495 rl_point = rl_end = rl_history_search_len;
496 rl_line_buffer[rl_end] = '\0';
7117c2d2 497 rl_mark = 0;
bb70624e
JA
498 }
499#else
28ef6c31 500 rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
7117c2d2 501 rl_mark = rl_end;
bb70624e
JA
502#endif
503 return 1;
726f6388
JA
504 }
505
bb70624e
JA
506 /* Copy the line we found into the current line buffer. */
507 make_history_line_current (temp);
508
509 rl_point = rl_history_search_len;
7117c2d2
JA
510 rl_mark = rl_end;
511
726f6388
JA
512 return 0;
513}
514
bb70624e
JA
515static void
516rl_history_search_reinit ()
517{
518 rl_history_search_pos = where_history ();
519 rl_history_search_len = rl_point;
520 prev_line_found = (char *)NULL;
521 if (rl_point)
522 {
523 if (rl_history_search_len >= history_string_size - 2)
524 {
525 history_string_size = rl_history_search_len + 2;
f73dda09 526 history_search_string = (char *)xrealloc (history_search_string, history_string_size);
bb70624e
JA
527 }
528 history_search_string[0] = '^';
529 strncpy (history_search_string + 1, rl_line_buffer, rl_point);
530 history_search_string[rl_point + 1] = '\0';
531 }
28ef6c31 532 _rl_free_saved_history_line ();
bb70624e
JA
533}
534
726f6388
JA
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
537 search. */
538int
539rl_history_search_forward (count, ignore)
540 int count, ignore;
541{
542 if (count == 0)
543 return (0);
bb70624e
JA
544
545 if (rl_last_func != rl_history_search_forward &&
546 rl_last_func != rl_history_search_backward)
547 rl_history_search_reinit ();
548
549 if (rl_history_search_len == 0)
550 return (rl_get_next_history (count, ignore));
726f6388
JA
551 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
552}
553
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
556 search. */
557int
558rl_history_search_backward (count, ignore)
559 int count, ignore;
560{
561 if (count == 0)
562 return (0);
bb70624e
JA
563
564 if (rl_last_func != rl_history_search_forward &&
565 rl_last_func != rl_history_search_backward)
566 rl_history_search_reinit ();
567
568 if (rl_history_search_len == 0)
569 return (rl_get_previous_history (count, ignore));
726f6388
JA
570 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
571}