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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -455,6 +458,9 @@ SHIFTING LINES LEFT OR RIGHT *shift-left-right*
|
||||
*>*
|
||||
>{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.
|
||||
|
||||
|
@@ -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
|
||||
@@ -2393,7 +2392,7 @@ sha256({string}) String SHA256 checksum of {string}
|
||||
shellescape({string} [, {special}])
|
||||
String escape {string} for use as shell
|
||||
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_getdefined([{name}]) List get a list of defined signs
|
||||
sign_getplaced([{expr} [, {dict}]])
|
||||
@@ -7899,7 +7898,7 @@ shellescape({string} [, {special}]) *shellescape()*
|
||||
< See also |::S|.
|
||||
|
||||
|
||||
shiftwidth() *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. 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.
|
||||
* 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);
|
||||
}
|
||||
validate_virtcol();
|
||||
return curwin->w_virtcol;
|
||||
}
|
||||
|
@@ -309,7 +309,7 @@ return {
|
||||
setwinvar={args=3},
|
||||
sha256={args=1},
|
||||
shellescape={args={1, 2}},
|
||||
shiftwidth={},
|
||||
shiftwidth={args={0, 1}},
|
||||
sign_define={args={1, 2}},
|
||||
sign_getdefined={args={0, 1}},
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -6777,9 +6777,10 @@ static void nv_g_cmd(cmdarg_T *cap)
|
||||
}
|
||||
coladvance((colnr_T)i);
|
||||
if (flag) {
|
||||
do
|
||||
do {
|
||||
i = gchar_cursor();
|
||||
while (ascii_iswhite(i) && oneright());
|
||||
} while (ascii_iswhite(i) && oneright());
|
||||
curwin->w_valid &= ~VALID_WCOL;
|
||||
}
|
||||
curwin->w_set_curswant = true;
|
||||
break;
|
||||
|
@@ -288,7 +288,7 @@ void shift_line(
|
||||
{
|
||||
int count;
|
||||
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
|
||||
|
||||
@@ -332,9 +332,9 @@ static void shift_block(oparg_T *oap, int amount)
|
||||
const int oldstate = State;
|
||||
char_u *newp;
|
||||
const int oldcol = curwin->w_cursor.col;
|
||||
const int p_sw = get_sw_value(curbuf);
|
||||
const long p_ts = curbuf->b_p_ts;
|
||||
int p_sw = (int)get_sw_value_indent(curbuf);
|
||||
long *p_vts = curbuf->b_p_vts_array;
|
||||
const long p_ts = curbuf->b_p_ts;
|
||||
struct block_def bd;
|
||||
int incr;
|
||||
int i = 0, j = 0;
|
||||
|
@@ -7342,11 +7342,39 @@ int tabstop_first(long *ts)
|
||||
/// 'tabstop' value when 'shiftwidth' is zero.
|
||||
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);
|
||||
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,
|
||||
/// using the shiftwidth value when 'softtabstop' is negative.
|
||||
int get_sts_value(void)
|
||||
|
@@ -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,')
|
||||
|
Reference in New Issue
Block a user