11" yankring.vim - Yank / Delete Ring for Vim
22" ---------------------------------------------------------------
3- " Version: 1.4
3+ " Version: 1.5
44" Authors: David Fishburn <fishburn@ianywhere.com>
5- " Last Modified: Fri Mar 25 2005 11:14:00 PM
5+ " Last Modified: Tue Mar 29 2005 3:06:25 PM
66" Script: http://www.vim.org/scripts/script.php?script_id=1234
77" Based On: Mocked up version by Yegappan Lakshmanan
88" http://groups.yahoo.com/group/vim/post?act=reply&messageNum=34406
@@ -18,7 +18,7 @@ if v:version < 602
1818 finish
1919endif
2020
21- let loaded_yankring = 14
21+ let loaded_yankring = 15
2222
2323" Allow the user to override the # of yanks/deletes recorded
2424if ! exists (' g:yankring_max_history' )
@@ -42,6 +42,20 @@ if !exists('g:yankring_max_display')
4242 let g: yankring_max_display = 0
4343endif
4444
45+ " Controls whether the . operator will repeat yank operations
46+ " The default is based on cpoptions: |cpo-y|
47+ " y A yank command can be redone with ".".
48+ if ! exists (' g:yankring_dot_repeat_yank' )
49+ let g: yankring_dot_repeat_yank = (&cpoptions = ~' y' ?1 :0 )
50+ endif
51+
52+ " Only adds unique items to the yankring.
53+ " If the item already exists, that element is set as the
54+ " top of the yankring.
55+ if ! exists (' g:yankring_ignore_duplicate' )
56+ let g: yankring_ignore_duplicate = 1
57+ endif
58+
4559" Allow the user to specify what characters to use for the mappings.
4660if ! exists (' g:yankring_n_keys' )
4761 let g: yankring_n_keys = ' yy,dd,yw,dw,ye,de,yE,dE,yiw,diw,yaw,daw,y$,d$,Y,D,yG,dG,ygg,dgg'
@@ -68,6 +82,14 @@ if !exists('g:yankring_paste_n_akey')
6882 let g: yankring_paste_n_akey = ' p'
6983endif
7084
85+ if ! exists (' g:yankring_paste_v_bkey' )
86+ let g: yankring_paste_v_bkey = ' P'
87+ endif
88+
89+ if ! exists (' g:yankring_paste_v_akey' )
90+ let g: yankring_paste_v_akey = ' p'
91+ endif
92+
7193if ! exists (' g:yankring_replace_n_pkey' )
7294 let g: yankring_replace_n_pkey = ' <C-P>'
7395endif
@@ -297,6 +319,10 @@ function! s:YRClear()
297319 let s: yr_prev_vis_lend = 0
298320 let s: yr_prev_vis_cstart = 0
299321 let s: yr_prev_vis_cend = 0
322+
323+ " This is used to determine if the visual selection should be
324+ " reset prior to issuing the YRReplace
325+ let s: yr_prev_vis_mode = 0
300326endfunction
301327
302328
@@ -394,6 +420,23 @@ endfunction
394420" Adds this value to the yankring.
395421function ! s: YRRecord (value)
396422
423+ if g: yankring_ignore_duplicate == 1
424+ " Ensure the element is not already in the yankring
425+ let iter = s: yr_count
426+
427+ let elem = s: yr_paste_idx
428+ " let iter = s:yr_count
429+ while iter > 0
430+ if getreg (a: value ) == s: yr_elem_ {elem}
431+ exec " YRSetTop " .elem
432+ " echomsg "YR: Same as element: ".elem
433+ return
434+ endif
435+ let iter = iter - 1
436+ let elem = s: YRGetNextElem (elem, -1 )
437+ endwhile
438+ endif
439+
397440 let s: yr_elem_ {s: yr_next_idx } = getreg (a: value )
398441 let s: yr_elem_type_ {s: yr_next_idx } = getregtype (a: value )
399442 let s: yr_paste_idx = s: yr_next_idx
@@ -427,7 +470,8 @@ function! s:YRSetPrevOP(op_code, count, reg)
427470 let s: yr_prev_chg_cstart = col (" '[" )
428471 let s: yr_prev_chg_cend = col (" ']" )
429472
430- " TODO
473+ " If storing the last change position (using '[, '])
474+ " is not good enough, then another option is to:
431475 " Use :redir on the :changes command
432476 " and grab the last item. Store this value
433477 " and compare it is YRDoRepeat.
@@ -458,6 +502,15 @@ function! s:YRDoRepeat()
458502 \ s: yr_prev_chg_cend == col (" ']" )
459503 let dorepeat = 1
460504 endif
505+ " If we are going to repeat check to see if the
506+ " previous command was a yank operation. If so determine
507+ " if yank operations are allowed to be repeated.
508+ if dorepeat == 1 && s: yr_prev_op_code = ~ ' ^y'
509+ " This value be default is set based on cpoptions.
510+ if g: yankring_dot_repeat_yank == 0
511+ let dorepeat = 0
512+ endif
513+ endif
461514 return dorepeat
462515endfunction
463516
@@ -589,7 +642,7 @@ endfunction
589642
590643" Paste from either the yankring or from a specified register
591644" Optionally a count can be provided, so paste the same value 10 times
592- function ! s: YRPaste (replace_last_paste_selection, nextvalue, direction)
645+ function ! s: YRPaste (replace_last_paste_selection, nextvalue, direction, ... )
593646 " Disabling the yankring removes the default maps.
594647 " But there are some maps the user can create on their own, and
595648 " these would most likely call this function. So place an extra
@@ -603,44 +656,56 @@ function! s:YRPaste(replace_last_paste_selection, nextvalue, direction)
603656 let default_buffer = ((&clipboard == ' unnamed' )?' *' :' "' )
604657 let v_count = v: count
605658
659+ " Default command mode to normal mode 'n'
660+ let cmd_mode = ' n'
661+ if a: 0 > 0
662+ " Change to visual mode, if command executed via
663+ " a visual map
664+ let cmd_mode = ((a: 1 == ' v' ) ? ' v' : ' n' )
665+ endif
666+
606667 " User has decided to bypass the yankring and specify a specific
607668 " register
608669 if user_register != default_buffer
609670 if a: replace_last_paste_selection == 1
610- " Supports this for example - 5p
611- exec " normal! " .
612- \ (
613- \ (v_count > 0 )?(v_count):' ' ).
614- \ (a: direction = ~ ' b' ?
615- \ (g: yankring_replace_n_pkey ):
616- \ (g: yankring_replace_n_nkey )
617- \ )
671+ echomsg ' YR: A register cannot be specified in replace mode'
672+ return
618673 else
619674 exec " normal! " .
620- \ ((v_count > 0 )?(v_count):' ' ).
621- \ (user_register== default_buffer?' ' :' "' .user_register).
622- \ (a: direction = ~ ' b' ?' P' :' p' )
675+ \ ((cmd_mode== ' n' ) ? " " : " gv" ).
676+ \ ((v_count > 0 )?(v_count):' ' ).
677+ \ (user_register== default_buffer?' ' :' "' .user_register).
678+ \ (a: direction = ~ ' b' ?' P' :' p' )
623679 endif
624- let s: yr_paste_dir = a: direction
680+ let s: yr_paste_dir = a: direction
681+ let s: yr_prev_vis_mode = ((cmd_mode== ' n' ) ? 0 : 1 )
625682 return
626683 endif
627684
628685 " Try to second guess the user to make these mappings less intrusive.
629686 " If the user hits paste compare the contents of the paste register
630687 " to the current entry in the yankring. If they are different, lets
631688 " assume the user wants the contents of the paste register.
632- " So if they pressed yw (yank word ) and hit paste, the yankring
689+ " So if they pressed [yt ] (yank to space ) and hit paste, the yankring
633690 " would not have the word in it, so assume they want the word pasted.
634691 if a: replace_last_paste_selection != 1
635692 if s: yr_count > 0
636693 if getreg (default_buffer) != s: yr_elem_ {s: yr_paste_idx }
637- exec ' normal! ' .(a: direction = ~ ' b' ?' P' :' p' )
638- let s: yr_paste_dir = a: direction
694+ exec " normal! " .
695+ \ ((cmd_mode== ' n' ) ? " " : " gv" ).
696+ \ ((v_count > 0 )?(v_count):' ' ).
697+ \ (a: direction = ~ ' b' ?' P' :' p' )
698+ let s: yr_paste_dir = a: direction
699+ let s: yr_prev_vis_mode = ((cmd_mode== ' n' ) ? 0 : 1 )
639700 return
640701 endif
641702 else
642- exec ' normal! ' .(a: direction = ~ ' b' ?' P' :' p' )
643- let s: yr_paste_dir = a: direction
703+ exec " normal! " .
704+ \ ((cmd_mode== ' n' ) ? " " : " gv" ).
705+ \ ((v_count > 0 )?(v_count):' ' ).
706+ \ (a: direction = ~ ' b' ?' P' :' p' )
707+ let s: yr_paste_dir = a: direction
708+ let s: yr_prev_vis_mode = ((cmd_mode== ' n' ) ? 0 : 1 )
644709 return
645710 endif
646711 endif
@@ -678,10 +743,13 @@ function! s:YRPaste(replace_last_paste_selection, nextvalue, direction)
678743
679744 " First undo the previous paste
680745 exec " normal! u"
746+ " Check if the visual selection should be reselected
681747 " Next paste the correct item from the ring
682748 " This is done as separate statements since it appeared that if
683749 " there was nothing to undo, the paste never happened.
684- exec " normal! " .((s: yr_paste_dir = ~ ' b' )?' P' :' p' )
750+ exec " normal! " .
751+ \ ((s: yr_prev_vis_mode== 0 ) ? " " : " gv" ).
752+ \ ((s: yr_paste_dir = ~ ' b' )?' P' :' p' )
685753 call setreg (default_buffer, save_reg, save_reg_type)
686754 call s: YRSetPrevOP (' ' , ' ' , ' ' )
687755 else
@@ -694,16 +762,18 @@ function! s:YRPaste(replace_last_paste_selection, nextvalue, direction)
694762 \ , s: yr_elem_ {s: yr_paste_idx }
695763 \ , s: yr_elem_type_ {s: yr_paste_idx })
696764 exec " normal! " .
697- \ (
698- \ ((v_count > 0 )?(v_count):' ' ).
699- \ ((a: direction = ~ ' b' )?' P' :' p' )
700- \ )
765+ \ ((cmd_mode== ' n' ) ? " " : " gv" ).
766+ \ (
767+ \ ((v_count > 0 )?(v_count):' ' ).
768+ \ ((a: direction = ~ ' b' )?' P' :' p' )
769+ \ )
701770 call setreg (default_buffer, save_reg, save_reg_type)
702771 call s: YRSetPrevOP (
703772 \ ((a: direction = ~ ' b' )?' P' :' p' )
704773 \ , v_count
705774 \ , default_buffer)
706- let s: yr_paste_dir = a: direction
775+ let s: yr_paste_dir = a: direction
776+ let s: yr_prev_vis_mode = ((cmd_mode== ' n' ) ? 0 : 1 )
707777 endif
708778
709779endfunction
@@ -752,6 +822,12 @@ function! YRMapsCreate()
752822 if g: yankring_paste_n_akey != ' '
753823 exec ' nnoremap <silent>' .g: yankring_paste_n_akey ." :<C-U>YRPaste 'a'<CR>"
754824 endif
825+ if g: yankring_paste_v_bkey != ' '
826+ exec ' vnoremap <silent>' .g: yankring_paste_v_bkey ." :<C-U>YRPaste 'b', 'v'<CR>"
827+ endif
828+ if g: yankring_paste_v_akey != ' '
829+ exec ' vnoremap <silent>' .g: yankring_paste_v_akey ." :<C-U>YRPaste 'a', 'v'<CR>"
830+ endif
755831 if g: yankring_replace_n_pkey != ' '
756832 exec ' nnoremap <silent>' .g: yankring_replace_n_pkey ." :<C-U>YRReplace '-1', 'b'<CR>"
757833 endif
@@ -806,6 +882,12 @@ function! YRMapsDelete()
806882 if g: yankring_paste_n_akey != ' '
807883 exec ' nunmap ' .g: yankring_paste_n_akey
808884 endif
885+ if g: yankring_paste_v_bkey != ' '
886+ exec ' vunmap ' .g: yankring_paste_v_bkey
887+ endif
888+ if g: yankring_paste_v_akey != ' '
889+ exec ' vunmap ' .g: yankring_paste_v_akey
890+ endif
809891 if g: yankring_replace_n_pkey != ' '
810892 exec ' nunmap ' .g: yankring_replace_n_pkey
811893 endif
0 commit comments