From e3f89438582c12b4d058dd7752c294ad6bb33fac Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Wed, 11 May 2022 11:05:49 -0300 Subject: Default to xterm-mode selection This allows snippet plugins to do their magic tabbed selection of positions to fill in a snippet. For example when you want to complete an `if~`, snippet plugins populate the buffer at that cursor position with a skeleton of an `if` statement and select the parts that you want to customise yourself. This is only possible if the default selection mode is xterm. So in this commit we carefully manage using mswin-style selection when the user initiates it with SHIFT keys etc. The only downside is that I haven't found a way to detect when mouse selection starts in order to move it away from xterm selection to mswin sselection. --- autoload/novim_mode.vim | 107 ++++++++++++++++++++++++++++++++++++++---------- spec/novim_mode_spec.rb | 7 ++-- 2 files changed, 89 insertions(+), 25 deletions(-) diff --git a/autoload/novim_mode.vim b/autoload/novim_mode.vim index 3f271e8..9d57c15 100644 --- a/autoload/novim_mode.vim +++ b/autoload/novim_mode.vim @@ -54,18 +54,15 @@ function! s:InsertAndSelectionBehaviour() else autocmd BufEnter * call s:InsertMode() endif - augroup END - " Mostly changes the way selection works. - " See: http://vimdoc.sourceforge.net/htmldoc/gui.html#:behave - " An extract from the docs about the difference between `behave mswin` - " and `behave xterm`: - " mswin xterm - " 'selectmode' 'mouse,key' '' - " 'mousemodel' 'popup' 'extend' - " 'keymodel' 'startsel,stopsel' '' - " 'selection' 'exclusive' 'inclusive' - behave mswin + " See `novim_mode#EnterSelectionMode` + " `xterm` behviour is standard Vim behaviour in terms of selecting, which although + " is contrary to what we want in this plugin, it's still what most plugins expect. + " So far I know `xterm` selection behaviour is critical for autocompletion plugins + " that do things like paste a snippet with placeholders that get selected and hence + " replaced when you start typing. + autocmd InsertEnter * behave xterm + augroup END " Make 'v' commands default to Visual mode. " Not sure how useful this is because the mappings that use 'v'-based @@ -112,7 +109,6 @@ function! g:SetNoVimModeShortcuts() " Fix HOME to go back to the first non-whitespace character of the line. inoremap ^ " The same but for selection behaviour - inoremap ^ snoremap ^ " Tweaks PageUp behaviour to get cursor to first line on top page @@ -158,14 +154,21 @@ function! g:SetNoVimModeShortcuts() snoremap "+ygv snoremap "+xi " Select word under cursor - inoremap viw + inoremap :call novim_mode#EnterSelectionMode('word') " Select current line - inoremap V + inoremap :call novim_mode#EnterSelectionMode('line') " Append next line to selection snoremap gj + inoremap :call novim_mode#EnterSelectionMode('left') + inoremap :call novim_mode#EnterSelectionMode('right') + inoremap :call novim_mode#EnterSelectionMode('up') + inoremap :call novim_mode#EnterSelectionMode('down') + inoremap :call novim_mode#EnterSelectionMode('home') + inoremap :call novim_mode#EnterSelectionMode('end') + " CTRL-A for selecting all text - inoremap gggHG + inoremap :call novim_mode#EnterSelectionMode('all') snoremap gggHG endif @@ -263,19 +266,26 @@ function! s:WrappedTextBehaviour() " * Scroll window 1 wrapped soft line at a time rather than entire block " of wrapped lines -- I'm as good as certain this will need a patch to " (n)vim's internals. - inoremap gk + + " Up/Down for *visible* lines, not literal lines + inoremap gk inoremap gj + snoremap gk + snoremap gj " For selection behaviour - snoremap gk - snoremap gj + inoremap :call novim_mode#EnterSelectionMode('up-wrapped-text') + snoremap gk + inoremap :call novim_mode#EnterSelectionMode('down-wrapped-text') + snoremap gj + " HOME/END for *visible* lines, not literal lines inoremap g^ - inoremap g$ + inoremap g$ " For selection behaviour - inoremap g^ + inoremap :call novim_mode#EnterSelectionMode('home-wrapped-text') snoremap g^ - inoremap g$ - snoremap g$ + inoremap :call novim_mode#EnterSelectionMode('end-wrapped-text') + snoremap g$ endfunction " Try to intuitively and intelligently close things like buffers, splits, @@ -355,3 +365,56 @@ function! g:novim_mode#StartNoVimMode() call g:SetNoVimModeShortcuts() endif endfunction + +function! novim_mode#EnterSelectionMode(type) + " Mostly changes the way selection works. + " See: http://vimdoc.sourceforge.net/htmldoc/gui.html#:behave + " An extract from the docs about the difference between `behave mswin` + " and `behave xterm`: + " mswin xterm + " 'selectmode' 'mouse,key' '' + " 'mousemodel' 'popup' 'extend' + " 'keymodel' 'startsel,stopsel' '' + " 'selection' 'exclusive' 'inclusive' + behave mswin + + if a:type == 'left' + execute "normal! \" + endif + if a:type == 'right' + execute "normal! \" + endif + if a:type == 'up' + execute "normal! \" + endif + if a:type == 'up-wrapped-text' + execute "normal! \\\gk\" + endif + if a:type == 'down' + execute "normal! \" + endif + if a:type == 'down-wrapped-text' + execute "normal! \\\gj\" + endif + if a:type == 'home' + execute "normal! \" + endif + if a:type == 'home-wrapped-text' + execute "normal! \\\g^" + endif + if a:type == 'end' + execute "normal! \" + endif + if a:type == 'end-wrapped-text' + execute "normal! \\\g$" + endif + if a:type == 'word' + execute "normal! viw\" + endif + if a:type == 'line' + execute "normal! V\" + endif + if a:type == 'all' + execute "normal! ggVG\" + endif +endfunction diff --git a/spec/novim_mode_spec.rb b/spec/novim_mode_spec.rb index 1d0bc99..c784772 100644 --- a/spec/novim_mode_spec.rb +++ b/spec/novim_mode_spec.rb @@ -56,7 +56,8 @@ end describe 'Selecting' do specify 'select all and replace' do initial <<-EOF - select me + select me more, just to make sure + even a hard line EOF type 'gone' @@ -203,7 +204,7 @@ describe 'Wrapped text' do type '!' final <<-EOF - line1 !line3 line4 + line1 !line4 EOF end @@ -216,7 +217,7 @@ describe 'Wrapped text' do type '!' final <<-EOF - line1 !line3 line4 + !line3 line4 EOF end -- cgit v1.2.3-70-g09d2