mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
feat(autocmd): add Recording autocmds
feat(eval): add reg_recorded() This function is used the get the last recorded register. style(Recording): rename handler to match suggestions fix(RecordingLeave): send autocommand earlier This makes the autocommand fire just before setting reg_recorded to reg_recording, this way we clearly show that we are actually just before actually quitting the recording mode.
This commit is contained in:
parent
b1757e1c29
commit
8a4e26c6fe
@ -828,6 +828,14 @@ RemoteReply When a reply from a Vim that functions as
|
||||
SearchWrapped After making a search with |n| or |N| if the
|
||||
search wraps around the document back to
|
||||
the start/finish respectively.
|
||||
*RecordingEnter*
|
||||
RecordingEnter When a macro starts to be recorded.
|
||||
The pattern is the current file name, and
|
||||
|reg_recording()| is the current register that
|
||||
is used.
|
||||
*RecordinLeave*
|
||||
RecordingLeave When the is the end of a macro recording.
|
||||
The pattern is the current file name.
|
||||
*SessionLoadPost*
|
||||
SessionLoadPost After loading the session file created using
|
||||
the |:mksession| command.
|
||||
|
@ -2588,6 +2588,7 @@ readdir({dir} [, {expr}]) List file names in {dir} selected by {expr}
|
||||
readfile({fname} [, {type} [, {max}]])
|
||||
List get list of lines from file {fname}
|
||||
reg_executing() String get the executing register name
|
||||
reg_recorded() String get the last recorded register name
|
||||
reg_recording() String get the recording register name
|
||||
reltime([{start} [, {end}]]) List get time value
|
||||
reltimefloat({time}) Float turn the time value into a Float
|
||||
@ -7825,6 +7826,11 @@ reg_executing() *reg_executing()*
|
||||
Returns an empty string when no register is being executed.
|
||||
See |@|.
|
||||
|
||||
reg_recorded() *reg_recorded()*
|
||||
Returns the single letter name of the last recorded register.
|
||||
Returns an empty string string when nothing was recorded yet.
|
||||
See |q|.
|
||||
|
||||
reg_recording() *reg_recording()*
|
||||
Returns the single letter name of the register being recorded.
|
||||
Returns an empty string string when not recording. See |q|.
|
||||
|
@ -563,8 +563,8 @@ The command CTRL-\ CTRL-G or <C-\><C-G> can be used to go to Insert mode when
|
||||
make sure Vim is in the mode indicated by 'insertmode', without knowing in
|
||||
what mode Vim currently is.
|
||||
|
||||
*gQ* *Q* *mode-Ex* *Ex-mode* *Ex* *EX* *E501*
|
||||
Q or gQ Switch to Ex mode. This is like typing ":" commands
|
||||
*gQ* *mode-Ex* *Ex-mode* *Ex* *EX* *E501*
|
||||
gQ Switch to Ex mode. This is like typing ":" commands
|
||||
one after another, except:
|
||||
- You don't have to keep pressing ":".
|
||||
- The screen doesn't get updated after each command.
|
||||
|
@ -147,6 +147,9 @@ q Stops recording.
|
||||
*@@* *E748*
|
||||
@@ Repeat the previous @{0-9a-z":*} [count] times.
|
||||
|
||||
*Q*
|
||||
Q Repeat the last recorded register [count] times.
|
||||
|
||||
*:@*
|
||||
:[addr]@{0-9a-z".=*+} Execute the contents of register {0-9a-z".=*+} as an Ex
|
||||
command. First set cursor at line [addr] (default is
|
||||
|
@ -218,6 +218,7 @@ Input/Mappings:
|
||||
|
||||
Normal commands:
|
||||
|gO| shows a filetype-defined "outline" of the current buffer.
|
||||
|Q| replays the last recorded macro.
|
||||
|
||||
Options:
|
||||
'cpoptions' flags: |cpo-_|
|
||||
|
@ -75,6 +75,8 @@ return {
|
||||
'QuickFixCmdPost', -- after :make, :grep etc.
|
||||
'QuickFixCmdPre', -- before :make, :grep etc.
|
||||
'QuitPre', -- before :quit
|
||||
'RecordingEnter', -- when starting to record a macro
|
||||
'RecordingLeave', -- when stopping to record a macro
|
||||
'RemoteReply', -- upon string reception from a remote vim
|
||||
'SearchWrapped', -- after the search wrapped around
|
||||
'SessionLoadPost', -- after loading a session file
|
||||
@ -131,6 +133,8 @@ return {
|
||||
BufModifiedSet=true,
|
||||
DiagnosticChanged=true,
|
||||
DirChanged=true,
|
||||
RecordingEnter=true,
|
||||
RecordingLeave=true,
|
||||
Signal=true,
|
||||
TabClosed=true,
|
||||
TabNew=true,
|
||||
|
@ -277,6 +277,7 @@ return {
|
||||
readfile={args={1, 3}, base=1},
|
||||
reg_executing={},
|
||||
reg_recording={},
|
||||
reg_recorded={},
|
||||
reltime={args={0, 2}, base=1},
|
||||
reltimefloat={args=1, base=1},
|
||||
reltimestr={args=1, base=1},
|
||||
|
@ -7398,6 +7398,11 @@ static void f_reg_recording(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
return_register(reg_recording, rettv);
|
||||
}
|
||||
|
||||
static void f_reg_recorded(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
return_register(reg_recorded, rettv);
|
||||
}
|
||||
|
||||
/// list2proftime - convert a List to proftime_T
|
||||
///
|
||||
/// @param arg The input list, must be of type VAR_LIST and have
|
||||
|
@ -632,6 +632,7 @@ EXTERN bool ex_no_reprint INIT(=false); // No need to print after z or p.
|
||||
|
||||
EXTERN int reg_recording INIT(= 0); // register for recording or zero
|
||||
EXTERN int reg_executing INIT(= 0); // register being executed or zero
|
||||
EXTERN int reg_recorded INIT(= 0); // last recorded register or zero
|
||||
|
||||
EXTERN int no_mapping INIT(= false); // currently no mapping allowed
|
||||
EXTERN int no_zero_mapping INIT(= 0); // mapping zero not allowed
|
||||
|
@ -229,7 +229,7 @@ static const struct nv_cmd {
|
||||
{ 'N', nv_next, 0, SEARCH_REV },
|
||||
{ 'O', nv_open, 0, 0 },
|
||||
{ 'P', nv_put, 0, 0 },
|
||||
{ 'Q', nv_exmode, NV_NCW, 0 },
|
||||
{ 'Q', nv_regreplay, 0, 0 },
|
||||
{ 'R', nv_Replace, 0, false },
|
||||
{ 'S', nv_subst, NV_KEEPREG, 0 },
|
||||
{ 'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD },
|
||||
@ -4028,15 +4028,18 @@ dozet:
|
||||
/*
|
||||
* "Q" command.
|
||||
*/
|
||||
static void nv_exmode(cmdarg_T *cap)
|
||||
static void nv_regreplay(cmdarg_T *cap)
|
||||
{
|
||||
/*
|
||||
* Ignore 'Q' in Visual mode, just give a beep.
|
||||
*/
|
||||
if (VIsual_active) {
|
||||
vim_beep(BO_EX);
|
||||
} else if (!checkclearop(cap->oap)) {
|
||||
do_exmode();
|
||||
if (checkclearop(cap->oap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (cap->count1-- && !got_int) {
|
||||
if (do_execreg(reg_recorded, false, false, false) == false) {
|
||||
clearopbeep(cap->oap);
|
||||
break;
|
||||
}
|
||||
line_breakcheck();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -912,13 +912,14 @@ int do_record(int c)
|
||||
showmode();
|
||||
regname = c;
|
||||
retval = OK;
|
||||
apply_autocmds(EVENT_RECORDINGENTER, NULL, NULL, false, curbuf);
|
||||
}
|
||||
} else { // stop recording
|
||||
/*
|
||||
* Get the recorded key hits. K_SPECIAL and CSI will be escaped, this
|
||||
* needs to be removed again to put it in a register. exec_reg then
|
||||
* adds the escaping back later.
|
||||
*/
|
||||
} else { // stop recording
|
||||
// Get the recorded key hits. K_SPECIAL and CSI will be escaped, this
|
||||
// needs to be removed again to put it in a register. exec_reg then
|
||||
// adds the escaping back later.
|
||||
apply_autocmds(EVENT_RECORDINGLEAVE, NULL, NULL, false, curbuf);
|
||||
reg_recorded = reg_recording;
|
||||
reg_recording = 0;
|
||||
if (ui_has(kUIMessages)) {
|
||||
showmode();
|
||||
@ -932,10 +933,8 @@ int do_record(int c)
|
||||
// Remove escaping for CSI and K_SPECIAL in multi-byte chars.
|
||||
vim_unescape_csi(p);
|
||||
|
||||
/*
|
||||
* We don't want to change the default register here, so save and
|
||||
* restore the current register name.
|
||||
*/
|
||||
// We don't want to change the default register here, so save and
|
||||
// restore the current register name.
|
||||
old_y_previous = y_previous;
|
||||
|
||||
retval = stuff_yank(regname, p);
|
||||
|
52
test/functional/autocmd/recording_spec.lua
Normal file
52
test/functional/autocmd/recording_spec.lua
Normal file
@ -0,0 +1,52 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local clear = helpers.clear
|
||||
local eq = helpers.eq
|
||||
local eval = helpers.eval
|
||||
local source_vim = helpers.source
|
||||
|
||||
describe('RecordingEnter', function()
|
||||
before_each(clear)
|
||||
it('works', function()
|
||||
source_vim [[
|
||||
let g:recorded = 0
|
||||
autocmd RecordingEnter * let g:recorded += 1
|
||||
execute "normal! qqyyq"
|
||||
]]
|
||||
eq(1, eval('g:recorded'))
|
||||
end)
|
||||
|
||||
it('gives a correct reg_recording()', function()
|
||||
source_vim [[
|
||||
let g:recording = ''
|
||||
autocmd RecordingEnter * let g:recording = reg_recording()
|
||||
execute "normal! qqyyq"
|
||||
]]
|
||||
eq('q', eval('g:recording'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('RecordingLeave', function()
|
||||
before_each(clear)
|
||||
it('works', function()
|
||||
source_vim [[
|
||||
let g:recorded = 0
|
||||
autocmd RecordingLeave * let g:recorded += 1
|
||||
execute "normal! qqyyq"
|
||||
]]
|
||||
eq(1, eval('g:recorded'))
|
||||
end)
|
||||
|
||||
it('gives the correct reg_recorded()', function()
|
||||
source_vim [[
|
||||
let g:recorded = 'a'
|
||||
let g:recording = ''
|
||||
autocmd RecordingLeave * let g:recording = reg_recording()
|
||||
autocmd RecordingLeave * let g:recorded = reg_recorded()
|
||||
execute "normal! qqyyq"
|
||||
]]
|
||||
eq('q', eval 'g:recording')
|
||||
eq('', eval 'g:recorded')
|
||||
eq('q', eval 'reg_recorded()')
|
||||
end)
|
||||
end)
|
@ -6,6 +6,8 @@ local feed = helpers.feed
|
||||
local clear = helpers.clear
|
||||
local expect = helpers.expect
|
||||
local command = helpers.command
|
||||
local insert = helpers.insert
|
||||
local curbufmeths = helpers.curbufmeths
|
||||
|
||||
describe('macros', function()
|
||||
before_each(clear)
|
||||
@ -27,4 +29,29 @@ describe('macros', function()
|
||||
expect('llllll')
|
||||
eq(eval('@i'), 'lxxx')
|
||||
end)
|
||||
|
||||
it('can be replayed with Q', 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[[G3Q]]
|
||||
eq({'helloFOOFOO', 'hello', 'helloFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('reg_recorded()', function()
|
||||
before_each(clear)
|
||||
|
||||
it('returns the correct value', function()
|
||||
feed [[qqyyq]]
|
||||
eq('q', eval('reg_recorded()'))
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user