[vim/vim] Add setrepeat() and getrepeat() functions for dot command control (PR #19413)

0 views
Skip to first unread message

Shougo

unread,
2:46 AM (5 hours ago) 2:46 AM
to vim/vim, Subscribed

Summary

Add setrepeat() and getrepeat() functions to allow scripts to programmatically control the dot (.) repeat command.

This enables plugins to:

  • Save and restore the repeat command
  • Make custom commands repeatable with .
  • Build repeat history functionality

Motivation

This addresses several long-standing feature requests:

  • neovim/neovim#33030: Telescope needs to save/restore repeat because prompt-buffer edits overwrite it
  • #6299: Users want to save the . command while making other changes, then restore it
  • #6346: Previous attempt to add repeat history (closed due to complexity)

Current Limitations

  • No way to save/restore the repeat command from scripts
  • Plugins like vim-repeat require complex workarounds
  • Temporary edits (e.g., in prompt buffers) permanently overwrite user's repeat command
  • No way for plugins to integrate custom commands with . repeat

Design

API

" Set repeat command
call setrepeat({'cmd': 'dd'})                    " Normal mode
call setrepeat({'cmd': 'i', 'text': 'Hello'})    " Insert mode

" Get repeat command
echo getrepeat()
" → {'cmd': 'dd', 'text': ''}
" → {'cmd': 'i', 'text': 'Hello'}

" Existing functionality unchanged
echo getreg('.')  " Still returns last inserted text (read-only)

Dictionary Structure

Phase 1 (this PR):

{
  'cmd': 'string'   " Required - the command to repeat
  'text': 'string'  " Optional - text to insert (for insert mode)
}

Future extensions (Phase 2):

{
  'cmd': 'string'
  'text': 'string'
  'type': 'string'      " 'normal', 'insert', 'visual'
  'mode': 'string'      " 'v', 'V', CTRL-V
  'count': number       " Repeat count
  'register': 'string'  " Target register
}

Use Cases

1. Save/Restore (Telescope)

function! PromptBufferOperation()
  " Save current repeat
  let saved = getrepeat()

  " Temporary edits in prompt buffer
  " (these would normally overwrite the repeat)

  " Restore original repeat
  call setrepeat(saved)
endfunction

2. Plugin Integration (vim-repeat replacement)

function! MyComplexCommand()
  " ... complex operation ...

  " Make it repeatable with .
  call setrepeat({'cmd': ':call MyComplexCommand()'})
endfunction

command! MyCommand call MyComplexCommand()

" User can now use . to repeat :MyCommand

3. Repeat History

let g:repeat_history = []

" Save current repeat
call add(g:repeat_history, getrepeat())

" Later, restore from history
call setrepeat(g:repeat_history[0])
normal! .

Design Decisions

Why dedicated functions instead of writable . register?

This is a redesign of #19342 based on community feedback. The original approach had several issues:

  1. Backward compatibility: Changing getreg('.') behavior could break scripts
  2. Double duty: Register would serve two different purposes
  3. Limited extensibility: Hard to add features like visual mode support

The new approach:

  • ✅ Keeps getreg('.') unchanged (backward compatible)
  • ✅ Separate interfaces for separate purposes (cleaner)
  • ✅ Dictionary allows future extensions without breaking changes

Why dictionary interface?

  • Extensible: Can add new fields in Phase 2 without breaking existing code
  • Flexible: Supports both simple and complex operations
  • Clear: Self-documenting structure

Phase 1 Limitations

Documented in the help files:

  1. Insert mode overwrites setrepeat()
    When entering/leaving insert mode, Vim's automatic recording overwrites custom repeats.
    Workaround: Call setrepeat() after insert mode operations.

  2. setline() and similar not recorded
    Text modification functions don't update the repeat command.
    Workaround: Use feedkeys() to simulate typing.

  3. Visual mode not supported
    Will be added in Phase 2 with additional dictionary fields.

  4. Limited info for user operations
    getrepeat() provides full info only for setrepeat()-set values.
    User operations return limited information.

These limitations don't affect the primary use cases (save/restore, plugin integration, history).

Related Work

Future Work (Phase 2)

Potential enhancements:

  • Visual mode support (via type and mode fields)
  • Count support (via count field)
  • Register support (via register field)
  • Enhanced getrepeat() for user operations

All can be added via dictionary fields without breaking changes.


Ready for review. This provides a solid foundation for script control of
the dot command while maintaining backward compatibility and allowing future
enhancements.


You can view, comment on, or merge this pull request online at:

  https://github.com/vim/vim/pull/19413

Commit Summary

File Changes

(8 files)

Patch Links:


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/19413@github.com>

Shougo

unread,
2:57 AM (5 hours ago) 2:57 AM
to vim/vim, Push

@Shougo pushed 2 commits.


View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/19413/before/c6715aec1d11fd0788da3fce5448934ca5861be7/after/ea73edeeca2671ae14a0a7e31e0370bf31b8d1e7@github.com>

Shougo

unread,
3:08 AM (5 hours ago) 3:08 AM
to vim/vim, Push

@Shougo pushed 2 commits.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/19413/before/ea73edeeca2671ae14a0a7e31e0370bf31b8d1e7/after/42ca3c3918682e4a86ea7e03e83c826f6d5dc33c@github.com>

Reply all
Reply to author
Forward
0 new messages