]> granicus.if.org Git - vim/commitdiff
patch 9.0.1300: 'statusline' only supports one "%=" item v9.0.1300
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sat, 11 Feb 2023 11:15:25 +0000 (11:15 +0000)
committerBram Moolenaar <Bram@vim.org>
Sat, 11 Feb 2023 11:15:25 +0000 (11:15 +0000)
Problem:    'statusline' only supports one "%=" item.
Solution:   Add support for multiple "%=" items. (TJ DeVries, Yegappan
            Lakshmanan, closes #11970, closes #11965)

runtime/doc/options.txt
src/buffer.c
src/option.h
src/optionstr.c
src/testdir/test_statusline.vim
src/version.c

index eece6008ed2301f9ee14aeb40b18e7be8f509c84..3d1f2ff8d293865d7f454b12ac728a35f640cfb6 100644 (file)
@@ -7776,7 +7776,10 @@ A jump table for the options with a short description can be found at |Q_op|.
              mark.  This information is used for mouse clicks.
        < -   Where to truncate line if too long.  Default is at the start.
              No width fields allowed.
-       = -   Separation point between left and right aligned items.
+       = -   Separation point between alignment sections.  Each section will
+             be separated by an equal number of spaces.  With one %= what
+             comes after it will be right-aligned.  With two %= there is a
+             middle part, with white space left and right of it.
              No width fields allowed.
        # -   Set highlight group.  The name must follow and then a # again.
              Thus use %#HLname# for highlight group HLname.  The same
index a3de68df29922409ab38e5b6684254960609a3b1..0d523bd05662a835e45e5bc2d993c74efbc36f3a 100644 (file)
@@ -4179,7 +4179,7 @@ typedef struct
        Normal,
        Empty,
        Group,
-       Middle,
+       Separate,
        Highlight,
        TabPage,
        Trunc
@@ -4191,6 +4191,7 @@ static stl_item_T      *stl_items = NULL;
 static int            *stl_groupitem = NULL;
 static stl_hlrec_T     *stl_hltab = NULL;
 static stl_hlrec_T     *stl_tabtab = NULL;
+static int             *stl_separator_locations = NULL;
 
 /*
  * Build a string from the status line items in "fmt".
@@ -4200,7 +4201,7 @@ static stl_hlrec_T     *stl_tabtab = NULL;
  * is "curwin".
  *
  * Items are drawn interspersed with the text that surrounds it
- * Specials: %-<wid>(xxx%) => group, %= => middle marker, %< => truncation
+ * Specials: %-<wid>(xxx%) => group, %= => separation marker, %< => truncation
  * Item: %-<minwid>.<maxwid><itemch> All but <itemch> are optional
  *
  * If maxwidth is not zero, the string will be filled at any middle marker
@@ -4282,6 +4283,8 @@ build_stl_str_hl(
        // end of the list.
        stl_hltab  = ALLOC_MULT(stl_hlrec_T, stl_items_len + 1);
        stl_tabtab = ALLOC_MULT(stl_hlrec_T, stl_items_len + 1);
+
+       stl_separator_locations = ALLOC_MULT(int, stl_items_len);
     }
 
 #ifdef FEAT_EVAL
@@ -4350,19 +4353,20 @@ build_stl_str_hl(
        if (curitem == (int)stl_items_len)
        {
            size_t      new_len = stl_items_len * 3 / 2;
-           stl_item_T  *new_items;
-           int         *new_groupitem;
-           stl_hlrec_T *new_hlrec;
 
-           new_items = vim_realloc(stl_items, sizeof(stl_item_T) * new_len);
+           stl_item_T *new_items =
+                         vim_realloc(stl_items, sizeof(stl_item_T) * new_len);
            if (new_items == NULL)
                break;
            stl_items = new_items;
-           new_groupitem = vim_realloc(stl_groupitem, sizeof(int) * new_len);
+
+           int *new_groupitem =
+                            vim_realloc(stl_groupitem, sizeof(int) * new_len);
            if (new_groupitem == NULL)
                break;
            stl_groupitem = new_groupitem;
-           new_hlrec = vim_realloc(stl_hltab,
+
+           stl_hlrec_T *new_hlrec = vim_realloc(stl_hltab,
                                          sizeof(stl_hlrec_T) * (new_len + 1));
            if (new_hlrec == NULL)
                break;
@@ -4372,6 +4376,13 @@ build_stl_str_hl(
            if (new_hlrec == NULL)
                break;
            stl_tabtab = new_hlrec;
+
+           int *new_separator_locs = vim_realloc(stl_separator_locations,
+                                           sizeof(int) * new_len);
+           if (new_separator_locs == NULL)
+               break;
+           stl_separator_locations = new_separator_locs;;
+
            stl_items_len = new_len;
        }
 
@@ -4400,12 +4411,13 @@ build_stl_str_hl(
            prevchar_isflag = prevchar_isitem = FALSE;
            continue;
        }
-       if (*s == STL_MIDDLEMARK)
+       // STL_SEPARATE: Separation between items, filled with white space.
+       if (*s == STL_SEPARATE)
        {
            s++;
            if (groupdepth > 0)
                continue;
-           stl_items[curitem].stl_type = Middle;
+           stl_items[curitem].stl_type = Separate;
            stl_items[curitem++].stl_start = p;
            continue;
        }
@@ -5121,19 +5133,45 @@ build_stl_str_hl(
     }
     else if (width < maxwidth && STRLEN(out) + maxwidth - width + 1 < outlen)
     {
-       // Apply STL_MIDDLE if any
+       // Find how many separators there are, which we will use when
+       // figuring out how many groups there are.
+       int num_separators = 0;
+
        for (l = 0; l < itemcnt; l++)
-           if (stl_items[l].stl_type == Middle)
-               break;
-       if (l < itemcnt)
        {
-           int middlelength = (maxwidth - width) * MB_CHAR2LEN(fillchar);
-           p = stl_items[l].stl_start + middlelength;
-           STRMOVE(p, stl_items[l].stl_start);
-           for (s = stl_items[l].stl_start; s < p;)
-               MB_CHAR2BYTES(fillchar, s);
-           for (l++; l < itemcnt; l++)
-               stl_items[l].stl_start += middlelength;
+           if (stl_items[l].stl_type == Separate)
+           {
+               // Create an array of the start location for each separator
+               // mark.
+               stl_separator_locations[num_separators] = l;
+               num_separators++;
+           }
+       }
+
+       // If we have separated groups, then we deal with it now
+       if (num_separators)
+       {
+           int standard_spaces;
+           int final_spaces;
+
+           standard_spaces = (maxwidth - width) / num_separators;
+           final_spaces = (maxwidth - width) -
+                                       standard_spaces * (num_separators - 1);
+           for (l = 0; l < num_separators; l++)
+           {
+               int dislocation = (l == (num_separators - 1)) ?
+                                       final_spaces : standard_spaces;
+               dislocation *= MB_CHAR2LEN(fillchar);
+               char_u *start = stl_items[stl_separator_locations[l]].stl_start;
+               char_u *seploc = start + dislocation;
+               STRMOVE(seploc, start);
+               for (s = start; s < seploc;)
+                   MB_CHAR2BYTES(fillchar, s);
+
+               for (int i = stl_separator_locations[l] + 1; i < itemcnt; i++)
+                   stl_items[i].stl_start += dislocation;
+           }
+
            width = maxwidth;
        }
     }
index aa55bfbac23df9c9ee7727fb01aff3752dd49fd9..56b489b1979e96ebee474f773ec9db4cda3205ef 100644 (file)
@@ -347,7 +347,8 @@ typedef enum {
 #define STL_PAGENUM    'N'             // page number (when printing)
 #define STL_SHOWCMD    'S'             // 'showcmd' buffer
 #define STL_VIM_EXPR   '{'             // start of expression to substitute
-#define STL_MIDDLEMARK '='             // separation between left and right
+#define STL_SEPARATE   '='             // separation between alignment
+                                       // sections
 #define STL_TRUNCMARK  '<'             // truncation mark if line is too long
 #define STL_USER_HL    '*'             // highlight from (User)1..9 or 0
 #define STL_HIGHLIGHT  '#'             // highlight name
index d218d5662b5f4650ec038f7a7fe3e661dd44b290..7dfb7b7ff58f3719d6f9c21303cbd94fd4adb433 100644 (file)
@@ -587,7 +587,7 @@ check_stl_option(char_u *s)
        if (!*s)
            break;
        s++;
-       if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_MIDDLEMARK)
+       if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_SEPARATE)
        {
            s++;
            continue;
index 8061d1507a82dea960b14b368c5923590888503f..1239e4e4ee3f7169fc76ea835693a1db5e59a5ab 100644 (file)
@@ -231,6 +231,10 @@ func Test_statusline()
   " %=: Separation point between left and right aligned items.
   set statusline=foo%=bar
   call assert_match('^foo\s\+bar\s*$', s:get_statusline())
+  set statusline=foo%=bar%=baz
+  call assert_match('^foo\s\+bar\s\+baz\s*$', s:get_statusline())
+  set statusline=foo%=bar%=baz%=qux
+  call assert_match('^foo\s\+bar\s\+baz\s\+qux\s*$', s:get_statusline())
 
   " Test min/max width, leading zeroes, left/right justify.
   set statusline=%04B
index 9e8e975a967f3be50a74ec3fe889e73fd57d7c0e..f28cfd8e237be77dc9f5b10d5a1be20577504845 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1300,
 /**/
     1299,
 /**/