From 836e54f5de8479a39f6d1dd4a13202af0e447311 Mon Sep 17 00:00:00 2001 From: Hirohito Higashi Date: Mon, 14 Jul 2025 22:11:34 +0200 Subject: [PATCH] patch 9.1.1544: :retab cannot be limited to indentation only Problem: :retab cannot be limited to indentation only Solution: add the optional -indentonly parameter (Hirohito Higashi) closes: #17730 Signed-off-by: Hirohito Higashi Signed-off-by: Christian Brabandt --- runtime/doc/builtin.txt | 3 +- runtime/doc/change.txt | 24 ++-- runtime/doc/map.txt | 3 +- runtime/doc/version9.txt | 4 +- runtime/syntax/vim.vim | 4 +- src/cmdexpand.c | 18 +++ src/indent.c | 50 +++++--- src/po/vim.pot | 197 +++++++++++++++--------------- src/testdir/test_cmdline.vim | 7 ++ src/testdir/test_retab.vim | 74 ++++++++++- src/testdir/test_usercommands.vim | 4 + src/usercmd.c | 1 + src/version.c | 2 + src/vim.h | 1 + 14 files changed, 259 insertions(+), 133 deletions(-) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index c437f8da81..5e395e6d70 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.1. Last change: 2025 Jul 11 +*builtin.txt* For Vim version 9.1. Last change: 2025 Jul 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4333,6 +4333,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()* messages |:messages| suboptions option options packadd optional package |pack-add| names + retab |:retab| suboptions runtime |:runtime| completion scriptnames sourced script names |:scriptnames| shellcmd Shell command diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index e958e038bd..bd56d4313c 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1,4 +1,4 @@ -*change.txt* For Vim version 9.1. Last change: 2025 Jun 26 +*change.txt* For Vim version 9.1. Last change: 2025 Jul 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -991,22 +991,26 @@ This replaces each 'E' character with a euro sign. Read more in ||. 4.4 Changing tabs *change-tabs* *:ret* *:retab* *:retab!* -:[range]ret[ab][!] [new_tabstop] +:[range]ret[ab][!] [-indentonly] [{new-tabstop}] Replace all sequences of white-space containing a - with new strings of white-space using the new - tabstop value given. If you do not specify a new - tabstop size or it is zero, Vim uses the current value - of 'tabstop'. + with new strings of white-space using + {new-tabstop}. If you do not specify {new-tabstop} or + it is zero, Vim uses the current value of 'tabstop'. The current value of 'tabstop' is always used to compute the width of existing tabs. With !, Vim also replaces strings of only normal spaces with tabs where appropriate. With 'expandtab' on, Vim replaces all tabs with the appropriate number of spaces. - This command sets 'tabstop' to the new value given, - and if performed on the whole file, which is default, - should not make any visible change. - Careful: This command modifies any characters + This command sets 'tabstop' to {new-tabstop} and if + performed on the whole file, which is default, should + not make any visible change. + + When [-indentonly] is specified, only the leading + white-space will be targeted. Any other consecutive + white-space will not be changed. + + Warning: This command modifies any characters inside of strings in a C program. Use "\t" to avoid this (that's a good habit anyway). `:retab!` may also change a sequence of spaces by diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 899b24bac1..5a904b05bc 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1,4 +1,4 @@ -*map.txt* For Vim version 9.1. Last change: 2024 Oct 08 +*map.txt* For Vim version 9.1. Last change: 2025 Jul 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1654,6 +1654,7 @@ completion can be enabled: -complete=messages |:messages| suboptions -complete=option options -complete=packadd optional package |pack-add| names + -complete=retab |:retab| suboptions -complete=runtime file and directory names in |'runtimepath'| -complete=scriptnames sourced script names -complete=shellcmd Shell command diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index a89ab4f1e5..9b7aeefcb9 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2025 Jul 10 +*version9.txt* For Vim version 9.1. Last change: 2025 Jul 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41692,6 +41692,8 @@ Ex commands: ~ documented and skips help buffers (if not run from a help buffer, else moves to the next/previous help buffer). - |:keeppatterns| preserves the last substitute pattern when used with |:s| +- |:retab| accepts the new optional parameter -indentonly to only change + whitespace in indented lines. Functions: ~ - provide information about function arguments using the get(func, "arity") diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index b30314e617..c5bafe67a5 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -2,7 +2,7 @@ " Language: Vim script " Maintainer: Hirohito Higashi " Doug Kearns -" Last Change: 2025 Jul 11 +" Last Change: 2025 Jul 14 " Former Maintainer: Charles E. Campbell " DO NOT CHANGE DIRECTLY. @@ -842,7 +842,7 @@ syn case ignore syn keyword vimUserCmdAttrKey contained a[ddr] ban[g] bar bu[ffer] com[plete] cou[nt] k[eepscript] n[args] ra[nge] re[gister] " GEN_SYN_VIM: vimUserCmdAttrComplete, START_STR='syn keyword vimUserCmdAttrComplete contained', END_STR='' -syn keyword vimUserCmdAttrComplete contained arglist augroup behave breakpoint buffer color command compiler cscope diff_buffer dir dir_in_path environment event expression file file_in_path filetype filetypecmd function help highlight history keymap locale mapclear mapping menu messages option packadd runtime scriptnames shellcmd shellcmdline sign syntax syntime tag tag_listfiles user var +syn keyword vimUserCmdAttrComplete contained arglist augroup behave breakpoint buffer color command compiler cscope diff_buffer dir dir_in_path environment event expression file file_in_path filetype filetypecmd function help highlight history keymap locale mapclear mapping menu messages option packadd retab runtime scriptnames shellcmd shellcmdline sign syntax syntime tag tag_listfiles user var syn keyword vimUserCmdAttrComplete contained arglist augroup behave breakpoint buffer color command compiler cscope diff_buffer dir dir_in_path environment event expression file file_in_path filetype function help highlight history keymap locale mapclear mapping menu messages option packadd runtime scriptnames shellcmd shellcmdline sign syntax syntime tag tag_listfiles user var syn keyword vimUserCmdAttrComplete contained custom customlist nextgroup=vimUserCmdAttrCompleteFunc,vimUserCmdError syn match vimUserCmdAttrCompleteFunc contained ",\%([bwglstav]:\|<[sS][iI][dD]>\)\=\h\w*\%([.#]\h\w*\)*"hs=s+1 nextgroup=vimUserCmdError contains=vimVarScope,vimFunctionSID diff --git a/src/cmdexpand.c b/src/cmdexpand.c index bdfa679457..ffefada749 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -2622,6 +2622,11 @@ set_context_by_cmdname( xp->xp_pattern = arg; break; + case CMD_retab: + xp->xp_context = EXPAND_RETAB; + xp->xp_pattern = arg; + break; + case CMD_messages: xp->xp_context = EXPAND_MESSAGES; xp->xp_pattern = arg; @@ -3204,6 +3209,18 @@ get_scriptnames_arg(expand_T *xp UNUSED, int idx) } #endif +/* + * Function given to ExpandGeneric() to obtain the possible arguments of the + * ":retab {-indentonly}" option. + */ + static char_u * +get_retab_arg(expand_T *xp UNUSED, int idx) +{ + if (idx == 0) + return (char_u *)"-indentonly"; + return NULL; +} + /* * Function given to ExpandGeneric() to obtain the possible arguments of the * ":messages {clear}" command. @@ -3294,6 +3311,7 @@ ExpandOther( {EXPAND_BREAKPOINT, get_breakadd_arg, TRUE, TRUE}, {EXPAND_SCRIPTNAMES, get_scriptnames_arg, TRUE, FALSE}, #endif + {EXPAND_RETAB, get_retab_arg, TRUE, TRUE}, }; int i; int ret = FAIL; diff --git a/src/indent.c b/src/indent.c index b2861e9674..7a2c16d3c4 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1716,21 +1716,29 @@ ex_retab(exarg_T *eap) char_u *new_ts_str; // string value of tab argument #else int temp; - int new_ts; + int new_ts = 0; #endif int save_list; linenr_T first_line = 0; // first changed line linenr_T last_line = 0; // last changed line + int is_indent_only = 0; // Only process leading whitespace save_list = curwin->w_p_list; curwin->w_p_list = 0; // don't want list mode here + ptr = eap->arg; + if (STRNCMP(ptr, "-indentonly", 11) == 0 && IS_WHITE_OR_NUL(ptr[11])) + { + is_indent_only = 1; + ptr = skipwhite(ptr + 11); + } + #ifdef FEAT_VARTABS - new_ts_str = eap->arg; - if (tabstop_set(eap->arg, &new_vts_array) == FAIL) + new_ts_str = ptr; + if (tabstop_set(ptr, &new_vts_array) == FAIL) return; - while (vim_isdigit(*(eap->arg)) || *(eap->arg) == ',') - ++(eap->arg); + while (vim_isdigit(*ptr) || *ptr == ',') + ++ptr; // This ensures that either new_vts_array and new_ts_str are freshly // allocated, or new_vts_array points to an existing array and new_ts_str @@ -1741,19 +1749,26 @@ ex_retab(exarg_T *eap) new_ts_str = NULL; } else - new_ts_str = vim_strnsave(new_ts_str, eap->arg - new_ts_str); + new_ts_str = vim_strnsave(new_ts_str, ptr - new_ts_str); #else - ptr = eap->arg; - new_ts = getdigits(&ptr); - if (new_ts < 0 && *eap->arg == '-') + if (ptr[0] != NUL && (ptr[0] != '0' || ptr[1] != NUL)) { - emsg(_(e_argument_must_be_positive)); - return; - } - if (new_ts < 0 || new_ts > TABSTOP_MAX) - { - semsg(_(e_invalid_argument_str), eap->arg); - return; + char_u *end; + + if (strtol((char *)ptr, (char **)&end, 10) <= 0) + { + if (ptr != end) + emsg(_(e_argument_must_be_positive)); + else + semsg(_(e_invalid_argument_str), ptr); + return; + } + new_ts = getdigits(&ptr); + if (new_ts < 0 || new_ts > TABSTOP_MAX) + { + semsg(_(e_invalid_argument_str), eap->arg); + return; + } } if (new_ts == 0) new_ts = curbuf->b_p_ts; @@ -1854,6 +1869,9 @@ ex_retab(exarg_T *eap) } got_tab = FALSE; num_spaces = 0; + + if (is_indent_only) + break; } if (ptr[col] == NUL) break; diff --git a/src/po/vim.pot b/src/po/vim.pot index e40fc1c3f7..63e4ef2a24 100644 --- a/src/po/vim.pot +++ b/src/po/vim.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-07-12 22:03+0200\n" +"POT-Creation-Date: 2025-07-14 22:09+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1762,66 +1762,63 @@ msgstr "" msgid "Scanning dictionary: %s" msgstr "" -#: ../insexpand.c:2637 +#: ../insexpand.c:2642 msgid " (insert) Scroll (^E/^Y)" msgstr "" -#: ../insexpand.c:2639 +#: ../insexpand.c:2644 msgid " (replace) Scroll (^E/^Y)" msgstr "" #. reset in msg_trunc_attr() -#: ../insexpand.c:4165 +#: ../insexpand.c:4170 #, c-format msgid "Scanning: %s" msgstr "" #. reset in msg_trunc_attr() -#: ../insexpand.c:4213 +#: ../insexpand.c:4218 msgid "Scanning tags." msgstr "" -#: ../insexpand.c:5562 +#: ../insexpand.c:5567 msgid "match in file" msgstr "" -#: ../insexpand.c:6603 +#: ../insexpand.c:6609 msgid " Adding" msgstr "" -#. showmode might reset the internal line pointers, so it must -#. be called before line = ml_get(), or when this address is no -#. longer needed. -- Acevedo. -#: ../insexpand.c:6658 +#: ../insexpand.c:6669 msgid "-- Searching..." msgstr "" -#: ../insexpand.c:6677 +#: ../insexpand.c:6689 msgid "Hit end of paragraph" msgstr "" -#: ../insexpand.c:6678 +#: ../insexpand.c:6690 msgid "Pattern not found" msgstr "" -#: ../insexpand.c:6686 +#: ../insexpand.c:6698 msgid "Back at original" msgstr "" -#: ../insexpand.c:6691 +#: ../insexpand.c:6703 msgid "Word from other line" msgstr "" -#: ../insexpand.c:6696 +#: ../insexpand.c:6708 msgid "The only match" msgstr "" -#: ../insexpand.c:6717 +#: ../insexpand.c:6729 #, c-format msgid "match %d of %d" msgstr "" -#: ../insexpand.c:6721 +#: ../insexpand.c:6733 #, c-format msgid "match %d" msgstr "" @@ -4215,13 +4212,13 @@ msgstr "" msgid "number changes when saved" msgstr "" -#: ../usercmd.c:592 +#: ../usercmd.c:593 msgid "" "\n" " Name Args Address Complete Definition" msgstr "" -#: ../usercmd.c:741 +#: ../usercmd.c:742 msgid "No user-defined commands found" msgstr "" @@ -4260,327 +4257,327 @@ msgstr "" msgid "%s (%s, compiled %s)" msgstr "" -#: ../version.c:4010 +#: ../version.c:4022 msgid "" "\n" "MS-Windows ARM64 GUI/console version" msgstr "" -#: ../version.c:4012 +#: ../version.c:4024 msgid "" "\n" "MS-Windows 64-bit GUI/console version" msgstr "" -#: ../version.c:4015 +#: ../version.c:4027 msgid "" "\n" "MS-Windows 32-bit GUI/console version" msgstr "" -#: ../version.c:4020 +#: ../version.c:4032 msgid "" "\n" "MS-Windows ARM64 GUI version" msgstr "" -#: ../version.c:4022 +#: ../version.c:4034 msgid "" "\n" "MS-Windows 64-bit GUI version" msgstr "" -#: ../version.c:4025 +#: ../version.c:4037 msgid "" "\n" "MS-Windows 32-bit GUI version" msgstr "" -#: ../version.c:4029 +#: ../version.c:4041 msgid " with OLE support" msgstr "" -#: ../version.c:4034 +#: ../version.c:4046 msgid "" "\n" "MS-Windows ARM64 console version" msgstr "" -#: ../version.c:4036 +#: ../version.c:4048 msgid "" "\n" "MS-Windows 64-bit console version" msgstr "" -#: ../version.c:4039 +#: ../version.c:4051 msgid "" "\n" "MS-Windows 32-bit console version" msgstr "" -#: ../version.c:4045 +#: ../version.c:4057 msgid "" "\n" "macOS version" msgstr "" -#: ../version.c:4047 +#: ../version.c:4059 msgid "" "\n" "macOS version w/o darwin feat." msgstr "" -#: ../version.c:4057 +#: ../version.c:4069 msgid "" "\n" "OpenVMS version" msgstr "" -#: ../version.c:4072 +#: ../version.c:4084 msgid "" "\n" "Included patches: " msgstr "" -#: ../version.c:4097 +#: ../version.c:4109 msgid "" "\n" "Extra patches: " msgstr "" -#: ../version.c:4109 ../version.c:4420 +#: ../version.c:4121 ../version.c:4432 msgid "Modified by " msgstr "" -#: ../version.c:4116 +#: ../version.c:4128 msgid "" "\n" "Compiled " msgstr "" -#: ../version.c:4119 +#: ../version.c:4131 msgid "by " msgstr "" -#: ../version.c:4131 +#: ../version.c:4143 msgid "" "\n" "Huge version " msgstr "" -#: ../version.c:4133 +#: ../version.c:4145 msgid "" "\n" "Normal version " msgstr "" -#: ../version.c:4135 +#: ../version.c:4147 msgid "" "\n" "Tiny version " msgstr "" -#: ../version.c:4138 +#: ../version.c:4150 msgid "without GUI." msgstr "" -#: ../version.c:4141 +#: ../version.c:4153 msgid "with GTK3 GUI." msgstr "" -#: ../version.c:4143 +#: ../version.c:4155 msgid "with GTK2-GNOME GUI." msgstr "" -#: ../version.c:4145 +#: ../version.c:4157 msgid "with GTK2 GUI." msgstr "" -#: ../version.c:4148 +#: ../version.c:4160 msgid "with X11-Motif GUI." msgstr "" -#: ../version.c:4150 +#: ../version.c:4162 msgid "with Haiku GUI." msgstr "" -#: ../version.c:4152 +#: ../version.c:4164 msgid "with Photon GUI." msgstr "" -#: ../version.c:4154 +#: ../version.c:4166 msgid "with GUI." msgstr "" -#: ../version.c:4156 +#: ../version.c:4168 msgid " Features included (+) or not (-):\n" msgstr "" -#: ../version.c:4163 +#: ../version.c:4175 msgid " system vimrc file: \"" msgstr "" -#: ../version.c:4168 +#: ../version.c:4180 msgid " user vimrc file: \"" msgstr "" -#: ../version.c:4173 +#: ../version.c:4185 msgid " 2nd user vimrc file: \"" msgstr "" -#: ../version.c:4178 ../version.c:4185 ../version.c:4189 +#: ../version.c:4190 ../version.c:4197 ../version.c:4201 msgid " 3rd user vimrc file: \"" msgstr "" -#: ../version.c:4181 +#: ../version.c:4193 msgid " 4th user vimrc file: \"" msgstr "" -#: ../version.c:4194 +#: ../version.c:4206 msgid " user exrc file: \"" msgstr "" -#: ../version.c:4199 +#: ../version.c:4211 msgid " 2nd user exrc file: \"" msgstr "" -#: ../version.c:4205 +#: ../version.c:4217 msgid " system gvimrc file: \"" msgstr "" -#: ../version.c:4209 +#: ../version.c:4221 msgid " user gvimrc file: \"" msgstr "" -#: ../version.c:4213 +#: ../version.c:4225 msgid "2nd user gvimrc file: \"" msgstr "" -#: ../version.c:4218 +#: ../version.c:4230 msgid "3rd user gvimrc file: \"" msgstr "" -#: ../version.c:4223 +#: ../version.c:4235 msgid " defaults file: \"" msgstr "" -#: ../version.c:4228 +#: ../version.c:4240 msgid " system menu file: \"" msgstr "" -#: ../version.c:4236 +#: ../version.c:4248 msgid " fall-back for $VIM: \"" msgstr "" -#: ../version.c:4242 +#: ../version.c:4254 msgid " f-b for $VIMRUNTIME: \"" msgstr "" -#: ../version.c:4246 +#: ../version.c:4258 msgid "Compilation: " msgstr "" -#: ../version.c:4252 +#: ../version.c:4264 msgid "Compiler: " msgstr "" -#: ../version.c:4257 +#: ../version.c:4269 msgid "Linking: " msgstr "" -#: ../version.c:4262 +#: ../version.c:4274 msgid " DEBUG BUILD" msgstr "" -#: ../version.c:4298 +#: ../version.c:4310 msgid "VIM - Vi IMproved" msgstr "" -#: ../version.c:4300 +#: ../version.c:4312 msgid "version " msgstr "" -#: ../version.c:4301 +#: ../version.c:4313 msgid "by Bram Moolenaar et al." msgstr "" -#: ../version.c:4305 +#: ../version.c:4317 msgid "Vim is open source and freely distributable" msgstr "" -#: ../version.c:4307 +#: ../version.c:4319 msgid "Help poor children in Uganda!" msgstr "" -#: ../version.c:4308 +#: ../version.c:4320 msgid "type :help iccf for information " msgstr "" -#: ../version.c:4310 +#: ../version.c:4322 msgid "type :q to exit " msgstr "" -#: ../version.c:4311 +#: ../version.c:4323 msgid "type :help or for on-line help" msgstr "" -#: ../version.c:4312 +#: ../version.c:4324 msgid "type :help version9 for version info" msgstr "" -#: ../version.c:4315 +#: ../version.c:4327 msgid "Running in Vi compatible mode" msgstr "" -#: ../version.c:4316 +#: ../version.c:4328 msgid "type :set nocp for Vim defaults" msgstr "" -#: ../version.c:4317 +#: ../version.c:4329 msgid "type :help cp-default for info on this" msgstr "" -#: ../version.c:4332 +#: ../version.c:4344 msgid "menu Help->Orphans for information " msgstr "" -#: ../version.c:4334 +#: ../version.c:4346 msgid "Running modeless, typed text is inserted" msgstr "" -#: ../version.c:4335 +#: ../version.c:4347 msgid "menu Edit->Global Settings->Toggle Insert Mode " msgstr "" -#: ../version.c:4336 +#: ../version.c:4348 msgid " for two modes " msgstr "" -#: ../version.c:4340 +#: ../version.c:4352 msgid "menu Edit->Global Settings->Toggle Vi Compatible" msgstr "" -#: ../version.c:4341 +#: ../version.c:4353 msgid " for Vim defaults " msgstr "" -#: ../version.c:4382 +#: ../version.c:4394 msgid "Sponsor Vim development!" msgstr "" -#: ../version.c:4383 +#: ../version.c:4395 msgid "Become a registered Vim user!" msgstr "" -#: ../version.c:4386 +#: ../version.c:4398 msgid "type :help sponsor for information " msgstr "" -#: ../version.c:4387 +#: ../version.c:4399 msgid "type :help register for information " msgstr "" -#: ../version.c:4389 +#: ../version.c:4401 msgid "menu Help->Sponsor/Register for information " msgstr "" @@ -4744,12 +4741,12 @@ msgstr "" msgid "wayland protocol error -> " msgstr "" -#: ../wayland.c:2430 +#: ../wayland.c:2461 #, c-format msgid "restoring Wayland display %s" msgstr "" -#: ../wayland.c:2437 +#: ../wayland.c:2468 msgid "failed restoring, lost connection to Wayland display" msgstr "" @@ -11611,17 +11608,17 @@ msgid "" "You should now append vim.VIM_SPECIAL_PATH to sys.path" msgstr "" -#: ../vim.h:2540 +#: ../vim.h:2541 msgid "" "Vim macro files (*.vim)\t*.vim\n" "All Files (*.*)\t*.*\n" msgstr "" -#: ../vim.h:2541 +#: ../vim.h:2542 msgid "All Files (*.*)\t*.*\n" msgstr "" -#: ../vim.h:2543 +#: ../vim.h:2544 msgid "" "All Files (*.*)\t*.*\n" "C source (*.c, *.h)\t*.c;*.h\n" @@ -11630,17 +11627,17 @@ msgid "" "Vim files (*.vim, _vimrc, _gvimrc)\t*.vim;_vimrc;_gvimrc\n" msgstr "" -#: ../vim.h:2546 +#: ../vim.h:2547 msgid "" "Vim macro files (*.vim)\t*.vim\n" "All Files (*)\t*\n" msgstr "" -#: ../vim.h:2547 +#: ../vim.h:2548 msgid "All Files (*)\t*\n" msgstr "" -#: ../vim.h:2549 +#: ../vim.h:2550 msgid "" "All Files (*)\t*\n" "C source (*.c, *.h)\t*.c;*.h\n" diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 46ace66161..203ab770f5 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -764,6 +764,11 @@ func Test_getcompletion() let l = getcompletion('not', 'mapclear') call assert_equal([], l) + let l = getcompletion('', 'retab') + call assert_true(index(l, '-indentonly') >= 0) + let l = getcompletion('not', 'retab') + call assert_equal([], l) + let l = getcompletion('.', 'shellcmd') call assert_equal(['./', '../'], filter(l, 'v:val =~ "\\./"')) call assert_equal(-1, match(l[2:], '^\.\.\?/$')) @@ -820,6 +825,8 @@ func Test_getcompletion() call assert_equal([], l) let l = getcompletion('autocmd BufEnter * map '], l) + let l = getcompletion('retab! ', 'cmdline') + call assert_true(index(l, '-indentonly') >= 0) func T(a, c, p) let g:cmdline_compl_params = [a:a, a:c, a:p] diff --git a/src/testdir/test_retab.vim b/src/testdir/test_retab.vim index 8cd6f77be3..47a718ff16 100644 --- a/src/testdir/test_retab.vim +++ b/src/testdir/test_retab.vim @@ -9,10 +9,13 @@ func TearDown() bwipe! endfunc -func Retab(bang, n) +func Retab(bang, n, subopt='', test_line='') let l:old_tabstop = &tabstop let l:old_line = getline(1) - exe "retab" . a:bang . a:n + if a:test_line != '' + call setline(1, a:test_line) + endif + exe "retab" . a:bang . ' ' . a:subopt . ' ' . a:n let l:line = getline(1) call setline(1, l:old_line) if a:n > 0 @@ -71,6 +74,70 @@ func Test_retab() call assert_equal(" a b c ", Retab('', 5)) call assert_equal(" a b c ", Retab('!', 5)) + " Test with '-indentonly' + let so='-indentonly' + set tabstop=8 noexpandtab + call assert_equal("\ta \t b c ", Retab('', '', so)) + call assert_equal("\ta \t b c ", Retab('', 0, so)) + call assert_equal("\ta \t b c ", Retab('', 8, so)) + call assert_equal("\ta \t b c ", Retab('!', '', so)) + call assert_equal("\ta \t b c ", Retab('!', 0, so)) + call assert_equal("\ta \t b c ", Retab('!', 8, so)) + + call assert_equal("\t\ta \t b c ", Retab('', 4, so)) + call assert_equal("\t\ta \t b c ", Retab('!', 4, so)) + + call assert_equal(" a \t b c ", Retab('', 10, so)) + call assert_equal(" a \t b c ", Retab('!', 10, so)) + + set tabstop=8 expandtab + call assert_equal(" a \t b c ", Retab('', '', so)) + call assert_equal(" a \t b c ", Retab('', 0, so)) + call assert_equal(" a \t b c ", Retab('', 8, so)) + call assert_equal(" a \t b c ", Retab('!', '', so)) + call assert_equal(" a \t b c ", Retab('!', 0, so)) + call assert_equal(" a \t b c ", Retab('!', 8, so)) + + call assert_equal(" a \t b c ", Retab(' ', 4, so)) + call assert_equal(" a \t b c ", Retab('!', 4, so)) + + call assert_equal(" a \t b c ", Retab(' ', 10, so)) + call assert_equal(" a \t b c ", Retab('!', 10, so)) + + set tabstop=4 noexpandtab + call assert_equal("\ta \t b c ", Retab('', '', so)) + call assert_equal("\ta \t b c ", Retab('!', '', so)) + call assert_equal("\t a \t b c ", Retab('', 3, so)) + call assert_equal("\t a \t b c ", Retab('!', 3, so)) + call assert_equal(" a \t b c ", Retab('', 5, so)) + call assert_equal(" a \t b c ", Retab('!', 5, so)) + + set tabstop=4 expandtab + call assert_equal(" a \t b c ", Retab('', '', so)) + call assert_equal(" a \t b c ", Retab('!', '', so)) + call assert_equal(" a \t b c ", Retab('', 3, so)) + call assert_equal(" a \t b c ", Retab('!', 3, so)) + call assert_equal(" a \t b c ", Retab('', 5, so)) + call assert_equal(" a \t b c ", Retab('!', 5, so)) + + " Test for variations in leading whitespace + let so='-indentonly' + let test_line=" \t a\t " + set tabstop=8 noexpandtab + call assert_equal("\t a\t ", Retab('', '', so, test_line)) + call assert_equal("\t a\t ", Retab('!', '', so, test_line)) + set tabstop=8 expandtab + call assert_equal(" a\t ", Retab('', '', so, test_line)) + call assert_equal(" a\t ", Retab('!', '', so, test_line)) + + let test_line=" a\t " + set tabstop=8 noexpandtab + call assert_equal(test_line, Retab('', '', so, test_line)) + call assert_equal("\t a\t ", Retab('!', '', so, test_line)) + set tabstop=8 expandtab + call assert_equal(test_line, Retab('', '', so, test_line)) + call assert_equal(test_line, Retab('!', '', so, test_line)) + set tabstop& expandtab& endfunc @@ -80,6 +147,9 @@ func Test_retab_error() call assert_fails('ret -1000', 'E487:') call assert_fails('ret 10000', 'E475:') call assert_fails('ret 80000000000000000000', 'E475:') + call assert_fails('retab! -in', 'E475:') + call assert_fails('retab! -indentonly2', 'E475:') + call assert_fails('retab! -indentonlyx 0', 'E475:') endfunc func RetabLoop() diff --git a/src/testdir/test_usercommands.vim b/src/testdir/test_usercommands.vim index 636ac2bd15..2718a24dd3 100644 --- a/src/testdir/test_usercommands.vim +++ b/src/testdir/test_usercommands.vim @@ -425,6 +425,10 @@ func Test_CmdCompletion() call feedkeys(":DoCmd \\\"\", 'tx') call assert_equal('"DoCmd mswin xterm', @:) + com! -nargs=1 -complete=retab DoCmd : + call feedkeys(":DoCmd \\\"\", 'tx') + call assert_equal('"DoCmd -indentonly', @:) + " Test for file name completion com! -nargs=1 -complete=file DoCmd : call feedkeys(":DoCmd READM\\\"\", 'tx') diff --git a/src/usercmd.c b/src/usercmd.c index 0ed9598d83..7c10a51dfa 100644 --- a/src/usercmd.c +++ b/src/usercmd.c @@ -88,6 +88,7 @@ static keyvalue_T command_complete_tab[] = KEYVALUE_ENTRY(EXPAND_MESSAGES, "messages"), KEYVALUE_ENTRY(EXPAND_SETTINGS, "option"), KEYVALUE_ENTRY(EXPAND_PACKADD, "packadd"), + KEYVALUE_ENTRY(EXPAND_RETAB, "retab"), KEYVALUE_ENTRY(EXPAND_RUNTIME, "runtime"), #if defined(FEAT_EVAL) KEYVALUE_ENTRY(EXPAND_SCRIPTNAMES, "scriptnames"), diff --git a/src/version.c b/src/version.c index 634bf58b48..62dd30ad91 100644 --- a/src/version.c +++ b/src/version.c @@ -719,6 +719,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1544, /**/ 1543, /**/ diff --git a/src/vim.h b/src/vim.h index b8569d85e2..74a349dccc 100644 --- a/src/vim.h +++ b/src/vim.h @@ -860,6 +860,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); #define EXPAND_HIGHLIGHT_GROUP 62 #define EXPAND_FILETYPECMD 63 #define EXPAND_PATTERN_IN_BUF 64 +#define EXPAND_RETAB 65 // Values for exmode_active (0 is no exmode)