Opening a line above the current line with the 'O' command should
use the current, not previous, line to determine how much to
autoindent.

function                                             old     new   delta
char_insert                                          531     563     +32
do_cmd                                              4746    4723     -23
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 32/-23)              Total: 9 bytes

Signed-off-by: Ron Yorston <[email protected]>
---
 editors/vi.c | 41 +++++++++++++++++++++++++++++------------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/editors/vi.c b/editors/vi.c
index 0a82f9e38..b77406967 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -286,6 +286,7 @@ struct globals {
        int text_size;          // size of the allocated buffer
 
        // the rest
+#if ENABLE_FEATURE_VI_SETOPTS
        smallint vi_setops;     // set by setops()
 #define VI_AUTOINDENT (1 << 0)
 #define VI_ERR_METHOD (1 << 1)
@@ -296,6 +297,7 @@ struct globals {
 #define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or 
flash
 #define ignorecase (vi_setops & VI_IGNORECASE)
 #define showmatch  (vi_setops & VI_SHOWMATCH )
+#define openabove  (vi_setops & VI_TABSTOP   )
 // order of constants and strings must match
 #define OPTS_STR \
                "ai\0""autoindent\0" \
@@ -303,6 +305,15 @@ struct globals {
                "ic\0""ignorecase\0" \
                "sm\0""showmatch\0" \
                "ts\0""tabstop\0"
+#define set_openabove() (vi_setops |= VI_TABSTOP)
+#define clear_openabove() (vi_setops &= ~VI_TABSTOP)
+#else
+#define autoindent (0)
+#define err_method (0)
+#define openabove  (0)
+#define set_openabove() ((void)0)
+#define clear_openabove() ((void)0)
+#endif
 
 #if ENABLE_FEATURE_VI_READONLY
        smallint readonly_mode;
@@ -2130,8 +2141,13 @@ static char *char_insert(char *p, char c, int undo) // 
insert the char c at 'p'
                        showmatching(p - 1);
                }
                if (autoindent && c == '\n') {  // auto indent the new line
-                       q = prev_line(p);       // use prev line as template
+                       // use current/previous line as template
+                       q = openabove ? p : prev_line(p);
                        len = strspn(q, " \t"); // space or tab
+                       if (openabove) {
+                               p--;            // this replaces dot_prev() in 
do_cmd()
+                               q += len;       // template will be shifted by 
text_hole_make()
+                       }
                        if (len) {
                                uintptr_t bias;
                                bias = text_hole_make(p, len);
@@ -2445,6 +2461,7 @@ static void setops(char *args, int flg_no)
        index = 1 << (index >> 1); // convert to VI_bit
 
        if (index & VI_TABSTOP) {
+               // don't set this bit in vi_setops, it's reused as 'openabove'
                int t;
                if (!eq || flg_no) // no "=NNN" or it is "notabstop"?
                        goto bad;
@@ -3841,19 +3858,19 @@ static void do_cmd(int c)
                        dot = next_line(dot);
                dot_skip_over_ws();
                break;
-       case 'O':                       // O- open a empty line above
-               //    0i\n ESC -i
-               p = begin_line(dot);
-               if (p[-1] == '\n') {
+       case 'O':                       // O- open an empty line above
+               dot_begin();
+               set_openabove();
+               goto dc3;
+       case 'o':                       // o- open an empty line below
+               dot_end();
+ dc3:
+               dot = char_insert(dot, '\n', ALLOW_UNDO);
+               if (c == 'O' && !autoindent) {
+                       // done in char_insert() for openabove+autoindent
                        dot_prev();
-       case 'o':                       // o- open a empty line below; Yes, I 
know it is in the middle of the "if (..."
-                       dot_end();
-                       dot = char_insert(dot, '\n', ALLOW_UNDO);
-               } else {
-                       dot_begin();    // 0
-                       dot = char_insert(dot, '\n', ALLOW_UNDO);       // i\n 
ESC
-                       dot_prev();     // -
                }
+               clear_openabove();
                goto dc_i;
                break;
        case 'R':                       // R- continuous Replace char
-- 
2.30.2

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to