diff options
Diffstat (limited to 'data/vim/patches/8.1.0105')
-rw-r--r-- | data/vim/patches/8.1.0105 | 3397 |
1 files changed, 3397 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.0105 b/data/vim/patches/8.1.0105 new file mode 100644 index 000000000..fe689753b --- /dev/null +++ b/data/vim/patches/8.1.0105 @@ -0,0 +1,3397 @@ +To: vim_dev@googlegroups.com +Subject: Patch 8.1.0105 +Fcc: outbox +From: Bram Moolenaar <Bram@moolenaar.net> +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +------------ + +Patch 8.1.0105 +Problem: All tab stops are the same. +Solution: Add the variable tabstop feature. (Christian Brabandt, + closes #2711) +Files: runtime/doc/change.txt, runtime/doc/options.txt, + runtime/doc/various.txt, runtime/optwin.vim, src/beval.c, + src/beval.h, src/buffer.c, src/charset.c, src/edit.c, + src/evalfunc.c, src/ex_cmds.c, src/feature.h, src/gui_beval.c, + src/gui_w32.c, src/hardcopy.c, src/message.c, src/misc1.c, + src/ops.c, src/option.c, src/option.h, src/proto/misc1.pro, + src/proto/option.pro, src/screen.c, src/structs.h, + src/testdir/Make_all.mak, src/testdir/gen_opt_test.vim, + src/testdir/test_breakindent.vim, src/testdir/test_vartabs.vim, + src/version.c, src/workshop.c, src/Makefile + + +*** ../vim-8.1.0104/runtime/doc/change.txt 2018-05-17 13:40:51.000000000 +0200 +--- runtime/doc/change.txt 2018-06-23 17:41:10.096366118 +0200 +*************** +*** 987,992 **** +--- 987,997 ---- + this (that's a good habit anyway). + `:retab!` may also change a sequence of spaces by + <Tab> characters, which can mess up a printf(). ++ If the |+vartabs| feature is enabled then a list of ++ tab widths separated by commas may be used in place of ++ a single tabstop. Each value in the list represents ++ the width of one tabstop, except the final value which ++ applies to all following tabstops. + {not in Vi} + + *retab-example* +*** ../vim-8.1.0104/runtime/doc/options.txt 2018-06-03 14:42:17.832505129 +0200 +--- runtime/doc/options.txt 2018-06-23 17:41:10.100366093 +0200 +*************** +*** 7172,7177 **** +--- 7172,7181 ---- + set. + NOTE: This option is set to 0 when 'compatible' is set. + ++ If Vim is compiled with the |+vartabs| feature then the value of ++ 'softtabstop' will be ignored if |'varsofttabstop'| is set to ++ anything other than an empty string. ++ + *'spell'* *'nospell'* + 'spell' boolean (default off) + local to window +*************** +*** 7723,7728 **** +--- 7727,7736 ---- + though. Otherwise aligned comments will be wrong when 'tabstop' is + changed. + ++ If Vim is compiled with the |+vartabs| feature then the value of ++ 'tabstop' will be ignored if |'vartabstop'| is set to anything other ++ than an empty string. ++ + *'tagbsearch'* *'tbs'* *'notagbsearch'* *'notbs'* + 'tagbsearch' 'tbs' boolean (default on) + global +*************** +*** 8468,8473 **** +--- 8476,8519 ---- + written to disk (see |crash-recovery|). Also used for the + |CursorHold| autocommand event. + ++ *'varsofttabstop'* *'vsts'* ++ 'varsofttabstop' 'vsts' string (default "") ++ local to buffer ++ {only available when compiled with the |+vartabs| ++ feature} ++ {not in Vi} ++ A list of the number of spaces that a <Tab> counts for while editing, ++ such as inserting a <Tab> or using <BS>. It "feels" like variable- ++ width <Tab>s are being inserted, while in fact a mixture of spaces ++ and <Tab>s is used. Tab widths are separated with commas, with the ++ final value applying to all subsequent tabs. ++ ++ For example, when editing assembly language files where statements ++ start in the 8th column and comments in the 40th, it may be useful ++ to use the following: > ++ :set varsofttabstop=8,32,8 ++ < This will set soft tabstops at the 8th and 40th columns, and at every ++ 8th column thereafter. ++ ++ Note that the value of |'softtabstop'| will be ignored while ++ 'varsofttabstop' is set. ++ ++ *'vartabstop'* *'vts'* ++ 'vartabstop' 'vts' string (default "") ++ local to buffer ++ {only available when compiled with the |+vartabs| ++ feature} ++ {not in Vi} ++ A list of the number of spaces that a <Tab> in the file counts for, ++ separated by commas. Each value corresponds to one tab, with the ++ final value applying to all subsequent tabs. For example: > ++ :set vartabstop=4,20,10,8 ++ < This will make the first tab 4 spaces wide, the second 20 spaces, ++ the third 10 spaces, and all following tabs 8 spaces. ++ ++ Note that the value of |'tabstop'| will be ignored while 'vartabstop' ++ is set. ++ + *'verbose'* *'vbs'* + 'verbose' 'vbs' number (default 0) + global +*** ../vim-8.1.0104/runtime/doc/various.txt 2018-05-17 13:42:04.000000000 +0200 +--- runtime/doc/various.txt 2018-06-23 17:41:10.100366093 +0200 +*************** +*** 453,458 **** +--- 453,459 ---- + N *+title* Setting the window 'title' and 'icon' + N *+toolbar* |gui-toolbar| + N *+user_commands* User-defined commands. |user-commands| ++ B *+vartabs* Variable-width tabstops. |'vartabstop'| + N *+viminfo* |'viminfo'| + *+vertsplit* Vertically split windows |:vsplit|; Always enabled + since 8.0.1118. +*** ../vim-8.1.0104/runtime/optwin.vim 2018-05-15 21:39:18.000000000 +0200 +--- runtime/optwin.vim 2018-06-23 17:41:10.100366093 +0200 +*************** +*** 856,861 **** +--- 856,869 ---- + call append("$", "shiftwidth\tnumber of spaces used for each step of (auto)indent") + call append("$", "\t(local to buffer)") + call <SID>OptionL("sw") ++ if has("vartabs") ++ call append("$", "vartabstop\tlist of number of spaces a tab counts for") ++ call append("$", "\t(local to buffer)") ++ call <SID>OptionL("vts") ++ call append("$", "varsofttabstop\tlist of number of spaces a soft tabsstop counts for") ++ call append("$", "\t(local to buffer)") ++ call <SID>OptionL("vsts") ++ endif + call append("$", "smarttab\ta <Tab> in an indent inserts 'shiftwidth' spaces") + call <SID>BinOptionG("sta", &sta) + call append("$", "softtabstop\tif non-zero, number of spaces to insert for a <Tab>") +*** ../vim-8.1.0104/src/beval.c 2018-02-06 22:46:29.000000000 +0100 +--- src/beval.c 2018-06-23 18:34:30.918950814 +0200 +*************** +*** 124,129 **** +--- 124,134 ---- + *lnump = lnum; + *textp = lbuf; + *colp = col; ++ #ifdef FEAT_VARTABS ++ if (beval->vts) ++ vim_free(beval->vts); ++ beval->vts = tabstop_copy(wp->w_buffer->b_p_vts_array); ++ #endif + beval->ts = wp->w_buffer->b_p_ts; + return OK; + } +*** ../vim-8.1.0104/src/beval.h 2017-11-19 20:22:17.000000000 +0100 +--- src/beval.h 2018-06-23 18:42:21.444354814 +0200 +*************** +*** 71,77 **** + void *clientData; /* For callback */ + #endif + +! int ts; /* tabstop setting for this buffer */ + char_u *msg; + } BalloonEval; + +--- 71,80 ---- + void *clientData; /* For callback */ + #endif + +! int ts; // tabstop setting for this buffer +! #ifdef FEAT_VARTABS +! int *vts; // vartabstop setting for this buffer +! #endif + char_u *msg; + } BalloonEval; + +*** ../vim-8.1.0104/src/buffer.c 2018-06-16 22:58:11.791025515 +0200 +--- src/buffer.c 2018-06-23 18:34:40.502898381 +0200 +*************** +*** 271,277 **** + /* + * Set/reset the Changed flag first, autocmds may change the buffer. + * Apply the automatic commands, before processing the modelines. +! * So the modelines have priority over auto commands. + */ + /* When reading stdin, the buffer contents always needs writing, so set + * the changed flag. Unless in readonly mode: "ls | gview -". +--- 271,277 ---- + /* + * Set/reset the Changed flag first, autocmds may change the buffer. + * Apply the automatic commands, before processing the modelines. +! * So the modelines have priority over autocommands. + */ + /* When reading stdin, the buffer contents always needs writing, so set + * the changed flag. Unless in readonly mode: "ls | gview -". +*************** +*** 2159,2164 **** +--- 2159,2177 ---- + clear_string_option(&buf->b_p_fo); + clear_string_option(&buf->b_p_flp); + clear_string_option(&buf->b_p_isk); ++ #ifdef FEAT_VARTABS ++ clear_string_option(&buf->b_p_vsts); ++ if (buf->b_p_vsts_nopaste) ++ vim_free(buf->b_p_vsts_nopaste); ++ buf->b_p_vsts_nopaste = NULL; ++ if (buf->b_p_vsts_array) ++ vim_free(buf->b_p_vsts_array); ++ buf->b_p_vsts_array = NULL; ++ clear_string_option(&buf->b_p_vts); ++ if (buf->b_p_vts_array) ++ vim_free(buf->b_p_vts_array); ++ buf->b_p_vts_array = NULL; ++ #endif + #ifdef FEAT_KEYMAP + clear_string_option(&buf->b_p_keymap); + keymap_clear(&buf->b_kmap_ga); +*************** +*** 5190,5196 **** + win_close(wp, FALSE); + wpnext = firstwin; /* just in case an autocommand does + something strange with windows */ +! tpnext = first_tabpage; /* start all over...*/ + open_wins = 0; + } + else +--- 5203,5209 ---- + win_close(wp, FALSE); + wpnext = firstwin; /* just in case an autocommand does + something strange with windows */ +! tpnext = first_tabpage; /* start all over... */ + open_wins = 0; + } + else +*************** +*** 5650,5657 **** + } + + /* +! * Return TRUE if "buf" is a "nofile", "acwrite" or "terminal" buffer. +! * This means the buffer name is not a file name. + */ + int + bt_nofile(buf_T *buf) +--- 5663,5670 ---- + } + + /* +! * Return TRUE if "buf" is a "nofile", "acwrite", "terminal" or "prompt" +! * buffer. This means the buffer name is not a file name. + */ + int + bt_nofile(buf_T *buf) +*************** +*** 5663,5669 **** + } + + /* +! * Return TRUE if "buf" is a "nowrite", "nofile" or "terminal" buffer. + */ + int + bt_dontwrite(buf_T *buf) +--- 5676,5683 ---- + } + + /* +! * Return TRUE if "buf" is a "nowrite", "nofile", "terminal" or "prompt" +! * buffer. + */ + int + bt_dontwrite(buf_T *buf) +*** ../vim-8.1.0104/src/charset.c 2018-06-12 17:25:32.054404315 +0200 +--- src/charset.c 2018-06-23 18:42:59.804141756 +0200 +*************** +*** 812,818 **** + * Also see getvcol() below. + */ + +! #define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \ + if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) \ + { \ + int ts; \ +--- 812,827 ---- + * Also see getvcol() below. + */ + +! #ifdef FEAT_VARTABS +! # define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \ +! if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) \ +! { \ +! return tabstop_padding(col, (buf)->b_p_ts, (buf)->b_p_vts_array); \ +! } \ +! else \ +! return ptr2cells(p); +! #else +! # define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \ + if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) \ + { \ + int ts; \ +*************** +*** 821,826 **** +--- 830,836 ---- + } \ + else \ + return ptr2cells(p); ++ #endif + + int + chartabsize(char_u *p, colnr_T col) +*************** +*** 1221,1228 **** +--- 1231,1243 ---- + + if (*s == TAB && (!wp->w_p_list || lcs_tab1)) + { ++ # ifdef FEAT_VARTABS ++ return tabstop_padding(col, wp->w_buffer->b_p_ts, ++ wp->w_buffer->b_p_vts_array); ++ # else + n = wp->w_buffer->b_p_ts; + return (int)(n - (col % n)); ++ # endif + } + n = ptr2cells(s); + /* Add one cell for a double-width character in the last column of the +*************** +*** 1282,1287 **** +--- 1297,1305 ---- + char_u *line; /* start of the line */ + int incr; + int head; ++ #ifdef FEAT_VARTABS ++ int *vts = wp->w_buffer->b_p_vts_array; ++ #endif + int ts = wp->w_buffer->b_p_ts; + int c; + +*************** +*** 1332,1338 **** +--- 1350,1360 ---- + } + /* A tab gets expanded, depending on the current column */ + if (c == TAB) ++ #ifdef FEAT_VARTABS ++ incr = tabstop_padding(vcol, ts, vts); ++ #else + incr = ts - (vcol % ts); ++ #endif + else + { + #ifdef FEAT_MBYTE +*** ../vim-8.1.0104/src/edit.c 2018-06-17 19:36:30.215317108 +0200 +--- src/edit.c 2018-06-23 18:56:42.835538285 +0200 +*************** +*** 742,748 **** + mincol = curwin->w_wcol; + validate_cursor_col(); + +! if ((int)curwin->w_wcol < mincol - curbuf->b_p_ts + && curwin->w_wrow == W_WINROW(curwin) + + curwin->w_height - 1 - p_so + && (curwin->w_cursor.lnum != curwin->w_topline +--- 742,755 ---- + mincol = curwin->w_wcol; + validate_cursor_col(); + +! if ( +! #ifdef FEAT_VARTABS +! (int)curwin->w_wcol < mincol - tabstop_at( +! get_nolist_virtcol(), curbuf->b_p_ts, +! curbuf->b_p_vts_array) +! #else +! (int)curwin->w_wcol < mincol - curbuf->b_p_ts +! #endif + && curwin->w_wrow == W_WINROW(curwin) + + curwin->w_height - 1 - p_so + && (curwin->w_cursor.lnum != curwin->w_topline +*************** +*** 9329,9351 **** + */ + if ( mode == BACKSPACE_CHAR + && ((p_sta && in_indent) +! || (get_sts_value() != 0 + && curwin->w_cursor.col > 0 + && (*(ml_get_cursor() - 1) == TAB + || (*(ml_get_cursor() - 1) == ' ' + && (!*inserted_space_p + || arrow_used)))))) + { + int ts; + colnr_T vcol; + colnr_T want_vcol; + colnr_T start_vcol; + + *inserted_space_p = FALSE; + if (p_sta && in_indent) + ts = (int)get_sw_value(curbuf); + else + ts = (int)get_sts_value(); + /* Compute the virtual column where we want to be. Since + * 'showbreak' may get in the way, need to get the last column of + * the previous character. */ +--- 9336,9366 ---- + */ + if ( mode == BACKSPACE_CHAR + && ((p_sta && in_indent) +! || ((get_sts_value() != 0 +! #ifdef FEAT_VARTABS +! || tabstop_count(curbuf->b_p_vsts_array) +! #endif +! ) + && curwin->w_cursor.col > 0 + && (*(ml_get_cursor() - 1) == TAB + || (*(ml_get_cursor() - 1) == ' ' + && (!*inserted_space_p + || arrow_used)))))) + { ++ #ifndef FEAT_VARTABS + int ts; ++ #endif + colnr_T vcol; + colnr_T want_vcol; + colnr_T start_vcol; + + *inserted_space_p = FALSE; ++ #ifndef FEAT_VARTABS + if (p_sta && in_indent) + ts = (int)get_sw_value(curbuf); + else + ts = (int)get_sts_value(); ++ #endif + /* Compute the virtual column where we want to be. Since + * 'showbreak' may get in the way, need to get the last column of + * the previous character. */ +*************** +*** 9354,9360 **** +--- 9369,9383 ---- + dec_cursor(); + getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol); + inc_cursor(); ++ #ifdef FEAT_VARTABS ++ if (p_sta && in_indent) ++ want_vcol = (want_vcol / curbuf->b_p_sw) * curbuf->b_p_sw; ++ else ++ want_vcol = tabstop_start(want_vcol, curbuf->b_p_sts, ++ curbuf->b_p_vsts_array); ++ #else + want_vcol = (want_vcol / ts) * ts; ++ #endif + + /* delete characters until we are at or before want_vcol */ + while (vcol > want_vcol +*************** +*** 10144,10153 **** + #endif + + /* +! * When nothing special, insert TAB like a normal character + */ + if (!curbuf->b_p_et + && !(p_sta && ind && curbuf->b_p_ts != get_sw_value(curbuf)) + && get_sts_value() == 0) + return TRUE; + +--- 10167,10188 ---- + #endif + + /* +! * When nothing special, insert TAB like a normal character. + */ + if (!curbuf->b_p_et ++ #ifdef FEAT_VARTABS ++ && !(p_sta && ind ++ /* These five lines mean 'tabstop' != 'shiftwidth' */ ++ && ((tabstop_count(curbuf->b_p_vts_array) > 1) ++ || (tabstop_count(curbuf->b_p_vts_array) == 1 ++ && tabstop_first(curbuf->b_p_vts_array) ++ != get_sw_value(curbuf)) ++ || (tabstop_count(curbuf->b_p_vts_array) == 0 ++ && curbuf->b_p_ts != get_sw_value(curbuf)))) ++ && tabstop_count(curbuf->b_p_vsts_array) == 0 ++ #else + && !(p_sta && ind && curbuf->b_p_ts != get_sw_value(curbuf)) ++ #endif + && get_sts_value() == 0) + return TRUE; + +*************** +*** 10162,10167 **** +--- 10197,10216 ---- + #endif + AppendToRedobuff((char_u *)"\t"); + ++ #ifdef FEAT_VARTABS ++ if (p_sta && ind) /* insert tab in indent, use 'shiftwidth' */ ++ { ++ temp = (int)curbuf->b_p_sw; ++ temp -= get_nolist_virtcol() % temp; ++ } ++ else if (tabstop_count(curbuf->b_p_vsts_array) > 0 || curbuf->b_p_sts > 0) ++ /* use 'softtabstop' when set */ ++ temp = tabstop_padding(get_nolist_virtcol(), curbuf->b_p_sts, ++ curbuf->b_p_vsts_array); ++ else /* otherwise use 'tabstop' */ ++ temp = tabstop_padding(get_nolist_virtcol(), curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ #else + if (p_sta && ind) /* insert tab in indent, use 'shiftwidth' */ + temp = (int)get_sw_value(curbuf); + else if (curbuf->b_p_sts != 0) /* use 'softtabstop' when set */ +*************** +*** 10169,10174 **** +--- 10218,10224 ---- + else /* otherwise use 'tabstop' */ + temp = (int)curbuf->b_p_ts; + temp -= get_nolist_virtcol() % temp; ++ #endif + + /* + * Insert the first space with ins_char(). It will delete one char in +*************** +*** 10193,10199 **** +--- 10243,10255 ---- + /* + * When 'expandtab' not set: Replace spaces by TABs where possible. + */ ++ #ifdef FEAT_VARTABS ++ if (!curbuf->b_p_et && (tabstop_count(curbuf->b_p_vsts_array) > 0 ++ || get_sts_value() > 0 ++ || (p_sta && ind))) ++ #else + if (!curbuf->b_p_et && (get_sts_value() || (p_sta && ind))) ++ #endif + { + char_u *ptr; + #ifdef FEAT_VREPLACE +*** ../vim-8.1.0104/src/evalfunc.c 2018-06-23 14:21:38.467484932 +0200 +--- src/evalfunc.c 2018-06-23 17:41:10.108366044 +0200 +*************** +*** 6436,6441 **** +--- 6436,6444 ---- + "user-commands", /* was accidentally included in 5.4 */ + "user_commands", + #endif ++ #ifdef FEAT_VARTABS ++ "vartabs", ++ #endif + #ifdef FEAT_VIMINFO + "viminfo", + #endif +*** ../vim-8.1.0104/src/ex_cmds.c 2018-06-04 20:34:07.607373577 +0200 +--- src/ex_cmds.c 2018-06-23 18:49:09.570076283 +0200 +*************** +*** 673,684 **** + 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 */ + int new_ts; + int save_list; + linenr_T first_line = 0; /* first changed line */ + linenr_T last_line = 0; /* last changed line */ +--- 673,689 ---- + long vcol; + long start_col = 0; /* For start of white-space string */ + long start_vcol = 0; /* For start of white-space string */ + 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,691 **** +--- 691,713 ---- + 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,699 **** +--- 716,722 ---- + } + 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,731 **** +--- 749,764 ---- + 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,739 **** +--- 767,773 ---- + } + 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,804 **** +--- 825,877 ---- + 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(); +*** ../vim-8.1.0104/src/feature.h 2018-03-29 15:32:30.000000000 +0200 +--- src/feature.h 2018-06-23 17:41:10.108366044 +0200 +*************** +*** 806,811 **** +--- 806,818 ---- + #endif + + /* ++ * +vartabs 'vartabstop' and 'varsofttabstop' options. ++ */ ++ #ifdef FEAT_BIG ++ # define FEAT_VARTABS ++ #endif ++ ++ /* + * Preferences: + * ============ + */ +*** ../vim-8.1.0104/src/gui_beval.c 2017-11-18 21:20:07.000000000 +0100 +--- src/gui_beval.c 2018-06-23 18:50:11.437730010 +0200 +*************** +*** 130,135 **** +--- 130,138 ---- + beval->msg = mesg; + beval->msgCB = mesgCB; + beval->clientData = clientData; ++ #ifdef FEAT_VARTABS ++ beval->vts = NULL; ++ #endif + + /* + * Set up event handler which will keep its eyes on the pointer, +*************** +*** 172,177 **** +--- 175,184 ---- + # else + XtDestroyWidget(beval->balloonShell); + # endif ++ # ifdef FEAT_VARTABS ++ if (beval->vts) ++ vim_free(beval->vts); ++ # endif + vim_free(beval); + } + #endif +*** ../vim-8.1.0104/src/gui_w32.c 2018-06-19 14:45:33.583620880 +0200 +--- src/gui_w32.c 2018-06-23 18:50:14.853710890 +0200 +*************** +*** 8934,8939 **** +--- 8934,8942 ---- + beval->msg = mesg; + beval->msgCB = mesgCB; + beval->clientData = clientData; ++ #ifdef FEAT_VARTABS ++ beval->vts = NULL; ++ #endif + + InitCommonControls(); + cur_beval = beval; +*************** +*** 8990,8995 **** +--- 8993,9002 ---- + void + gui_mch_destroy_beval_area(BalloonEval *beval) + { ++ #ifdef FEAT_VARTABS ++ if (beval->vts) ++ vim_free(beval->vts); ++ #endif + vim_free(beval); + } + #endif /* FEAT_BEVAL_GUI */ +*** ../vim-8.1.0104/src/hardcopy.c 2018-06-16 14:44:05.750081612 +0200 +--- src/hardcopy.c 2018-06-23 18:35:24.530657199 +0200 +*************** +*** 915,921 **** +--- 915,926 ---- + if (line[col] == TAB || tab_spaces != 0) + { + if (tab_spaces == 0) ++ #ifdef FEAT_VARTABS ++ tab_spaces = tabstop_padding(print_pos, curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ #else + tab_spaces = (int)(curbuf->b_p_ts - (print_pos % curbuf->b_p_ts)); ++ #endif + + while (tab_spaces > 0) + { +*** ../vim-8.1.0104/src/message.c 2018-06-19 17:49:20.300015350 +0200 +--- src/message.c 2018-06-23 18:35:29.794628331 +0200 +*************** +*** 1831,1837 **** +--- 1831,1842 ---- + if (c == TAB && (!list || lcs_tab1)) + { + /* tab amount depends on current column */ ++ #ifdef FEAT_VARTABS ++ n_extra = tabstop_padding(col, curbuf->b_p_ts, ++ curbuf->b_p_vts_array) - 1; ++ #else + n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1; ++ #endif + if (!list) + { + c = ' '; +*** ../vim-8.1.0104/src/misc1.c 2018-06-19 18:58:04.010489820 +0200 +--- src/misc1.c 2018-06-23 18:50:28.649633665 +0200 +*************** +*** 36,42 **** +--- 36,47 ---- + int + get_indent(void) + { ++ #ifdef FEAT_VARTABS ++ return get_indent_str_vtab(ml_get_curline(), (int)curbuf->b_p_ts, ++ curbuf->b_p_vts_array, FALSE); ++ #else + return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts, FALSE); ++ #endif + } + + /* +*************** +*** 45,51 **** +--- 50,61 ---- + int + get_indent_lnum(linenr_T lnum) + { ++ #ifdef FEAT_VARTABS ++ return get_indent_str_vtab(ml_get(lnum), (int)curbuf->b_p_ts, ++ curbuf->b_p_vts_array, FALSE); ++ #else + return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts, FALSE); ++ #endif + } + + #if defined(FEAT_FOLDING) || defined(PROTO) +*************** +*** 56,62 **** +--- 66,77 ---- + int + get_indent_buf(buf_T *buf, linenr_T lnum) + { ++ #ifdef FEAT_VARTABS ++ return get_indent_str_vtab(ml_get_buf(buf, lnum, FALSE), ++ (int)curbuf->b_p_ts, buf->b_p_vts_array, FALSE); ++ #else + return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts, FALSE); ++ #endif + } + #endif + +*************** +*** 91,96 **** +--- 106,142 ---- + return count; + } + ++ #ifdef FEAT_VARTABS ++ /* ++ * Count the size (in window cells) of the indent in line "ptr", using ++ * variable tabstops. ++ * if "list" is TRUE, count only screen size for tabs. ++ */ ++ int ++ get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list) ++ { ++ int count = 0; ++ ++ for ( ; *ptr; ++ptr) ++ { ++ if (*ptr == TAB) /* count a tab for what it is worth */ ++ { ++ if (!list || lcs_tab1) ++ count += tabstop_padding(count, ts, vts); ++ else ++ /* In list mode, when tab is not set, count screen char width ++ * for Tab, displays: ^I */ ++ count += ptr2cells(ptr); ++ } ++ else if (*ptr == ' ') ++ ++count; /* count a space for one */ ++ else ++ break; ++ } ++ return count; ++ } ++ #endif ++ + /* + * Set the indent of the current line. + * Leaves the cursor on the first non-blank in the line. +*************** +*** 115,120 **** +--- 161,169 ---- + int line_len; + int doit = FALSE; + int ind_done = 0; /* measured in spaces */ ++ #ifdef FEAT_VARTABS ++ int ind_col = 0; ++ #endif + int tab_pad; + int retval = FALSE; + int orig_char_len = -1; /* number of initial whitespace chars when +*************** +*** 147,154 **** +--- 196,208 ---- + { + if (*p == TAB) + { ++ #ifdef FEAT_VARTABS ++ tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ #else + tab_pad = (int)curbuf->b_p_ts + - (ind_done % (int)curbuf->b_p_ts); ++ #endif + /* stop if this tab will overshoot the target */ + if (todo < tab_pad) + break; +*************** +*** 165,187 **** +--- 219,269 ---- + ++p; + } + ++ #ifdef FEAT_VARTABS ++ /* These diverge from this point. */ ++ ind_col = ind_done; ++ #endif + /* Set initial number of whitespace chars to copy if we are + * preserving indent but expandtab is set */ + if (curbuf->b_p_et) + orig_char_len = ind_len; + + /* Fill to next tabstop with a tab, if possible */ ++ #ifdef FEAT_VARTABS ++ tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ #else + tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); ++ #endif + if (todo >= tab_pad && orig_char_len == -1) + { + doit = TRUE; + todo -= tab_pad; + ++ind_len; + /* ind_done += tab_pad; */ ++ #ifdef FEAT_VARTABS ++ ind_col += tab_pad; ++ #endif + } + } + + /* count tabs required for indent */ ++ #ifdef FEAT_VARTABS ++ for (;;) ++ { ++ tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ if (todo < tab_pad) ++ break; ++ if (*p != TAB) ++ doit = TRUE; ++ else ++ ++p; ++ todo -= tab_pad; ++ ++ind_len; ++ ind_col += tab_pad; ++ } ++ #else + while (todo >= (int)curbuf->b_p_ts) + { + if (*p != TAB) +*************** +*** 192,197 **** +--- 274,280 ---- + ++ind_len; + /* ind_done += (int)curbuf->b_p_ts; */ + } ++ #endif + } + /* count spaces required for indent */ + while (todo > 0) +*************** +*** 266,273 **** +--- 349,361 ---- + { + if (*p == TAB) + { ++ #ifdef FEAT_VARTABS ++ tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ #else + tab_pad = (int)curbuf->b_p_ts + - (ind_done % (int)curbuf->b_p_ts); ++ #endif + /* stop if this tab will overshoot the target */ + if (todo < tab_pad) + break; +*************** +*** 283,303 **** +--- 371,412 ---- + } + + /* Fill to next tabstop with a tab, if possible */ ++ #ifdef FEAT_VARTABS ++ tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ #else + tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); ++ #endif + if (todo >= tab_pad) + { + *s++ = TAB; + todo -= tab_pad; ++ #ifdef FEAT_VARTABS ++ ind_done += tab_pad; ++ #endif + } + + p = skipwhite(p); + } + ++ #ifdef FEAT_VARTABS ++ for (;;) ++ { ++ tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ if (todo < tab_pad) ++ break; ++ *s++ = TAB; ++ todo -= tab_pad; ++ ind_done += tab_pad; ++ } ++ #else + while (todo >= (int)curbuf->b_p_ts) + { + *s++ = TAB; + todo -= (int)curbuf->b_p_ts; + } ++ #endif + } + while (todo > 0) + { +*************** +*** 350,355 **** +--- 459,467 ---- + int tab_pad; + int ind_done; + int round; ++ #ifdef FEAT_VARTABS ++ int ind_col; ++ #endif + + /* Round 1: compute the number of characters needed for the indent + * Round 2: copy the characters. */ +*************** +*** 358,363 **** +--- 470,478 ---- + todo = size; + ind_len = 0; + ind_done = 0; ++ #ifdef FEAT_VARTABS ++ ind_col = 0; ++ #endif + s = src; + + /* Count/copy the usable portion of the source line */ +*************** +*** 365,382 **** +--- 480,508 ---- + { + if (*s == TAB) + { ++ #ifdef FEAT_VARTABS ++ tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ #else + tab_pad = (int)curbuf->b_p_ts + - (ind_done % (int)curbuf->b_p_ts); ++ #endif + /* Stop if this tab will overshoot the target */ + if (todo < tab_pad) + break; + todo -= tab_pad; + ind_done += tab_pad; ++ #ifdef FEAT_VARTABS ++ ind_col += tab_pad; ++ #endif + } + else + { + --todo; + ++ind_done; ++ #ifdef FEAT_VARTABS ++ ++ind_col; ++ #endif + } + ++ind_len; + if (p != NULL) +*************** +*** 385,406 **** + } + + /* Fill to next tabstop with a tab, if possible */ + tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); + if (todo >= tab_pad && !curbuf->b_p_et) + { + todo -= tab_pad; + ++ind_len; + if (p != NULL) + *p++ = TAB; + } + + /* Add tabs required for indent */ +! while (todo >= (int)curbuf->b_p_ts && !curbuf->b_p_et) + { +! todo -= (int)curbuf->b_p_ts; +! ++ind_len; +! if (p != NULL) +! *p++ = TAB; + } + + /* Count/add spaces required for indent */ +--- 511,558 ---- + } + + /* Fill to next tabstop with a tab, if possible */ ++ #ifdef FEAT_VARTABS ++ tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, ++ curbuf->b_p_vts_array); ++ #else + tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); ++ #endif + if (todo >= tab_pad && !curbuf->b_p_et) + { + todo -= tab_pad; + ++ind_len; ++ #ifdef FEAT_VARTABS ++ ind_col += tab_pad; ++ #endif + if (p != NULL) + *p++ = TAB; + } + + /* Add tabs required for indent */ +! if (!curbuf->b_p_et) + { +! #ifdef FEAT_VARTABS +! for (;;) +! { +! tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts, +! curbuf->b_p_vts_array); +! if (todo < tab_pad) +! break; +! todo -= tab_pad; +! ++ind_len; +! ind_col += tab_pad; +! if (p != NULL) +! *p++ = TAB; +! } +! #else +! while (todo >= (int)curbuf->b_p_ts) +! { +! todo -= (int)curbuf->b_p_ts; +! ++ind_len; +! if (p != NULL) +! *p++ = TAB; +! } +! #endif + } + + /* Count/add spaces required for indent */ +*************** +*** 497,502 **** +--- 649,657 ---- + static long prev_ts = 0L; /* cached tabstop value */ + static char_u *prev_line = NULL; /* cached pointer to line */ + static varnumber_T prev_tick = 0; /* changedtick of cached value */ ++ #ifdef FEAT_VARTABS ++ static int *prev_vts = NULL; /* cached vartabs values */ ++ #endif + int bri = 0; + /* window width minus window margin space, i.e. what rests for text */ + const int eff_wwidth = wp->w_width +*************** +*** 506,518 **** + + /* used cached indent, unless pointer or 'tabstop' changed */ + if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts +! || prev_tick != CHANGEDTICK(wp->w_buffer)) + { + prev_line = line; + prev_ts = wp->w_buffer->b_p_ts; + prev_tick = CHANGEDTICK(wp->w_buffer); + prev_indent = get_indent_str(line, + (int)wp->w_buffer->b_p_ts, wp->w_p_list); + } + bri = prev_indent + wp->w_p_brishift; + +--- 661,684 ---- + + /* used cached indent, unless pointer or 'tabstop' changed */ + if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts +! || prev_tick != CHANGEDTICK(wp->w_buffer) +! #ifdef FEAT_VARTABS +! || prev_vts != wp->w_buffer->b_p_vts_array +! #endif +! ) + { + prev_line = line; + prev_ts = wp->w_buffer->b_p_ts; + prev_tick = CHANGEDTICK(wp->w_buffer); ++ #ifdef FEAT_VARTABS ++ prev_vts = wp->w_buffer->b_p_vts_array; ++ prev_indent = get_indent_str_vtab(line, ++ (int)wp->w_buffer->b_p_ts, ++ wp->w_buffer->b_p_vts_array, wp->w_p_list); ++ #else + prev_indent = get_indent_str(line, + (int)wp->w_buffer->b_p_ts, wp->w_p_list); ++ #endif + } + bri = prev_indent + wp->w_p_brishift; + +*************** +*** 741,747 **** +--- 907,918 ---- + /* + * count white space on current line + */ ++ #ifdef FEAT_VARTABS ++ newindent = get_indent_str_vtab(saved_line, curbuf->b_p_ts, ++ curbuf->b_p_vts_array, FALSE); ++ #else + newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts, FALSE); ++ #endif + if (newindent == 0 && !(flags & OPENLINE_COM_LIST)) + newindent = second_line_indent; /* for ^^D command in insert mode */ + +*************** +*** 1264,1270 **** + || do_si + #endif + ) +! newindent = get_indent_str(leader, (int)curbuf->b_p_ts, FALSE); + + /* Add the indent offset */ + if (newindent + off < 0) +--- 1435,1447 ---- + || do_si + #endif + ) +! #ifdef FEAT_VARTABS +! newindent = get_indent_str_vtab(leader, curbuf->b_p_ts, +! curbuf->b_p_vts_array, FALSE); +! #else +! newindent = get_indent_str(leader, +! (int)curbuf->b_p_ts, FALSE); +! #endif + + /* Add the indent offset */ + if (newindent + off < 0) +*** ../vim-8.1.0104/src/ops.c 2018-06-03 14:42:17.844505109 +0200 +--- src/ops.c 2018-06-23 18:36:27.566311089 +0200 +*************** +*** 398,403 **** +--- 398,406 ---- + char_u *newp, *oldp; + int oldcol = curwin->w_cursor.col; + int p_sw = (int)get_sw_value(curbuf); ++ #ifdef FEAT_VARTABS ++ int *p_vts = curbuf->b_p_vts_array; ++ #endif + int p_ts = (int)curbuf->b_p_ts; + struct block_def bd; + int incr; +*************** +*** 459,470 **** +--- 462,480 ---- + } + /* OK, now total=all the VWS reqd, and textstart points at the 1st + * non-ws char in the block. */ ++ #ifdef FEAT_VARTABS ++ if (!curbuf->b_p_et) ++ tabstop_fromto(ws_vcol, ws_vcol + total, p_ts, p_vts, &i, &j); ++ else ++ j = total; ++ #else + if (!curbuf->b_p_et) + i = ((ws_vcol % p_ts) + total) / p_ts; /* number of tabs */ + if (i) + j = ((ws_vcol % p_ts) + total) % p_ts; /* number of spp */ + else + j = total; ++ #endif + /* if we're splitting a TAB, allow for it */ + bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); + len = (int)STRLEN(bd.textstart) + 1; +*************** +*** 3697,3706 **** +--- 3707,3725 ---- + { + /* Don't need to insert spaces when "p" on the last position of a + * tab or "P" on the first position. */ ++ #ifdef FEAT_VARTABS ++ int viscol = getviscol(); ++ if (dir == FORWARD ++ ? tabstop_padding(viscol, curbuf->b_p_ts, ++ curbuf->b_p_vts_array) != 1 ++ : curwin->w_cursor.coladd > 0) ++ coladvance_force(viscol); ++ #else + if (dir == FORWARD + ? (int)curwin->w_cursor.coladd < curbuf->b_p_ts - 1 + : curwin->w_cursor.coladd > 0) + coladvance_force(getviscol()); ++ #endif + else + curwin->w_cursor.coladd = 0; + } +*** ../vim-8.1.0104/src/option.c 2018-06-17 19:08:26.472323943 +0200 +--- src/option.c 2018-06-23 18:53:46.500525908 +0200 +*************** +*** 182,187 **** +--- 182,191 ---- + # define PV_UDF OPT_BUF(BV_UDF) + #endif + #define PV_WM OPT_BUF(BV_WM) ++ #ifdef FEAT_VARTABS ++ # define PV_VSTS OPT_BUF(BV_VSTS) ++ # define PV_VTS OPT_BUF(BV_VTS) ++ #endif + + /* + * Definition of the PV_ values for window-local options. +*************** +*** 371,376 **** +--- 375,384 ---- + static int p_udf; + #endif + static long p_wm; ++ #ifdef FEAT_VARTABS ++ static char_u *p_vsts; ++ static char_u *p_vts; ++ #endif + #ifdef FEAT_KEYMAP + static char_u *p_keymap; + #endif +*************** +*** 390,395 **** +--- 398,406 ---- + static long p_sts_nopaste; + static long p_tw_nopaste; + static long p_wm_nopaste; ++ #ifdef FEAT_VARTABS ++ static char_u *p_vsts_nopaste; ++ #endif + + struct vimoption + { +*************** +*** 2925,2930 **** +--- 2936,2959 ---- + {"updatetime", "ut", P_NUM|P_VI_DEF, + (char_u *)&p_ut, PV_NONE, + {(char_u *)4000L, (char_u *)0L} SCRIPTID_INIT}, ++ {"varsofttabstop", "vsts", P_STRING|P_VI_DEF|P_VIM|P_COMMA, ++ #ifdef FEAT_VARTABS ++ (char_u *)&p_vsts, PV_VSTS, ++ {(char_u *)"", (char_u *)0L} ++ #else ++ (char_u *)NULL, PV_NONE, ++ {(char_u *)"", (char_u *)NULL} ++ #endif ++ SCRIPTID_INIT}, ++ {"vartabstop", "vts", P_STRING|P_VI_DEF|P_VIM|P_RBUF|P_COMMA, ++ #ifdef FEAT_VARTABS ++ (char_u *)&p_vts, PV_VTS, ++ {(char_u *)"", (char_u *)0L} ++ #else ++ (char_u *)NULL, PV_NONE, ++ {(char_u *)"", (char_u *)NULL} ++ #endif ++ SCRIPTID_INIT}, + {"verbose", "vbs", P_NUM|P_VI_DEF, + (char_u *)&p_verbose, PV_NONE, + {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, +*************** +*** 5608,5613 **** +--- 5637,5646 ---- + /* Parse default for 'clipboard' */ + (void)check_clipboard_option(); + #endif ++ #ifdef FEAT_VARTABS ++ tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array); ++ tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array); ++ #endif + } + + /* +*************** +*** 5725,5730 **** +--- 5758,5767 ---- + #ifdef FEAT_MBYTE + check_string_option(&buf->b_p_menc); + #endif ++ #ifdef FEAT_VARTABS ++ check_string_option(&buf->b_p_vsts); ++ check_string_option(&buf->b_p_vts); ++ #endif + } + + /* +*************** +*** 7472,7477 **** +--- 7509,7596 ---- + } + #endif + ++ #ifdef FEAT_VARTABS ++ /* 'varsofttabstop' */ ++ else if (varp == &(curbuf->b_p_vsts)) ++ { ++ char_u *cp; ++ ++ if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) ++ { ++ if (curbuf->b_p_vsts_array) ++ { ++ vim_free(curbuf->b_p_vsts_array); ++ curbuf->b_p_vsts_array = 0; ++ } ++ } ++ else ++ { ++ for (cp = *varp; *cp; ++cp) ++ { ++ if (vim_isdigit(*cp)) ++ continue; ++ if (*cp == ',' && cp > *varp && *(cp-1) != ',') ++ continue; ++ errmsg = e_invarg; ++ break; ++ } ++ if (errmsg == NULL) ++ { ++ int *oldarray = curbuf->b_p_vsts_array; ++ if (tabstop_set(*varp, &(curbuf->b_p_vsts_array))) ++ { ++ if (oldarray) ++ vim_free(oldarray); ++ } ++ else ++ errmsg = e_invarg; ++ } ++ } ++ } ++ ++ /* 'vartabstop' */ ++ else if (varp == &(curbuf->b_p_vts)) ++ { ++ char_u *cp; ++ ++ if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) ++ { ++ if (curbuf->b_p_vts_array) ++ { ++ vim_free(curbuf->b_p_vts_array); ++ curbuf->b_p_vts_array = NULL; ++ } ++ } ++ else ++ { ++ for (cp = *varp; *cp; ++cp) ++ { ++ if (vim_isdigit(*cp)) ++ continue; ++ if (*cp == ',' && cp > *varp && *(cp-1) != ',') ++ continue; ++ errmsg = e_invarg; ++ break; ++ } ++ if (errmsg == NULL) ++ { ++ int *oldarray = curbuf->b_p_vts_array; ++ if (tabstop_set(*varp, &(curbuf->b_p_vts_array))) ++ { ++ if (oldarray) ++ vim_free(oldarray); ++ #ifdef FEAT_FOLDING ++ if (foldmethodIsIndent(curwin)) ++ foldUpdateAll(curwin); ++ #endif /* FEAT_FOLDING */ ++ } ++ else ++ errmsg = e_invarg; ++ } ++ } ++ } ++ #endif ++ + /* Options that are a list of flags. */ + else + { +*************** +*** 8780,8786 **** +--- 8899,8912 ---- + if (curbuf->b_p_sw < 0) + { + errmsg = e_positive; ++ #ifdef FEAT_VARTABS ++ // Use the first 'vartabstop' value, or 'tabstop' if vts isn't in use. ++ curbuf->b_p_sw = tabstop_count(curbuf->b_p_vts_array) > 0 ++ ? tabstop_first(curbuf->b_p_vts_array) ++ : curbuf->b_p_ts; ++ #else + curbuf->b_p_sw = curbuf->b_p_ts; ++ #endif + } + + /* +*************** +*** 10814,10819 **** +--- 10940,10949 ---- + #ifdef FEAT_SIGNS + case PV_SCL: return (char_u *)&(curwin->w_p_scl); + #endif ++ #ifdef FEAT_VARTABS ++ case PV_VSTS: return (char_u *)&(curbuf->b_p_vsts); ++ case PV_VTS: return (char_u *)&(curbuf->b_p_vts); ++ #endif + default: IEMSG(_("E356: get_varp ERROR")); + } + /* always return a valid pointer to avoid a crash! */ +*************** +*** 11138,11143 **** +--- 11268,11282 ---- + #endif + buf->b_p_sts = p_sts; + buf->b_p_sts_nopaste = p_sts_nopaste; ++ #ifdef FEAT_VARTABS ++ buf->b_p_vsts = vim_strsave(p_vsts); ++ if (p_vsts && p_vsts != empty_option) ++ tabstop_set(p_vsts, &buf->b_p_vsts_array); ++ else ++ buf->b_p_vsts_array = 0; ++ buf->b_p_vsts_nopaste = p_vsts_nopaste ++ ? vim_strsave(p_vsts_nopaste) : NULL; ++ #endif + buf->b_p_sn = p_sn; + #ifdef FEAT_COMMENTS + buf->b_p_com = vim_strsave(p_com); +*************** +*** 11259,11270 **** +--- 11398,11424 ---- + * or to a help buffer. + */ + if (dont_do_help) ++ { + buf->b_p_isk = save_p_isk; ++ #ifdef FEAT_VARTABS ++ if (p_vts && p_vts != empty_option && !buf->b_p_vts_array) ++ tabstop_set(p_vts, &buf->b_p_vts_array); ++ else ++ buf->b_p_vts_array = NULL; ++ #endif ++ } + else + { + buf->b_p_isk = vim_strsave(p_isk); + did_isk = TRUE; + buf->b_p_ts = p_ts; ++ #ifdef FEAT_VARTABS ++ buf->b_p_vts = vim_strsave(p_vts); ++ if (p_vts && p_vts != empty_option && !buf->b_p_vts_array) ++ tabstop_set(p_vts, &buf->b_p_vts_array); ++ else ++ buf->b_p_vts_array = NULL; ++ #endif + buf->b_help = FALSE; + if (buf->b_p_bt[0] == 'h') + clear_string_option(&buf->b_p_bt); +*************** +*** 12084,12089 **** +--- 12238,12249 ---- + buf->b_p_sts_nopaste = buf->b_p_sts; + buf->b_p_ai_nopaste = buf->b_p_ai; + buf->b_p_et_nopaste = buf->b_p_et; ++ #ifdef FEAT_VARTABS ++ if (buf->b_p_vsts_nopaste) ++ vim_free(buf->b_p_vsts_nopaste); ++ buf->b_p_vsts_nopaste = buf->b_p_vsts && buf->b_p_vsts != empty_option ++ ? vim_strsave(buf->b_p_vsts) : NULL; ++ #endif + } + + /* save global options */ +*************** +*** 12102,12107 **** +--- 12262,12272 ---- + p_sts_nopaste = p_sts; + p_tw_nopaste = p_tw; + p_wm_nopaste = p_wm; ++ #ifdef FEAT_VARTABS ++ if (p_vsts_nopaste) ++ vim_free(p_vsts_nopaste); ++ p_vsts_nopaste = p_vsts && p_vsts != empty_option ? vim_strsave(p_vsts) : NULL; ++ #endif + } + + /* +*************** +*** 12116,12121 **** +--- 12281,12294 ---- + buf->b_p_sts = 0; /* softtabstop is 0 */ + buf->b_p_ai = 0; /* no auto-indent */ + buf->b_p_et = 0; /* no expandtab */ ++ #ifdef FEAT_VARTABS ++ if (buf->b_p_vsts) ++ free_string_option(buf->b_p_vsts); ++ buf->b_p_vsts = empty_option; ++ if (buf->b_p_vsts_array) ++ vim_free(buf->b_p_vsts_array); ++ buf->b_p_vsts_array = 0; ++ #endif + } + + /* set global options */ +*************** +*** 12135,12140 **** +--- 12308,12318 ---- + p_wm = 0; + p_sts = 0; + p_ai = 0; ++ #ifdef FEAT_VARTABS ++ if (p_vsts) ++ free_string_option(p_vsts); ++ p_vsts = empty_option; ++ #endif + } + + /* +*************** +*** 12150,12155 **** +--- 12328,12345 ---- + buf->b_p_sts = buf->b_p_sts_nopaste; + buf->b_p_ai = buf->b_p_ai_nopaste; + buf->b_p_et = buf->b_p_et_nopaste; ++ #ifdef FEAT_VARTABS ++ if (buf->b_p_vsts) ++ free_string_option(buf->b_p_vsts); ++ buf->b_p_vsts = buf->b_p_vsts_nopaste ++ ? vim_strsave(buf->b_p_vsts_nopaste) : empty_option; ++ if (buf->b_p_vsts_array) ++ vim_free(buf->b_p_vsts_array); ++ if (buf->b_p_vsts && buf->b_p_vsts != empty_option) ++ tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array); ++ else ++ buf->b_p_vsts_array = 0; ++ #endif + } + + /* restore global options */ +*************** +*** 12170,12175 **** +--- 12360,12370 ---- + p_sts = p_sts_nopaste; + p_tw = p_tw_nopaste; + p_wm = p_wm_nopaste; ++ #ifdef FEAT_VARTABS ++ if (p_vsts) ++ free_string_option(p_vsts); ++ p_vsts = p_vsts_nopaste ? vim_strsave(p_vsts_nopaste) : empty_option; ++ #endif + } + + old_p_paste = p_paste; +*************** +*** 12510,12515 **** +--- 12705,12999 ---- + return check_opt_strings(p, p_ff_values, FALSE); + } + ++ #ifdef FEAT_VARTABS ++ ++ /* ++ * Set the integer values corresponding to the string setting of 'vartabstop'. ++ */ ++ int ++ tabstop_set(char_u *var, int **array) ++ { ++ int valcount = 1; ++ int t; ++ char_u *cp; ++ ++ if ((!var[0] || (var[0] == '0' && !var[1]))) ++ { ++ *array = NULL; ++ return TRUE; ++ } ++ ++ for (cp = var; *cp; ++cp) ++ { ++ if (cp == var || *(cp - 1) == ',') ++ { ++ char_u *end; ++ if (strtol((char *)cp, (char **)&end, 10) <= 0) ++ { ++ if (cp != end) ++ EMSG(_(e_positive)); ++ else ++ EMSG(_(e_invarg)); ++ return FALSE; ++ } ++ } ++ ++ if (VIM_ISDIGIT(*cp)) ++ continue; ++ if (*cp == ',' && cp > var && *(cp - 1) != ',') ++ { ++ ++valcount; ++ continue; ++ } ++ EMSG(_(e_invarg)); ++ return FALSE; ++ } ++ ++ *array = (int *) alloc((unsigned) ((valcount + 1) * sizeof(int))); ++ (*array)[0] = valcount; ++ ++ t = 1; ++ for (cp = var; *cp;) ++ { ++ (*array)[t++] = atoi((char *)cp); ++ while (*cp && *cp != ',') ++ ++cp; ++ if (*cp) ++ ++cp; ++ } ++ ++ return TRUE; ++ } ++ ++ /* ++ * Calculate the number of screen spaces a tab will occupy. ++ * If "vts" is set then the tab widths are taken from that array, ++ * otherwise the value of ts is used. ++ */ ++ int ++ tabstop_padding(colnr_T col, int ts_arg, int *vts) ++ { ++ int ts = ts_arg == 0 ? 8 : ts_arg; ++ int tabcount; ++ colnr_T tabcol = 0; ++ int t; ++ int padding = 0; ++ ++ if (vts == NULL || vts[0] == 0) ++ return ts - (col % ts); ++ ++ tabcount = vts[0]; ++ ++ for (t = 1; t <= tabcount; ++t) ++ { ++ tabcol += vts[t]; ++ if (tabcol > col) ++ { ++ padding = (int)(tabcol - col); ++ break; ++ } ++ } ++ if (t > tabcount) ++ padding = vts[tabcount] - (int)((col - tabcol) % vts[tabcount]); ++ ++ return padding; ++ } ++ ++ /* ++ * Find the size of the tab that covers a particular column. ++ */ ++ int ++ tabstop_at(colnr_T col, int ts, int *vts) ++ { ++ int tabcount; ++ colnr_T tabcol = 0; ++ int t; ++ int tab_size = 0; ++ ++ if (vts == 0 || vts[0] == 0) ++ return ts; ++ ++ tabcount = vts[0]; ++ for (t = 1; t <= tabcount; ++t) ++ { ++ tabcol += vts[t]; ++ if (tabcol > col) ++ { ++ tab_size = vts[t]; ++ break; ++ } ++ } ++ if (t > tabcount) ++ tab_size = vts[tabcount]; ++ ++ return tab_size; ++ } ++ ++ /* ++ * Find the column on which a tab starts. ++ */ ++ colnr_T ++ tabstop_start(colnr_T col, int ts, int *vts) ++ { ++ int tabcount; ++ colnr_T tabcol = 0; ++ int t; ++ int excess; ++ ++ if (vts == 0 || vts[0] == 0) ++ return (col / ts) * ts; ++ ++ tabcount = vts[0]; ++ for (t = 1; t <= tabcount; ++t) ++ { ++ tabcol += vts[t]; ++ if (tabcol > col) ++ return tabcol - vts[t]; ++ } ++ ++ excess = tabcol % vts[tabcount]; ++ return excess + ((col - excess) / vts[tabcount]) * vts[tabcount]; ++ } ++ ++ /* ++ * Find the number of tabs and spaces necessary to get from one column ++ * to another. ++ */ ++ void ++ tabstop_fromto( ++ colnr_T start_col, ++ colnr_T end_col, ++ int ts, ++ int *vts, ++ int *ntabs, ++ int *nspcs) ++ { ++ int spaces = end_col - start_col; ++ colnr_T tabcol = 0; ++ int padding = 0; ++ int tabcount; ++ int t; ++ ++ if (vts == 0 || vts[0] == 0) ++ { ++ int tabs = 0; ++ int initspc = ts - (start_col % ts); ++ if (spaces >= initspc) ++ { ++ spaces -= initspc; ++ tabs++; ++ } ++ tabs += spaces / ts; ++ spaces -= (spaces / ts) * ts; ++ ++ *ntabs = tabs; ++ *nspcs = spaces; ++ return; ++ } ++ ++ /* Find the padding needed to reach the next tabstop. */ ++ tabcount = vts[0]; ++ for (t = 1; t <= tabcount; ++t) ++ { ++ tabcol += vts[t]; ++ if (tabcol > start_col) ++ { ++ padding = (int)(tabcol - start_col); ++ break; ++ } ++ } ++ if (t > tabcount) ++ padding = vts[tabcount] - (int)((start_col - tabcol) % vts[tabcount]); ++ ++ /* If the space needed is less than the padding no tabs can be used. */ ++ if (spaces < padding) ++ { ++ *ntabs = 0; ++ *nspcs = spaces; ++ return; ++ } ++ ++ *ntabs = 1; ++ spaces -= padding; ++ ++ /* At least one tab has been used. See if any more will fit. */ ++ while (spaces != 0 && ++t <= tabcount) ++ { ++ padding = vts[t]; ++ if (spaces < padding) ++ { ++ *nspcs = spaces; ++ return; ++ } ++ ++*ntabs; ++ spaces -= padding; ++ } ++ ++ *ntabs += spaces / vts[tabcount]; ++ *nspcs = spaces % vts[tabcount]; ++ } ++ ++ /* ++ * See if two tabstop arrays contain the same values. ++ */ ++ int ++ tabstop_eq(int *ts1, int *ts2) ++ { ++ int t; ++ ++ if ((ts1 == 0 && ts2) || (ts1 && ts2 == 0)) ++ return FALSE; ++ if (ts1 == ts2) ++ return TRUE; ++ if (ts1[0] != ts2[0]) ++ return FALSE; ++ ++ for (t = 1; t <= ts1[0]; ++t) ++ if (ts1[t] != ts2[t]) ++ return FALSE; ++ ++ return TRUE; ++ } ++ ++ /* ++ * Copy a tabstop array, allocating space for the new array. ++ */ ++ int * ++ tabstop_copy(int *oldts) ++ { ++ int *newts; ++ int t; ++ ++ if (oldts == 0) ++ return 0; ++ ++ newts = (int *) alloc((unsigned) ((oldts[0] + 1) * sizeof(int))); ++ for (t = 0; t <= oldts[0]; ++t) ++ newts[t] = oldts[t]; ++ ++ return newts; ++ } ++ ++ /* ++ * Return a count of the number of tabstops. ++ */ ++ int ++ tabstop_count(int *ts) ++ { ++ return ts != NULL ? ts[0] : 0; ++ } ++ ++ /* ++ * Return the first tabstop, or 8 if there are no tabstops defined. ++ */ ++ int ++ tabstop_first(int *ts) ++ { ++ return ts != NULL ? ts[1] : 8; ++ } ++ ++ #endif ++ + /* + * Return the effective shiftwidth value for current buffer, using the + * 'tabstop' value when 'shiftwidth' is zero. +*** ../vim-8.1.0104/src/option.h 2018-05-05 16:28:11.000000000 +0200 +--- src/option.h 2018-06-23 17:41:10.116365995 +0200 +*************** +*** 1114,1119 **** +--- 1114,1123 ---- + #ifdef FEAT_TERMINAL + , BV_TWSL + #endif ++ #ifdef FEAT_VARTABS ++ , BV_VSTS ++ , BV_VTS ++ #endif + , BV_COUNT /* must be the last one */ + }; + +*** ../vim-8.1.0104/src/proto/misc1.pro 2018-05-17 13:52:45.000000000 +0200 +--- src/proto/misc1.pro 2018-06-23 18:20:45.471296904 +0200 +*************** +*** 3,8 **** +--- 3,9 ---- + int get_indent_lnum(linenr_T lnum); + int get_indent_buf(buf_T *buf, linenr_T lnum); + int get_indent_str(char_u *ptr, int ts, int list); ++ int get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list); + int set_indent(int size, int flags); + int get_number_indent(linenr_T lnum); + int get_breakindent_win(win_T *wp, char_u *line); +*** ../vim-8.1.0104/src/proto/option.pro 2018-05-17 13:52:47.000000000 +0200 +--- src/proto/option.pro 2018-06-23 18:38:40.189580238 +0200 +*************** +*** 60,65 **** +--- 60,74 ---- + void save_file_ff(buf_T *buf); + int file_ff_differs(buf_T *buf, int ignore_empty); + int check_ff_value(char_u *p); ++ 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); ++ colnr_T tabstop_start(colnr_T col, int ts, int *vts); ++ void tabstop_fromto(colnr_T start_col, colnr_T end_col, int ts, int *vts, int *ntabs, int *nspcs); ++ int tabstop_eq(int *ts1, int *ts2); ++ int *tabstop_copy(int *oldts); ++ int tabstop_count(int *ts); ++ int tabstop_first(int *ts); + long get_sw_value(buf_T *buf); + long get_sts_value(void); + void find_mps_values(int *initc, int *findc, int *backwards, int switchit); +*** ../vim-8.1.0104/src/screen.c 2018-06-23 14:21:38.467484932 +0200 +--- src/screen.c 2018-06-23 18:36:56.702150819 +0200 +*************** +*** 4848,4855 **** + vcol_adjusted = vcol - MB_CHARLEN(p_sbr); + #endif + /* tab amount depends on current column */ + tab_len = (int)wp->w_buffer->b_p_ts +! - vcol_adjusted % (int)wp->w_buffer->b_p_ts - 1; + + #ifdef FEAT_LINEBREAK + if (!wp->w_p_lbr || !wp->w_p_list) +--- 4848,4861 ---- + vcol_adjusted = vcol - MB_CHARLEN(p_sbr); + #endif + /* tab amount depends on current column */ ++ #ifdef FEAT_VARTABS ++ tab_len = tabstop_padding(vcol_adjusted, ++ wp->w_buffer->b_p_ts, ++ wp->w_buffer->b_p_vts_array) - 1; ++ #else + tab_len = (int)wp->w_buffer->b_p_ts +! - vcol_adjusted % (int)wp->w_buffer->b_p_ts - 1; +! #endif + + #ifdef FEAT_LINEBREAK + if (!wp->w_p_lbr || !wp->w_p_list) +*** ../vim-8.1.0104/src/structs.h 2018-06-17 20:10:36.208066158 +0200 +--- src/structs.h 2018-06-23 18:39:12.357402504 +0200 +*************** +*** 2236,2241 **** +--- 2236,2248 ---- + long b_p_wm; /* 'wrapmargin' */ + long b_p_wm_nobin; /* b_p_wm saved for binary mode */ + long b_p_wm_nopaste; /* b_p_wm saved for paste mode */ ++ #ifdef FEAT_VARTABS ++ char_u *b_p_vsts; /* 'varsofttabstop' */ ++ int *b_p_vsts_array; /* 'varsofttabstop' in internal format */ ++ char_u *b_p_vsts_nopaste; /* b_p_vsts saved for paste mode */ ++ char_u *b_p_vts; /* 'vartabstop' */ ++ int *b_p_vts_array; /* 'vartabstop' in internal format */ ++ #endif + #ifdef FEAT_KEYMAP + char_u *b_p_keymap; /* 'keymap' */ + #endif +*** ../vim-8.1.0104/src/testdir/Make_all.mak 2018-06-03 14:42:17.848505102 +0200 +--- src/testdir/Make_all.mak 2018-06-23 17:41:10.116365995 +0200 +*************** +*** 147,154 **** + test_perl.res \ + test_plus_arg_edit.res \ + test_preview.res \ +- test_prompt_buffer.res \ + test_profile.res \ + test_python2.res \ + test_python3.res \ + test_pyx2.res \ +--- 147,154 ---- + test_perl.res \ + test_plus_arg_edit.res \ + test_preview.res \ + test_profile.res \ ++ test_prompt_buffer.res \ + test_python2.res \ + test_python3.res \ + test_pyx2.res \ +*************** +*** 180,185 **** +--- 180,186 ---- + test_undo.res \ + test_user_func.res \ + test_usercommands.res \ ++ test_vartabs.res \ + test_viminfo.res \ + test_vimscript.res \ + test_visual.res \ +*** ../vim-8.1.0104/src/testdir/gen_opt_test.vim 2018-05-05 16:32:49.000000000 +0200 +--- src/testdir/gen_opt_test.vim 2018-06-23 17:41:10.116365995 +0200 +*************** +*** 136,141 **** +--- 136,143 ---- + \ 'toolbariconsize': [['', 'tiny', 'huge'], ['xxx']], + \ 'ttymouse': [['', 'xterm'], ['xxx']], + \ 'ttytype': [[], []], ++ \ 'varsofttabstop': [['8', '4,8,16,32'], ['xxx', '-1', '4,-1,20']], ++ \ 'vartabstop': [['8', '4,8,16,32'], ['xxx', '-1', '4,-1,20']], + \ 'viewoptions': [['', 'cursor', 'unix,slash'], ['xxx']], + \ 'viminfo': [['', '''50', '"30'], ['xxx']], + \ 'virtualedit': [['', 'all', 'all,block'], ['xxx']], +*** ../vim-8.1.0104/src/testdir/test_breakindent.vim 2017-03-01 17:42:25.000000000 +0100 +--- src/testdir/test_breakindent.vim 2018-06-23 19:21:36.118945791 +0200 +*************** +*** 12,146 **** + + let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" + +! function s:screen_lines(lnum, width) abort + return ScreenLines([a:lnum, a:lnum + 2], a:width) +! endfunction + +! function! s:compare_lines(expect, actual) + call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) +! endfunction + +! function s:test_windows(...) + call NewWindow(10, 20) + setl ts=4 sw=4 sts=4 breakindent + put =s:input + exe get(a:000, 0, '') +! endfunction + +! function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +! endfunction + +! function Test_breakindent01() + " simple breakindent test + call s:test_windows('setl briopt=min:0') +! let lines=s:screen_lines(line('.'),8) +! let expect=[ +! \ " abcd", +! \ " qrst", +! \ " GHIJ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunction + +! function Test_breakindent02() + " simple breakindent test with showbreak set + call s:test_windows('setl briopt=min:0 sbr=>>') +! let lines=s:screen_lines(line('.'),8) +! let expect=[ +! \ " abcd", +! \ " >>qr", +! \ " >>EF", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +! endfunction + +! function Test_breakindent03() + " simple breakindent test with showbreak set and briopt including sbr + call s:test_windows('setl briopt=sbr,min:0 sbr=++') +! let lines=s:screen_lines(line('.'),8) +! let expect=[ +! \ " abcd", +! \ "++ qrst", +! \ "++ GHIJ", +! \ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +! endfunction + +! function Test_breakindent04() + " breakindent set with min width 18 + call s:test_windows('setl sbr= briopt=min:18') +! let lines=s:screen_lines(line('.'),8) +! let expect=[ +! \ " abcd", +! \ " qrstuv", +! \ " IJKLMN", +! \ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +! endfunction + +! function Test_breakindent05() + " breakindent set and shift by 2 + call s:test_windows('setl briopt=shift:2,min:0') +! let lines=s:screen_lines(line('.'),8) +! let expect=[ +! \ " abcd", +! \ " qr", +! \ " EF", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunction + +! function Test_breakindent06() + " breakindent set and shift by -1 + call s:test_windows('setl briopt=shift:-1,min:0') +! let lines=s:screen_lines(line('.'),8) +! let expect=[ +! \ " abcd", +! \ " qrstu", +! \ " HIJKL", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunction + +! function Test_breakindent07() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 cpo+=n') +! let lines=s:screen_lines(line('.'),10) +! let expect=[ +! \ " 2 ab", +! \ "? m", +! \ "? x", +! \ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr= cpo-=n') +! endfunction + +! function Test_breakindent07a() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') +! let lines=s:screen_lines(line('.'),10) +! let expect=[ +! \ " 2 ab", +! \ " ? m", +! \ " ? x", +! \ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +! endfunction + +! function Test_breakindent08() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list cpo+=n ts=4') + " make sure, cache is invalidated! +--- 12,278 ---- + + let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" + +! func s:screen_lines(lnum, width) abort + return ScreenLines([a:lnum, a:lnum + 2], a:width) +! endfunc + +! func s:compare_lines(expect, actual) + call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) +! endfunc + +! func s:test_windows(...) + call NewWindow(10, 20) + setl ts=4 sw=4 sts=4 breakindent + put =s:input + exe get(a:000, 0, '') +! endfunc + +! func s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +! endfunc + +! func Test_breakindent01() + " simple breakindent test + call s:test_windows('setl briopt=min:0') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " qrst", +! \ " GHIJ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunc + +! func Test_breakindent01_vartabs() +! " like 01 but with vartabs feature +! if !has("vartabs") +! return +! endif +! call s:test_windows('setl briopt=min:0 vts=4') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " qrst", +! \ " GHIJ", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set vts&') +! endfunc +! +! func Test_breakindent02() + " simple breakindent test with showbreak set + call s:test_windows('setl briopt=min:0 sbr=>>') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " >>qr", +! \ " >>EF", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +! endfunc +! +! func Test_breakindent02_vartabs() +! if !has("vartabs") +! return +! endif +! " simple breakindent test with showbreak set +! call s:test_windows('setl briopt=min:0 sbr=>> vts=4') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " >>qr", +! \ " >>EF", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set sbr= vts&') +! endfunc + +! func Test_breakindent03() + " simple breakindent test with showbreak set and briopt including sbr + call s:test_windows('setl briopt=sbr,min:0 sbr=++') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ "++ qrst", +! \ "++ GHIJ", +! \ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +! endfunc + +! func Test_breakindent03_vartabs() +! " simple breakindent test with showbreak set and briopt including sbr +! if !has("vartabs") +! return +! endif +! call s:test_windows('setl briopt=sbr,min:0 sbr=++ vts=4') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ "++ qrst", +! \ "++ GHIJ", +! \ ] +! call s:compare_lines(expect, lines) +! " clean up +! call s:close_windows('set sbr= vts&') +! endfunc +! +! func Test_breakindent04() + " breakindent set with min width 18 + call s:test_windows('setl sbr= briopt=min:18') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " qrstuv", +! \ " IJKLMN", +! \ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +! endfunc + +! func Test_breakindent04_vartabs() +! " breakindent set with min width 18 +! if !has("vartabs") +! return +! endif +! call s:test_windows('setl sbr= briopt=min:18 vts=4') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " qrstuv", +! \ " IJKLMN", +! \ ] +! call s:compare_lines(expect, lines) +! " clean up +! call s:close_windows('set sbr= vts&') +! endfunc +! +! func Test_breakindent05() + " breakindent set and shift by 2 + call s:test_windows('setl briopt=shift:2,min:0') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " qr", +! \ " EF", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunc +! +! func Test_breakindent05_vartabs() +! " breakindent set and shift by 2 +! if !has("vartabs") +! return +! endif +! call s:test_windows('setl briopt=shift:2,min:0 vts=4') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " qr", +! \ " EF", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set vts&') +! endfunc + +! func Test_breakindent06() + " breakindent set and shift by -1 + call s:test_windows('setl briopt=shift:-1,min:0') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " qrstu", +! \ " HIJKL", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunc + +! func Test_breakindent06_vartabs() +! " breakindent set and shift by -1 +! if !has("vartabs") +! return +! endif +! call s:test_windows('setl briopt=shift:-1,min:0 vts=4') +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ " abcd", +! \ " qrstu", +! \ " HIJKL", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set vts&') +! endfunc +! +! func Test_breakindent07() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 cpo+=n') +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ab", +! \ "? m", +! \ "? x", +! \ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr= cpo-=n') +! endfunc +! +! func Test_breakindent07_vartabs() +! if !has("vartabs") +! return +! endif +! " breakindent set and shift by 1, Number set sbr=? and briopt:sbr +! call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 cpo+=n vts=4') +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ab", +! \ "? m", +! \ "? x", +! \ ] +! call s:compare_lines(expect, lines) +! " clean up +! call s:close_windows('set sbr= cpo-=n vts&') +! endfunc + +! func Test_breakindent07a() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ab", +! \ " ? m", +! \ " ? x", +! \ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +! endfunc +! +! func Test_breakindent07a_vartabs() +! if !has("vartabs") +! return +! endif +! " breakindent set and shift by 1, Number set sbr=? and briopt:sbr +! call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 vts=4') +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ab", +! \ " ? m", +! \ " ? x", +! \ ] +! call s:compare_lines(expect, lines) +! " clean up +! call s:close_windows('set sbr= vts&') +! endfunc + +! func Test_breakindent08() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list cpo+=n ts=4') + " make sure, cache is invalidated! +*************** +*** 148,190 **** + redraw! + set ts=4 + redraw! +! let lines=s:screen_lines(line('.'),10) +! let expect=[ +! \ " 2 ^Iabcd", +! \ "# opq", +! \ "# BCD", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +! endfunction + +! function Test_breakindent08a() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list') +! let lines=s:screen_lines(line('.'),10) +! let expect=[ +! \ " 2 ^Iabcd", +! \ " # opq", +! \ " # BCD", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +! endfunction + +! function Test_breakindent09() + " breakindent set and shift by 1, Number and list set sbr=# + call s:test_windows('setl briopt=shift:1,min:0 nu nuw=4 sbr=# list') +! let lines=s:screen_lines(line('.'),10) +! let expect=[ +! \ " 2 ^Iabcd", +! \ " #op", +! \ " #AB", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +! endfunction + +! function Test_breakindent10() + " breakindent set, Number set sbr=~ + call s:test_windows('setl cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') + " make sure, cache is invalidated! +--- 280,375 ---- + redraw! + set ts=4 + redraw! +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ^Iabcd", +! \ "# opq", +! \ "# BCD", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +! endfunc + +! func Test_breakindent08_vartabs() +! if !has("vartabs") +! return +! endif +! " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr +! call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list cpo+=n ts=4 vts=4') +! " make sure, cache is invalidated! +! set ts=8 +! redraw! +! set ts=4 +! redraw! +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ^Iabcd", +! \ "# opq", +! \ "# BCD", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set sbr= cpo-=n vts&') +! endfunc +! +! func Test_breakindent08a() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list') +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ^Iabcd", +! \ " # opq", +! \ " # BCD", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +! endfunc +! +! func Test_breakindent08a_vartabs() +! if !has("vartabs") +! return +! endif +! " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr +! call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list vts=4') +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ^Iabcd", +! \ " # opq", +! \ " # BCD", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set sbr= vts&') +! endfunc + +! func Test_breakindent09() + " breakindent set and shift by 1, Number and list set sbr=# + call s:test_windows('setl briopt=shift:1,min:0 nu nuw=4 sbr=# list') +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ^Iabcd", +! \ " #op", +! \ " #AB", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +! endfunc + +! func Test_breakindent09_vartabs() +! if !has("vartabs") +! return +! endif +! " breakindent set and shift by 1, Number and list set sbr=# +! call s:test_windows('setl briopt=shift:1,min:0 nu nuw=4 sbr=# list vts=4') +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ^Iabcd", +! \ " #op", +! \ " #AB", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set sbr= vts&') +! endfunc +! +! func Test_breakindent10() + " breakindent set, Number set sbr=~ + call s:test_windows('setl cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') + " make sure, cache is invalidated! +*************** +*** 192,232 **** + redraw! + set ts=4 + redraw! +! let lines=s:screen_lines(line('.'),10) +! let expect=[ +! \ " 2 ab", +! \ "~ mn", +! \ "~ yz", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +! endfunction + +! function Test_breakindent11() + " test strdisplaywidth() + call s:test_windows('setl cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') +! let text=getline(2) + let width = strlen(text[1:])+indent(2)+strlen(&sbr)*3 " text wraps 3 times + call assert_equal(width, strdisplaywidth(text)) + call s:close_windows('set sbr=') +! endfunction + +! function Test_breakindent12() + " test breakindent with long indent +! let s:input="\t\t\t\t\t{" + call s:test_windows('setl breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 list listchars=tab:>-') +! let lines=s:screen_lines(2,16) +! let expect=[ +! \ " 2 >--->--->--->", +! \ " ---{ ", +! \ "~ ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set nuw=4 listchars=') +! endfunction + +! function Test_breakindent13() +! let s:input="" + call s:test_windows('setl breakindent briopt=min:10 ts=8') + vert resize 20 + call setline(1, [" a\tb\tc\td\te", " z y x w v"]) +--- 377,467 ---- + redraw! + set ts=4 + redraw! +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ab", +! \ "~ mn", +! \ "~ yz", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +! endfunc + +! func Test_breakindent10_vartabs() +! if !has("vartabs") +! return +! endif +! " breakindent set, Number set sbr=~ +! call s:test_windows('setl cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0 vts=4') +! " make sure, cache is invalidated! +! set ts=8 +! redraw! +! set ts=4 +! redraw! +! let lines = s:screen_lines(line('.'),10) +! let expect = [ +! \ " 2 ab", +! \ "~ mn", +! \ "~ yz", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set sbr= cpo-=n vts&') +! endfunc +! +! func Test_breakindent11() + " test strdisplaywidth() + call s:test_windows('setl cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') +! let text = getline(2) + let width = strlen(text[1:])+indent(2)+strlen(&sbr)*3 " text wraps 3 times + call assert_equal(width, strdisplaywidth(text)) + call s:close_windows('set sbr=') +! endfunc +! +! func Test_breakindent11_vartabs() +! if !has("vartabs") +! return +! endif +! " test strdisplaywidth() +! call s:test_windows('setl cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4 vts=4') +! let text = getline(2) +! let width = strlen(text[1:])+indent(2)+strlen(&sbr)*3 " text wraps 3 times +! call assert_equal(width, strdisplaywidth(text)) +! call s:close_windows('set sbr= vts&') +! endfunc + +! func Test_breakindent12() + " test breakindent with long indent +! let s:input = "\t\t\t\t\t{" + call s:test_windows('setl breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 list listchars=tab:>-') +! let lines = s:screen_lines(2,16) +! let expect = [ +! \ " 2 >--->--->--->", +! \ " ---{ ", +! \ "~ ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows('set nuw=4 listchars=') +! endfunc + +! func Test_breakindent12_vartabs() +! if !has("vartabs") +! return +! endif +! " test breakindent with long indent +! let s:input = "\t\t\t\t\t{" +! call s:test_windows('setl breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 list listchars=tab:>- vts=4') +! let lines = s:screen_lines(2,16) +! let expect = [ +! \ " 2 >--->--->--->", +! \ " ---{ ", +! \ "~ ", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set nuw=4 listchars= vts&') +! endfunc +! +! func Test_breakindent13() +! let s:input = "" + call s:test_windows('setl breakindent briopt=min:10 ts=8') + vert resize 20 + call setline(1, [" a\tb\tc\td\te", " z y x w v"]) +*************** +*** 237,298 **** + call assert_equal('d', @a) + call assert_equal('w', @b) + call s:close_windows() +! endfunction + +! function Test_breakindent14() +! let s:input="" + call s:test_windows('setl breakindent briopt= ts=8') + vert resize 30 + norm! 3a1234567890 + norm! a abcde + exec "norm! 0\<C-V>tex" +! let lines=s:screen_lines(line('.'),8) +! let expect=[ +! \ "e ", +! \ "~ ", +! \ "~ ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunction + +! function Test_breakindent15() +! let s:input="" + call s:test_windows('setl breakindent briopt= ts=8 sw=8') + vert resize 30 + norm! 4a1234567890 + exe "normal! >>\<C-V>3f0x" +! let lines=s:screen_lines(line('.'),20) +! let expect=[ +! \ " 1234567890 ", +! \ "~ ", +! \ "~ ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunction + +! function Test_breakindent16() + " Check that overlong lines are indented correctly. +! let s:input="" + call s:test_windows('setl breakindent briopt=min:0 ts=4') + call setline(1, "\t".repeat("1234567890", 10)) + resize 6 + norm! 1gg$ + redraw! +! let lines=s:screen_lines(1,10) +! let expect=[ +! \ " 789012", +! \ " 345678", +! \ " 901234", +! \ ] +! call s:compare_lines(expect, lines) +! let lines=s:screen_lines(4,10) +! let expect=[ +! \ " 567890", +! \ " 123456", +! \ " 7890 ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunction +--- 472,617 ---- + call assert_equal('d', @a) + call assert_equal('w', @b) + call s:close_windows() +! endfunc + +! func Test_breakindent13_vartabs() +! if !has("vartabs") +! return +! endif +! let s:input = "" +! call s:test_windows('setl breakindent briopt=min:10 ts=8 vts=8') +! vert resize 20 +! call setline(1, [" a\tb\tc\td\te", " z y x w v"]) +! 1 +! norm! fbgj"ayl +! 2 +! norm! fygj"byl +! call assert_equal('d', @a) +! call assert_equal('w', @b) +! call s:close_windows('set vts&') +! endfunc +! +! func Test_breakindent14() +! let s:input = "" + call s:test_windows('setl breakindent briopt= ts=8') + vert resize 30 + norm! 3a1234567890 + norm! a abcde + exec "norm! 0\<C-V>tex" +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ "e ", +! \ "~ ", +! \ "~ ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunc +! +! func Test_breakindent14_vartabs() +! if !has("vartabs") +! return +! endif +! let s:input = "" +! call s:test_windows('setl breakindent briopt= ts=8 vts=8') +! vert resize 30 +! norm! 3a1234567890 +! norm! a abcde +! exec "norm! 0\<C-V>tex" +! let lines = s:screen_lines(line('.'),8) +! let expect = [ +! \ "e ", +! \ "~ ", +! \ "~ ", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set vts&') +! endfunc + +! func Test_breakindent15() +! let s:input = "" + call s:test_windows('setl breakindent briopt= ts=8 sw=8') + vert resize 30 + norm! 4a1234567890 + exe "normal! >>\<C-V>3f0x" +! let lines = s:screen_lines(line('.'),20) +! let expect = [ +! \ " 1234567890 ", +! \ "~ ", +! \ "~ ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunc +! +! func Test_breakindent15_vartabs() +! if !has("vartabs") +! return +! endif +! let s:input = "" +! call s:test_windows('setl breakindent briopt= ts=8 sw=8 vts=8') +! vert resize 30 +! norm! 4a1234567890 +! exe "normal! >>\<C-V>3f0x" +! let lines = s:screen_lines(line('.'),20) +! let expect = [ +! \ " 1234567890 ", +! \ "~ ", +! \ "~ ", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set vts&') +! endfunc + +! func Test_breakindent16() + " Check that overlong lines are indented correctly. +! let s:input = "" + call s:test_windows('setl breakindent briopt=min:0 ts=4') + call setline(1, "\t".repeat("1234567890", 10)) + resize 6 + norm! 1gg$ + redraw! +! let lines = s:screen_lines(1,10) +! let expect = [ +! \ " 789012", +! \ " 345678", +! \ " 901234", +! \ ] +! call s:compare_lines(expect, lines) +! let lines = s:screen_lines(4,10) +! let expect = [ +! \ " 567890", +! \ " 123456", +! \ " 7890 ", +! \ ] + call s:compare_lines(expect, lines) + call s:close_windows() +! endfunc +! +! func Test_breakindent16_vartabs() +! if !has("vartabs") +! return +! endif +! " Check that overlong lines are indented correctly. +! let s:input = "" +! call s:test_windows('setl breakindent briopt=min:0 ts=4 vts=4') +! call setline(1, "\t".repeat("1234567890", 10)) +! resize 6 +! norm! 1gg$ +! redraw! +! let lines = s:screen_lines(1,10) +! let expect = [ +! \ " 789012", +! \ " 345678", +! \ " 901234", +! \ ] +! call s:compare_lines(expect, lines) +! let lines = s:screen_lines(4,10) +! let expect = [ +! \ " 567890", +! \ " 123456", +! \ " 7890 ", +! \ ] +! call s:compare_lines(expect, lines) +! call s:close_windows('set vts&') +! endfunc +*** ../vim-8.1.0104/src/testdir/test_vartabs.vim 2018-06-23 19:18:52.740059396 +0200 +--- src/testdir/test_vartabs.vim 2018-06-23 18:05:31.387656858 +0200 +*************** +*** 0 **** +--- 1,257 ---- ++ " Test for variable tabstops ++ ++ if !has("vartabs") ++ finish ++ endif ++ ++ func! Test_vartabs() ++ new ++ %d ++ ++ " Test normal operation of tabstops ... ++ set ts=4 ++ call setline(1, join(split('aaaaa', '\zs'), "\t")) ++ retab 8 ++ let expect = "a a\<tab>a a\<tab>a" ++ call assert_equal(expect, getline(1)) ++ ++ " ... and softtabstops ++ set ts=8 sts=6 ++ exe "norm! Sb\<tab>b\<tab>b\<tab>b\<tab>b" ++ let expect = "b b\<tab> b\<tab> b\<tab>b" ++ call assert_equal(expect, getline(1)) ++ ++ " Test variable tabstops. ++ set sts=0 vts=4,8,4,8 ++ exe "norm! Sc\<tab>c\<tab>c\<tab>c\<tab>c\<tab>c" ++ retab 8 ++ let expect = "c c\<tab> c\<tab>c\<tab>c\<tab>c" ++ call assert_equal(expect, getline(1)) ++ ++ set et vts=4,8,4,8 ++ exe "norm! Sd\<tab>d\<tab>d\<tab>d\<tab>d\<tab>d" ++ let expect = "d d d d d d" ++ call assert_equal(expect, getline(1)) ++ ++ " Changing ts should have no effect if vts is in use. ++ call cursor(1, 1) ++ set ts=6 ++ exe "norm! Se\<tab>e\<tab>e\<tab>e\<tab>e\<tab>e" ++ let expect = "e e e e e e" ++ call assert_equal(expect, getline(1)) ++ ++ " Clearing vts should revert to using ts. ++ set vts= ++ exe "norm! Sf\<tab>f\<tab>f\<tab>f\<tab>f\<tab>f" ++ let expect = "f f f f f f" ++ call assert_equal(expect, getline(1)) ++ ++ " Test variable softtabstops. ++ set noet ts=8 vsts=12,2,6 ++ exe "norm! Sg\<tab>g\<tab>g\<tab>g\<tab>g\<tab>g" ++ let expect = "g\<tab> g g\<tab> g\<tab> g\<tab>g" ++ call assert_equal(expect, getline(1)) ++ ++ " Variable tabstops and softtabstops combined. ++ set vsts=6,12,8 vts=4,6,8 ++ exe "norm! Sh\<tab>h\<tab>h\<tab>h\<tab>h" ++ let expect = "h\<tab> h\<tab>\<tab>h\<tab>h\<tab>h" ++ call assert_equal(expect, getline(1)) ++ ++ " Retab with a single value, not using vts. ++ set ts=8 sts=0 vts= vsts= ++ exe "norm! Si\<tab>i\<tab>i\<tab>i\<tab>i" ++ retab 4 ++ let expect = "i\<tab>\<tab>i\<tab>\<tab>i\<tab>\<tab>i\<tab>\<tab>i" ++ call assert_equal(expect, getline(1)) ++ ++ " Retab with a single value, using vts. ++ set ts=8 sts=0 vts=6 vsts= ++ exe "norm! Sj\<tab>j\<tab>j\<tab>j\<tab>j" ++ retab 4 ++ let expect = "j\<tab> j\<tab>\<tab>j\<tab> j\<tab>\<tab>j" ++ call assert_equal(expect, getline(1)) ++ ++ " Retab with multiple values, not using vts. ++ set ts=6 sts=0 vts= vsts= ++ exe "norm! Sk\<tab>k\<tab>k\<tab>k\<tab>k\<tab>k" ++ retab 4,8 ++ let expect = "k\<tab> k\<tab>k k\<tab> k\<tab> k" ++ call assert_equal(expect, getline(1)) ++ ++ " Retab with multiple values, using vts. ++ set ts=8 sts=0 vts=6 vsts= ++ exe "norm! Sl\<tab>l\<tab>l\<tab>l\<tab>l\<tab>l" ++ retab 4,8 ++ let expect = "l\<tab> l\<tab>l l\<tab> l\<tab> l" ++ call assert_equal(expect, getline(1)) ++ ++ " Check that global and local values are set. ++ set ts=4 vts=6 sts=8 vsts=10 ++ call assert_equal(&ts, 4) ++ call assert_equal(&vts, '6') ++ call assert_equal(&sts, 8) ++ call assert_equal(&vsts, '10') ++ new ++ call assert_equal(&ts, 4) ++ call assert_equal(&vts, '6') ++ call assert_equal(&sts, 8) ++ call assert_equal(&vsts, '10') ++ bwipeout! ++ ++ " Check that local values only are set. ++ setlocal ts=5 vts=7 sts=9 vsts=11 ++ call assert_equal(&ts, 5) ++ call assert_equal(&vts, '7') ++ call assert_equal(&sts, 9) ++ call assert_equal(&vsts, '11') ++ new ++ call assert_equal(&ts, 4) ++ call assert_equal(&vts, '6') ++ call assert_equal(&sts, 8) ++ call assert_equal(&vsts, '10') ++ bwipeout! ++ ++ " Check that global values only are set. ++ setglobal ts=6 vts=8 sts=10 vsts=12 ++ call assert_equal(&ts, 5) ++ call assert_equal(&vts, '7') ++ call assert_equal(&sts, 9) ++ call assert_equal(&vsts, '11') ++ new ++ call assert_equal(&ts, 6) ++ call assert_equal(&vts, '8') ++ call assert_equal(&sts, 10) ++ call assert_equal(&vsts, '12') ++ bwipeout! ++ ++ set ts& vts& sts& vsts& et& ++ bwipeout! ++ endfunc ++ ++ func! Test_vartabs_breakindent() ++ if !exists("+breakindent") ++ return ++ endif ++ new ++ %d ++ ++ " Test normal operation of tabstops ... ++ set ts=4 ++ call setline(1, join(split('aaaaa', '\zs'), "\t")) ++ retab 8 ++ let expect = "a a\<tab>a a\<tab>a" ++ call assert_equal(expect, getline(1)) ++ ++ " ... and softtabstops ++ set ts=8 sts=6 ++ exe "norm! Sb\<tab>b\<tab>b\<tab>b\<tab>b" ++ let expect = "b b\<tab> b\<tab> b\<tab>b" ++ call assert_equal(expect, getline(1)) ++ ++ " Test variable tabstops. ++ set sts=0 vts=4,8,4,8 ++ exe "norm! Sc\<tab>c\<tab>c\<tab>c\<tab>c\<tab>c" ++ retab 8 ++ let expect = "c c\<tab> c\<tab>c\<tab>c\<tab>c" ++ call assert_equal(expect, getline(1)) ++ ++ set et vts=4,8,4,8 ++ exe "norm! Sd\<tab>d\<tab>d\<tab>d\<tab>d\<tab>d" ++ let expect = "d d d d d d" ++ call assert_equal(expect, getline(1)) ++ ++ " Changing ts should have no effect if vts is in use. ++ call cursor(1, 1) ++ set ts=6 ++ exe "norm! Se\<tab>e\<tab>e\<tab>e\<tab>e\<tab>e" ++ let expect = "e e e e e e" ++ call assert_equal(expect, getline(1)) ++ ++ " Clearing vts should revert to using ts. ++ set vts= ++ exe "norm! Sf\<tab>f\<tab>f\<tab>f\<tab>f\<tab>f" ++ let expect = "f f f f f f" ++ call assert_equal(expect, getline(1)) ++ ++ " Test variable softtabstops. ++ set noet ts=8 vsts=12,2,6 ++ exe "norm! Sg\<tab>g\<tab>g\<tab>g\<tab>g\<tab>g" ++ let expect = "g\<tab> g g\<tab> g\<tab> g\<tab>g" ++ call assert_equal(expect, getline(1)) ++ ++ " Variable tabstops and softtabstops combined. ++ set vsts=6,12,8 vts=4,6,8 ++ exe "norm! Sh\<tab>h\<tab>h\<tab>h\<tab>h" ++ let expect = "h\<tab> h\<tab>\<tab>h\<tab>h\<tab>h" ++ call assert_equal(expect, getline(1)) ++ ++ " Retab with a single value, not using vts. ++ set ts=8 sts=0 vts= vsts= ++ exe "norm! Si\<tab>i\<tab>i\<tab>i\<tab>i" ++ retab 4 ++ let expect = "i\<tab>\<tab>i\<tab>\<tab>i\<tab>\<tab>i\<tab>\<tab>i" ++ call assert_equal(expect, getline(1)) ++ ++ " Retab with a single value, using vts. ++ set ts=8 sts=0 vts=6 vsts= ++ exe "norm! Sj\<tab>j\<tab>j\<tab>j\<tab>j" ++ retab 4 ++ let expect = "j\<tab> j\<tab>\<tab>j\<tab> j\<tab>\<tab>j" ++ call assert_equal(expect, getline(1)) ++ ++ " Retab with multiple values, not using vts. ++ set ts=6 sts=0 vts= vsts= ++ exe "norm! Sk\<tab>k\<tab>k\<tab>k\<tab>k\<tab>k" ++ retab 4,8 ++ let expect = "k\<tab> k\<tab>k k\<tab> k\<tab> k" ++ call assert_equal(expect, getline(1)) ++ ++ " Retab with multiple values, using vts. ++ set ts=8 sts=0 vts=6 vsts= ++ exe "norm! Sl\<tab>l\<tab>l\<tab>l\<tab>l\<tab>l" ++ retab 4,8 ++ let expect = "l\<tab> l\<tab>l l\<tab> l\<tab> l" ++ call assert_equal(expect, getline(1)) ++ ++ " Check that global and local values are set. ++ set ts=4 vts=6 sts=8 vsts=10 ++ call assert_equal(&ts, 4) ++ call assert_equal(&vts, '6') ++ call assert_equal(&sts, 8) ++ call assert_equal(&vsts, '10') ++ new ++ call assert_equal(&ts, 4) ++ call assert_equal(&vts, '6') ++ call assert_equal(&sts, 8) ++ call assert_equal(&vsts, '10') ++ bwipeout! ++ ++ " Check that local values only are set. ++ setlocal ts=5 vts=7 sts=9 vsts=11 ++ call assert_equal(&ts, 5) ++ call assert_equal(&vts, '7') ++ call assert_equal(&sts, 9) ++ call assert_equal(&vsts, '11') ++ new ++ call assert_equal(&ts, 4) ++ call assert_equal(&vts, '6') ++ call assert_equal(&sts, 8) ++ call assert_equal(&vsts, '10') ++ bwipeout! ++ ++ " Check that global values only are set. ++ setglobal ts=6 vts=8 sts=10 vsts=12 ++ call assert_equal(&ts, 5) ++ call assert_equal(&vts, '7') ++ call assert_equal(&sts, 9) ++ call assert_equal(&vsts, '11') ++ new ++ call assert_equal(&ts, 6) ++ call assert_equal(&vts, '8') ++ call assert_equal(&sts, 10) ++ call assert_equal(&vsts, '12') ++ bwipeout! ++ ++ bwipeout! ++ endfunc +*** ../vim-8.1.0104/src/version.c 2018-06-23 17:14:36.801909989 +0200 +--- src/version.c 2018-06-23 19:18:18.788276086 +0200 +*************** +*** 677,682 **** +--- 677,687 ---- + #else + "-user_commands", + #endif ++ #ifdef FEAT_VARTABS ++ "+vartabs", ++ #else ++ "-vartabs", ++ #endif + "+vertsplit", + #ifdef FEAT_VIRTUALEDIT + "+virtualedit", +*** ../vim-8.1.0104/src/workshop.c 2017-11-18 21:10:42.000000000 +0100 +--- src/workshop.c 2018-06-23 17:41:10.116365995 +0200 +*************** +*** 49,55 **** +--- 49,59 ---- + static void warp_to_pc(int); + #ifdef FEAT_BEVAL_GUI + void workshop_beval_cb(BalloonEval *, int); ++ # ifdef FEAT_VARTABS ++ static int computeIndex(int, char_u *, int, int *); ++ # else + static int computeIndex(int, char_u *, int); ++ # endif + #endif + static char *fixAccelText(char *); + static void addMenu(char *, char *, char *); +*************** +*** 1534,1540 **** +--- 1538,1548 ---- + * a column number. Compute the index from col. Also set + * line to 0 because thats what dbx expects. + */ ++ #ifdef FEAT_VARTABS ++ idx = computeIndex(col, text, beval->ts, beval->vts); ++ #else + idx = computeIndex(col, text, beval->ts); ++ #endif + if (idx > 0) + { + lnum = 0; +*************** +*** 1569,1575 **** + computeIndex( + int wantedCol, + char_u *line, +! int ts) + { + int col = 0; + int idx = 0; +--- 1577,1587 ---- + computeIndex( + int wantedCol, + char_u *line, +! int ts +! #ifdef FEAT_VARTABS +! int *vts +! #else +! ) + { + int col = 0; + int idx = 0; +*************** +*** 1577,1583 **** +--- 1589,1599 ---- + while (line[idx]) + { + if (line[idx] == '\t') ++ #ifdef FEAT_VARTABS ++ col += tabstop_padding(col, ts, vts); ++ #else + col += ts - (col % ts); ++ #endif + else + col++; + idx++; +*** ../vim-8.1.0104/src/Makefile 2018-06-03 14:42:17.836505122 +0200 +--- src/Makefile 2018-06-23 18:09:24.498279403 +0200 +*************** +*** 2305,2310 **** +--- 2305,2311 ---- + test_usercommands \ + test_utf8 \ + test_utf8_comparisons \ ++ test_vartabs \ + test_viminfo \ + test_vimscript \ + test_virtualedit \ +*** ../vim-8.1.0104/src/version.c 2018-06-23 17:14:36.801909989 +0200 +--- src/version.c 2018-06-23 19:18:18.788276086 +0200 +*************** +*** 780,781 **** +--- 785,788 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 105, + /**/ + +-- +# echo reboot >universe +# chmod +x universe +# ./universe + + /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ +/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ +\\\ an exciting new programming language -- http://www.Zimbu.org /// + \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |