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 <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Hirohito Higashi
2025-07-14 22:11:34 +02:00
committed by Christian Brabandt
parent e85a66a4d4
commit 836e54f5de
14 changed files with 259 additions and 133 deletions

View File

@ -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

View File

@ -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 |<Char->|.
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
<Tab> 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'.
<Tab> 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 <Tab> 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 <Tab> 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

View File

@ -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

View File

@ -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")

View File

@ -2,7 +2,7 @@
" Language: Vim script
" Maintainer: Hirohito Higashi <h.east.727 ATMARK gmail.com>
" Doug Kearns <dougkearns@gmail.com>
" 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

View File

@ -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;

View File

@ -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;

View File

@ -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 <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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<Enter> for information "
msgstr ""
#: ../version.c:4310
#: ../version.c:4322
msgid "type :q<Enter> to exit "
msgstr ""
#: ../version.c:4311
#: ../version.c:4323
msgid "type :help<Enter> or <F1> for on-line help"
msgstr ""
#: ../version.c:4312
#: ../version.c:4324
msgid "type :help version9<Enter> 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<Enter> for Vim defaults"
msgstr ""
#: ../version.c:4317
#: ../version.c:4329
msgid "type :help cp-default<Enter> 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<Enter> for information "
msgstr ""
#: ../version.c:4387
#: ../version.c:4399
msgid "type :help register<Enter> 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"

View File

@ -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 <bu', 'cmdline')
call assert_equal(['<buffer>'], 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]

View File

@ -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()

View File

@ -425,6 +425,10 @@ func Test_CmdCompletion()
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"DoCmd mswin xterm', @:)
com! -nargs=1 -complete=retab DoCmd :
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"DoCmd -indentonly', @:)
" Test for file name completion
com! -nargs=1 -complete=file DoCmd :
call feedkeys(":DoCmd READM\<Tab>\<C-B>\"\<CR>", 'tx')

View File

@ -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"),

View File

@ -719,6 +719,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1544,
/**/
1543,
/**/

View File

@ -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)