]> granicus.if.org Git - vim/commitdiff
patch 8.1.0542: shiftwidth() does not take 'vartabstop' into account v8.1.0542
authorBram Moolenaar <Bram@vim.org>
Thu, 22 Nov 2018 02:08:29 +0000 (03:08 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 22 Nov 2018 02:08:29 +0000 (03:08 +0100)
Problem:    shiftwidth() does not take 'vartabstop' into account.
Solution:   Use the cursor position or a position explicitly passed.
            Also make >> and << work better with 'vartabstop'. (Christian
            Brabandt)

runtime/doc/change.txt
runtime/doc/eval.txt
src/edit.c
src/evalfunc.c
src/normal.c
src/ops.c
src/option.c
src/proto/edit.pro
src/proto/option.pro
src/testdir/test_vartabs.vim
src/version.c

index d6b0242d2cc40a8ad8fef0e89be060301b86b094..dc3a23c5996b170f86c4da9b990ba2dbe47bc0fa 100644 (file)
@@ -476,6 +476,10 @@ SHIFTING LINES LEFT OR RIGHT                               *shift-left-right*
                                                        *<*
 <{motion}              Shift {motion} lines one 'shiftwidth' leftwards.
 
+                       If the 'vartabstop' feature is enabled, and the
+                       'shiftwidth' option is set to zero, the amount of
+                       indent is calculated at the first non-blank character
+                       in the line.
                                                        *<<*
 <<                     Shift [count] lines one 'shiftwidth' leftwards.
 
@@ -487,6 +491,10 @@ SHIFTING LINES LEFT OR RIGHT                               *shift-left-right*
                                                        *>*
  >{motion}             Shift {motion} lines one 'shiftwidth' rightwards.
 
+                       If the 'vartabstop' feature is enabled, and the
+                       'shiftwidth' option is set to zero, the amount of
+                       indent is calculated at the first non-blank character
+                       in the line.
                                                        *>>*
  >>                    Shift [count] lines one 'shiftwidth' rightwards.
 
index 07c88d114cbbf8df7255a752bab065e24202f34e..5e6545cbdda66c5aed0b4b697ecb9f20df48a075 100644 (file)
@@ -2308,7 +2308,6 @@ perleval({expr})          any     evaluate |Perl| expression
 pow({x}, {y})                  Float   {x} to the power of {y}
 prevnonblank({lnum})           Number  line nr of non-blank line <= {lnum}
 printf({fmt}, {expr1}...)      String  format text
-prompt_addtext({buf}, {expr})  none    add text to a prompt buffer
 prompt_setcallback({buf}, {expr}) none set prompt callback function
 prompt_setinterrupt({buf}, {text}) none        set prompt interrupt function
 prompt_setprompt({buf}, {text}) none   set prompt text
@@ -2386,7 +2385,7 @@ sha256({string})          String  SHA256 checksum of {string}
 shellescape({string} [, {special}])
                                String  escape {string} for use as shell
                                        command argument
-shiftwidth([{list}])           Number  effective value of 'shiftwidth'
+shiftwidth([{col}])            Number  effective value of 'shiftwidth'
 simplify({filename})           String  simplify filename as much as possible
 sin({expr})                    Float   sine of {expr}
 sinh({expr})                   Float   hyperbolic sine of {expr}
@@ -7639,19 +7638,17 @@ shellescape({string} [, {special}])                     *shellescape()*
 <              See also |::S|.
 
 
-shiftwidth([{list}])                                           *shiftwidth()*
+shiftwidth([{col}])                                            *shiftwidth()*
                Returns the effective value of 'shiftwidth'. This is the
                'shiftwidth' value unless it is zero, in which case it is the
                'tabstop' value.  This function was introduced with patch
-               7.3.694 in 2012, everybody should have it by now.
-
-               When there is one argument {list} this is used as position
-               |List| for which to return the 'shiftwidth' value (actually
-               only the column number is relevant). This matters for the
-               'vartabstop' feature. For the {list} arguments see |cursor()|
-               function. If the 'vartabstop' setting is enabled and no
-               {list} argument is given, the current cursor position is
-               taken into account.
+               7.3.694 in 2012, everybody should have it by now (however it
+               did not allow for the optional {col} argument until 8.1.542).
+
+               When there is one argument {col} this is used as column number
+               for which to return the 'shiftwidth' value. This matters for the
+               'vartabstop' feature. If the 'vartabstop' setting is enabled and
+               no {col} argument is given, column 1 will be assumed.
 
 
 simplify({filename})                                   *simplify()*
index 239881ee5cf1ed78af9bf12d379aeb6d1254ec4b..6b5bc0f63169ce8811ac5fe42afa42bd9a63516b 100644 (file)
@@ -262,7 +262,6 @@ static int  ins_ctrl_ey(int tc);
 #ifdef FEAT_SMARTINDENT
 static void ins_try_si(int c);
 #endif
-static colnr_T get_nolist_virtcol(void);
 #if defined(FEAT_EVAL)
 static char_u *do_insert_char_pre(int c);
 #endif
@@ -10681,9 +10680,14 @@ ins_try_si(int c)
  * Get the value that w_virtcol would have when 'list' is off.
  * Unless 'cpo' contains the 'L' flag.
  */
-    static colnr_T
+    colnr_T
 get_nolist_virtcol(void)
 {
+    // check validity of cursor in current buffer
+    if (curwin->w_buffer == NULL
+       || curwin->w_buffer->b_ml.ml_mfp == NULL
+       || curwin->w_cursor.lnum > curwin->w_buffer->b_ml.ml_line_count)
+       return 0;
     if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
        return getvcol_nolist(&curwin->w_cursor);
     validate_virtcol();
index f55739ed5dfd2a8a41987d4ec675bb110a6015d2..d3bacad7785b49ba0ba621c49b27be94fa8a0183 100644 (file)
@@ -835,7 +835,7 @@ static struct fst
     {"sha256",         1, 1, f_sha256},
 #endif
     {"shellescape",    1, 2, f_shellescape},
-    {"shiftwidth",     0, 0, f_shiftwidth},
+    {"shiftwidth",     0, 1, f_shiftwidth},
     {"simplify",       1, 1, f_simplify},
 #ifdef FEAT_FLOAT
     {"sin",            1, 1, f_sin},
@@ -11241,6 +11241,21 @@ f_shellescape(typval_T *argvars, typval_T *rettv)
     static void
 f_shiftwidth(typval_T *argvars UNUSED, typval_T *rettv)
 {
+    rettv->vval.v_number = 0;
+
+    if (argvars[0].v_type != VAR_UNKNOWN)
+    {
+       long    col;
+
+       col = (long)get_tv_number_chk(argvars, NULL);
+       if (col < 0)
+           return;     // type error; errmsg already given
+#ifdef FEAT_VARTABS
+       rettv->vval.v_number = get_sw_value_col(curbuf, col);
+       return;
+#endif
+    }
+
     rettv->vval.v_number = get_sw_value(curbuf);
 }
 
index a0683b2074037365bf7206963bc6cc6d8161b220..5310824eeef3733b2faa8d133f1e96fe4bd56416 100644 (file)
@@ -8143,6 +8143,7 @@ nv_g_cmd(cmdarg_T *cap)
            do
                i = gchar_cursor();
            while (VIM_ISWHITE(i) && oneright() == OK);
+           curwin->w_valid &= ~VALID_WCOL;
        }
        curwin->w_set_curswant = TRUE;
        break;
index 7564fac7dbbba26add98f2862d6e5307fcdabd1f..004d5093c213b622a3e1ab9cb78c429bdef64252 100644 (file)
--- a/src/ops.c
+++ b/src/ops.c
@@ -334,7 +334,7 @@ shift_line(
 {
     int                count;
     int                i, j;
-    int                p_sw = (int)get_sw_value(curbuf);
+    int                p_sw = (int)get_sw_value_indent(curbuf);
 
     count = get_indent();      /* get current indent */
 
@@ -386,7 +386,7 @@ shift_block(oparg_T *oap, int amount)
     int                        total;
     char_u             *newp, *oldp;
     int                        oldcol = curwin->w_cursor.col;
-    int                        p_sw = (int)get_sw_value(curbuf);
+    int                        p_sw = (int)get_sw_value_indent(curbuf);
 #ifdef FEAT_VARTABS
     int                        *p_vts = curbuf->b_p_vts_array;
 #endif
index 50d405a952175cdaef585e6222f0062702631694..fdb99adddfbba3a74efb3c84422808fc8a61d140 100644 (file)
@@ -13113,7 +13113,48 @@ tabstop_first(int *ts)
     long
 get_sw_value(buf_T *buf)
 {
-    return buf->b_p_sw ? buf->b_p_sw : buf->b_p_ts;
+    return get_sw_value_col(buf, 0);
+}
+
+/*
+ * Idem, using the first non-black in the current line.
+ */
+    long
+get_sw_value_indent(buf_T *buf)
+{
+    pos_T pos = curwin->w_cursor;
+
+    pos.col = getwhitecols_curline();
+    return get_sw_value_pos(buf, &pos);
+}
+
+/*
+ * Idem, using "pos".
+ */
+    long
+get_sw_value_pos(buf_T *buf, pos_T *pos)
+{
+    pos_T save_cursor = curwin->w_cursor;
+    long sw_value;
+
+    curwin->w_cursor = *pos;
+    sw_value = get_sw_value_col(buf, get_nolist_virtcol());
+    curwin->w_cursor = save_cursor;
+    return sw_value;
+}
+
+/*
+ * Idem, using virtual column "col".
+ */
+    long
+get_sw_value_col(buf_T *buf, colnr_T col UNUSED)
+{
+    return buf->b_p_sw ? buf->b_p_sw :
+ #ifdef FEAT_VARTABS
+       tabstop_at(col, buf->b_p_ts, buf->b_p_vts_array);
+ #else
+       buf->b_p_ts;
+ #endif
 }
 
 /*
index 9ba71645b5b6e40ad5f21bbb26eb9cd7fc38b588..768af3a484cac08afe1d64931b37298312b5b63a 100644 (file)
@@ -46,4 +46,5 @@ int bracketed_paste(paste_mode_T mode, int drop, garray_T *gap);
 void ins_scroll(void);
 void ins_horscroll(void);
 int ins_copychar(linenr_T lnum);
+colnr_T get_nolist_virtcol(void);
 /* vim: set ft=c : */
index 228036587570d3b9787603bd41f21d87caaf5156..b198c75160055806e8f728bd76887176438f175f 100644 (file)
@@ -72,6 +72,9 @@ int *tabstop_copy(int *oldts);
 int tabstop_count(int *ts);
 int tabstop_first(int *ts);
 long get_sw_value(buf_T *buf);
+long get_sw_value_indent(buf_T *buf);
+long get_sw_value_pos(buf_T *buf, pos_T *pos);
+long get_sw_value_col(buf_T *buf, colnr_T col);
 long get_sts_value(void);
 void find_mps_values(int *initc, int *findc, int *backwards, int switchit);
 unsigned int get_bkc_value(buf_T *buf);
index c8470952d10554ca0fc7147b846922bf4b6ccacb..81e81b7fbe98037cc8237801194e4f655d0722cf 100644 (file)
@@ -297,6 +297,71 @@ func Test_vartabs_linebreak()
   set nolist listchars&vim
 endfunc
 
+func Test_vartabs_shiftwidth()
+  "return
+  if winwidth(0) < 40
+    return
+  endif
+  new
+  40vnew
+  %d
+"  setl varsofttabstop=10,20,30,40
+  setl shiftwidth=0 vartabstop=10,20,30,40
+  call setline(1, "x")
+
+  " Check without any change.
+  let expect = ['x                                       ']
+  let lines = ScreenLines(1, winwidth(0))
+  call s:compare_lines(expect, lines)
+  " Test 1:
+  " shiftwidth depends on the indent, first check with cursor at the end of the
+  " line (which is the same as the start of the line, since there is only one
+  " character).
+  norm! $>>
+  let expect1 = ['          x                             ']
+  let lines = ScreenLines(1, winwidth(0))
+  call s:compare_lines(expect1, lines)
+  call assert_equal(10, shiftwidth())
+  call assert_equal(10, shiftwidth(1))
+  call assert_equal(20, shiftwidth(virtcol('.')))
+  norm! $>>
+  let expect2 = ['                              x         ', '~                                       ']
+  let lines = ScreenLines([1, 2], winwidth(0))
+  call s:compare_lines(expect2, lines)
+  call assert_equal(20, shiftwidth(virtcol('.')-2))
+  call assert_equal(30, shiftwidth(virtcol('.')))
+  norm! $>>
+  let expect3 = ['                                        ', '                    x                   ', '~                                       ']
+  let lines = ScreenLines([1, 3], winwidth(0))
+  call s:compare_lines(expect3, lines)
+  call assert_equal(30, shiftwidth(virtcol('.')-2))
+  call assert_equal(40, shiftwidth(virtcol('.')))
+  norm! $>>
+  let expect4 = ['                                        ', '                                        ', '                    x                   ']
+  let lines = ScreenLines([1, 3], winwidth(0))
+  call assert_equal(40, shiftwidth(virtcol('.')))
+  call s:compare_lines(expect4, lines)
+
+  " Test 2: Put the cursor at the first column, result should be the same
+  call setline(1, "x")
+  norm! 0>>
+  let lines = ScreenLines(1, winwidth(0))
+  call s:compare_lines(expect1, lines)
+  norm! 0>>
+  let lines = ScreenLines([1, 2], winwidth(0))
+  call s:compare_lines(expect2, lines)
+  norm! 0>>
+  let lines = ScreenLines([1, 3], winwidth(0))
+  call s:compare_lines(expect3, lines)
+  norm! 0>>
+  let lines = ScreenLines([1, 3], winwidth(0))
+  call s:compare_lines(expect4, lines)
+
+  " cleanup
+  bw!
+  bw!
+endfunc
+
 func Test_vartabs_failures()
   call assert_fails('set vts=8,')
   call assert_fails('set vsts=8,')
index 37f4b1f47dc731c0e87226f8c1e9b87e3e721d94..82b8abe5d5eb78915d1d489c222d3f97257014e7 100644 (file)
@@ -792,6 +792,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    542,
 /**/
     541,
 /**/