aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNacho Nieva <83428506+NachoNievaG@users.noreply.github.com>2023-12-26 20:26:18 -0300
committerGitHub <noreply@github.com>2023-12-27 07:26:18 +0800
commitc26dc1f77c792fe5cbefd578dc8d1e23c80d3688 (patch)
treee5419c542cdd3099a3e9d65cf7b7c4f5f3945201
parent5cb906e91cb56302d0737aa80e2d890dde452029 (diff)
downloadrneovim-c26dc1f77c792fe5cbefd578dc8d1e23c80d3688.tar.gz
rneovim-c26dc1f77c792fe5cbefd578dc8d1e23c80d3688.tar.bz2
rneovim-c26dc1f77c792fe5cbefd578dc8d1e23c80d3688.zip
feat(defaults): map Q and @x to repeat in Visual mode (#26495)
-rw-r--r--runtime/doc/news.txt3
-rw-r--r--runtime/doc/repeat.txt10
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--runtime/doc/visual.txt14
-rw-r--r--runtime/lua/vim/_defaults.lua15
-rw-r--r--test/functional/editor/macro_spec.lua69
6 files changed, 112 insertions, 1 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index bc3902bc4c..a256db76d6 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -112,6 +112,9 @@ The following changes may require adaptations in user config or plugins.
• 'termguicolors' is enabled by default when Nvim is able to determine that
the host terminal emulator supports 24-bit color.
+• `Q` now repeats a macro for each line of a visual selection.
+• `@` now repeats the indicated macro for each line of a visual selection.
+
==============================================================================
BREAKING CHANGES IN HEAD *news-breaking-dev*
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 53f6904170..726d7a9591 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -148,10 +148,20 @@ q Stops recording.
*@@* *E748*
@@ Repeat the previous @{0-9a-z":*} [count] times.
+ *v_@-default*
+{Visual}@{0-9a-z".=*+} In Visual mode, execute the contents of the register
+{Visual}@@ but for each selected line.
+ See |visual-repeat|, |default-mappings|.
+
*Q*
Q Repeat the last recorded register [count] times.
See |reg_recorded()|.
+ *v_Q-default*
+{Visual}Q In Visual mode, repeat the last recorded register for
+ each selected line.
+ See |visual-repeat|, |default-mappings|.
+
*:@*
:[addr]@{0-9a-z".=*+} Execute the contents of register {0-9a-z".=*+} as an Ex
command. First set cursor at line [addr] (default is
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 77b9ff6864..5b0b5655b4 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -129,6 +129,8 @@ of these in your config by simply removing the mapping, e.g. ":unmap Y".
- <C-W> |i_CTRL-W-default|
- <C-L> |CTRL-L-default|
- & |&-default|
+- Q |v_Q-default|
+- @ |v_@-default|
- # |v_#-default|
- * |v_star-default|
- Nvim LSP client defaults |lsp-defaults|
diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt
index 0d1ea937c0..a20fb6d31e 100644
--- a/runtime/doc/visual.txt
+++ b/runtime/doc/visual.txt
@@ -366,6 +366,20 @@ one of the last commands to extend the highlighted text, the repeating will
be applied up to the rightmost column of the longest line. Any count passed
to the `.` command is not used.
+Visual mode |default-mappings| "@" and "Q" can repeat commands in a register
+for all selected lines. See |v_@-default| and |v_Q-default| for details. For
+example, given the text:
+
+ 123(hello)321
+ 456(world)654
+ 456(NOT THIS)654
+
+With register "x" containing the commands `yi(VP`, Visually selecting the
+first two lines and typing `@x` produces:
+
+ hello
+ world
+ 456(NOT THIS)654
==============================================================================
7. Examples *visual-examples*
diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua
index 2627cbcd0d..0d756b8701 100644
--- a/runtime/lua/vim/_defaults.lua
+++ b/runtime/lua/vim/_defaults.lua
@@ -67,6 +67,21 @@ do
--- See |&-default|
vim.keymap.set('n', '&', ':&&<CR>', { desc = ':help &-default' })
+ --- Use Q in visual mode to execute a macro on each line of the selection. #21422
+ ---
+ --- Applies to @x and includes @@ too.
+ vim.keymap.set(
+ 'x',
+ 'Q',
+ ':normal! @<C-R>=reg_recorded()<CR><CR>',
+ { silent = true, desc = ':help v_Q-default' }
+ )
+ vim.keymap.set(
+ 'x',
+ '@',
+ "':normal! @'.getcharstr().'<CR>'",
+ { silent = true, expr = true, desc = ':help v_@-default' }
+ )
--- Map |gx| to call |vim.ui.open| on the identifier under the cursor
do
-- TODO: use vim.region() when it lands... #13896 #16843
diff --git a/test/functional/editor/macro_spec.lua b/test/functional/editor/macro_spec.lua
index 53be7dcc62..151d803faa 100644
--- a/test/functional/editor/macro_spec.lua
+++ b/test/functional/editor/macro_spec.lua
@@ -11,9 +11,11 @@ local meths = helpers.meths
local insert = helpers.insert
local curbufmeths = helpers.curbufmeths
-before_each(clear)
describe('macros', function()
+ before_each(function()
+ clear({args_rm = {'--cmd'}})
+ end)
it('can be recorded and replayed', function()
feed('qiahello<esc>q')
expect('hello')
@@ -47,11 +49,75 @@ hello]]
feed[[G3Q]]
eq({'helloFOOFOO', 'hello', 'helloFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false))
+
+ feed[[ggV3jQ]]
+ eq({'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false))
+ end)
+
+ it('can be replayed with @', function()
+ insert [[hello
+hello
+hello]]
+ feed [[gg]]
+
+ feed [[qqAFOO<esc>q]]
+ eq({'helloFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+
+ feed[[Q]]
+ eq({'helloFOOFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+
+ feed[[G3@@]]
+ eq({'helloFOOFOO', 'hello', 'helloFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false))
+
+ feed[[ggV2j@@]]
+ eq({'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false))
+ end)
+
+ it('can be replayed with @q and @w', function()
+
+ insert [[hello
+hello
+hello]]
+ feed [[gg]]
+
+ feed [[qqAFOO<esc>qu]]
+ eq({'hello', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+
+ feed [[qwA123<esc>qu]]
+ eq({'hello', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+
+ feed[[V3j@q]]
+ eq({'helloFOO', 'helloFOO', 'helloFOO'}, curbufmeths.get_lines(0, -1, false))
+
+ feed [[gg]]
+ feed[[Vj@w]]
+ eq({'helloFOO123', 'helloFOO123', 'helloFOO'}, curbufmeths.get_lines(0, -1, false))
+ end)
+
+ it('can be replayed with @q and @w visual-block', function()
+ insert [[hello
+hello
+hello]]
+ feed [[gg]]
+
+ feed [[qqAFOO<esc>qu]]
+ eq({'hello', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+
+ feed [[qwA123<esc>qu]]
+ eq({'hello', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+
+ feed[[<C-v>3j@q]]
+ eq({'helloFOO', 'helloFOO', 'helloFOO'}, curbufmeths.get_lines(0, -1, false))
+
+ feed [[gg]]
+ feed[[<C-v>j@w]]
+ eq({'helloFOO123', 'helloFOO123', 'helloFOO'}, curbufmeths.get_lines(0, -1, false))
end)
end)
describe('immediately after a macro has finished executing,', function()
before_each(function()
+ clear()
command([[let @a = 'gg0']])
end)
@@ -91,6 +157,7 @@ describe('immediately after a macro has finished executing,', function()
end)
describe('reg_recorded()', function()
+ before_each(clear)
it('returns the correct value', function()
feed [[qqyyq]]
eq('q', eval('reg_recorded()'))