mirror of
https://github.com/neovim/neovim.git
synced 2025-09-11 22:08:18 +00:00
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)
f951416a83
This commit is contained in:
@@ -445,6 +445,9 @@ SHIFTING LINES LEFT OR RIGHT *shift-left-right*
|
|||||||
*<*
|
*<*
|
||||||
<{motion} Shift {motion} lines one 'shiftwidth' leftwards.
|
<{motion} Shift {motion} lines one 'shiftwidth' leftwards.
|
||||||
|
|
||||||
|
If 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.
|
<< Shift [count] lines one 'shiftwidth' leftwards.
|
||||||
|
|
||||||
@@ -455,6 +458,9 @@ SHIFTING LINES LEFT OR RIGHT *shift-left-right*
|
|||||||
*>*
|
*>*
|
||||||
>{motion} Shift {motion} lines one 'shiftwidth' rightwards.
|
>{motion} Shift {motion} lines one 'shiftwidth' rightwards.
|
||||||
|
|
||||||
|
If 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.
|
>> 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}
|
pow({x}, {y}) Float {x} to the power of {y}
|
||||||
prevnonblank({lnum}) Number line nr of non-blank line <= {lnum}
|
prevnonblank({lnum}) Number line nr of non-blank line <= {lnum}
|
||||||
printf({fmt}, {expr1}...) String format text
|
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_setcallback({buf}, {expr}) none set prompt callback function
|
||||||
prompt_setinterrupt({buf}, {text}) none set prompt interrupt function
|
prompt_setinterrupt({buf}, {text}) none set prompt interrupt function
|
||||||
prompt_setprompt({buf}, {text}) none set prompt text
|
prompt_setprompt({buf}, {text}) none set prompt text
|
||||||
@@ -2393,7 +2392,7 @@ sha256({string}) String SHA256 checksum of {string}
|
|||||||
shellescape({string} [, {special}])
|
shellescape({string} [, {special}])
|
||||||
String escape {string} for use as shell
|
String escape {string} for use as shell
|
||||||
command argument
|
command argument
|
||||||
shiftwidth() Number effective value of 'shiftwidth'
|
shiftwidth([{col}]) Number effective value of 'shiftwidth'
|
||||||
sign_define({name} [, {dict}]) Number define or update a sign
|
sign_define({name} [, {dict}]) Number define or update a sign
|
||||||
sign_getdefined([{name}]) List get a list of defined signs
|
sign_getdefined([{name}]) List get a list of defined signs
|
||||||
sign_getplaced([{expr} [, {dict}]])
|
sign_getplaced([{expr} [, {dict}]])
|
||||||
@@ -7899,7 +7898,7 @@ shellescape({string} [, {special}]) *shellescape()*
|
|||||||
< See also |::S|.
|
< See also |::S|.
|
||||||
|
|
||||||
|
|
||||||
shiftwidth() *shiftwidth()*
|
shiftwidth([{col}]) *shiftwidth()*
|
||||||
Returns the effective value of 'shiftwidth'. This is the
|
Returns the effective value of 'shiftwidth'. This is the
|
||||||
'shiftwidth' value unless it is zero, in which case it is the
|
'shiftwidth' value unless it is zero, in which case it is the
|
||||||
'tabstop' value. To be backwards compatible in indent
|
'tabstop' value. To be backwards compatible in indent
|
||||||
|
@@ -9156,10 +9156,16 @@ static void ins_try_si(int c)
|
|||||||
* Get the value that w_virtcol would have when 'list' is off.
|
* Get the value that w_virtcol would have when 'list' is off.
|
||||||
* Unless 'cpo' contains the 'L' flag.
|
* Unless 'cpo' contains the 'L' flag.
|
||||||
*/
|
*/
|
||||||
static colnr_T get_nolist_virtcol(void)
|
colnr_T get_nolist_virtcol(void)
|
||||||
{
|
{
|
||||||
if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
|
// 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);
|
return getvcol_nolist(&curwin->w_cursor);
|
||||||
|
}
|
||||||
validate_virtcol();
|
validate_virtcol();
|
||||||
return curwin->w_virtcol;
|
return curwin->w_virtcol;
|
||||||
}
|
}
|
||||||
|
@@ -309,7 +309,7 @@ return {
|
|||||||
setwinvar={args=3},
|
setwinvar={args=3},
|
||||||
sha256={args=1},
|
sha256={args=1},
|
||||||
shellescape={args={1, 2}},
|
shellescape={args={1, 2}},
|
||||||
shiftwidth={},
|
shiftwidth={args={0, 1}},
|
||||||
sign_define={args={1, 2}},
|
sign_define={args={1, 2}},
|
||||||
sign_getdefined={args={0, 1}},
|
sign_getdefined={args={0, 1}},
|
||||||
sign_getplaced={args={0, 2}},
|
sign_getplaced={args={0, 2}},
|
||||||
|
@@ -8849,6 +8849,18 @@ static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
*/
|
*/
|
||||||
static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
|
rettv->vval.v_number = 0;
|
||||||
|
|
||||||
|
if (argvars[0].v_type != VAR_UNKNOWN) {
|
||||||
|
long col;
|
||||||
|
|
||||||
|
col = (long)tv_get_number_chk(argvars, NULL);
|
||||||
|
if (col < 0) {
|
||||||
|
return; // type error; errmsg already given
|
||||||
|
}
|
||||||
|
rettv->vval.v_number = get_sw_value_col(curbuf, col);
|
||||||
|
return;
|
||||||
|
}
|
||||||
rettv->vval.v_number = get_sw_value(curbuf);
|
rettv->vval.v_number = get_sw_value(curbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6777,9 +6777,10 @@ static void nv_g_cmd(cmdarg_T *cap)
|
|||||||
}
|
}
|
||||||
coladvance((colnr_T)i);
|
coladvance((colnr_T)i);
|
||||||
if (flag) {
|
if (flag) {
|
||||||
do
|
do {
|
||||||
i = gchar_cursor();
|
i = gchar_cursor();
|
||||||
while (ascii_iswhite(i) && oneright());
|
} while (ascii_iswhite(i) && oneright());
|
||||||
|
curwin->w_valid &= ~VALID_WCOL;
|
||||||
}
|
}
|
||||||
curwin->w_set_curswant = true;
|
curwin->w_set_curswant = true;
|
||||||
break;
|
break;
|
||||||
|
@@ -288,7 +288,7 @@ void shift_line(
|
|||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
int i, j;
|
int i, j;
|
||||||
int p_sw = get_sw_value(curbuf);
|
int p_sw = (int)get_sw_value_indent(curbuf);
|
||||||
|
|
||||||
count = get_indent(); // get current indent
|
count = get_indent(); // get current indent
|
||||||
|
|
||||||
@@ -332,9 +332,9 @@ static void shift_block(oparg_T *oap, int amount)
|
|||||||
const int oldstate = State;
|
const int oldstate = State;
|
||||||
char_u *newp;
|
char_u *newp;
|
||||||
const int oldcol = curwin->w_cursor.col;
|
const int oldcol = curwin->w_cursor.col;
|
||||||
const int p_sw = get_sw_value(curbuf);
|
int p_sw = (int)get_sw_value_indent(curbuf);
|
||||||
const long p_ts = curbuf->b_p_ts;
|
|
||||||
long *p_vts = curbuf->b_p_vts_array;
|
long *p_vts = curbuf->b_p_vts_array;
|
||||||
|
const long p_ts = curbuf->b_p_ts;
|
||||||
struct block_def bd;
|
struct block_def bd;
|
||||||
int incr;
|
int incr;
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
|
@@ -7342,11 +7342,39 @@ int tabstop_first(long *ts)
|
|||||||
/// 'tabstop' value when 'shiftwidth' is zero.
|
/// 'tabstop' value when 'shiftwidth' is zero.
|
||||||
int get_sw_value(buf_T *buf)
|
int get_sw_value(buf_T *buf)
|
||||||
{
|
{
|
||||||
long result = buf->b_p_sw ? buf->b_p_sw : buf->b_p_ts;
|
long result = get_sw_value_col(buf, 0);
|
||||||
assert(result >= 0 && result <= INT_MAX);
|
assert(result >= 0 && result <= INT_MAX);
|
||||||
return (int)result;
|
return (int)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 = (colnr_T)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)
|
||||||
|
{
|
||||||
|
return buf->b_p_sw ? buf->b_p_sw
|
||||||
|
: tabstop_at(col, buf->b_p_ts, buf->b_p_vts_array);
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the effective softtabstop value for the current buffer,
|
/// Return the effective softtabstop value for the current buffer,
|
||||||
/// using the shiftwidth value when 'softtabstop' is negative.
|
/// using the shiftwidth value when 'softtabstop' is negative.
|
||||||
int get_sts_value(void)
|
int get_sts_value(void)
|
||||||
|
@@ -297,6 +297,71 @@ func Test_vartabs_linebreak()
|
|||||||
set nolist listchars&vim
|
set nolist listchars&vim
|
||||||
endfunc
|
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()
|
func Test_vartabs_failures()
|
||||||
call assert_fails('set vts=8,')
|
call assert_fails('set vts=8,')
|
||||||
call assert_fails('set vsts=8,')
|
call assert_fails('set vsts=8,')
|
||||||
|
Reference in New Issue
Block a user