OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [readline/] [vi_mode.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* vi_mode.c -- A vi emulation mode for Bash.
2
   Derived from code written by Jeff Sparkes (jsparkes@bnr.ca).  */
3
 
4
/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
5
 
6
   This file is part of the GNU Readline Library, a library for
7
   reading lines of text with interactive input and history editing.
8
 
9
   The GNU Readline Library is free software; you can redistribute it
10
   and/or modify it under the terms of the GNU General Public License
11
   as published by the Free Software Foundation; either version 2, or
12
   (at your option) any later version.
13
 
14
   The GNU Readline Library is distributed in the hope that it will be
15
   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16
   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU 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,
22
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23
#define READLINE_LIBRARY
24
 
25
/* **************************************************************** */
26
/*                                                                  */
27
/*                      VI Emulation Mode                           */
28
/*                                                                  */
29
/* **************************************************************** */
30
#include "rlconf.h"
31
 
32
#if defined (VI_MODE)
33
 
34
#if defined (HAVE_CONFIG_H)
35
#  include <config.h>
36
#endif
37
 
38
#include <sys/types.h>
39
 
40
#if defined (HAVE_STDLIB_H)
41
#  include <stdlib.h>
42
#else
43
#  include "ansi_stdlib.h"
44
#endif /* HAVE_STDLIB_H */
45
 
46
#if defined (HAVE_UNISTD_H)
47
#  include <unistd.h>
48
#endif
49
 
50
#include <stdio.h>
51
 
52
/* Some standard library routines. */
53
#include "rldefs.h"
54
#include "readline.h"
55
#include "history.h"
56
 
57
#include "rlprivate.h"
58
#include "xmalloc.h"
59
 
60
#ifndef _rl_digit_p
61
#define _rl_digit_p(c)  ((c) >= '0' && (c) <= '9')
62
#endif
63
 
64
#ifndef _rl_digit_value
65
#define _rl_digit_value(c) ((c) - '0')
66
#endif
67
 
68
#ifndef member
69
#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
70
#endif
71
 
72
#ifndef isident
73
#define isident(c) ((_rl_pure_alphabetic (c) || _rl_digit_p (c) || c == '_'))
74
#endif
75
 
76
#ifndef exchange
77
#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0)
78
#endif
79
 
80
/* Non-zero means enter insertion mode. */
81
static int _rl_vi_doing_insert;
82
 
83
/* Command keys which do movement for xxx_to commands. */
84
static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
85
 
86
/* Keymap used for vi replace characters.  Created dynamically since
87
   rarely used. */
88
static Keymap vi_replace_map;
89
 
90
/* The number of characters inserted in the last replace operation. */
91
static int vi_replace_count;
92
 
93
/* If non-zero, we have text inserted after a c[motion] command that put
94
   us implicitly into insert mode.  Some people want this text to be
95
   attached to the command so that it is `redoable' with `.'. */
96
static int vi_continued_command;
97
static char *vi_insert_buffer;
98
static int vi_insert_buffer_size;
99
 
100
static int _rl_vi_last_command = 'i';   /* default `.' puts you in insert mode */
101
static int _rl_vi_last_repeat = 1;
102
static int _rl_vi_last_arg_sign = 1;
103
static int _rl_vi_last_motion;
104
static int _rl_vi_last_search_char;
105
static int _rl_vi_last_replacement;
106
 
107
static int _rl_vi_last_key_before_insert;
108
 
109
static int vi_redoing;
110
 
111
/* Text modification commands.  These are the `redoable' commands. */
112
static char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
113
 
114
/* Arrays for the saved marks. */
115
static int vi_mark_chars[27];
116
 
117
static int rl_digit_loop1 __P((void));
118
 
119
void
120
_rl_vi_initialize_line ()
121
{
122
  register int i;
123
 
124
  for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
125
    vi_mark_chars[i] = -1;
126
}
127
 
128
void
129
_rl_vi_reset_last ()
130
{
131
  _rl_vi_last_command = 'i';
132
  _rl_vi_last_repeat = 1;
133
  _rl_vi_last_arg_sign = 1;
134
  _rl_vi_last_motion = 0;
135
}
136
 
137
void
138
_rl_vi_set_last (key, repeat, sign)
139
     int key, repeat, sign;
140
{
141
  _rl_vi_last_command = key;
142
  _rl_vi_last_repeat = repeat;
143
  _rl_vi_last_arg_sign = sign;
144
}
145
 
146
/* Is the command C a VI mode text modification command? */
147
int
148
_rl_vi_textmod_command (c)
149
     int c;
150
{
151
  return (member (c, vi_textmod));
152
}
153
 
154
static void
155
_rl_vi_stuff_insert (count)
156
     int count;
157
{
158
  rl_begin_undo_group ();
159
  while (count--)
160
    rl_insert_text (vi_insert_buffer);
161
  rl_end_undo_group ();
162
}
163
 
164
/* Bound to `.'.  Called from command mode, so we know that we have to
165
   redo a text modification command.  The default for _rl_vi_last_command
166
   puts you back into insert mode. */
167
int
168
rl_vi_redo (count, c)
169
     int count, c;
170
{
171
  if (!rl_explicit_arg)
172
    {
173
      rl_numeric_arg = _rl_vi_last_repeat;
174
      rl_arg_sign = _rl_vi_last_arg_sign;
175
    }
176
 
177
  vi_redoing = 1;
178
  /* If we're redoing an insert with `i', stuff in the inserted text
179
     and do not go into insertion mode. */
180
  if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
181
    {
182
      _rl_vi_stuff_insert (count);
183
      /* And back up point over the last character inserted. */
184
      if (rl_point > 0)
185
        rl_point--;
186
    }
187
  else
188
    _rl_dispatch (_rl_vi_last_command, _rl_keymap);
189
  vi_redoing = 0;
190
 
191
  return (0);
192
}
193
 
194
/* A placeholder for further expansion. */
195
int
196
rl_vi_undo (count, key)
197
     int count, key;
198
{
199
  return (rl_undo_command (count, key));
200
}
201
 
202
/* Yank the nth arg from the previous line into this line at point. */
203
int
204
rl_vi_yank_arg (count, key)
205
     int count, key;
206
{
207
  /* Readline thinks that the first word on a line is the 0th, while vi
208
     thinks the first word on a line is the 1st.  Compensate. */
209
  if (rl_explicit_arg)
210
    rl_yank_nth_arg (count - 1, 0);
211
  else
212
    rl_yank_nth_arg ('$', 0);
213
 
214
  return (0);
215
}
216
 
217
/* With an argument, move back that many history lines, else move to the
218
   beginning of history. */
219
int
220
rl_vi_fetch_history (count, c)
221
     int count, c;
222
{
223
  int wanted;
224
 
225
  /* Giving an argument of n means we want the nth command in the history
226
     file.  The command number is interpreted the same way that the bash
227
     `history' command does it -- that is, giving an argument count of 450
228
     to this command would get the command listed as number 450 in the
229
     output of `history'. */
230
  if (rl_explicit_arg)
231
    {
232
      wanted = history_base + where_history () - count;
233
      if (wanted <= 0)
234
        rl_beginning_of_history (0, 0);
235
      else
236
        rl_get_previous_history (wanted, c);
237
    }
238
  else
239
    rl_beginning_of_history (count, 0);
240
  return (0);
241
}
242
 
243
/* Search again for the last thing searched for. */
244
int
245
rl_vi_search_again (count, key)
246
     int count, key;
247
{
248
  switch (key)
249
    {
250
    case 'n':
251
      rl_noninc_reverse_search_again (count, key);
252
      break;
253
 
254
    case 'N':
255
      rl_noninc_forward_search_again (count, key);
256
      break;
257
    }
258
  return (0);
259
}
260
 
261
/* Do a vi style search. */
262
int
263
rl_vi_search (count, key)
264
     int count, key;
265
{
266
  switch (key)
267
    {
268
    case '?':
269
      rl_noninc_forward_search (count, key);
270
      break;
271
 
272
    case '/':
273
      rl_noninc_reverse_search (count, key);
274
      break;
275
 
276
    default:
277
      ding ();
278
      break;
279
    }
280
  return (0);
281
}
282
 
283
/* Completion, from vi's point of view. */
284
int
285
rl_vi_complete (ignore, key)
286
     int ignore, key;
287
{
288
  if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
289
    {
290
      if (!whitespace (rl_line_buffer[rl_point + 1]))
291
        rl_vi_end_word (1, 'E');
292
      rl_point++;
293
    }
294
 
295
  if (key == '*')
296
    rl_complete_internal ('*'); /* Expansion and replacement. */
297
  else if (key == '=')
298
    rl_complete_internal ('?'); /* List possible completions. */
299
  else if (key == '\\')
300
    rl_complete_internal (TAB); /* Standard Readline completion. */
301
  else
302
    rl_complete (0, key);
303
 
304
  if (key == '*' || key == '\\')
305
    {
306
      _rl_vi_set_last (key, 1, rl_arg_sign);
307
      rl_vi_insertion_mode (1, key);
308
    }
309
  return (0);
310
}
311
 
312
/* Tilde expansion for vi mode. */
313
int
314
rl_vi_tilde_expand (ignore, key)
315
     int ignore, key;
316
{
317
  rl_tilde_expand (0, key);
318
  _rl_vi_set_last (key, 1, rl_arg_sign);        /* XXX */
319
  rl_vi_insertion_mode (1, key);
320
  return (0);
321
}
322
 
323
/* Previous word in vi mode. */
324
int
325
rl_vi_prev_word (count, key)
326
     int count, key;
327
{
328
  if (count < 0)
329
    return (rl_vi_next_word (-count, key));
330
 
331
  if (rl_point == 0)
332
    {
333
      ding ();
334
      return (0);
335
    }
336
 
337
  if (_rl_uppercase_p (key))
338
    rl_vi_bWord (count, key);
339
  else
340
    rl_vi_bword (count, key);
341
 
342
  return (0);
343
}
344
 
345
/* Next word in vi mode. */
346
int
347
rl_vi_next_word (count, key)
348
     int count, key;
349
{
350
  if (count < 0)
351
    return (rl_vi_prev_word (-count, key));
352
 
353
  if (rl_point >= (rl_end - 1))
354
    {
355
      ding ();
356
      return (0);
357
    }
358
 
359
  if (_rl_uppercase_p (key))
360
    rl_vi_fWord (count, key);
361
  else
362
    rl_vi_fword (count, key);
363
  return (0);
364
}
365
 
366
/* Move to the end of the ?next? word. */
367
int
368
rl_vi_end_word (count, key)
369
     int count, key;
370
{
371
  if (count < 0)
372
    {
373
      ding ();
374
      return -1;
375
    }
376
 
377
  if (_rl_uppercase_p (key))
378
    rl_vi_eWord (count, key);
379
  else
380
    rl_vi_eword (count, key);
381
  return (0);
382
}
383
 
384
/* Move forward a word the way that 'W' does. */
385
int
386
rl_vi_fWord (count, ignore)
387
     int count, ignore;
388
{
389
  while (count-- && rl_point < (rl_end - 1))
390
    {
391
      /* Skip until whitespace. */
392
      while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
393
        rl_point++;
394
 
395
      /* Now skip whitespace. */
396
      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
397
        rl_point++;
398
    }
399
  return (0);
400
}
401
 
402
int
403
rl_vi_bWord (count, ignore)
404
     int count, ignore;
405
{
406
  while (count-- && rl_point > 0)
407
    {
408
      /* If we are at the start of a word, move back to whitespace so
409
         we will go back to the start of the previous word. */
410
      if (!whitespace (rl_line_buffer[rl_point]) &&
411
          whitespace (rl_line_buffer[rl_point - 1]))
412
        rl_point--;
413
 
414
      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
415
        rl_point--;
416
 
417
      if (rl_point > 0)
418
        {
419
          while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
420
          rl_point++;
421
        }
422
    }
423
  return (0);
424
}
425
 
426
int
427
rl_vi_eWord (count, ignore)
428
     int count, ignore;
429
{
430
  while (count-- && rl_point < (rl_end - 1))
431
    {
432
      if (!whitespace (rl_line_buffer[rl_point]))
433
        rl_point++;
434
 
435
      /* Move to the next non-whitespace character (to the start of the
436
         next word). */
437
      while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
438
 
439
      if (rl_point && rl_point < rl_end)
440
        {
441
          /* Skip whitespace. */
442
          while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
443
            rl_point++;
444
 
445
          /* Skip until whitespace. */
446
          while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
447
            rl_point++;
448
 
449
          /* Move back to the last character of the word. */
450
          rl_point--;
451
        }
452
    }
453
  return (0);
454
}
455
 
456
int
457
rl_vi_fword (count, ignore)
458
     int count, ignore;
459
{
460
  while (count-- && rl_point < (rl_end - 1))
461
    {
462
      /* Move to white space (really non-identifer). */
463
      if (isident (rl_line_buffer[rl_point]))
464
        {
465
          while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
466
            rl_point++;
467
        }
468
      else /* if (!whitespace (rl_line_buffer[rl_point])) */
469
        {
470
          while (!isident (rl_line_buffer[rl_point]) &&
471
                 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
472
            rl_point++;
473
        }
474
 
475
      /* Move past whitespace. */
476
      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
477
        rl_point++;
478
    }
479
  return (0);
480
}
481
 
482
int
483
rl_vi_bword (count, ignore)
484
     int count, ignore;
485
{
486
  while (count-- && rl_point > 0)
487
    {
488
      int last_is_ident;
489
 
490
      /* If we are at the start of a word, move back to whitespace
491
         so we will go back to the start of the previous word. */
492
      if (!whitespace (rl_line_buffer[rl_point]) &&
493
          whitespace (rl_line_buffer[rl_point - 1]))
494
        rl_point--;
495
 
496
      /* If this character and the previous character are `opposite', move
497
         back so we don't get messed up by the rl_point++ down there in
498
         the while loop.  Without this code, words like `l;' screw up the
499
         function. */
500
      last_is_ident = isident (rl_line_buffer[rl_point - 1]);
501
      if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
502
          (!isident (rl_line_buffer[rl_point]) && last_is_ident))
503
        rl_point--;
504
 
505
      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
506
        rl_point--;
507
 
508
      if (rl_point > 0)
509
        {
510
          if (isident (rl_line_buffer[rl_point]))
511
            while (--rl_point >= 0 && isident (rl_line_buffer[rl_point]));
512
          else
513
            while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) &&
514
                   !whitespace (rl_line_buffer[rl_point]));
515
          rl_point++;
516
        }
517
    }
518
  return (0);
519
}
520
 
521
int
522
rl_vi_eword (count, ignore)
523
     int count, ignore;
524
{
525
  while (count-- && rl_point < rl_end - 1)
526
    {
527
      if (!whitespace (rl_line_buffer[rl_point]))
528
        rl_point++;
529
 
530
      while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
531
        rl_point++;
532
 
533
      if (rl_point < rl_end)
534
        {
535
          if (isident (rl_line_buffer[rl_point]))
536
            while (++rl_point < rl_end && isident (rl_line_buffer[rl_point]));
537
          else
538
            while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point])
539
                   && !whitespace (rl_line_buffer[rl_point]));
540
        }
541
      rl_point--;
542
    }
543
  return (0);
544
}
545
 
546
int
547
rl_vi_insert_beg (count, key)
548
     int count, key;
549
{
550
  rl_beg_of_line (1, key);
551
  rl_vi_insertion_mode (1, key);
552
  return (0);
553
}
554
 
555
int
556
rl_vi_append_mode (count, key)
557
     int count, key;
558
{
559
  if (rl_point < rl_end)
560
    rl_point++;
561
  rl_vi_insertion_mode (1, key);
562
  return (0);
563
}
564
 
565
int
566
rl_vi_append_eol (count, key)
567
     int count, key;
568
{
569
  rl_end_of_line (1, key);
570
  rl_vi_append_mode (1, key);
571
  return (0);
572
}
573
 
574
/* What to do in the case of C-d. */
575
int
576
rl_vi_eof_maybe (count, c)
577
     int count, c;
578
{
579
  return (rl_newline (1, '\n'));
580
}
581
 
582
/* Insertion mode stuff. */
583
 
584
/* Switching from one mode to the other really just involves
585
   switching keymaps. */
586
int
587
rl_vi_insertion_mode (count, key)
588
     int count, key;
589
{
590
  _rl_keymap = vi_insertion_keymap;
591
  _rl_vi_last_key_before_insert = key;
592
  return (0);
593
}
594
 
595
static void
596
_rl_vi_save_insert (up)
597
      UNDO_LIST *up;
598
{
599
  int len, start, end;
600
 
601
  if (up == 0)
602
    {
603
      if (vi_insert_buffer_size >= 1)
604
        vi_insert_buffer[0] = '\0';
605
      return;
606
    }
607
 
608
  start = up->start;
609
  end = up->end;
610
  len = end - start + 1;
611
  if (len >= vi_insert_buffer_size)
612
    {
613
      vi_insert_buffer_size += (len + 32) - (len % 32);
614
      vi_insert_buffer = xrealloc (vi_insert_buffer, vi_insert_buffer_size);
615
    }
616
  strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
617
  vi_insert_buffer[len-1] = '\0';
618
}
619
 
620
void
621
_rl_vi_done_inserting ()
622
{
623
  if (_rl_vi_doing_insert)
624
    {
625
      rl_end_undo_group ();
626
      /* Now, the text between rl_undo_list->next->start and
627
         rl_undo_list->next->end is what was inserted while in insert
628
         mode.  It gets copied to VI_INSERT_BUFFER because it depends
629
         on absolute indices into the line which may change (though they
630
         probably will not). */
631
      _rl_vi_doing_insert = 0;
632
      _rl_vi_save_insert (rl_undo_list->next);
633
      vi_continued_command = 1;
634
    }
635
  else
636
    {
637
      if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list)
638
        _rl_vi_save_insert (rl_undo_list);
639
      /* XXX - Other keys probably need to be checked. */
640
      else if (_rl_vi_last_key_before_insert == 'C')
641
        rl_end_undo_group ();
642
      while (_rl_undo_group_level > 0)
643
        rl_end_undo_group ();
644
      vi_continued_command = 0;
645
    }
646
}
647
 
648
int
649
rl_vi_movement_mode (count, key)
650
     int count, key;
651
{
652
  if (rl_point > 0)
653
    rl_backward (1, key);
654
 
655
  _rl_keymap = vi_movement_keymap;
656
  _rl_vi_done_inserting ();
657
  return (0);
658
}
659
 
660
int
661
rl_vi_arg_digit (count, c)
662
     int count, c;
663
{
664
  if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
665
    return (rl_beg_of_line (1, c));
666
  else
667
    return (rl_digit_argument (count, c));
668
}
669
 
670
int
671
rl_vi_change_case (count, ignore)
672
     int count, ignore;
673
{
674
  char c = 0;
675
 
676
  /* Don't try this on an empty line. */
677
  if (rl_point >= rl_end)
678
    return (0);
679
 
680
  while (count-- && rl_point < rl_end)
681
    {
682
      if (_rl_uppercase_p (rl_line_buffer[rl_point]))
683
        c = _rl_to_lower (rl_line_buffer[rl_point]);
684
      else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
685
        c = _rl_to_upper (rl_line_buffer[rl_point]);
686
      else
687
        {
688
          /* Just skip over characters neither upper nor lower case. */
689
          rl_forward (1, c);
690
          continue;
691
        }
692
 
693
      /* Vi is kind of strange here. */
694
      if (c)
695
        {
696
          rl_begin_undo_group ();
697
          rl_delete (1, c);
698
          rl_insert (1, c);
699
          rl_end_undo_group ();
700
          rl_vi_check ();
701
        }
702
      else
703
        rl_forward (1, c);
704
    }
705
  return (0);
706
}
707
 
708
int
709
rl_vi_put (count, key)
710
     int count, key;
711
{
712
  if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
713
    rl_point++;
714
 
715
  rl_yank (1, key);
716
  rl_backward (1, key);
717
  return (0);
718
}
719
 
720
int
721
rl_vi_check ()
722
{
723
  if (rl_point && rl_point == rl_end)
724
    rl_point--;
725
  return (0);
726
}
727
 
728
int
729
rl_vi_column (count, key)
730
     int count, key;
731
{
732
  if (count > rl_end)
733
    rl_end_of_line (1, key);
734
  else
735
    rl_point = count - 1;
736
  return (0);
737
}
738
 
739
int
740
rl_vi_domove (key, nextkey)
741
     int key, *nextkey;
742
{
743
  int c, save;
744
  int old_end;
745
 
746
  rl_mark = rl_point;
747
  c = rl_read_key ();
748
  *nextkey = c;
749
 
750
  if (!member (c, vi_motion))
751
    {
752
      if (_rl_digit_p (c))
753
        {
754
          save = rl_numeric_arg;
755
          rl_numeric_arg = _rl_digit_value (c);
756
          rl_digit_loop1 ();
757
          rl_numeric_arg *= save;
758
          c = rl_read_key ();   /* real command */
759
          *nextkey = c;
760
        }
761
      else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
762
        {
763
          rl_mark = rl_end;
764
          rl_beg_of_line (1, c);
765
          _rl_vi_last_motion = c;
766
          return (0);
767
        }
768
      else
769
        return (-1);
770
    }
771
 
772
  _rl_vi_last_motion = c;
773
 
774
  /* Append a blank character temporarily so that the motion routines
775
     work right at the end of the line. */
776
  old_end = rl_end;
777
  rl_line_buffer[rl_end++] = ' ';
778
  rl_line_buffer[rl_end] = '\0';
779
 
780
  _rl_dispatch (c, _rl_keymap);
781
 
782
  /* Remove the blank that we added. */
783
  rl_end = old_end;
784
  rl_line_buffer[rl_end] = '\0';
785
  if (rl_point > rl_end)
786
    rl_point = rl_end;
787
 
788
  /* No change in position means the command failed. */
789
  if (rl_mark == rl_point)
790
    return (-1);
791
 
792
  /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
793
     word.  If we are not at the end of the line, and we are on a
794
     non-whitespace character, move back one (presumably to whitespace). */
795
  if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
796
      !whitespace (rl_line_buffer[rl_point]))
797
    rl_point--;
798
 
799
  /* If cw or cW, back up to the end of a word, so the behaviour of ce
800
     or cE is the actual result.  Brute-force, no subtlety. */
801
  if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
802
    {
803
      /* Don't move farther back than where we started. */
804
      while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
805
        rl_point--;
806
 
807
      /* Posix.2 says that if cw or cW moves the cursor towards the end of
808
         the line, the character under the cursor should be deleted. */
809
      if (rl_point == rl_mark)
810
        rl_point++;
811
      else
812
        {
813
          /* Move past the end of the word so that the kill doesn't
814
             remove the last letter of the previous word.  Only do this
815
             if we are not at the end of the line. */
816
          if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
817
            rl_point++;
818
        }
819
    }
820
 
821
  if (rl_mark < rl_point)
822
    exchange (rl_point, rl_mark);
823
 
824
  return (0);
825
}
826
 
827
/* A simplified loop for vi. Don't dispatch key at end.
828
   Don't recognize minus sign? */
