1
0
forked from aniani/vim

patch 8.1.0542: shiftwidth() does not take 'vartabstop' into account

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)
This commit is contained in:
Bram Moolenaar
2018-11-22 03:08:29 +01:00
parent 2b84949ad8
commit f951416a83
11 changed files with 154 additions and 17 deletions

View 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.

View 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.
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 {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.
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()*

View 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();

View 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);
}

View 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;

View File

@@ -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

View 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
}
/*

View 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 : */

View 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);

View 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,')

View File

@@ -792,6 +792,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
542,
/**/
541,
/**/