From e4bb185441ca57b739775d3f01a13419d9299f29 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 10 Dec 2024 14:05:39 +0800 Subject: [PATCH] vim-patch:9.1.0917: various vartabstop and shiftround bugs when shifting lines Problem: various vartabstop and shiftround bugs when shifting lines Solution: Fix the bugs, add new tests for shifting lines in various ways (Gary Johnson) fixes: vim/vim#14891 closes: vim/vim#16193 https://github.com/vim/vim/commit/eed63f96d26723ff31a9728647eed526d06a553d Co-authored-by: Gary Johnson --- src/nvim/ops.c | 141 +++++- test/old/testdir/test_shift.vim | 807 +++++++++++++++++++++++++++++++- 2 files changed, 931 insertions(+), 17 deletions(-) diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 9524c67301..71a005bd24 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -274,21 +274,53 @@ void op_shift(oparg_T *oap, bool curs_top, int amount) changed_lines(curbuf, oap->start.lnum, 0, oap->end.lnum + 1, 0, true); } -/// Shift the current line one shiftwidth left (if left != 0) or right -/// leaves cursor on first blank in the line. -/// -/// @param call_changed_bytes call changed_bytes() -void shift_line(bool left, bool round, int amount, int call_changed_bytes) +/// Return the tabstop width at the index of the variable tabstop array. If an +/// index greater than the length of the array is given, the last tabstop width +/// in the array is returned. +static int get_vts(const int *vts_array, int index) { - int sw_val = get_sw_value_indent(curbuf, left); - if (sw_val == 0) { - sw_val = 1; // shouldn't happen, just in case + int ts; + + if (index < 1) { + ts = 0; + } else if (index <= vts_array[0]) { + ts = vts_array[index]; + } else { + ts = vts_array[vts_array[0]]; } + + return ts; +} + +/// Return the sum of all the tabstops through the index-th. +static int get_vts_sum(const int *vts_array, int index) +{ + int sum = 0; + int i; + + // Perform the summation for indeces within the actual array. + for (i = 1; i <= index && i <= vts_array[0]; i++) { + sum += vts_array[i]; + } + + // Add topstops whose indeces exceed the actual array. + if (i <= index) { + sum += vts_array[vts_array[0]] * (index - vts_array[0]); + } + + return sum; +} + +/// @param left true if shift is to the left +/// @param count true if new indent is to be to a tabstop +/// @param amount number of shifts +static int64_t get_new_sw_indent(bool left, bool round, int64_t amount, int64_t sw_val) +{ int64_t count = get_indent(); // get current indent if (round) { // round off indent - int i = trim_to_int(count / sw_val); // number of 'shiftwidth' rounded down - int j = trim_to_int(count % sw_val); // extra spaces + int64_t i = trim_to_int(count / sw_val); // number of 'shiftwidth' rounded down + int64_t j = trim_to_int(count % sw_val); // extra spaces if (j && left) { // first remove extra spaces amount--; } @@ -297,15 +329,98 @@ void shift_line(bool left, bool round, int amount, int call_changed_bytes) } else { i += amount; } - count = (int64_t)i * (int64_t)sw_val; + count = i * sw_val; } else { // original vi indent if (left) { - count = MAX(count - (int64_t)sw_val * (int64_t)amount, 0); + count = MAX(count - sw_val * amount, 0); } else { - count += (int64_t)sw_val * (int64_t)amount; + count += sw_val * amount; } } + return count; +} + +/// @param left true if shift is to the left +/// @param count true if new indent is to be to a tabstop +/// @param amount number of shifts +static int64_t get_new_vts_indent(bool left, bool round, int amount, int *vts_array) +{ + int64_t indent = get_indent(); + int vtsi = 0; + int vts_indent = 0; + int ts = 0; // Silence uninitialized variable warning. + + // Find the tabstop at or to the left of the current indent. + while (vts_indent <= indent) { + vtsi++; + ts = get_vts(vts_array, vtsi); + vts_indent += ts; + } + vts_indent -= ts; + vtsi--; + + // Extra indent spaces to the right of the tabstop + int64_t offset = indent - vts_indent; + + if (round) { + if (left) { + if (offset == 0) { + indent = get_vts_sum(vts_array, vtsi - amount); + } else { + indent = get_vts_sum(vts_array, vtsi - (amount - 1)); + } + } else { + indent = get_vts_sum(vts_array, vtsi + amount); + } + } else { + if (left) { + if (amount > vtsi) { + indent = 0; + } else { + indent = get_vts_sum(vts_array, vtsi - amount) + offset; + } + } else { + indent = get_vts_sum(vts_array, vtsi + amount) + offset; + } + } + + return indent; +} + +/// Shift the current line 'amount' shiftwidth(s) left (if 'left' is true) or +/// right. +/// +/// The rules for choosing a shiftwidth are: If 'shiftwidth' is non-zero, use +/// 'shiftwidth'; else if 'vartabstop' is not empty, use 'vartabstop'; else use +/// 'tabstop'. The Vim documentation says nothing about 'softtabstop' or +/// 'varsofttabstop' affecting the shiftwidth, and neither affects the +/// shiftwidth in current versions of Vim, so they are not considered here. +/// +/// @param left true if shift is to the left +/// @param count true if new indent is to be to a tabstop +/// @param amount number of shifts +/// @param call_changed_bytes call changed_bytes() +void shift_line(bool left, bool round, int amount, int call_changed_bytes) +{ + int64_t count; + int64_t sw_val = curbuf->b_p_sw; + int64_t ts_val = curbuf->b_p_ts; + int *vts_array = curbuf->b_p_vts_array; + + if (sw_val != 0) { + // 'shiftwidth' is not zero; use it as the shift size. + count = get_new_sw_indent(left, round, amount, sw_val); + } else if ((vts_array == NULL) || (vts_array[0] == 0)) { + // 'shiftwidth' is zero and 'vartabstop' is empty; use 'tabstop' as the + // shift size. + count = get_new_sw_indent(left, round, amount, ts_val); + } else { + // 'shiftwidth' is zero and 'vartabstop' is defined; use 'vartabstop' + // to determine the new indent. + count = get_new_vts_indent(left, round, amount, vts_array); + } + // Set new indent if (State & VREPLACE_FLAG) { change_indent(INDENT_SET, trim_to_int(count), false, call_changed_bytes); diff --git a/test/old/testdir/test_shift.vim b/test/old/testdir/test_shift.vim index ec357dac88..f31c5a11e6 100644 --- a/test/old/testdir/test_shift.vim +++ b/test/old/testdir/test_shift.vim @@ -108,10 +108,809 @@ func Test_ex_shift_errors() call assert_fails('>!', 'E477:') call assert_fails('', 'E493:') - call assert_fails('execute "2,1>"', 'E493:') - " call assert_fails('2,1<', 'E493:') - call assert_fails('execute "2,1<"', 'E493:') + call assert_fails('2,1>', 'E493:') + call assert_fails('2,1<', 'E493:') +endfunc + +" Test inserting a backspace at the start of a line. +" +" This is to verify the proper behavior of tabstop_start() as called from +" ins_bs(). +" +func Test_shift_ins_bs() + set backspace=indent,start + set softtabstop=11 + + call setline(1, repeat(" ", 33) . "word") + exe "norm! I\" + call assert_equal(repeat(" ", 22) . "word", getline(1)) + call setline(1, repeat(" ", 23) . "word") + exe "norm! I\" + call assert_equal(repeat(" ", 22) . "word", getline(1)) + exe "norm! I\" + call assert_equal(repeat(" ", 11) . "word", getline(1)) + + set backspace& softtabstop& + bw! +endfunc + +" Test inserting a backspace at the start of a line, with 'varsofttabstop'. +" +func Test_shift_ins_bs_vartabs() + CheckFeature vartabs + set backspace=indent,start + set varsofttabstop=13,11,7 + + call setline(1, repeat(" ", 44) . "word") + exe "norm! I\" + call assert_equal(repeat(" ", 38) . "word", getline(1)) + call setline(1, repeat(" ", 39) . "word") + exe "norm! I\" + call assert_equal(repeat(" ", 38) . "word", getline(1)) + exe "norm! I\" + call assert_equal(repeat(" ", 31) . "word", getline(1)) + exe "norm! I\" + call assert_equal(repeat(" ", 24) . "word", getline(1)) + exe "norm! I\" + call assert_equal(repeat(" ", 13) . "word", getline(1)) + exe "norm! I\" + call assert_equal( "word", getline(1)) + exe "norm! I\" + call assert_equal( "word", getline(1)) + + set backspace& varsofttabstop& + bw! +endfunc + +" Test the >> and << normal-mode commands. +" +func Test_shift_norm() + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftwidth=5 + set tabstop=7 + + call setline(1, " word") + + " Shift by 'shiftwidth' right and left. + + norm! >> + call assert_equal(repeat(" ", 7) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 12) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 17) . "word", getline(1)) + + norm! << + call assert_equal(repeat(" ", 12) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 7) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 2) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + " Shift by 'tabstop' right and left. + + set shiftwidth=0 + call setline(1, " word") + + norm! >> + call assert_equal(repeat(" ", 9) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 16) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 23) . "word", getline(1)) + + norm! << + call assert_equal(repeat(" ", 16) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 9) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 2) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftwidth& tabstop& + bw! +endfunc + +" Test the >> and << normal-mode commands, with 'vartabstop'. +" +func Test_shift_norm_vartabs() + CheckFeature vartabs + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftwidth=0 + set vartabstop=19,17,11 + + " Shift by 'vartabstop' right and left. + + call setline(1, " word") + + norm! >> + call assert_equal(repeat(" ", 21) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 38) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 49) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 60) . "word", getline(1)) + + norm! << + call assert_equal(repeat(" ", 49) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 38) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 21) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 2) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftwidth& vartabstop& + bw! +endfunc + +" Test the >> and << normal-mode commands with 'shiftround'. +" +func Test_shift_norm_round() + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftround + set shiftwidth=5 + set tabstop=7 + + call setline(1, "word") + + " Shift by 'shiftwidth' right and left. + + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 5) . "word", getline(1)) + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 10) . "word", getline(1)) + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 15) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 20) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 25) . "word", getline(1)) + + norm! << + call assert_equal(repeat(" ", 20) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 15) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 10) . "word", getline(1)) + exe "norm! I " + norm! << + call assert_equal(repeat(" ", 10) . "word", getline(1)) + + call setline(1, repeat(" ", 7) . "word") + norm! << + call assert_equal(repeat(" ", 5) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + call setline(1, repeat(" ", 2) . "word") + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + " Shift by 'tabstop' right and left. + + set shiftwidth=0 + call setline(1, "word") + + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 7) . "word", getline(1)) + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 14) . "word", getline(1)) + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 21) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 28) . "word", getline(1)) + norm! >> + call assert_equal(repeat(" ", 35) . "word", getline(1)) + + norm! << + call assert_equal(repeat(" ", 28) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 21) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 14) . "word", getline(1)) + exe "norm! I " + norm! << + call assert_equal(repeat(" ", 14) . "word", getline(1)) + + call setline(1, repeat(" ", 9) . "word") + norm! << + call assert_equal(repeat(" ", 7) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + call setline(1, repeat(" ", 2) . "word") + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftround& shiftwidth& tabstop& + bw! +endfunc + +" Test the >> and << normal-mode commands with 'shiftround' and 'vartabstop'. +" +func Test_shift_norm_round_vartabs() + CheckFeature vartabs + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftround + set shiftwidth=0 + set vartabstop=19,17,11 + + " Shift by 'vartabstop' right and left. + + call setline(1, "word") + + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 19) . "word", getline(1)) + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 36) . "word", getline(1)) + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 47) . "word", getline(1)) + exe "norm! I " + norm! >> + call assert_equal(repeat(" ", 58) . "word", getline(1)) + + exe "norm! I " + norm! << + call assert_equal(repeat(" ", 58) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 47) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 36) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 19) . "word", getline(1)) + exe "norm! I " + norm! << + call assert_equal(repeat(" ", 19) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + exe "norm! I " + call assert_equal(repeat(" ", 2) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + norm! << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftround& shiftwidth& vartabstop& + bw! +endfunc + +" Test the V> and V< visual-mode commands. +" +" See ":help v_<" and ":help v_>". See also the last paragraph of "3. Simple +" changes", ":help simple-change", immediately above "4. Complex changes", +" ":help complex-change". +" +func Test_shift_vis() + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftwidth=5 + set tabstop=7 + + call setline(1, " word") + + " Shift by 'shiftwidth' right and left. + + norm! V> + call assert_equal(repeat(" ", 7) . "word", getline(1)) + norm! V2> + call assert_equal(repeat(" ", 17) . "word", getline(1)) + norm! V3> + call assert_equal(repeat(" ", 32) . "word", getline(1)) + + norm! V< + call assert_equal(repeat(" ", 27) . "word", getline(1)) + norm! V2< + call assert_equal(repeat(" ", 17) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 2) . "word", getline(1)) + norm! V< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + " Shift by 'tabstop' right and left. + + set shiftwidth=0 + call setline(1, " word") + + norm! V> + call assert_equal(repeat(" ", 9) . "word", getline(1)) + norm! V2> + call assert_equal(repeat(" ", 23) . "word", getline(1)) + norm! V3> + call assert_equal(repeat(" ", 44) . "word", getline(1)) + + norm! V< + call assert_equal(repeat(" ", 37) . "word", getline(1)) + norm! V2< + call assert_equal(repeat(" ", 23) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 2) . "word", getline(1)) + norm! V< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftwidth& tabstop& + bw! +endfunc + +" Test the V> and V< visual-mode commands, with 'vartabstop'. +" +" See ":help v_<" and ":help v_>". See also the last paragraph of "3. Simple +" changes", ":help simple-change", immediately above "4. Complex changes", +" ":help complex-change". +" +func Test_shift_vis_vartabs() + CheckFeature vartabs + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftwidth=0 + set vartabstop=19,17,11 + + " Shift by 'vartabstop' right and left. + + call setline(1, " word") + + norm! V> + call assert_equal(repeat(" ", 21) . "word", getline(1)) + norm! V2> + call assert_equal(repeat(" ", 49) . "word", getline(1)) + norm! V3> + call assert_equal(repeat(" ", 82) . "word", getline(1)) + + norm! V< + call assert_equal(repeat(" ", 71) . "word", getline(1)) + norm! V2< + call assert_equal(repeat(" ", 49) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 2) . "word", getline(1)) + norm! V< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftwidth& vartabstop& + bw! +endfunc + +" Test the V> and V< visual-mode commands with 'shiftround'. +" +func Test_shift_vis_round() + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftround + set shiftwidth=5 + set tabstop=7 + + call setline(1, "word") + + " Shift by 'shiftwidth' right and left. + + exe "norm! I " + norm! V> + call assert_equal(repeat(" ", 5) . "word", getline(1)) + exe "norm! I " + norm! V2> + call assert_equal(repeat(" ", 15) . "word", getline(1)) + exe "norm! I " + norm! V3> + call assert_equal(repeat(" ", 30) . "word", getline(1)) + + exe "norm! I " + norm! V2< + call assert_equal(repeat(" ", 25) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 10) . "word", getline(1)) + norm! V< + call assert_equal(repeat(" ", 5) . "word", getline(1)) + norm! V< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + " Shift by 'tabstop' right and left. + + set shiftwidth=0 + call setline(1, "word") + + exe "norm! I " + norm! V> + call assert_equal(repeat(" ", 7) . "word", getline(1)) + exe "norm! I " + norm! V2> + call assert_equal(repeat(" ", 21) . "word", getline(1)) + exe "norm! I " + norm! V3> + call assert_equal(repeat(" ", 42) . "word", getline(1)) + + exe "norm! I " + norm! V< + call assert_equal(repeat(" ", 42) . "word", getline(1)) + norm! V< + call assert_equal(repeat(" ", 35) . "word", getline(1)) + norm! V2< + call assert_equal(repeat(" ", 21) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + norm! V< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + norm! V3< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + call setline(1, " word") + norm! V< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + + set expandtab& shiftround& shiftwidth& tabstop& + bw! +endfunc + +" Test the V> and V< visual-mode commands with 'shiftround' and 'vartabstop'. +" +func Test_shift_vis_round_vartabs() + CheckFeature vartabs + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftround + set shiftwidth=0 + set vartabstop=19,17,11 + + " Shift by 'vartabstop' right and left. + + call setline(1, "word") + + exe "norm! I " + norm! V> + call assert_equal(repeat(" ", 19) . "word", getline(1)) + exe "norm! I " + norm! V3> + call assert_equal(repeat(" ", 58) . "word", getline(1)) + + exe "norm! I " + norm! V2< + call assert_equal(repeat(" ", 47) . "word", getline(1)) + exe "norm! I " + norm! V3< + call assert_equal(repeat(" ", 19) . "word", getline(1)) + exe "norm! I " + norm! V3< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + exe "norm! I " + norm! V< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftround& shiftwidth& vartabstop& + bw! +endfunc + +" Test the :> and :< ex-mode commands. +" +func Test_shift_ex() + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftwidth=5 + set tabstop=7 + + call setline(1, " word") + + " Shift by 'shiftwidth' right and left. + + > + call assert_equal(repeat(" ", 7) . "word", getline(1)) + >> + call assert_equal(repeat(" ", 17) . "word", getline(1)) + >>> + call assert_equal(repeat(" ", 32) . "word", getline(1)) + + <<<< + call assert_equal(repeat(" ", 12) . "word", getline(1)) + < + call assert_equal(repeat(" ", 7) . "word", getline(1)) + < + call assert_equal(repeat(" ", 2) . "word", getline(1)) + < + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + " Shift by 'tabstop' right and left. + + set shiftwidth=0 + call setline(1, " word") + + > + call assert_equal(repeat(" ", 9) . "word", getline(1)) + >> + call assert_equal(repeat(" ", 23) . "word", getline(1)) + >>> + call assert_equal(repeat(" ", 44) . "word", getline(1)) + + <<<< + call assert_equal(repeat(" ", 16) . "word", getline(1)) + << + call assert_equal(repeat(" ", 2) . "word", getline(1)) + < + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftwidth& tabstop& + bw! +endfunc + +" Test the :> and :< ex-mode commands, with vartabstop. +" +func Test_shift_ex_vartabs() + CheckFeature vartabs + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftwidth=0 + set vartabstop=19,17,11 + + " Shift by 'vartabstop' right and left. + + call setline(1, " word") + + > + call assert_equal(repeat(" ", 21) . "word", getline(1)) + >> + call assert_equal(repeat(" ", 49) . "word", getline(1)) + >>> + call assert_equal(repeat(" ", 82) . "word", getline(1)) + + <<<< + call assert_equal(repeat(" ", 38) . "word", getline(1)) + << + call assert_equal(repeat(" ", 2) . "word", getline(1)) + < + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftwidth& vartabstop& + bw! +endfunc + +" Test the :> and :< ex-mode commands with 'shiftround'. +" +func Test_shift_ex_round() + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftround + set shiftwidth=5 + set tabstop=7 + + call setline(1, "word") + + " Shift by 'shiftwidth' right and left. + + exe "norm! I " + > + call assert_equal(repeat(" ", 5) . "word", getline(1)) + exe "norm! I " + >> + call assert_equal(repeat(" ", 15) . "word", getline(1)) + exe "norm! I " + >>> + call assert_equal(repeat(" ", 30) . "word", getline(1)) + + exe "norm! I " + <<<< + call assert_equal(repeat(" ", 15) . "word", getline(1)) + exe "norm! I " + << + call assert_equal(repeat(" ", 10) . "word", getline(1)) + << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + >> + <<< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + " Shift by 'tabstop' right and left. + + set shiftwidth=0 + call setline(1, "word") + + exe "norm! I " + > + call assert_equal(repeat(" ", 7) . "word", getline(1)) + exe "norm! I " + >> + call assert_equal(repeat(" ", 21) . "word", getline(1)) + exe "norm! I " + >>> + call assert_equal(repeat(" ", 42) . "word", getline(1)) + + exe "norm! I " + <<<< + call assert_equal(repeat(" ", 21) . "word", getline(1)) + exe "norm! I " + << + call assert_equal(repeat(" ", 14) . "word", getline(1)) + exe "norm! I " + <<< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + >> + <<< + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftround& shiftwidth& tabstop& + bw! +endfunc + +" Test the :> and :< ex-mode commands with 'shiftround' and 'vartabstop'. +" +func Test_shift_ex_round_vartabs() + CheckFeature vartabs + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftround + set shiftwidth=0 + set vartabstop=19,17,11 + + " Shift by 'vartabstop' right and left. + + call setline(1, "word") + + exe "norm! I " + > + call assert_equal(repeat(" ", 19) . "word", getline(1)) + exe "norm! I " + >> + call assert_equal(repeat(" ", 47) . "word", getline(1)) + >>> + call assert_equal(repeat(" ", 80) . "word", getline(1)) + + <<<< + call assert_equal(repeat(" ", 36) . "word", getline(1)) + exe "norm! I " + << + call assert_equal(repeat(" ", 19) . "word", getline(1)) + exe "norm! I " + << + call assert_equal(repeat(" ", 0) . "word", getline(1)) + < + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftround& shiftwidth& vartabstop& + bw! +endfunc + +" Test shifting lines with and . +" +func Test_shift_ins() + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftwidth=5 + set tabstop=7 + + " Shift by 'shiftwidth' right and left. + + call setline(1, repeat(" ", 7) . "word") + exe "norm! 9|i\" + call assert_equal(repeat(" ", 10) . "word", getline(1)) + exe "norm! A\" + call assert_equal(repeat(" ", 15) . "word", getline(1)) + exe "norm! I \" + call assert_equal(repeat(" ", 20) . "word", getline(1)) + + exe "norm! I \" + call assert_equal(repeat(" ", 20) . "word", getline(1)) + exe "norm! I " + exe "norm! 24|i\" + call assert_equal(repeat(" ", 20) . "word", getline(1)) + exe "norm! A\" + call assert_equal(repeat(" ", 15) . "word", getline(1)) + exe "norm! I " + exe "norm! A\\" + call assert_equal(repeat(" ", 10) . "word", getline(1)) + exe "norm! I\\\" + call assert_equal(repeat(" ", 0) . "word", getline(1)) + exe "norm! I\" + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + " Shift by 'tabstop' right and left. + + set shiftwidth=0 + call setline(1, "word") + + call setline(1, repeat(" ", 9) . "word") + exe "norm! 11|i\" + call assert_equal(repeat(" ", 14) . "word", getline(1)) + exe "norm! A\" + call assert_equal(repeat(" ", 21) . "word", getline(1)) + exe "norm! I \" + call assert_equal(repeat(" ", 28) . "word", getline(1)) + + exe "norm! I \" + call assert_equal(repeat(" ", 28) . "word", getline(1)) + exe "norm! I " + exe "norm! 32|i\" + call assert_equal(repeat(" ", 28) . "word", getline(1)) + exe "norm! A\" + call assert_equal(repeat(" ", 21) . "word", getline(1)) + exe "norm! I " + exe "norm! A\\" + call assert_equal(repeat(" ", 14) . "word", getline(1)) + exe "norm! I\\\" + call assert_equal(repeat(" ", 0) . "word", getline(1)) + exe "norm! I\" + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftwidth& tabstop& + bw! +endfunc + +" Test shifting lines with and , with 'vartabstop'. +" +func Test_shift_ins_vartabs() + CheckFeature vartabs + set expandtab " Don't want to worry about tabs vs. spaces in + " results. + + set shiftwidth=0 + set vartabstop=19,17,11 + + " Shift by 'vartabstop' right and left. + + call setline(1, "word") + + call setline(1, repeat(" ", 9) . "word") + exe "norm! 11|i\" + call assert_equal(repeat(" ", 19) . "word", getline(1)) + exe "norm! A\" + call assert_equal(repeat(" ", 36) . "word", getline(1)) + exe "norm! I \" + call assert_equal(repeat(" ", 47) . "word", getline(1)) + + exe "norm! I \" + call assert_equal(repeat(" ", 47) . "word", getline(1)) + exe "norm! I " + exe "norm! 51|i\" + call assert_equal(repeat(" ", 47) . "word", getline(1)) + exe "norm! A\" + call assert_equal(repeat(" ", 36) . "word", getline(1)) + exe "norm! I " + exe "norm! A\\" + call assert_equal(repeat(" ", 19) . "word", getline(1)) + exe "norm! I\\\" + call assert_equal(repeat(" ", 0) . "word", getline(1)) + exe "norm! I\" + call assert_equal(repeat(" ", 0) . "word", getline(1)) + + set expandtab& shiftwidth& vartabstop& + bw! endfunc " vim: shiftwidth=2 sts=2 expandtab