829
static int
830
rl_digit_loop1 ()
831
{
832
  int key, c;
833
 
834
  while (1)
835
    {
836
      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0);
837
      key = c = rl_read_key ();
838
 
839
      if (_rl_keymap[c].type == ISFUNC &&
840
          _rl_keymap[c].function == rl_universal_argument)
841
        {
842
          rl_numeric_arg *= 4;
843
          continue;
844
        }
845
 
846
      c = UNMETA (c);
847
      if (_rl_digit_p (c))
848
        {
849
          if (rl_explicit_arg)
850
            rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
851
          else
852
            rl_numeric_arg = _rl_digit_value (c);
853
          rl_explicit_arg = 1;
854
        }
855
      else
856
        {
857
          rl_clear_message ();
858
          rl_stuff_char (key);
859
          break;
860
        }
861
    }
862
  return (0);
863
}
864
 
865
int
866
rl_vi_delete_to (count, key)
867
     int count, key;
868
{
869
  int c;
870
 
871
  if (_rl_uppercase_p (key))
872
    rl_stuff_char ('$');
873
  else if (vi_redoing)
874
    rl_stuff_char (_rl_vi_last_motion);
875
 
876
  if (rl_vi_domove (key, &c))
877
    {
878
      ding ();
879
      return -1;
880
    }
881
 
882
  /* These are the motion commands that do not require adjusting the
883
     mark. */
884
  if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
885
    rl_mark++;
886
 
887
  rl_kill_text (rl_point, rl_mark);
888
  return (0);
889
}
890
 
891
int
892
rl_vi_change_to (count, key)
893
     int count, key;
894
{
895
  int c, start_pos;
896
 
897
  if (_rl_uppercase_p (key))
898
    rl_stuff_char ('$');
899
  else if (vi_redoing)
900
    rl_stuff_char (_rl_vi_last_motion);
901
 
902
  start_pos = rl_point;
903
 
904
  if (rl_vi_domove (key, &c))
905
    {
906
      ding ();
907
      return -1;
908
    }
909
 
910
  /* These are the motion commands that do not require adjusting the
911
     mark.  c[wW] are handled by special-case code in rl_vi_domove(),
912
     and already leave the mark at the correct location. */
913
  if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
914
    rl_mark++;
915
 
916
  /* The cursor never moves with c[wW]. */
917
  if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
918
    rl_point = start_pos;
919
 
920
  if (vi_redoing)
921
    {
922
      if (vi_insert_buffer && *vi_insert_buffer)
923
        rl_begin_undo_group ();
924
      rl_delete_text (rl_point, rl_mark);
925
      if (vi_insert_buffer && *vi_insert_buffer)
926
        {
927
          rl_insert_text (vi_insert_buffer);
928
          rl_end_undo_group ();
929
        }
930
    }
931
  else
932
    {
933
      rl_begin_undo_group ();           /* to make the `u' command work */
934
      rl_kill_text (rl_point, rl_mark);
935
      /* `C' does not save the text inserted for undoing or redoing. */
936
      if (_rl_uppercase_p (key) == 0)
937
        _rl_vi_doing_insert = 1;
938
      _rl_vi_set_last (key, count, rl_arg_sign);
939
      rl_vi_insertion_mode (1, key);
940
    }
941
 
942
  return (0);
943
}
944
 
945
int
946
rl_vi_yank_to (count, key)
947
     int count, key;
948
{
949
  int c, save = rl_point;
950
 
951
  if (_rl_uppercase_p (key))
952
    rl_stuff_char ('$');
953
 
954
  if (rl_vi_domove (key, &c))
955
    {
956
      ding ();
957
      return -1;
958
    }
959
 
960
  /* These are the motion commands that do not require adjusting the
961
     mark. */
962
  if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
963
    rl_mark++;
964
 
965
  rl_begin_undo_group ();
966
  rl_kill_text (rl_point, rl_mark);
967
  rl_end_undo_group ();
968
  rl_do_undo ();
969
  rl_point = save;
970
 
971
  return (0);
972
}
973
 
974
int
975
rl_vi_delete (count, key)
976
     int count, key;
977
{
978
  int end;
979
 
980
  if (rl_end == 0)
981
    {
982
      ding ();
983
      return -1;
984
    }
985
 
986
  end = rl_point + count;
987
 
988
  if (end >= rl_end)
989
    end = rl_end;
990
 
991
  rl_kill_text (rl_point, end);
992
 
993
  if (rl_point > 0 && rl_point == rl_end)
994
    rl_backward (1, key);
995
  return (0);
996
}
997
 
998
int
999
rl_vi_back_to_indent (count, key)
1000
     int count, key;
1001
{
1002
  rl_beg_of_line (1, key);
1003
  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1004
    rl_point++;
1005
  return (0);
1006
}
1007
 
1008
int
1009
rl_vi_first_print (count, key)
1010
     int count, key;
1011
{
1012
  return (rl_vi_back_to_indent (1, key));
1013
}
1014
 
1015
int
1016
rl_vi_char_search (count, key)
1017
     int count, key;
