diff options
author | Ron Yorston <rmy@pobox.com> | 2021-04-25 11:51:55 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-04-28 11:29:33 +0200 |
commit | 7a8ceb4eb25f1b136bf9a79b04d46dc4d7f440a7 (patch) | |
tree | bbc4bc69aa3e42f2750c4fe5b5a6a97f2b9eb419 | |
parent | 81f9a0035b857206ac03afb729be3c8438f218b9 (diff) | |
download | busybox-w32-7a8ceb4eb25f1b136bf9a79b04d46dc4d7f440a7.tar.gz busybox-w32-7a8ceb4eb25f1b136bf9a79b04d46dc4d7f440a7.tar.bz2 busybox-w32-7a8ceb4eb25f1b136bf9a79b04d46dc4d7f440a7.zip |
vi: changes to line addresses for colon commands
Make line addresses behave more like vi:
- Vi allows the user to enter an arbitrary number of addresses,
though only the last two are used. This simplifies get_address()
by reducing the amount of state that needs to be carried.
- When a command requires a single address the last one entered is
used.
- If addresses are separated by a ';' instead of a ',' the current
line is updated to the left address. This may be useful when a
search is used to specify a range, e.g. ':/first/;/last/d'.
- When the last address is empty it should refer to the current line.
function old new delta
colon 3855 3834 -21
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-21) Total: -21 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 110 |
1 files changed, 60 insertions, 50 deletions
diff --git a/editors/vi.c b/editors/vi.c index caf01acd3..77c42641e 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -2473,37 +2473,43 @@ static char *get_one_address(char *p, int *result) // get colon addr, if present | |||
2473 | return p; | 2473 | return p; |
2474 | } | 2474 | } |
2475 | 2475 | ||
2476 | # define GET_FIRST 0 | 2476 | # define GET_ADDRESS 0 |
2477 | # define GET_SECOND 1 | 2477 | # define GET_SEPARATOR 1 |
2478 | # define GOT_FIRST 2 | ||
2479 | # define GOT_SECOND 3 | ||
2480 | # define GOT 2 | ||
2481 | 2478 | ||
2482 | static char *get_address(char *p, int *b, int *e) // get two colon addrs, if present | 2479 | // Read line addresses for a colon command. The user can enter as |
2480 | // many as they like but only the last two will be used. | ||
2481 | static char *get_address(char *p, int *b, int *e) | ||
2483 | { | 2482 | { |
2484 | int state = GET_FIRST; | 2483 | int state = GET_ADDRESS; |
2484 | char *save_dot = dot; | ||
2485 | 2485 | ||
2486 | //----- get the address' i.e., 1,3 'a,'b ----- | 2486 | //----- get the address' i.e., 1,3 'a,'b ----- |
2487 | for (;;) { | 2487 | for (;;) { |
2488 | if (isblank(*p)) { | 2488 | if (isblank(*p)) { |
2489 | p++; | 2489 | p++; |
2490 | } else if (*p == '%' && state == GET_FIRST) { // alias for 1,$ | 2490 | } else if (*p == '%' && state == GET_ADDRESS) { // alias for 1,$ |
2491 | p++; | 2491 | p++; |
2492 | *b = 1; | 2492 | *b = 1; |
2493 | *e = count_lines(text, end-1); | 2493 | *e = count_lines(text, end-1); |
2494 | state = GOT_SECOND; | 2494 | state = GET_SEPARATOR; |
2495 | } else if (*p == ',' && state == GOT_FIRST) { | 2495 | } else if (state == GET_SEPARATOR && (*p == ',' || *p == ';')) { |
2496 | if (*p == ';') | ||
2497 | dot = find_line(*e); | ||
2496 | p++; | 2498 | p++; |
2497 | state = GET_SECOND; | 2499 | *b = *e; |
2498 | } else if (state == GET_FIRST || state == GET_SECOND) { | 2500 | state = GET_ADDRESS; |
2499 | p = get_one_address(p, state == GET_FIRST ? b : e); | 2501 | } else if (state == GET_ADDRESS) { |
2502 | p = get_one_address(p, e); | ||
2500 | if (p == NULL) | 2503 | if (p == NULL) |
2501 | break; | 2504 | break; |
2502 | state |= GOT; | 2505 | state = GET_SEPARATOR; |
2503 | } else { | 2506 | } else { |
2507 | if (state == GET_SEPARATOR && *e < 0) | ||
2508 | *e = count_lines(text, dot); | ||
2504 | break; | 2509 | break; |
2505 | } | 2510 | } |
2506 | } | 2511 | } |
2512 | dot = save_dot; | ||
2507 | return p; | 2513 | return p; |
2508 | } | 2514 | } |
2509 | 2515 | ||
@@ -2637,8 +2643,6 @@ static void colon(char *buf) | |||
2637 | 2643 | ||
2638 | li = i = 0; | 2644 | li = i = 0; |
2639 | b = e = -1; | 2645 | b = e = -1; |
2640 | q = text; // assume 1,$ for the range | ||
2641 | r = end - 1; | ||
2642 | li = count_lines(text, end - 1); | 2646 | li = count_lines(text, end - 1); |
2643 | fn = current_filename; | 2647 | fn = current_filename; |
2644 | 2648 | ||
@@ -2673,27 +2677,33 @@ static void colon(char *buf) | |||
2673 | useforce = TRUE; | 2677 | useforce = TRUE; |
2674 | *buf1 = '\0'; // get rid of ! | 2678 | *buf1 = '\0'; // get rid of ! |
2675 | } | 2679 | } |
2676 | if (b >= 0) { | 2680 | // assume the command will want a range, certain commands |
2677 | // if there is only one addr, then the addr | 2681 | // (read, substitute) need to adjust these assumptions |
2678 | // is the line number of the single line the | 2682 | if (e < 0) { |
2679 | // user wants. So, reset the end | 2683 | q = text; // no addr, use 1,$ for the range |
2680 | // pointer to point at end of the "b" line | 2684 | r = end - 1; |
2681 | q = find_line(b); // what line is #b | 2685 | } else { |
2682 | r = end_line(q); | 2686 | // at least one addr was given, get its details |
2683 | li = 1; | 2687 | q = r = find_line(e); |
2684 | } | 2688 | if (b < 0) { |
2685 | if (e >= 0) { | 2689 | // if there is only one addr, then it's the line |
2686 | // we were given two addrs. change the | 2690 | // number of the single line the user wants. |
2687 | // end pointer to the addr given by user. | 2691 | // Reset the end pointer to the end of that line. |
2688 | r = find_line(e); // what line is #e | 2692 | r = end_line(q); |
2689 | r = end_line(r); | 2693 | li = 1; |
2690 | li = e - b + 1; | 2694 | } else { |
2695 | // we were given two addrs. change the | ||
2696 | // start pointer to the addr given by user. | ||
2697 | q = find_line(b); // what line is #b | ||
2698 | r = end_line(r); | ||
2699 | li = e - b + 1; | ||
2700 | } | ||
2691 | } | 2701 | } |
2692 | // ------------ now look for the command ------------ | 2702 | // ------------ now look for the command ------------ |
2693 | i = strlen(cmd); | 2703 | i = strlen(cmd); |
2694 | if (i == 0) { // :123CR goto line #123 | 2704 | if (i == 0) { // :123CR goto line #123 |
2695 | if (b >= 0) { | 2705 | if (e >= 0) { |
2696 | dot = find_line(b); // what line is #b | 2706 | dot = find_line(e); // what line is #e |
2697 | dot_skip_over_ws(); | 2707 | dot_skip_over_ws(); |
2698 | } | 2708 | } |
2699 | } | 2709 | } |
@@ -2711,12 +2721,12 @@ static void colon(char *buf) | |||
2711 | } | 2721 | } |
2712 | # endif | 2722 | # endif |
2713 | else if (cmd[0] == '=' && !cmd[1]) { // where is the address | 2723 | else if (cmd[0] == '=' && !cmd[1]) { // where is the address |
2714 | if (b < 0) { // no addr given- use defaults | 2724 | if (e < 0) { // no addr given- use defaults |
2715 | b = e = count_lines(text, dot); | 2725 | e = count_lines(text, dot); |
2716 | } | 2726 | } |
2717 | status_line("%d", b); | 2727 | status_line("%d", e); |
2718 | } else if (strncmp(cmd, "delete", i) == 0) { // delete lines | 2728 | } else if (strncmp(cmd, "delete", i) == 0) { // delete lines |
2719 | if (b < 0) { // no addr given- use defaults | 2729 | if (e < 0) { // no addr given- use defaults |
2720 | q = begin_line(dot); // assume .,. for the range | 2730 | q = begin_line(dot); // assume .,. for the range |
2721 | r = end_line(dot); | 2731 | r = end_line(dot); |
2722 | } | 2732 | } |
@@ -2767,7 +2777,7 @@ static void colon(char *buf) | |||
2767 | li, (int)(end - text) | 2777 | li, (int)(end - text) |
2768 | ); | 2778 | ); |
2769 | } else if (strncmp(cmd, "file", i) == 0) { // what File is this | 2779 | } else if (strncmp(cmd, "file", i) == 0) { // what File is this |
2770 | if (b != -1 || e != -1) { | 2780 | if (e >= 0) { |
2771 | status_line_bold("No address allowed on this command"); | 2781 | status_line_bold("No address allowed on this command"); |
2772 | goto ret; | 2782 | goto ret; |
2773 | } | 2783 | } |
@@ -2787,7 +2797,7 @@ static void colon(char *buf) | |||
2787 | rawmode(); | 2797 | rawmode(); |
2788 | Hit_Return(); | 2798 | Hit_Return(); |
2789 | } else if (strncmp(cmd, "list", i) == 0) { // literal print line | 2799 | } else if (strncmp(cmd, "list", i) == 0) { // literal print line |
2790 | if (b < 0) { // no addr given- use defaults | 2800 | if (e < 0) { // no addr given- use defaults |
2791 | q = begin_line(dot); // assume .,. for the range | 2801 | q = begin_line(dot); // assume .,. for the range |
2792 | r = end_line(dot); | 2802 | r = end_line(dot); |
2793 | } | 2803 | } |
@@ -2861,12 +2871,12 @@ static void colon(char *buf) | |||
2861 | status_line_bold("No filename given"); | 2871 | status_line_bold("No filename given"); |
2862 | goto ret; | 2872 | goto ret; |
2863 | } | 2873 | } |
2864 | if (b < 0) { // no addr given- use defaults | 2874 | if (e < 0) { // no addr given- read after current line |
2865 | q = begin_line(dot); // assume "dot" | 2875 | q = begin_line(dot); |
2866 | } | 2876 | } else if (e == 0) { // user said ":0r foo" |
2867 | // read after current line- unless user said ":0r foo" | 2877 | q = text; |
2868 | if (b != 0) { | 2878 | } else { // addr given- read after that line |
2869 | q = next_line(q); | 2879 | q = next_line(find_line(e)); |
2870 | // read after last line | 2880 | // read after last line |
2871 | if (q == end-1) | 2881 | if (q == end-1) |
2872 | ++q; | 2882 | ++q; |
@@ -2969,13 +2979,13 @@ static void colon(char *buf) | |||
2969 | } | 2979 | } |
2970 | len_R = strlen(R); | 2980 | len_R = strlen(R); |
2971 | 2981 | ||
2972 | q = begin_line(q); | 2982 | if (e < 0) { // no addr given |
2973 | if (b < 0) { // maybe :s/foo/bar/ | ||
2974 | q = begin_line(dot); // start with cur line | 2983 | q = begin_line(dot); // start with cur line |
2975 | b = count_lines(text, q); // cur line number | 2984 | r = end_line(dot); |
2985 | b = e = count_lines(text, q); // cur line number | ||
2986 | } else if (b < 0) { // one addr given | ||
2987 | b = e; | ||
2976 | } | 2988 | } |
2977 | if (e < 0) | ||
2978 | e = b; // maybe :.s/foo/bar/ | ||
2979 | 2989 | ||
2980 | for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0 | 2990 | for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0 |
2981 | char *ls = q; // orig line start | 2991 | char *ls = q; // orig line start |