aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-04-25 11:51:55 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2021-04-28 11:29:33 +0200
commit7a8ceb4eb25f1b136bf9a79b04d46dc4d7f440a7 (patch)
treebbc4bc69aa3e42f2750c4fe5b5a6a97f2b9eb419
parent81f9a0035b857206ac03afb729be3c8438f218b9 (diff)
downloadbusybox-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.c110
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
2482static 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.
2481static 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