diff options
Diffstat (limited to 'src/nvim/indent.c')
-rw-r--r-- | src/nvim/indent.c | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/src/nvim/indent.c b/src/nvim/indent.c index d635c7d7bf..b7e3842aad 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -13,6 +13,7 @@ #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" @@ -146,25 +147,42 @@ int tabstop_padding(colnr_T col, OptInt ts_arg, const colnr_T *vts) } /// Find the size of the tab that covers a particular column. -int tabstop_at(colnr_T col, OptInt ts, const colnr_T *vts) +/// +/// 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, OptInt ts, const colnr_T *vts, bool left) { - colnr_T tabcol = 0; - int t; - int tab_size = 0; - if (vts == NULL || vts[0] == 0) { return (int)ts; } - const int tabcount = vts[0]; + 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. + const int tabcount // Number of tab stops in the list of variable tab stops. + = vts[0]; for (t = 1; t <= tabcount; t++) { tabcol += vts[t]; if (tabcol > col) { - tab_size = vts[t]; + // If shifting left (left == true), 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]; } @@ -311,35 +329,35 @@ int tabstop_first(colnr_T *ts) /// 'tabstop' value when 'shiftwidth' is zero. int get_sw_value(buf_T *buf) { - int result = get_sw_value_col(buf, 0); + int result = get_sw_value_col(buf, 0, false); return result; } /// Idem, using "pos". -int get_sw_value_pos(buf_T *buf, pos_T *pos) +int get_sw_value_pos(buf_T *buf, pos_T *pos, bool left) { pos_T save_cursor = curwin->w_cursor; curwin->w_cursor = *pos; - int sw_value = get_sw_value_col(buf, get_nolist_virtcol()); + int sw_value = get_sw_value_col(buf, get_nolist_virtcol(), left); curwin->w_cursor = save_cursor; return sw_value; } /// Idem, using the first non-black in the current line. -int get_sw_value_indent(buf_T *buf) +int get_sw_value_indent(buf_T *buf, bool left) { pos_T pos = curwin->w_cursor; pos.col = (colnr_T)getwhitecols_curline(); - return get_sw_value_pos(buf, &pos); + return get_sw_value_pos(buf, &pos, left); } /// Idem, using virtual column "col". -int get_sw_value_col(buf_T *buf, colnr_T col) +int get_sw_value_col(buf_T *buf, colnr_T col, bool left) { return buf->b_p_sw ? (int)buf->b_p_sw - : 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); } /// Return the effective softtabstop value for the current buffer, @@ -873,7 +891,17 @@ int get_breakindent_win(win_T *wp, char *line) if (wp->w_briopt_list > 0) { prev_list += wp->w_briopt_list; } else { - prev_indent = (int)(*regmatch.endp - *regmatch.startp); + char *ptr = *regmatch.startp; + char *end_ptr = *regmatch.endp; + int indent = 0; + // Compute the width of the matched text. + // Use win_chartabsize() so that TAB size is correct, + // while wrapping is ignored. + while (ptr < end_ptr) { + indent += win_chartabsize(wp, ptr, indent); + MB_PTR_ADV(ptr); + } + prev_indent = indent; } } vim_regfree(regmatch.regprog); @@ -1143,7 +1171,7 @@ int get_expr_indent(void) // Need to make a copy, the 'indentexpr' option could be changed while // evaluating it. char *inde_copy = xstrdup(curbuf->b_p_inde); - int indent = (int)eval_to_number(inde_copy); + int indent = (int)eval_to_number(inde_copy, true); xfree(inde_copy); if (use_sandbox) { @@ -1389,7 +1417,7 @@ void fixthisline(IndentGetter get_the_indent) return; } - change_indent(INDENT_SET, amount, false, 0, true); + change_indent(INDENT_SET, amount, false, true); if (linewhite(curwin->w_cursor.lnum)) { did_ai = true; // delete the indent if the line stays empty } |