1018
{
1019
  static char target;
1020
  static int orig_dir, dir;
1021
 
1022
  if (key == ';' || key == ',')
1023
    dir = key == ';' ? orig_dir : -orig_dir;
1024
  else
1025
    {
1026
      if (vi_redoing)
1027
        target = _rl_vi_last_search_char;
1028
      else
1029
        _rl_vi_last_search_char = target = (*rl_getc_function) (rl_instream);
1030
 
1031
      switch (key)
1032
        {
1033
        case 't':
1034
          orig_dir = dir = FTO;
1035
          break;
1036
 
1037
        case 'T':
1038
          orig_dir = dir = BTO;
1039
          break;
1040
 
1041
        case 'f':
1042
          orig_dir = dir = FFIND;
1043
          break;
1044
 
1045
        case 'F':
1046
          orig_dir = dir = BFIND;
1047
          break;
1048
        }
1049
    }
1050
 
1051
  return (_rl_char_search_internal (count, dir, target));
1052
}
1053
 
1054
/* Match brackets */
1055
int
1056
rl_vi_match (ignore, key)
1057
     int ignore, key;
1058
{
1059
  int count = 1, brack, pos;
1060
 
1061
  pos = rl_point;
1062
  if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1063
    {
1064
      while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1065
             rl_point < rl_end - 1)
1066
        rl_forward (1, key);
1067
 
1068
      if (brack <= 0)
1069
        {
1070
          rl_point = pos;
1071
          ding ();
1072
          return -1;
1073
        }
1074
    }
1075
 
1076
  pos = rl_point;
1077
 
1078
  if (brack < 0)
1079
    {
1080
      while (count)
1081
        {
1082
          if (--pos >= 0)
1083
            {
1084
              int b = rl_vi_bracktype (rl_line_buffer[pos]);
1085
              if (b == -brack)
1086
                count--;
1087
              else if (b == brack)
1088
                count++;
1089
            }
1090
          else
1091
            {
1092
              ding ();
1093
              return -1;
1094
            }
1095
        }
1096
    }
1097
  else
1098
    {                   /* brack > 0 */
1099
      while (count)
1100
        {
1101
          if (++pos < rl_end)
1102
            {
1103
              int b = rl_vi_bracktype (rl_line_buffer[pos]);
1104
              if (b == -brack)
1105
                count--;
1106
              else if (b == brack)
1107
                count++;
1108
            }
1109
          else
1110
            {
1111
              ding ();
1112
              return -1;
1113
            }
1114
        }
1115
    }
1116
  rl_point = pos;
1117
  return (0);
1118
}
1119
 
1120
int
1121
rl_vi_bracktype (c)
1122
     int c;
1123
{
1124
  switch (c)
1125
    {
1126
    case '(': return  1;
1127
    case ')': return -1;
1128
    case '[': return  2;
1129
    case ']': return -2;
1130
    case '{': return  3;
1131
    case '}': return -3;
1132
    default:  return  0;
1133
    }
1134
}
1135
 
1136
int
1137
rl_vi_change_char (count, key)
1138
     int count, key;
1139
{
1140
  int c;
1141
 
1142
  if (vi_redoing)
1143
    c = _rl_vi_last_replacement;
1144
  else
1145
    _rl_vi_last_replacement = c = (*rl_getc_function) (rl_instream);
1146
 
1147
  if (c == '\033' || c == CTRL ('C'))
1148
    return -1;
1149
 
1150
  while (count-- && rl_point < rl_end)
1151
    {
1152
      rl_begin_undo_group ();
1153
 
1154
      rl_delete (1, c);
1155
      rl_insert (1, c);
1156
      if (count == 0)
1157
        rl_backward (1, c);
1158
 
1159
      rl_end_undo_group ();
1160
    }
1161
  return (0);
1162
}
1163
 
1164
int
1165
rl_vi_subst (count, key)
1166
     int count, key;
1167
{
1168
  rl_begin_undo_group ();
1169
 
1170
  if (_rl_uppercase_p (key))
1171
    {
1172
      rl_beg_of_line (1, key);
1173
      rl_kill_line (1, key);
1174
    }
1175
  else
1176
    rl_delete_text (rl_point, rl_point+count);
1177
 
1178
  rl_end_undo_group ();
1179
 
1180
  _rl_vi_set_last (key, count, rl_arg_sign);
1181
 
1182
  if (vi_redoing)
1183
    {
1184
      int o = _rl_doing_an_undo;
1185
 
1186
      _rl_doing_an_undo = 1;
1187
      if (vi_insert_buffer && *vi_insert_buffer)
1188
        rl_insert_text (vi_insert_buffer);
1189
      _rl_doing_an_undo = o;
1190
    }
1191
  else
1192
    {
1193
      rl_begin_undo_group ();
1194
      _rl_vi_doing_insert = 1;
1195
      rl_vi_insertion_mode (1, key);
1196
    }
1197
 
1198
  return (0);
1199
}
1200
 
