If your Vim version contains the patch 8.1.2044, you could try this:
let s:last_mode = 'n'
augroup visual_enter_normal_enter
au!
au SafeState * call s:fire_visualenter_or_normalenter()
augroup END
fu! s:fire_visualenter_or_normalenter() abort
if reg_executing() isnot# '' | return | endif
let mode = mode()
if s:last_mode is# 'n'
\ && index(['v', 'V', "\<c-v>"], mode) != -1
\ && exists('#User#VisualEnter')
do <nomodeline> User VisualEnter
elseif s:last_mode isnot# 'n'
\ && mode is# 'n'
\ && exists('#User#NormalEnter')
do <nomodeline> User NormalEnter
endif
let s:last_mode = mode
endfu
augroup record_keys_in_visual_mode
au!
au User VisualEnter call s:recording_start()
au User NormalEnter call s:recording_stop()
augroup END
fu! s:recording_start() abort
if reg_recording() is# ''
let @v = mode()
call feedkeys('qV', 'int')
endif
endfu
fu! s:recording_stop() abort
if reg_recording() is# 'V'
call feedkeys('q', 'int')
endif
endfu
I haven't tested the code a lot, but it seems to do what you want; i.e. record all the keys typed while in visual mode inside the register v
.
Note that SafeState
is fired frequently, so s:fire_visualenter_or_normalenter()
will be run frequently too, and I don't know how much impact it will have on Vim's performance, nor whether it can cause unexpected issues.
If you don't have SafeState
, you can use a timer which repeats invoking its callback forever:
let s:last_mode = 'n'
let s:waiting_time = 10
call timer_start(s:waiting_time, {-> s:fire_visualenter_or_normalenter()}, {'repeat': -1})
fu! s:fire_visualenter_or_normalenter() abort
if reg_executing() isnot# '' | return | endif
let mode = mode()
if s:last_mode is# 'n'
\ && index(['v', 'V', "\<c-v>"], mode) != -1
\ && exists('#User#VisualEnter')
do <nomodeline> User VisualEnter
elseif s:last_mode isnot# 'n'
\ && mode is# 'n'
\ && exists('#User#NormalEnter')
do <nomodeline> User NormalEnter
endif
let s:last_mode = mode
endfu
augroup record_keys_in_visual_mode
au!
au User VisualEnter call s:recording_start()
au User NormalEnter call s:recording_stop()
augroup END
fu! s:recording_start() abort
if reg_recording() is# ''
let @v = mode()
call feedkeys('qV', 'int')
endif
endfu
fu! s:recording_stop() abort
if reg_recording() is# 'V'
call feedkeys('q', 'int')
endif
endfu
If you notice a too big impact on Vim's performance, try to increase the value of s:waiting_time
.
If you notice that some typed keys are missing from the register v
, try to decrease the value of s:waiting_time
.
For more information, see:
:h SafeState
:h User
:h reg_executing(
:h reg_recording(
:h mode(
:h index(
:h exists(
:h feedkeys(
:h timer_start(
:h :do
I want to be able to automatically do :normal! qv
q
does not work insidenormal
(read:h q
). Also, visual mode is only good for text select, and you can restore a selection withgv
, for example. No need to save all the keypresses.:h autocmd-events
you can see there is no event for when you switch to visual or normal mode, only insert mode. But creating a mapping for changing modes shouldn't be too hard. The hard part is to log you keystrokes independently. I think I would try to use:h -w
and parse the produced file afterwards