summaryrefslogtreecommitdiffstats
path: root/src/ex_cmds.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-06-23 19:23:02 +0200
committerBram Moolenaar <Bram@vim.org>2018-06-23 19:23:02 +0200
commit04958cbaf25eea27eceedaa987adfb354ad5f7fd (patch)
tree9a47e4e99b5b702e12d08c0424a91ae701eabb4d /src/ex_cmds.c
parent5ec7414a1c0512832f60c17437d6374cbf4b08e9 (diff)
patch 8.1.0105: all tab stops are the samev8.1.0105
Problem: All tab stops are the same. Solution: Add the variable tabstop feature. (Christian Brabandt, closes #2711)
Diffstat (limited to 'src/ex_cmds.c')
-rw-r--r--src/ex_cmds.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 60d72023c9..53334342c1 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -673,12 +673,17 @@ ex_retab(exarg_T *eap)
long vcol;
long start_col = 0; /* For start of white-space string */
long start_vcol = 0; /* For start of white-space string */
- int temp;
long old_len;
char_u *ptr;
char_u *new_line = (char_u *)1; /* init to non-NULL */
int did_undo; /* called u_save for current line */
+#ifdef FEAT_VARTABS
+ int *new_ts = 0;
+ char_u *new_ts_str; /* string value of tab argument */
+#else
+ int temp;
int new_ts;
+#endif
int save_list;
linenr_T first_line = 0; /* first changed line */
linenr_T last_line = 0; /* last changed line */
@@ -686,6 +691,23 @@ ex_retab(exarg_T *eap)
save_list = curwin->w_p_list;
curwin->w_p_list = 0; /* don't want list mode here */
+#ifdef FEAT_VARTABS
+ new_ts_str = eap->arg;
+ if (!tabstop_set(eap->arg, &new_ts))
+ return;
+ while (vim_isdigit(*(eap->arg)) || *(eap->arg) == ',')
+ ++(eap->arg);
+
+ // This ensures that either new_ts and new_ts_str are freshly allocated,
+ // or new_ts points to an existing array and new_ts_str is null.
+ if (new_ts == 0)
+ {
+ new_ts = curbuf->b_p_vts_array;
+ new_ts_str = NULL;
+ }
+ else
+ new_ts_str = vim_strnsave(new_ts_str, eap->arg - new_ts_str);
+#else
new_ts = getdigits(&(eap->arg));
if (new_ts < 0)
{
@@ -694,6 +716,7 @@ ex_retab(exarg_T *eap)
}
if (new_ts == 0)
new_ts = curbuf->b_p_ts;
+#endif
for (lnum = eap->line1; !got_int && lnum <= eap->line2; ++lnum)
{
ptr = ml_get(lnum);
@@ -726,6 +749,16 @@ ex_retab(exarg_T *eap)
num_tabs = 0;
if (!curbuf->b_p_et)
{
+#ifdef FEAT_VARTABS
+ int t, s;
+
+ tabstop_fromto(start_vcol, vcol,
+ tabstop_count(new_ts)? 0: curbuf->b_p_ts,
+ new_ts,
+ &t, &s);
+ num_tabs = t;
+ num_spaces = s;
+#else
temp = new_ts - (start_vcol % new_ts);
if (num_spaces >= temp)
{
@@ -734,6 +767,7 @@ ex_retab(exarg_T *eap)
}
num_tabs += num_spaces / new_ts;
num_spaces -= (num_spaces / new_ts) * new_ts;
+#endif
}
if (curbuf->b_p_et || got_tab ||
(num_spaces + num_tabs < len))
@@ -791,14 +825,53 @@ ex_retab(exarg_T *eap)
if (got_int)
EMSG(_(e_interr));
+#ifdef FEAT_VARTABS
+ // If a single value was given then it can be considered equal to
+ // either the value of 'tabstop' or the value of 'vartabstop'.
+ if (tabstop_count(curbuf->b_p_vts_array) == 0
+ && tabstop_count(new_ts) == 1
+ && curbuf->b_p_ts == tabstop_first(new_ts))
+ ; /* not changed */
+ else if (tabstop_count(curbuf->b_p_vts_array) > 0
+ && tabstop_eq(curbuf->b_p_vts_array, new_ts))
+ ; /* not changed */
+ else
+ redraw_curbuf_later(NOT_VALID);
+#else
if (curbuf->b_p_ts != new_ts)
redraw_curbuf_later(NOT_VALID);
+#endif
if (first_line != 0)
changed_lines(first_line, 0, last_line + 1, 0L);
curwin->w_p_list = save_list; /* restore 'list' */
+#ifdef FEAT_VARTABS
+ if (new_ts_str != NULL) /* set the new tabstop */
+ {
+ // If 'vartabstop' is in use or if the value given to retab has more
+ // than one tabstop then update 'vartabstop'.
+ int *old_vts_ary = curbuf->b_p_vts_array;
+
+ if (tabstop_count(old_vts_ary) > 0 || tabstop_count(new_ts) > 1)
+ {
+ set_string_option_direct((char_u *)"vts", -1, new_ts_str,
+ OPT_FREE|OPT_LOCAL, 0);
+ vim_free(new_ts_str);
+ curbuf->b_p_vts_array = new_ts;
+ vim_free(old_vts_ary);
+ }
+ else
+ {
+ // 'vartabstop' wasn't in use and a single value was given to
+ // retab then update 'tabstop'.
+ curbuf->b_p_ts = tabstop_first(new_ts);
+ vim_free(new_ts);
+ }
+ }
+#else
curbuf->b_p_ts = new_ts;
+#endif
coladvance(curwin->w_curswant);
u_clearline();