1201
int
1202
rl_vi_overstrike (count, key)
1203
     int count, key;
1204
{
1205
  int i;
1206
 
1207
  if (_rl_vi_doing_insert == 0)
1208
    {
1209
      _rl_vi_doing_insert = 1;
1210
      rl_begin_undo_group ();
1211
    }
1212
 
1213
  for (i = 0; i < count; i++)
1214
    {
1215
      vi_replace_count++;
1216
      rl_begin_undo_group ();
1217
 
1218
      if (rl_point < rl_end)
1219
        {
1220
          rl_delete (1, key);
1221
          rl_insert (1, key);
1222
        }
1223
      else
1224
        rl_insert (1, key);
1225
 
1226
      rl_end_undo_group ();
1227
    }
1228
  return (0);
1229
}
1230
 
1231
int
1232
rl_vi_overstrike_delete (count, key)
1233
     int count, key;
1234
{
1235
  int i, s;
1236
 
1237
  for (i = 0; i < count; i++)
1238
    {
1239
      if (vi_replace_count == 0)
1240
        {
1241
          ding ();
1242
          break;
1243
        }
1244
      s = rl_point;
1245
 
1246
      if (rl_do_undo ())
1247
        vi_replace_count--;
1248
 
1249
      if (rl_point == s)
1250
        rl_backward (1, key);
1251
    }
1252
 
1253
  if (vi_replace_count == 0 && _rl_vi_doing_insert)
1254
    {
1255
      rl_end_undo_group ();
1256
      rl_do_undo ();
1257
      _rl_vi_doing_insert = 0;
1258
    }
1259
  return (0);
1260
}
1261
 
1262
int
1263
rl_vi_replace (count, key)
1264
     int count, key;
1265
{
1266
  int i;
1267
 
1268
  vi_replace_count = 0;
1269
 
1270
  if (!vi_replace_map)
1271
    {
1272
      vi_replace_map = rl_make_bare_keymap ();
1273
 
1274
      for (i = ' '; i < KEYMAP_SIZE; i++)
1275
        vi_replace_map[i].function = rl_vi_overstrike;
1276
 
1277
      vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1278
      vi_replace_map[ESC].function = rl_vi_movement_mode;
1279
      vi_replace_map[RETURN].function = rl_newline;
1280
      vi_replace_map[NEWLINE].function = rl_newline;
1281
 
1282
      /* If the normal vi insertion keymap has ^H bound to erase, do the
1283
         same here.  Probably should remove the assignment to RUBOUT up
1284
         there, but I don't think it will make a difference in real life. */
1285
      if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1286
          vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1287
        vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1288
 
1289
    }
1290
  _rl_keymap = vi_replace_map;
1291
  return (0);
1292
}
1293
 
1294
#if 0
1295
/* Try to complete the word we are standing on or the word that ends with
1296
   the previous character.  A space matches everything.  Word delimiters are
1297
   space and ;. */
1298
int
1299
rl_vi_possible_completions()
1300
{
1301
  int save_pos = rl_point;
1302
 
1303
  if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1304
    {
1305
      while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1306
             rl_line_buffer[rl_point] != ';')
1307
        rl_point++;
1308
    }
1309
  else if (rl_line_buffer[rl_point - 1] == ';')
1310
    {
1311
      ding ();
1312
      return (0);
1313
    }
1314
 
1315
  rl_possible_completions ();
1316
  rl_point = save_pos;
1317
 
1318
  return (0);
1319
}
1320
#endif
1321
 
1322
/* Functions to save and restore marks. */
1323
int
1324
rl_vi_set_mark (count, key)
1325
     int count, key;
1326
{
1327
  int ch;
1328
 
1329
  ch = rl_read_key ();
1330
  if (_rl_lowercase_p (ch) == 0)
1331
    {
1332
      ding ();
1333
      return -1;
1334
    }
1335
  ch -= 'a';
1336
  vi_mark_chars[ch] = rl_point;
1337
  return 0;
1338
}
1339
 
1340
int
1341
rl_vi_goto_mark (count, key)
1342
     int count, key;
1343
{
1344
  int ch;
1345
 
1346
  ch = rl_read_key ();
1347
  if (ch == '`')
1348
    {
1349
      rl_point = rl_mark;
1350
      return 0;
1351
    }
1352
  else if (_rl_lowercase_p (ch) == 0)
1353
    {
1354
      ding ();
1355
      return -1;
1356
    }
1357
 
1358
  ch -= 'a';
1359
  if (vi_mark_chars[ch] == -1)
1360
    {
1361
      ding ();
1362
      return -1;
1363
    }
1364
  rl_point = vi_mark_chars[ch];
1365
  return 0;
1366
}
1367
 
1368
#endif /* VI_MODE */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.