[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    Re: [PATCH 2/2] vi: handle autoindent in 'cc' command
From:       Denys Vlasenko <vda.linux () googlemail ! com>
Date:       2022-06-26 17:56:17
Message-ID: CAK1hOcPXWqY1EqXm0g=nmookKwErbhFdJQp8Qa5iUf0NjAkK9w () mail ! gmail ! com
[Download RAW message or body]

Applied both, thanks

On Fri, Mar 18, 2022 at 12:31 PM Ron Yorston <rmy@pobox.com> wrote:
>
> When the 'cc' command is invoked with autoindent enabled it
> should use the indent of the first line being changed.
>
> The size of the indent has to be established before char_insert()
> is called as the lines being changed are deleted.  Introduce a
> new global variable, newindent, to handle this.  The indentcol
> global is now effectively a static variable in char_insert().
>
> function                                             old     new   delta
> do_cmd                                              4247    4308     +61
> vi_main                                              416     422      +6
> char_insert                                          891     875     -16
> ------------------------------------------------------------------------------
> (add/remove: 0/0 grow/shrink: 2/1 up/down: 67/-16)             Total: 51 bytes
>
> Signed-off-by: Ron Yorston <rmy@pobox.com>
> ---
>  editors/vi.c | 71 ++++++++++++++++++++++++++++++++++------------------
>  1 file changed, 47 insertions(+), 24 deletions(-)
>
> diff --git a/editors/vi.c b/editors/vi.c
> index e63ca60d4..6edff0b5a 100644
> --- a/editors/vi.c
> +++ b/editors/vi.c
> @@ -380,7 +380,9 @@ struct globals {
>         char *last_search_pattern; // last pattern from a '/' or '?' search
>  #endif
>  #if ENABLE_FEATURE_VI_SETOPTS
> -       int indentcol;          // column of recently autoindent, 0 or -1
> +       int char_insert__indentcol;             // column of recent autoindent or 0
> +       int newindent;          // autoindent value for 'O'/'cc' commands
> +                                               // or -1 to use indent from previous line
>  #endif
>         smallint cmd_error;
>
> @@ -507,7 +509,8 @@ struct globals {
>  #define ioq_start               (G.ioq_start          )
>  #define dotcnt                  (G.dotcnt             )
>  #define last_search_pattern     (G.last_search_pattern)
> -#define indentcol               (G.indentcol          )
> +#define char_insert__indentcol  (G.char_insert__indentcol)
> +#define newindent               (G.newindent          )
>  #define cmd_error               (G.cmd_error          )
>
>  #define edit_file__cur_line     (G.edit_file__cur_line)
> @@ -540,10 +543,11 @@ struct globals {
>
>  #define INIT_G() do { \
>         SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
> -       last_modified_count = -1; \
> +       last_modified_count--; \
>         /* "" but has space for 2 chars: */ \
>         IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \
>         tabstop = 8; \
> +       IF_FEATURE_VI_SETOPTS(newindent--;) \
>  } while (0)
>
>  #if ENABLE_FEATURE_VI_CRASHME
> @@ -2112,6 +2116,7 @@ static size_t indent_len(char *p)
>  static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
>  {
>  #if ENABLE_FEATURE_VI_SETOPTS
> +# define indentcol char_insert__indentcol
>         size_t len;
>         int col, ntab, nspc;
>  #endif
> @@ -2140,7 +2145,8 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
>  #if ENABLE_FEATURE_VI_SETOPTS
>                 if (autoindent) {
>                         len = indent_len(bol);
> -                       if (len && get_column(bol + len) == indentcol && bol[len] == '\n') {
> +                       col = get_column(bol + len);
> +                       if (len && col == indentcol && bol[len] == '\n') {
>                                 // remove autoindent from otherwise empty line
>                                 text_hole_delete(bol, bol + len - 1, undo);
>                                 p = bol;
> @@ -2209,26 +2215,30 @@ 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
> -                       // use indent of current/previous line
> -                       bol = indentcol < 0 ? p : prev_line(p);
> -                       len = indent_len(bol);
> -                       col = get_column(bol + len);
> -
> -                       if (len && col == indentcol) {
> -                               // previous line was empty except for autoindent
> -                               // move the indent to the current line
> -                               memmove(bol + 1, bol, len);
> -                               *bol = '\n';
> -                               return p;
> +                       if (newindent < 0) {
> +                               // use indent of previous line
> +                               bol = prev_line(p);
> +                               len = indent_len(bol);
> +                               col = get_column(bol + len);
> +
> +                               if (len && col == indentcol) {
> +                                       // previous line was empty except for autoindent
> +                                       // move the indent to the current line
> +                                       memmove(bol + 1, bol, len);
> +                                       *bol = '\n';
> +                                       return p;
> +                               }
> +                       } else {
> +                               // for 'O'/'cc' commands add indent before newly inserted NL
> +                               if (p != end - 1)       // but not for 'cc' at EOF
> +                                       p--;
> +                               col = newindent;
>                         }
>
> -                       if (indentcol < 0)
> -                               p--;    // open above, indent before newly inserted NL
> -
> -                       if (len) {
> +                       if (col) {
>                                 // only record indent if in insert/replace mode or for
> -                               // the 'o'/'O' commands, which are switched to insert
> -                               // mode early.
> +                               // the 'o'/'O'/'cc' commands, which are switched to
> +                               // insert mode early.
>                                 indentcol = cmd_mode != 0 ? col : 0;
>                                 if (expandtab) {
>                                         ntab = 0;
> @@ -2251,6 +2261,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
>         }
>  #if ENABLE_FEATURE_VI_SETOPTS
>         indentcol = 0;
> +# undef indentcol
>  #endif
>         return p;
>  }
> @@ -4219,6 +4230,9 @@ static void do_cmd(int c)
>         case 'i':                       // i- insert before current char
>         case KEYCODE_INSERT:    // Cursor Key Insert
>   dc_i:
> +#if ENABLE_FEATURE_VI_SETOPTS
> +               newindent = -1;
> +#endif
>                 cmd_mode = 1;   // start inserting
>                 undo_queue_commit();    // commit queue when cmd_mode changes
>                 break;
> @@ -4261,7 +4275,8 @@ static void do_cmd(int c)
>         case 'O':                       // O- open an empty line above
>                 dot_begin();
>  #if ENABLE_FEATURE_VI_SETOPTS
> -               indentcol = -1;
> +               // special case: use indent of current line
> +               newindent = get_column(dot + indent_len(dot));
>  #endif
>                 goto dc3;
>         case 'o':                       // o- open an empty line below
> @@ -4384,14 +4399,22 @@ static void do_cmd(int c)
>                 if (buftype == WHOLE) {
>                         save_dot = p;   // final cursor position is start of range
>                         p = begin_line(p);
> +#if ENABLE_FEATURE_VI_SETOPTS
> +                       if (c == 'c')   // special case: use indent of current line
> +                               newindent = get_column(p + indent_len(p));
> +#endif
>                         q = end_line(q);
>                 }
>                 dot = yank_delete(p, q, buftype, yf, ALLOW_UNDO);       // delete word
>                 if (buftype == WHOLE) {
>                         if (c == 'c') {
> +#if ENABLE_FEATURE_VI_SETOPTS
> +                               cmd_mode = 1;   // switch to insert mode early
> +#endif
>                                 dot = char_insert(dot, '\n', ALLOW_UNDO_CHAIN);
> -                               // on the last line of file don't move to prev line
> -                               if (dot != (end-1)) {
> +                               // on the last line of file don't move to prev line,
> +                               // handled in char_insert() if autoindent is enabled
> +                               if (dot != (end-1) && !autoindent) {
>                                         dot_prev();
>                                 }
>                         } else if (c == 'd') {
> --
> 2.35.1
>
> _______________________________________________
> busybox mailing list
> busybox@busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic