diff options
-rw-r--r-- | src/edit.c | 11 | ||||
-rw-r--r-- | src/evalfunc.c | 4 | ||||
-rw-r--r-- | src/indent.c | 47 | ||||
-rw-r--r-- | src/ops.c | 16 | ||||
-rw-r--r-- | src/proto/indent.pro | 6 | ||||
-rw-r--r-- | src/testdir/test_vartabs.vim | 59 | ||||
-rw-r--r-- | src/version.c | 2 |
7 files changed, 113 insertions, 32 deletions
diff --git a/src/edit.c b/src/edit.c index 075b39bff0..e75a1cf118 100644 --- a/src/edit.c +++ b/src/edit.c @@ -519,9 +519,10 @@ edit( if ( #ifdef FEAT_VARTABS - curwin->w_wcol < mincol - tabstop_at( - get_nolist_virtcol(), curbuf->b_p_ts, - curbuf->b_p_vts_array) + curwin->w_wcol < mincol - tabstop_at(get_nolist_virtcol(), + curbuf->b_p_ts, + curbuf->b_p_vts_array, + FALSE) #else (int)curwin->w_wcol < mincol - curbuf->b_p_ts #endif @@ -1310,7 +1311,7 @@ docomplete: c = ins_ctrl_ey(c); break; - default: + default: #ifdef UNIX if (c == intr_char) // special interrupt char goto do_intr; @@ -1842,7 +1843,7 @@ backspace_until_column(int col) * Only matters when there are composing characters. * Return TRUE when something was deleted. */ - static int + static int del_char_after_col(int limit_col UNUSED) { if (enc_utf8 && limit_col >= 0) diff --git a/src/evalfunc.c b/src/evalfunc.c index 6e1eb037e4..3028cf9754 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -5464,7 +5464,7 @@ f_getpos(typval_T *argvars, typval_T *rettv) /* * Convert from block_def to string */ - static char_u * + static char_u * block_def2str(struct block_def *bd) { char_u *p, *ret; @@ -10948,7 +10948,7 @@ f_shiftwidth(typval_T *argvars UNUSED, typval_T *rettv) if (col < 0) return; // type error; errmsg already given #ifdef FEAT_VARTABS - rettv->vval.v_number = get_sw_value_col(curbuf, col); + rettv->vval.v_number = get_sw_value_col(curbuf, col, FALSE); return; #endif } diff --git a/src/indent.c b/src/indent.c index 1dfde7ddda..777db244af 100644 --- a/src/indent.c +++ b/src/indent.c @@ -123,14 +123,22 @@ tabstop_padding(colnr_T col, int ts_arg, int *vts) /* * Find the size of the tab that covers a particular column. + * + * If this is being called as part of a shift operation, col is not the cursor + * column but is the column number to the left of the first non-whitespace + * character in the line. If the shift is to the left (left = TRUE), then + * return the size of the tab interval to the left of the column. */ int -tabstop_at(colnr_T col, int ts, int *vts) +tabstop_at(colnr_T col, int ts, int *vts, int left) { - int tabcount; - colnr_T tabcol = 0; - int t; - int tab_size = 0; + int tabcount; // Number of tab stops in the list of variable + // tab stops. + colnr_T tabcol = 0; // Column of the tab stop under consideration. + int t; // Tabstop index in the list of variable tab + // stops. + int tab_size = 0; // Size of the tab stop interval to the right + // or left of the col. if (vts == 0 || vts[0] == 0) return ts; @@ -141,11 +149,22 @@ tabstop_at(colnr_T col, int ts, int *vts) tabcol += vts[t]; if (tabcol > col) { - tab_size = vts[t]; + // If shifting left (left != 0), and if the column to the left of + // the first first non-blank character (col) in the line is + // already to the left of the first tabstop, set the shift amount + // (tab_size) to just enough to shift the line to the left margin. + // The value doesn't seem to matter as long as it is at least that + // distance. + if (left && (t == 1)) + tab_size = col; + else + tab_size = vts[t - (left ? 1 : 0)]; break; } } - if (t > tabcount) + if (t > tabcount) // If the value of the index t is beyond the + // end of the list, use the tab stop value at + // the end of the list. tab_size = vts[tabcount]; return tab_size; @@ -327,20 +346,20 @@ tabstop_first(int *ts) long get_sw_value(buf_T *buf) { - return get_sw_value_col(buf, 0); + return get_sw_value_col(buf, 0, FALSE); } /* * Idem, using "pos". */ static long -get_sw_value_pos(buf_T *buf, pos_T *pos) +get_sw_value_pos(buf_T *buf, pos_T *pos, int left) { pos_T save_cursor = curwin->w_cursor; long sw_value; curwin->w_cursor = *pos; - sw_value = get_sw_value_col(buf, get_nolist_virtcol()); + sw_value = get_sw_value_col(buf, get_nolist_virtcol(), left); curwin->w_cursor = save_cursor; return sw_value; } @@ -349,23 +368,23 @@ get_sw_value_pos(buf_T *buf, pos_T *pos) * Idem, using the first non-black in the current line. */ long -get_sw_value_indent(buf_T *buf) +get_sw_value_indent(buf_T *buf, int left) { pos_T pos = curwin->w_cursor; pos.col = getwhitecols_curline(); - return get_sw_value_pos(buf, &pos); + return get_sw_value_pos(buf, &pos, left); } /* * Idem, using virtual column "col". */ long -get_sw_value_col(buf_T *buf, colnr_T col UNUSED) +get_sw_value_col(buf_T *buf, colnr_T col UNUSED, int left 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); + tabstop_at(col, buf->b_p_ts, buf->b_p_vts_array, left); #else buf->b_p_ts; #endif @@ -231,7 +231,7 @@ shift_line( { vimlong_T count; int i, j; - int sw_val = trim_to_int(get_sw_value_indent(curbuf)); + int sw_val = trim_to_int(get_sw_value_indent(curbuf, left)); count = get_indent(); // get current indent @@ -283,7 +283,7 @@ shift_block(oparg_T *oap, int amount) char_u *newp, *oldp; size_t newlen, oldlen; int oldcol = curwin->w_cursor.col; - int sw_val = (int)get_sw_value_indent(curbuf); + int sw_val = (int)get_sw_value_indent(curbuf, left); int ts_val = (int)curbuf->b_p_ts; struct block_def bd; int incr; @@ -1258,8 +1258,8 @@ op_replace(oparg_T *oap, int c) replace_character(c); else PBYTE(curwin->w_cursor, c); - if (inc(&curwin->w_cursor) == -1) - break; + if (inc(&curwin->w_cursor) == -1) + break; } } @@ -2523,11 +2523,11 @@ op_addsub( int change_cnt = 0; linenr_T amount = Prenum1; - // do_addsub() might trigger re-evaluation of 'foldexpr' halfway, when the - // buffer is not completely updated yet. Postpone updating folds until before - // the call to changed_lines(). + // do_addsub() might trigger re-evaluation of 'foldexpr' halfway, when the + // buffer is not completely updated yet. Postpone updating folds until before + // the call to changed_lines(). #ifdef FEAT_FOLDING - disable_fold_update++; + disable_fold_update++; #endif if (!VIsual_active) diff --git a/src/proto/indent.pro b/src/proto/indent.pro index bafcefc677..6e56a0e370 100644 --- a/src/proto/indent.pro +++ b/src/proto/indent.pro @@ -1,15 +1,15 @@ /* indent.c */ int tabstop_set(char_u *var, int **array); int tabstop_padding(colnr_T col, int ts_arg, int *vts); -int tabstop_at(colnr_T col, int ts, int *vts); +int tabstop_at(colnr_T col, int ts, int *vts, int left); colnr_T tabstop_start(colnr_T col, int ts, int *vts); void tabstop_fromto(colnr_T start_col, colnr_T end_col, int ts_arg, int *vts, int *ntabs, int *nspcs); 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_col(buf_T *buf, colnr_T col); +long get_sw_value_indent(buf_T *buf, int left); +long get_sw_value_col(buf_T *buf, colnr_T col, int left); long get_sts_value(void); int get_indent(void); int get_indent_lnum(linenr_T lnum); diff --git a/src/testdir/test_vartabs.vim b/src/testdir/test_vartabs.vim index e15a072f72..bae00dd057 100644 --- a/src/testdir/test_vartabs.vim +++ b/src/testdir/test_vartabs.vim @@ -454,5 +454,64 @@ func Test_vartabstop_latin1() set nocompatible linebreak& list& revins& smarttab& vartabstop& endfunc +" Verify that right-shifting and left-shifting adjust lines to the proper +" tabstops. +func Test_vartabstop_shift_right_left() + new + set expandtab + set shiftwidth=0 + set vartabstop=17,11,7 + exe "norm! aword" + let expect = "word" + call assert_equal(expect, getline(1)) + + " Shift to first tabstop. + norm! >> + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift to second tabstop. + norm! >> + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift to third tabstop. + norm! >> + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift to fourth tabstop, repeating the third shift width. + norm! >> + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift back to the third tabstop. + norm! << + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift back to the second tabstop. + norm! << + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift back to the first tabstop. + norm! << + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift back to the left margin. + norm! << + let expect = "word" + call assert_equal(expect, getline(1)) + + " Shift again back to the left margin. + norm! << + let expect = "word" + call assert_equal(expect, getline(1)) + + bwipeout! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index c0d6601772..6e02c3e58e 100644 --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 456, +/**/ 455, /**/ 454, |