Skip to content

inkarkat/vim-visualrepeat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VISUALREPEAT

by Ingo Karkat

DESCRIPTION

This plugin defines repetition of Vim built-in normal mode commands via . for visual mode. Additionally, it offers functions like the popular repeat.vim plugin that allow mappings to be repeated in visual mode, too.

VISUAL MODE REPETITION

This extends the built-in normal mode repeat . to visual mode.

VISUAL MODE MAPPING REPETITION

Like with repeat.vim for normal mode, visual mode mappings can register a <Plug> mapping to be used for visual mode repetition.

Likewise, normal mode mappings can (in addition to the repeat.vim registration of a normal mode mapping) register a visual mode mapping with visualrepeat.vim that will be repeated in visual mode.

Operator-pending mappings end with g@ and repeat naturally; i.e. Vim re-applies the 'opfunc' on the equivalent text (but at the current cursor position). But without a call to repeat#set(), it is impossible to repeat this operator-pending mapping to the current visual selection. Plugins cannot call repeat#set() in their operator-pending mapping, because then Vim's built-in repeat would be circumvented, the full mapping ending with g@ would be re-executed, and the repetition would then wait for the {motion}, what is not wanted. Therefore, this plugin offers a separate visualrepeat#set() function that can be invoked for operator-pending mappings. It can also be invoked for normal-mode mappings that have already called repeat#set(), and may override that mapping with a special repeat mapping for visual mode repeats. Together with the remapped {Visual}. command, this allows repetition - similar to what the built-in Vim commands do - across normal, operator-pending and visual mode.

SOURCE

