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:
@@ -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.
|
||||
|
||||
|
||||
@@ -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()*
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
43
src/option.c
43
src/option.c
@@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 : */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,')
|
||||
|
||||
@@ -792,6 +792,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
542,
|
||||
/**/
|
||||
541,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user