repeat.vim 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. " repeat.vim - Let the repeat command repeat plugin maps
  2. " Maintainer: Tim Pope
  3. " Version: 1.2
  4. " GetLatestVimScripts: 2136 1 :AutoInstall: repeat.vim
  5. " Installation:
  6. " Place in either ~/.vim/plugin/repeat.vim (to load at start up) or
  7. " ~/.vim/autoload/repeat.vim (to load automatically as needed).
  8. "
  9. " License:
  10. " Copyright (c) Tim Pope. Distributed under the same terms as Vim itself.
  11. " See :help license
  12. "
  13. " Developers:
  14. " Basic usage is as follows:
  15. "
  16. " silent! call repeat#set("\<Plug>MappingToRepeatCommand",3)
  17. "
  18. " The first argument is the mapping that will be invoked when the |.| key is
  19. " pressed. Typically, it will be the same as the mapping the user invoked.
  20. " This sequence will be stuffed into the input queue literally. Thus you must
  21. " encode special keys by prefixing them with a backslash inside double quotes.
  22. "
  23. " The second argument is the default count. This is the number that will be
  24. " prefixed to the mapping if no explicit numeric argument was given. The
  25. " value of the v:count variable is usually correct and it will be used if the
  26. " second parameter is omitted. If your mapping doesn't accept a numeric
  27. " argument and you never want to receive one, pass a value of -1.
  28. "
  29. " Make sure to call the repeat#set function _after_ making changes to the
  30. " file.
  31. "
  32. " For mappings that use a register and want the same register used on
  33. " repetition, use:
  34. "
  35. " silent! call repeat#setreg("\<Plug>MappingToRepeatCommand", v:register)
  36. "
  37. " This function can (and probably needs to be) called before making changes to
  38. " the file (as those typically clear v:register). Therefore, the call sequence
  39. " in your mapping will look like this:
  40. "
  41. " nnoremap <silent> <Plug>MyMap
  42. " \ :<C-U>execute 'silent! call repeat#setreg("\<lt>Plug>MyMap", v:register)'<Bar>
  43. " \ call <SID>MyFunction(v:register, ...)<Bar>
  44. " \ silent! call repeat#set("\<lt>Plug>MyMap")<CR>
  45. if exists("g:loaded_repeat") || &cp || v:version < 800
  46. finish
  47. endif
  48. let g:loaded_repeat = 1
  49. let g:repeat_tick = -1
  50. let g:repeat_reg = ['', '']
  51. " Special function to avoid spurious repeats in a related, naturally repeating
  52. " mapping when your repeatable mapping doesn't increase b:changedtick.
  53. function! repeat#invalidate()
  54. autocmd! repeat_custom_motion
  55. let g:repeat_tick = -1
  56. endfunction
  57. function! repeat#set(sequence,...)
  58. let g:repeat_sequence = a:sequence
  59. let g:repeat_count = a:0 ? a:1 : v:count
  60. let g:repeat_tick = b:changedtick
  61. augroup repeat_custom_motion
  62. autocmd!
  63. autocmd CursorMoved <buffer> let g:repeat_tick = b:changedtick | autocmd! repeat_custom_motion
  64. augroup END
  65. endfunction
  66. function! repeat#setreg(sequence,register)
  67. let g:repeat_reg = [a:sequence, a:register]
  68. endfunction
  69. function! s:default_register()
  70. let values = split(&clipboard, ',')
  71. if index(values, 'unnamedplus') != -1
  72. return '+'
  73. elseif index(values, 'unnamed') != -1
  74. return '*'
  75. else
  76. return '"'
  77. endif
  78. endfunction
  79. function! repeat#run(count)
  80. let s:errmsg = ''
  81. try
  82. if g:repeat_tick == b:changedtick
  83. let r = ''
  84. if g:repeat_reg[0] ==# g:repeat_sequence && !empty(g:repeat_reg[1])
  85. " Take the original register, unless another (non-default, we
  86. " unfortunately cannot detect no vs. a given default register)
  87. " register has been supplied to the repeat command (as an
  88. " explicit override).
  89. let regname = v:register ==# s:default_register() ? g:repeat_reg[1] : v:register
  90. if regname ==# '='
  91. " This causes a re-evaluation of the expression on repeat, which
  92. " is what we want.
  93. let r = '"=' . getreg('=', 1) . "\<CR>"
  94. else
  95. let r = '"' . regname
  96. endif
  97. endif
  98. let c = g:repeat_count
  99. let s = g:repeat_sequence
  100. let cnt = c == -1 ? "" : (a:count ? a:count : (c ? c : ''))
  101. call feedkeys(s, 'i')
  102. call feedkeys(r . cnt, 'ni')
  103. else
  104. call feedkeys((a:count ? a:count : '') . '.', 'ni')
  105. endif
  106. catch /^Vim(normal):/
  107. let s:errmsg = v:errmsg
  108. return 0
  109. endtry
  110. return 1
  111. endfunction
  112. function! repeat#errmsg()
  113. return s:errmsg
  114. endfunction
  115. function! repeat#wrap(command,count)
  116. let foldopen = &foldopen =~# 'undo\|all' ? 'zv' : ''
  117. let preserve = g:repeat_tick == b:changedtick ? ":let g:repeat_tick = b:changedtick\r" : ''
  118. return (a:count ? a:count : '') . a:command . preserve . foldopen
  119. endfunction
  120. nnoremap <silent> <Plug>(RepeatDot) :<C-U>if !repeat#run(v:count)<Bar>echoerr repeat#errmsg()<Bar>endif<CR>
  121. nmap <silent><expr><script> <Plug>(RepeatUndo) repeat#wrap('u',v:count)
  122. nmap <silent><expr><script> <Plug>(RepeatUndoLine) repeat#wrap('U',v:count)
  123. nmap <silent><expr><script> <Plug>(RepeatRedo) repeat#wrap("\022",v:count)
  124. if !hasmapto('<Plug>(RepeatDot)', 'n')
  125. nmap . <Plug>(RepeatDot)
  126. endif
  127. if !hasmapto('<Plug>(RepeatUndo)', 'n')
  128. nmap u <Plug>(RepeatUndo)
  129. endif
  130. if maparg('U','n') ==# '' && !hasmapto('<Plug>(RepeatUndoLine)', 'n')
  131. nmap U <Plug>(RepeatUndoLine)
  132. endif
  133. if !hasmapto('<Plug>(RepeatRedo)', 'n')
  134. nmap <C-R> <Plug>(RepeatRedo)
  135. endif
  136. augroup repeatPlugin
  137. autocmd!
  138. autocmd BufLeave,BufWritePre,BufReadPre * let g:repeat_tick = (g:repeat_tick == b:changedtick || g:repeat_tick == 0) ? 0 : -1
  139. autocmd BufEnter,BufWritePost * if g:repeat_tick == 0|let g:repeat_tick = b:changedtick|endif
  140. augroup END
  141. " vim:set ft=vim et sw=4 sts=4: