mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
vim-patch:9.1.1544: :retab cannot be limited to indentation only (#34939)
Problem: :retab cannot be limited to indentation only
Solution: add the optional -indentonly parameter
(Hirohito Higashi)
closes: vim/vim#17730
836e54f5de
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
This commit is contained in:
@@ -949,22 +949,26 @@ This replaces each 'E' character with a euro sign. Read more in |<Char->|.
|
||||
|
||||
4.3 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
|
||||
|
@@ -1410,6 +1410,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
|
||||
|
@@ -161,6 +161,8 @@ DIAGNOSTICS
|
||||
EDITOR
|
||||
|
||||
• |:iput| works like |:put| but adjusts indent.
|
||||
• |:retab| accepts new optional parameter -indentonly to only change leading
|
||||
whitespace in indented lines.
|
||||
• |:uniq| deduplicates text in the current buffer.
|
||||
• |omnicompletion| in `help` buffer. |ft-help-omni|
|
||||
• Setting "'0" in 'shada' prevents storing the jumplist in the shada file.
|
||||
|
@@ -69,7 +69,7 @@ Defaults *defaults* *nvim-defaults*
|
||||
- 'langremap' is disabled
|
||||
- 'laststatus' defaults to 2 (statusline is always shown)
|
||||
- 'listchars' defaults to "tab:> ,trail:-,nbsp:+"
|
||||
- 'maxsearchcount' defaults t0 999
|
||||
- 'maxsearchcount' defaults to 999
|
||||
- 'mouse' defaults to "nvi", see |default-mouse| for details
|
||||
- 'mousemodel' defaults to "popup_setpos"
|
||||
- 'nrformats' defaults to "bin,hex"
|
||||
|
@@ -3469,6 +3469,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
|
||||
|
1
runtime/lua/vim/_meta/vimfn.lua
generated
1
runtime/lua/vim/_meta/vimfn.lua
generated
@@ -3113,6 +3113,7 @@ function vim.fn.getcmdwintype() end
|
||||
--- 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
|
||||
|
@@ -778,7 +778,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
|
||||
|
@@ -2290,6 +2290,11 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa
|
||||
xp->xp_pattern = (char *)arg;
|
||||
break;
|
||||
|
||||
case CMD_retab:
|
||||
xp->xp_context = EXPAND_RETAB;
|
||||
xp->xp_pattern = (char *)arg;
|
||||
break;
|
||||
|
||||
case CMD_messages:
|
||||
xp->xp_context = EXPAND_MESSAGES;
|
||||
xp->xp_pattern = (char *)arg;
|
||||
@@ -2768,6 +2773,16 @@ static char *get_scriptnames_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
|
||||
return NameBuff;
|
||||
}
|
||||
|
||||
/// Function given to ExpandGeneric() to obtain the possible arguments of the
|
||||
/// ":retab {-indentonly}" option.
|
||||
static char *get_retab_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
|
||||
{
|
||||
if (idx == 0) {
|
||||
return "-indentonly";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Function given to ExpandGeneric() to obtain the possible arguments of the
|
||||
/// ":messages {clear}" command.
|
||||
static char *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
|
||||
@@ -2853,6 +2868,7 @@ static int ExpandOther(char *pat, expand_T *xp, regmatch_T *rmp, char ***matches
|
||||
{ EXPAND_ARGLIST, get_arglist_name, true, false },
|
||||
{ EXPAND_BREAKPOINT, get_breakadd_arg, true, true },
|
||||
{ EXPAND_SCRIPTNAMES, get_scriptnames_arg, true, false },
|
||||
{ EXPAND_RETAB, get_retab_arg, true, true },
|
||||
{ EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
|
||||
};
|
||||
int ret = FAIL;
|
||||
|
@@ -114,6 +114,7 @@ enum {
|
||||
EXPAND_FINDFUNC,
|
||||
EXPAND_FILETYPECMD,
|
||||
EXPAND_PATTERN_IN_BUF,
|
||||
EXPAND_RETAB,
|
||||
EXPAND_CHECKHEALTH,
|
||||
EXPAND_LUA,
|
||||
};
|
||||
|
@@ -3901,6 +3901,7 @@ M.funcs = {
|
||||
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
|
||||
|
@@ -1006,16 +1006,23 @@ void ex_retab(exarg_T *eap)
|
||||
|
||||
linenr_T first_line = 0; // first changed line
|
||||
linenr_T last_line = 0; // last changed line
|
||||
bool is_indent_only = false;
|
||||
|
||||
int save_list = curwin->w_p_list;
|
||||
curwin->w_p_list = 0; // don't want list mode here
|
||||
|
||||
new_ts_str = eap->arg;
|
||||
if (!tabstop_set(eap->arg, &new_vts_array)) {
|
||||
char *ptr = eap->arg;
|
||||
if (strncmp(ptr, "-indentonly", 11) == 0 && ascii_iswhite_or_nul(ptr[11])) {
|
||||
is_indent_only = true;
|
||||
ptr = skipwhite(ptr + 11);
|
||||
}
|
||||
|
||||
new_ts_str = ptr;
|
||||
if (!tabstop_set(ptr, &new_vts_array)) {
|
||||
return;
|
||||
}
|
||||
while (ascii_isdigit(*(eap->arg)) || *(eap->arg) == ',') {
|
||||
eap->arg++;
|
||||
while (ascii_isdigit(*ptr) || *ptr == ',') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
// This ensures that either new_vts_array and new_ts_str are freshly
|
||||
@@ -1025,10 +1032,10 @@ void ex_retab(exarg_T *eap)
|
||||
new_vts_array = curbuf->b_p_vts_array;
|
||||
new_ts_str = NULL;
|
||||
} else {
|
||||
new_ts_str = xmemdupz(new_ts_str, (size_t)(eap->arg - new_ts_str));
|
||||
new_ts_str = xmemdupz(new_ts_str, (size_t)(ptr - new_ts_str));
|
||||
}
|
||||
for (linenr_T lnum = eap->line1; !got_int && lnum <= eap->line2; lnum++) {
|
||||
char *ptr = ml_get(lnum);
|
||||
ptr = ml_get(lnum);
|
||||
int old_len = ml_get_len(lnum);
|
||||
int col = 0;
|
||||
int64_t vcol = 0;
|
||||
@@ -1106,6 +1113,10 @@ void ex_retab(exarg_T *eap)
|
||||
}
|
||||
got_tab = false;
|
||||
num_spaces = 0;
|
||||
|
||||
if (is_indent_only) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ptr[col] == NUL) {
|
||||
break;
|
||||
|
@@ -90,6 +90,7 @@ static const char *command_complete[] = {
|
||||
[EXPAND_SYNTIME] = "syntime",
|
||||
[EXPAND_SETTINGS] = "option",
|
||||
[EXPAND_PACKADD] = "packadd",
|
||||
[EXPAND_RETAB] = "retab",
|
||||
[EXPAND_RUNTIME] = "runtime",
|
||||
[EXPAND_SHELLCMD] = "shellcmd",
|
||||
[EXPAND_SHELLCMDLINE] = "shellcmdline",
|
||||
|
@@ -626,6 +626,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:], '^\.\.\?/$'))
|
||||
@@ -682,6 +687,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]
|
||||
|
@@ -11,10 +11,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
|
||||
@@ -73,6 +76,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
|
||||
|
||||
@@ -82,6 +149,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()
|
||||
|
@@ -406,6 +406,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')
|
||||
|
Reference in New Issue
Block a user