Problem: ':delete #' silently fails to update "# and clobbers "0.
Solution: Treat "# like "/, writable only with :let and setreg().
closes: #20592
Signed-off-by: Doug Kearns <dougkearns@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
-*change.txt* For Vim version 9.2. Last change: 2026 Jun 18
+*change.txt* For Vim version 9.2. Last change: 2026 Jun 22
VIM REFERENCE MANUAL by Bram Moolenaar
the command was executed completely from a mapping.
{not available when compiled without the |+cmdline_hist|
feature}
- *quote_#* *quote#*
-6. Alternate file register "#
+
+6. Alternate file register "# *quote_#* *quote#* *@#*
Contains the |alternate-file| name for current window
-This register is writeable and changes which buffer CTRL-^ enters.
+This register is writable with `:let` and |setreg()|. This changes which buffer
+CTRL-^ enters. You can't yank or delete into this register.
A String is matched against existing buffer names, like |:buffer|: >
let @# = 'buffer_name'
Also supports using buffer number and |file-pattern|.
text without affecting the normal registers. When reading from this register,
nothing is returned.
-10. Last search pattern register "/ *quote_/* *quote/*
+10. Last search pattern register "/ *quote_/* *quote/*
Contains the most recent search-pattern. This is used for "n" and 'hlsearch'.
-It is writable with `:let`, you can change it to have 'hlsearch' highlight
-other matches without actually searching. You can't yank or delete into this
-register. The search direction is available in |v:searchforward|.
+This register is writable with `:let` and |setreg()|. You can change it to have
+'hlsearch' highlight other matches without actually searching. You can't yank
+or delete into this register. The search direction is available in
+|v:searchforward|.
Note that the value is restored when returning from a function
|function-search-undo|.
?<CR> pattern.txt /*?<CR>*
?? eval.txt /*??*
@ repeat.txt /*@*
+@# change.txt /*@#*
@/ change.txt /*@\/*
@: repeat.txt /*@:*
@= change.txt /*@=*
#ifdef FEAT_EVAL
EXTERN char e_uniq_compare_function_failed[]
INIT(= N_("E882: Uniq compare function failed"));
-EXTERN char e_search_pattern_and_expression_register_may_not_contain_two_or_more_lines[]
- INIT(= N_("E883: Search pattern and expression register may not contain two or more lines"));
+EXTERN char e_register_char_cannot_contain_multiple_lines[]
+ INIT(= N_("E883: Register '%c' cannot contain multiple lines"));
EXTERN char e_function_name_cannot_contain_colon_str[]
INIT(= N_("E884: Function name cannot contain a colon: %s"));
#endif
msgstr ""
"Project-Id-Version: Vim\n"
"Report-Msgid-Bugs-To: vim-dev@vim.org\n"
-"POT-Creation-Date: 2026-06-16 19:21+0000\n"
+"POT-Creation-Date: 2026-06-22 19:36+0000\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"
msgid "E882: Uniq compare function failed"
msgstr ""
-msgid ""
-"E883: Search pattern and expression register may not contain two or more "
-"lines"
+#, c-format
+msgid "E883: Register '%c' cannot contain multiple lines"
msgstr ""
#, c-format
if ( (regname > 0 && ASCII_ISALNUM(regname))
|| (!writing && vim_strchr((char_u *)
#ifdef FEAT_EVAL
- "/.%:="
+ "/#.%:="
#else
- "/.%:"
+ "/#.%:"
#endif
, regname) != NULL)
- || regname == '#'
|| regname == '"'
|| regname == '-'
|| regname == '_'
{
yankreg_T *old_y_previous, *old_y_current;
- if (name == '/' || name == '=')
+ if (name == '/' || name == '=' || name == '#')
{
char_u *s;
s = (char_u *)"";
else if (strings[1] != NULL)
{
- emsg(_(e_search_pattern_and_expression_register_may_not_contain_two_or_more_lines));
+ semsg(_(e_register_char_cannot_contain_multiple_lines), name);
return;
}
else
func Test_ex_delete()
new
+
call setline(1, ['a', 'b', 'c'])
2
" :dl is :delete with the "l" flag, not :dlist
.dl
call assert_equal(['a', 'c'], getline(1, 2))
+ %delete _
+
+ " :delete # used to clobber "0
+ call setreg('#', '')
+ call setreg('0', '')
+ call setline(1, ['a', 'b', 'c'])
+ call assert_fails("1delete #", 'E488:')
+ call assert_equal(['a', 'b', 'c'], getline(1, '$'))
+ call assert_equal('', getreg('#'))
+ call assert_equal('', getreg('0'))
+
+ bw!
endfunc
func Test_range_error()
call assert_equal('', @=)
call assert_fails("call setreg('/', ['a', 'b'])", 'E883:')
call assert_fails("call setreg('=', ['a', 'b'])", 'E883:')
+ call assert_fails("call setreg('#', ['a', 'b'])", 'E883:')
call assert_equal(0, setreg('_', ['a', 'b']))
" Test for recording to a invalid register
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 705,
/**/
704,
/**/
{
if (name == '@')
name = '"';
- if (name == '/' || name == '=' || valid_yank_reg(name, TRUE))
+ if (name == '/' || name == '=' || name == '#' || valid_yank_reg(name, TRUE))
return TRUE;
emsg_invreg(name);
return FAIL;