50
50
" Internal Mappings
51
51
" ===============================================================================
52
52
53
- inoremap <silent> <Plug> (i) <C-o> :call <SID> process_user_inut('i' )<CR>
54
- nnoremap <silent> <Plug> (i) :call <SID> process_user_inut('n' )<CR>
55
- xnoremap <silent> <Plug> (i) :<C-u> call <SID> process_user_inut('v' )<CR>
53
+ inoremap <silent> <Plug> (i) <C-o> :call <SID> process_user_inut()<CR>
54
+ nnoremap <silent> <Plug> (i) :call <SID> process_user_inut()<CR>
55
+ xnoremap <silent> <Plug> (i) :<C-u> call <SID> process_user_inut()<CR>
56
56
57
57
inoremap <silent> <Plug> (a) <C-o> :call <SID> apply_user_input_next('i')<CR>
58
58
nnoremap <silent> <Plug> (a) :call <SID> apply_user_input_next('n')<CR>
@@ -347,11 +347,6 @@ function! s:CursorManager.reset(restore_view) dict
347
347
let self .saved_winview = []
348
348
let self .start_from_find = 0
349
349
call self .restore_user_settings ()
350
-
351
- " FIXME(terryma): Doesn't belong here
352
- let s: from_mode = ' '
353
- let s: to_mode = ' '
354
- let s: visualmode = ' '
355
350
endfunction
356
351
357
352
" Returns 0 if it's not managing any cursors at the moment
@@ -405,7 +400,6 @@ function! s:CursorManager.debug() dict
405
400
echom ' ' ' > = ' .string (s: pos (" '>" ))
406
401
echom ' to mode = ' .s: to_mode
407
402
echom ' from mode = ' .s: from_mode
408
- echom ' visual mode = ' .s: visualmode
409
403
" echom 'special keys = '.string(s:special_keys)
410
404
echom ' '
411
405
endfunction
@@ -415,7 +409,13 @@ endfunction
415
409
" position changed, false otherwise
416
410
function ! s: CursorManager .update_current () dict
417
411
let cur = self .get_current ()
418
- if s: to_mode == # ' v'
412
+ if s: to_mode == # ' v' || s: to_mode == # ' V'
413
+ " If we're in visual line mode, we need to go to visual mode before we can
414
+ " update the visual region
415
+ if s: to_mode == # ' V'
416
+ normal ! gvv
417
+ endif
418
+
419
419
" Sets the cursor at the right place
420
420
call s: exit_visual_mode ()
421
421
call cur.update_visual_selection (s: get_visual_region (s: pos (' .' )))
@@ -569,8 +569,6 @@ let s:char = ''
569
569
let s: from_mode = ' '
570
570
" This is the mode the user is in after s:char
571
571
let s: to_mode = ' '
572
- " If s:to_mode is 'v', this tells us what kind of visual mode the user was in
573
- let s: visualmode = ' '
574
572
" This is the total number of lines in the buffer before processing s:char
575
573
let s: saved_linecount = -1
576
574
" This is used to apply the highlight fix. See s:apply_highight_fix()
@@ -678,17 +676,21 @@ endfunction
678
676
" multiple places.
679
677
function ! s: highlight_region (region )
680
678
let s = sort (copy (a: region ), " s:compare_pos" )
681
- if (s [0 ][0 ] == s [1 ][0 ])
682
- " Same line
683
- let pattern = ' \%' .s [0 ][0 ].' l\%>' .(s [0 ][1 ]-1 ).' c.*\%<' .(s [1 ][1 ]+ 1 ).' c.'
679
+ if s: to_mode == # ' V'
680
+ let pattern = ' \%>' .(s [0 ][0 ]-1 ).' l\%<' .(s [1 ][0 ]+ 1 ).' l.*\ze.\_$'
684
681
else
685
- " Two lines
686
- let s1 = ' \%' .s [0 ][0 ].' l.\%>' .s [0 ][1 ].' c.*'
687
- let s2 = ' \%' .s [1 ][0 ].' l.*\%<' .s [1 ][1 ].' c..'
688
- let pattern = s1.' \|' .s2
689
- " More than two lines
690
- if (s [1 ][0 ] - s [0 ][0 ] > 1 )
691
- let pattern = pattern.' \|\%>' .s [0 ][0 ].' l\%<' .s [1 ][0 ].' l'
682
+ if (s [0 ][0 ] == s [1 ][0 ])
683
+ " Same line
684
+ let pattern = ' \%' .s [0 ][0 ].' l\%>' .(s [0 ][1 ]-1 ).' c.*\%<' .(s [1 ][1 ]+ 1 ).' c.'
685
+ else
686
+ " Two lines
687
+ let s1 = ' \%' .s [0 ][0 ].' l.\%>' .s [0 ][1 ].' c.*'
688
+ let s2 = ' \%' .s [1 ][0 ].' l.*\%<' .s [1 ][1 ].' c..'
689
+ let pattern = s1.' \|' .s2
690
+ " More than two lines
691
+ if (s [1 ][0 ] - s [0 ][0 ] > 1 )
692
+ let pattern = pattern.' \|\%>' .s [0 ][0 ].' l\%<' .s [1 ][0 ].' l.*\ze.\_$'
693
+ endif
692
694
endif
693
695
endif
694
696
return matchadd (s: hi_group_visual , pattern)
@@ -699,6 +701,10 @@ function! s:revert_mode(from, to)
699
701
if a: to == # ' v'
700
702
call s: cm .reapply_visual_selection ()
701
703
endif
704
+ if a: to == # ' V'
705
+ call s: cm .reapply_visual_selection ()
706
+ normal ! V
707
+ endif
702
708
if a: to == # ' i'
703
709
startinsert
704
710
endif
@@ -725,7 +731,7 @@ function! s:feedkeys(keys)
725
731
endfunction
726
732
727
733
" Take the user input and apply it at every cursor
728
- function ! s: process_user_inut (mode )
734
+ function ! s: process_user_inut ()
729
735
" Grr this is frustrating. In Insert mode, between the feedkey call and here,
730
736
" the current position could actually CHANGE for some odd reason. Forcing a
731
737
" position reset here
@@ -748,10 +754,15 @@ endfunction
748
754
749
755
" Apply the user input at the next cursor location
750
756
function ! s: apply_user_input_next (mode )
751
- " Save the current mode
752
- let s: to_mode = a: mode
753
-
754
- let s: visualmode = visualmode ()
757
+ " Save the current mode, only if we haven't already
758
+ if empty (s: to_mode )
759
+ let s: to_mode = a: mode
760
+ if s: to_mode == # ' v'
761
+ if visualmode () == # ' V'
762
+ let s: to_mode = ' V'
763
+ endif
764
+ endif
765
+ endif
755
766
756
767
" Update the current cursor's information
757
768
let changed = s: cm .update_current ()
@@ -764,14 +775,14 @@ function! s:apply_user_input_next(mode)
764
775
765
776
" We're done if we're made the full round
766
777
if s: cm .loop_done ()
767
- if s: to_mode == # ' v'
778
+ if s: to_mode == # ' v' || s: to_mode == # ' V '
768
779
" This is necessary to set the "'<" and "'>" markers properly
769
780
call s: update_visual_markers (s: cm .get_current ().visual )
770
781
endif
771
782
call s: wait_for_user_input (s: to_mode )
772
783
else
773
784
" Continue to next
774
- call s: process_user_inut (s: from_mode )
785
+ call s: process_user_inut ()
775
786
endif
776
787
endfunction
777
788
@@ -813,15 +824,22 @@ endfunction
813
824
" Quits multicursor mode and clears all cursors. Return true if exited
814
825
" successfully.
815
826
function ! s: exit ()
816
- if s: char == # g: multi_cursor_quit_key &&
817
- \ (s: from_mode == # ' n' ||
818
- \ s: from_mode == # ' v' && g: multi_cursor_exit_from_visual_mode ||
819
- \ s: from_mode == # ' i' && g: multi_cursor_exit_from_insert_mode )
820
- if s: from_mode == # ' i'
821
- stopinsert
822
- elseif s: from_mode == # ' v'
823
- call s: exit_visual_mode ()
824
- endif
827
+ if s: char !=# g: multi_cursor_quit_key
828
+ return 0
829
+ endif
830
+ let exit = 0
831
+ if s: from_mode == # ' n'
832
+ let exit = 1
833
+ elseif (s: from_mode == # ' v' || s: from_mode == # ' V' ) &&
834
+ \ g: multi_cursor_exit_from_visual_mode
835
+ " This isn't strictly necessary, but good to do nonetheless
836
+ call s: exit_visual_mode ()
837
+ let exit = 1
838
+ elseif s: from_mode == # ' i' && g: multi_cursor_exit_from_insert_mode
839
+ stopinsert
840
+ let exit = 1
841
+ endif
842
+ if exit
825
843
call s: cm .reset (1 )
826
844
return 1
827
845
endif
0 commit comments