RELATED WORKS

  • repeat.vim (vimscript #2136) has been the basis for this plugin and should be used in conjunction with visualrepeat.vim. (Otherwise, you'd have visual mode repeat, but no repeat in normal mode.)

USAGE

{Visual}.               Repeat last change in all visually selected lines.
                        - characterwise: Start from cursor position.
                        - linewise: Each line separately, starting from the
                          current column (usually the first in this mode).
                        - blockwise: Only the selected text. This is
                          implemented by temporarily duplicating the selection
                          to separate lines and repeating over those, starting
                          from the first column.

                        Note: If the last normal mode command included a
                        {motion} (e.g. g~e), the repetition will also move
                        exactly over this {motion}, NOT the visual selection!
                        It is thus best to repeat commands that work on the
                        entire line (e.g. g~$).

{Visual}g.              Repeat last built-in command in all visually selected
                        lines. Skips any plugin repeat actions; only repeats
                        the last Vim command.

INSTALLATION

The code is hosted in a Git repo at https://github.com/inkarkat/vim-visualrepeat You can use your favorite plugin manager, or "git clone" into a directory used for Vim packages. Releases are on the "stable" branch, the latest unstable development snapshot on "master".

This script is also packaged as a vimball. If you have the "gunzip" decompressor in your PATH, simply edit the *.vmb.gz package in Vim; otherwise, decompress the archive first, e.g. using WinZip. Inside Vim, install by sourcing the vimball or via the :UseVimball command.

vim visualrepeat*.vmb.gz
:so %

To uninstall, use the :RmVimball command.

DEPENDENCIES

  • Requires Vim 7.0 or higher.
  • repeat.vim (vimscript #2136) plugin (highly recommended)
  • ingo-library.vim plugin (vimscript #4433), version 1.013 or higher; optional, for blockwise repeat only

INTEGRATION

This plugin is meant to be used together with repeat.vim.

This plugin has helper functions that plugins with cross-repeat functionality can use in their normal mode repeat mappings of repeated visual mode mappings. With this, you save work and allow for a consistent user experience. Define your normal mode repeat mapping like this:

nnoremap <silent> <Plug>(MyPluginVisual)
\ :<C-u>execute 'normal!' visualrepeat#reapply#VisualMode(0)<Bar>
\call MyPlugin#Operator('visual', "\<lt>Plug>(MyPluginVisual)")<CR>

If your plugin uses a passed [count] (i.e. the count is not only used to determine the text area the mapping is applied to), you need to define a mapping:

vnoremap <silent> <expr> <SID>(ReapplyRepeatCount) visualrepeat#reapply#RepeatCount()

and apply the function followed by the mapping like this:

nnoremap <silent> <script> <Plug>(MyPluginVisual)
\ :<C-u>execute 'normal!' visualrepeat#reapply#VisualMode(1)<CR>
\<SID>(ReapplyRepeatCount)
\:<C-u>call MyPlugin#Operator('visual', v:count, "\<lt>Plug>(MyPluginVisual)")<CR>

If you want to support running without visualrepeat.vim, too, provide a wrapper that defaults to 1v:

function! s:VisualMode()
    let l:keys = "1v\<Esc>"
    silent! let l:keys = visualrepeat#reapply#VisualMode(0)
    return l:keys
endfunction
nnoremap <silent> <Plug>(MyPluginVisual)
\ :<C-u>execute 'normal!' <SID>VisualMode()<Bar>
\call MyPlugin#Operator('visual', "\<lt>Plug>(MyPluginVisual)")<CR>

CONTRIBUTING

Report any bugs, send patches, or suggest features via the issue tracker at https://github.com/inkarkat/vim-visualrepeat/issues or email (address below).

HISTORY

1.33 12-Nov-2024
  • Adapt: Compatibility: Adding one character to previous exclusive selection not needed since Vim 9.0.1172 in visualrepeat#reapply#VisualMode().
1.32 23-Feb-2020
  • BUG: visualrepeat#reapply#VisualMode() mistakenly adds the next full line when restoring a linewise visual selection (to a smaller target).
  • Use :normal for Vim 7.3.100..7.4.601 and feedkeys(..., 'i') for newer versions, aligning the used mechanism with what repeat.vim uses.
1.31 17-Mar-2019
  • ENH: Add g. mapping that forces built-in repeat; i.e. skips any custom repeat.vim or visualrepeat.vim actions. This can be useful if a plugin offers a special repeat for visual mode, but a built-in repeat on each selected line may make sense, too. For example, my KeepText.vim plugin would keep the entire linewise selection; forcing a built-in repeat (of the custom operator) would reapply e.g. a <Leader>ka" to all selected lines instead.
  • Factor out ingo#buffer#temprange#Call() into ingo-library. !!! You need to update the optional dependency to ingo-library (vimscript #4433) version 1.018! !!!
  • ENH: Make an explicit register on repeat override g:repeat_reg. As with built-in commands, this allows to override the original register on repeat, e.g. "a. uses register a instead of the original one. One limitation is that we cannot detect whether no or the default register has been given, so an override from a non-default to the default register (e.g. via "".) is not possible.
1.30 15-Nov-2013
  • ENH: When repeating over multiple lines / a blockwise selection, keep track of added or deleted lines, and only repeat exactly on the selected lines. Thanks to Israel Chauca for sending a patch!
  • When a repeat on a blockwise selection has introduced additional lines, append those properly indented instead of omitting them.
  • With linewise and blockwise repeat, set the change marks '[,'] to the changed selection. With the latter, one previously got "E19: Mark has invalid line number" due to the removed temporary range.
1.20 14-Nov-2013
  • ENH: Implement blockwise repeat through temporarily moving the block to a temporary range at the end of the buffer, like the vis.vim plugin. This feature requires the ingo-library.

You need to separately install ingo-library (vimscript #4433) version 1.013 (or higher)!

1.10 05-Sep-2013
  • Check for existence of actual visual mode mapping; do not accept a select mode mapping, because we're applying it to a visual selection.
  • Pass through a [count] to the :normal . command.
  • Add visualrepeat#reapply#VisualMode() and visualrepeat#reapply#RepeatCount() helper functions that plugins can use in their normal mode repeat mappings of repeated visual mode mappings.
  • Minor: Make substitute() robust against 'ignorecase'.
  • ENH: Use the current cursor virtual column when repeating in linewise visual mode. Inspired by http://stackoverflow.com/questions/18610564/vim-is-possible-to-use-dot-command-in-visual-block-mode
  • Abort further commands on error by using echoerr inside the mapping.
1.03 21-Feb-2013
  • REGRESSION: Fix in 1.02 does not repeat recorded register when the mappings in repeat.vim and visualrepeat.vim differ.
1.02 27-Dec-2012
  • BUG: "E121: Undefined variable: g:repeat_sequence" when using visual repeat of a mapping using registers without having used repeat.vim beforehand.
1.01 05-Apr-2012
  • FIX: Avoid error about undefined g:repeat_reg when (a proper version of) repeat.vim isn't available.
1.00 14-Dec-2011
  • First published version.
0.01 17-Mar-2011
  • Split off into dedicated plugin.
0.00 30-Jul-2008
  • Started development.

Copyright: (C) 2008-2024 Ingo Karkat - The VIM LICENSE applies to this plugin.

Maintainer: Ingo Karkat <ingo@karkat.de>

About

Repeat command extended to visual mode.

Resources

Stars

Watchers

Forks

Packages

No packages published