Advertisement
FocusedWolf

Vim: Windows common keyboard shortcuts

Mar 21st, 2016 (edited)
514
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VIM 15.64 KB | None | 0 0
  1. " Windows common keyboard shortcuts and pasting behavior {{{
  2.  
  3. " Online posts:
  4. " http://superuser.com/questions/321547/how-do-i-replace-paste-yanked-text-in-vim-without-yanking-the-deleted-lines
  5. " http://pastebin.com/aBEsm5mV
  6.  
  7. " Recommended vimrc settings:
  8. "     Set clipboard like this:
  9. "         NOTE: Use ^= to prepend a value to a comma-separated list. See :h set^=
  10. "         set clipboard^=unnamedplus            " Works on Linux but has issues yanking on Windows.
  11. "         set clipboard^=unnamed,unnamedplus    " Works on Linux and Windows (and probably MacVim which needed the unnamed option the last time i used it).
  12. "
  13. "     Set mouse like this:
  14. "         set mouse=a    " Ensures mouse binds work in all modes.
  15. "
  16. "     Disable autoselect:
  17. "         NOTE: This forces MiddleMouse clicks in other programs to paste the contents of Vim's "+ unnamedplus register instead of the "* unnamed selection register. See :h go-a
  18. "         set guioptions-=a
  19. "         set guioptions-=A
  20.  
  21. " Functions {{{
  22.  
  23. " Uncomment to enable debugging.
  24. " Check debug output with :messages
  25. " let s:debug_smart_cut = 1
  26. " let s:debug_smart_copy = 1
  27. " let s:debug_smart_paste = 1
  28.  
  29. function! SmartCut() " {{{
  30.     if !has('clipboard')
  31.         echoerr 'Clipboard support is required to use this function.'
  32.         return
  33.     endif
  34.  
  35.     let clipboard_register = '+'
  36.  
  37.     " Restore the visual selection with 'gv' and delete the selection into the clipboard.
  38.     " NOTE: 'd' (delete) is better than 'c' (copy) because it moves the caret to the right for us.
  39.     execute 'normal! gv"' . clipboard_register . 'd'
  40.  
  41.     " Enter insert mode.
  42.     startinsert
  43.  
  44.     " Gets the value if it exists, else returns 0.
  45.     if get(s:, 'debug_smart_cut')
  46.         echomsg "SmartCut"
  47.         echomsg "    clipboard contents: " . getreg(clipboard_register)
  48.     endif
  49. endfunction " }}}
  50.  
  51. function! SmartCopy() " {{{
  52.     if !has('clipboard')
  53.         echoerr 'Clipboard support is required to use this function.'
  54.         return
  55.     endif
  56.  
  57.     let clipboard_register = '+'
  58.  
  59.     " Restore the visual selection with 'gv' and yank the selection into the clipboard.
  60.     execute 'normal! gv"' . clipboard_register . 'y'
  61.  
  62.     " Gets the value if it exists, else returns 0.
  63.     if get(s:, 'debug_smart_copy')
  64.         echomsg "SmartCopy"
  65.         echomsg "    clipboard contents: " . getreg(clipboard_register)
  66.     endif
  67. endfunction " }}}
  68.  
  69. function! SmartPaste() " {{{
  70.     if !has('clipboard')
  71.         echoerr 'Clipboard support is required to use this function.'
  72.         return
  73.     endif
  74.  
  75.     if !&modifiable
  76.         return
  77.     endif
  78.  
  79.     " See :help '> for more information. Hint: if you select some text and press ':' you will see :'<,'>
  80.     " SOURCE: http://superuser.com/questions/723621/how-can-i-check-if-the-cursor-is-at-the-end-of-a-line
  81.     " SOURCE: http://stackoverflow.com/questions/7262536/vim-count-lines-in-selected-range
  82.     " SOURCE: https://git.zug.fr/config/vim/blob/master/init.vim
  83.     " SOURCE: https://git.zug.fr/config/vim/blob/master/after/plugin/zzzmappings.vim
  84.     let currentColumn = col(".")
  85.     let currentLine = line(".")
  86.     let lastVisibleLetterColumn = col("$") - 1
  87.     let lastLineOfBuffer = line("$")
  88.     let selectionEndLine = line("'>")
  89.     let selectionEndLineLength = strchars(getline(selectionEndLine))
  90.     let nextLineLength = strchars(getline(currentLine + 1))
  91.     let selectionStartColumn = col("'<")
  92.     let selectionEndColumn = col("'>")
  93.  
  94.     " If selection does not include or go beyond the last visible character of the line (by also selecting the invisible EOL character).
  95.     if selectionEndColumn < selectionEndLineLength
  96.         let pee = 'P'
  97.  
  98.         " Gets the value if it exists, else returns 0.
  99.         if get(s:, 'debug_smart_paste')
  100.             echomsg "SmartPaste special case #1"
  101.         endif
  102.  
  103.     " If attempting to paste on a blank last line.
  104.     elseif selectionEndLineLength == 0 && selectionEndLine == lastLineOfBuffer
  105.         let pee = 'P'
  106.  
  107.         " Gets the value if it exists, else returns 0.
  108.         if get(s:, 'debug_smart_paste')
  109.             echomsg "SmartPaste special case #2"
  110.         endif
  111.  
  112.     " If selection ends after the last visible character of the line (by also selecting the invisible EOL character),
  113.     " or the line is visually selected (Shift + V),
  114.     " and the next line is not blank,
  115.     " and selection does not end on the last line.
  116.     elseif selectionEndColumn > selectionEndLineLength && nextLineLength > 0 && selectionEndLine != lastLineOfBuffer
  117.         let pee = 'P'
  118.  
  119.         " Gets the value if it exists, else returns 0.
  120.         if get(s:, 'debug_smart_paste')
  121.             echomsg "SmartPaste special case #3"
  122.         endif
  123.  
  124.     else
  125.         let pee = 'p'
  126.  
  127.         " Gets the value if it exists, else returns 0.
  128.         if get(s:, 'debug_smart_paste')
  129.             echomsg "SmartPaste default case"
  130.         endif
  131.     endif
  132.  
  133.     let clipboard_register = '+'
  134.  
  135.     " Gets the value if it exists, else returns 0.
  136.     if get(s:, 'debug_smart_paste')
  137.         echomsg "SmartPaste"
  138.         echomsg "    clipboard contents: " . getreg(clipboard_register)
  139.         echomsg "    currentColumn: " . currentColumn
  140.         echomsg "    currentLine: " . currentLine
  141.         echomsg "    lastVisibleLetterColumn: " . lastVisibleLetterColumn
  142.         echomsg "    lastLineOfBuffer: " . lastLineOfBuffer
  143.         echomsg "    selectionEndLine: " . selectionEndLine
  144.         echomsg "    selectionEndLineLength: " . selectionEndLineLength
  145.         echomsg "    nextLineLength: " . nextLineLength
  146.         echomsg "    selectionStartColumn: " . selectionStartColumn
  147.         echomsg "    selectionEndColumn: " . selectionEndColumn
  148.         echomsg "    pee: " . pee
  149.         echomsg "    selection bounds" . string([getpos("'<")[1:2], getpos("'>")[1:2]])
  150.         echomsg "    visualmode(): " . visualmode()
  151.         echomsg "    mode(): " . mode()
  152.         echomsg "    getpos('.'): " . string(getpos('.'))
  153.     endif
  154.  
  155.     try
  156.         " Enter paste mode.
  157.         " NOTE: This prevents InsertCharPre autocommands from running repeatedly for each character in the pasted string.
  158.         set paste
  159.  
  160.         " Backup clipboard.
  161.         let clipboard_contents = getreg(clipboard_register)
  162.         let clipboard_type = getregtype(clipboard_register)
  163.  
  164.         " If clipboard type is linewise.
  165.         if clipboard_type[0] == 'V'
  166.             " Change clipboard register to characterwise mode.
  167.             call setreg(clipboard_register, clipboard_contents, 'v')
  168.         endif
  169.  
  170.         " Restore the visual selection with 'gv' and paste the clipboard contents there.
  171.         execute 'normal! gv"' . clipboard_register . pee
  172.  
  173.         " Restore clipboard.
  174.         call setreg(clipboard_register, clipboard_contents, clipboard_type)
  175.     catch /E353:\ Nothing\ in\ register/
  176.     finally
  177.         " Exit paste mode.
  178.         set nopaste
  179.     endtry
  180. endfunction " }}}
  181.  
  182. function! SmartFind() " {{{
  183.     let wordUnderCursor = expand('<cword>')
  184.     if wordUnderCursor == ''
  185.         execute 'promptfind'
  186.     else
  187.         execute 'promptfind' wordUnderCursor
  188.     endif
  189. endfunction " }}}
  190.  
  191. function! SmartReplace() " {{{
  192.     let wordUnderCursor = expand('<cword>')
  193.     if wordUnderCursor == ''
  194.         execute 'promptrepl'
  195.     else
  196.         execute 'promptrepl' wordUnderCursor
  197.     endif
  198. endfunction " }}}
  199.  
  200. function! SmartSaveFile() " {{{
  201.     " SOURCE: http://vim.wikia.com/wiki/Map_Ctrl-S_to_save_current_or_new_files
  202.  
  203.     " If file is saved.
  204.     if !&modified
  205.         return
  206.     endif
  207.  
  208.     try
  209.         " If the current buffer has no name.
  210.         if empty(bufname('%'))
  211.             " Display a save dialog so the user can specify a file name.
  212.             browse confirm write
  213.         else
  214.             " Force a write even if a file exists with that name.
  215.             confirm write
  216.         endif
  217.     catch /E212:\ Can't\ open\ file\ for\ writing/
  218.        if has("win32") || has("win64")
  219.            echomsg "ERROR: You lack write permission for this directory or the file name is not valid."
  220.        else
  221.            " NOTE: The [browse confirm write] call above will establish the filename in the case of an empty buffer.
  222.            try
  223.                " A hack that uses tee to output the buffer to the % filename with sudo permissions.
  224.                " SOURCE: https://stackoverflow.com/questions/2600783/how-does-the-vim-write-with-sudo-trick-work
  225.                execute("w !sudo tee %")
  226.  
  227.                if v:shell_error
  228.                    throw 'Failed to save file.'
  229.                else
  230.                    " Reload the file, otherwise vim will detect the file changed and ask you for permission to reload the file.
  231.                    silent edit!
  232.  
  233.                    " Clears the command line and removes 'Press ENTER or type command to continue' prompt.
  234.                    " SOURCE: https://vim.fandom.com/wiki/Avoiding_the_%22Hit_ENTER_to_continue%22_prompts
  235.                    redraw!
  236.                endif
  237.            catch /.*/
  238.                echomsg 'SmartSaveFile() Unhandled Exception: ' . v:exception
  239.            endtry
  240.        endif
  241.    endtry
  242. endfunction " }}}
  243.  
  244. function! SmartCopyMessageHistory() " {{{
  245.    redir @+
  246.    silent execute(':messages')
  247.    redir END
  248. endfunction " }}}
  249.  
  250. " }}} Functions
  251.  
  252. " Binds {{{
  253.  
  254. " Paste for MiddleMouse in normal, visual, and insert mode {{{
  255.  
  256. " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
  257. nnoremap <silent> <MiddleMouse> <C-v>:<C-u>call SmartPaste()<CR>
  258.  
  259. " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
  260. vnoremap <silent> <MiddleMouse> :<C-u>call SmartPaste()<CR>
  261.  
  262. " Characterwise paste for insert mode.
  263. " SOURCE: https://vim.fandom.com/wiki/Pasting_registers
  264. " NOTE: <C-o> executes a normal-mode command without leaving insert mode. See :help ins-special-special
  265. " NOTE: <C-r>+ inserts the contents of the unnamedplus register during insert mode. See :h i_CTRL-R
  266. " NOTE: <C-r>+ doesn't work for Ctrl-v yanked and pasted columns of text. It forces characterwise selections to be linewise pasted. <C-r><C-o>+ works though.
  267. " [bad, triggers InsertCharPre for each pasted letter] inoremap <silent> <MiddleMouse> <C-r><C-r>+
  268. " [works] inoremap <silent> <MiddleMouse> <C-o>"+<MiddleMouse>
  269. " [works, but no need for paste mode i think because it doesn't trigger InsertCharPre events for each pasted letter] inoremap <silent> <MiddleMouse> <C-o>:set paste<CR><C-r><C-o>+<C-o>:set nopaste<CR>
  270. inoremap <silent> <MiddleMouse> <C-r><C-o>+
  271.  
  272. " Disable weird multi-click things you can do with middle mouse button.
  273. " SOURCE: http://vim.wikia.com/wiki/Mouse_wheel_for_scroll_only_-_disable_middle_button_paste
  274. nnoremap <2-MiddleMouse> <Nop>
  275. inoremap <2-MiddleMouse> <Nop>
  276. vnoremap <2-MiddleMouse> <Nop>
  277. nnoremap <3-MiddleMouse> <Nop>
  278. inoremap <3-MiddleMouse> <Nop>
  279. vnoremap <3-MiddleMouse> <Nop>
  280. nnoremap <4-MiddleMouse> <Nop>
  281. inoremap <4-MiddleMouse> <Nop>
  282. vnoremap <4-MiddleMouse> <Nop>
  283.  
  284. " }}} Paste for MiddleMouse in normal, visual, and insert mode
  285.  
  286. " If OS is not mac.
  287. if system('uname') !~ 'Darwin' " NOTE: MacVim provides Command+C|X|V|A|S and undo/redo functionality and also can Command+C|V to the command line by default.
  288.     " Copy, paste, and select-all functionality for commandline {{{
  289.  
  290.     " SOURCE: https://opensource.apple.com/source/vim/vim-62.41.2/runtime/macmap.vim.auto.html
  291.     " NOTE: Only copy and paste are possible in the command line from what i can tell.
  292.     "       Their is no undo for text typed in the command line and you cannot paste text onto a selection of text to replace it.
  293.     cnoremap <C-c> <C-y>
  294.     cnoremap <C-v> <C-r>+
  295.  
  296.     " Everyone seems to bind this. No way to select-all, but we can move the caret all the way to the left of the command line. Yay.
  297.     cnoremap <C-A> <Home>
  298.  
  299.     " Copy message history to the clipboard.
  300.     " NOTE: This is a workaround for not being able to select all.
  301.     nnoremap <silent> <Leader>m :<C-u>call SmartCopyMessageHistory()<CR>
  302.  
  303.     " }}} Copy, paste, select-all functionality for commandline
  304.  
  305.     " Cut, copy, paste functionality for visual and insert mode {{{
  306.  
  307.     " Cut, copy, and paste functionality for visual mode.
  308.     " SOURCE: http://superuser.com/questions/10588/how-to-make-cut-copy-paste-in-gvim-on-ubuntu-work-with-ctrlx-ctrlc-ctrlv
  309.     " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
  310.     vnoremap <silent> <C-x> :<C-u>call SmartCut()<CR>
  311.     vnoremap <silent> <C-c> :<C-u>call SmartCopy()<CR>
  312.     vnoremap <silent> <C-v> :<C-u>call SmartPaste()<CR>
  313.  
  314.     " Characterwise paste for insert mode.
  315.     " SOURCE: https://vim.fandom.com/wiki/Pasting_registers
  316.     " NOTE: <C-o> executes a normal-mode command without leaving insert mode. See :help ins-special-special
  317.     " NOTE: <C-r>+ inserts the contents of the unnamedplus register during insert mode. See :h i_CTRL-R
  318.     " NOTE: <C-r>+ doesn't work for Ctrl-v yanked and pasted columns of text. It forces characterwise selections to be linewise pasted. <C-r><C-o>+ works though.
  319.     " [works, but no need for paste mode i think because it doesn't trigger InsertCharPre events for each pasted letter] inoremap <silent> <C-v> <C-o>:set paste<CR><C-r><C-o>+<C-o>:set nopaste<CR>
  320.     inoremap <silent> <C-v> <C-r><C-o>+
  321.  
  322.     " }}} Cut, copy, paste functionality for visual and insert mode
  323.  
  324.     " Select-all functionality for normal, visual, and insert mode {{{
  325.  
  326.     " SOURCE: http://vim.wikia.com/wiki/Using_standard_editor_shortcuts_in_Vim
  327.     nnoremap <C-a> ggVG
  328.     vnoremap <C-a> ggVG
  329.     inoremap <C-a> <Esc>ggVG
  330.  
  331.     " }}} Select-all functionality for normal, visual, and insert mode
  332.  
  333.     " Save functionality for normal, visual, and insert mode {{{
  334.  
  335.     nnoremap <silent> <C-s> :call SmartSaveFile()<CR>
  336.  
  337.     " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
  338.     vnoremap <silent> <C-s> :<C-u>call SmartSaveFile()<CR>gv
  339.  
  340.     " NOTE: <C-o> executes a normal-mode command without leaving insert mode. See :help ins-special-special
  341.     inoremap <silent> <C-s> <C-o>:call SmartSaveFile()<CR>
  342.  
  343.     " }}} Save functionality for normal, visual, and insert mode
  344.  
  345.     " Undo and redo functionality for normal, visual, and insert mode {{{
  346.  
  347.     nnoremap <C-z> <Esc>u
  348.     nnoremap <C-y> <Esc><C-r>
  349.  
  350.     " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
  351.     vnoremap <C-z> :<C-u>uV
  352.     vnoremap <C-y> :<C-u><C-r>V
  353.  
  354.     inoremap <C-z> <Esc>uI
  355.     inoremap <C-y> <Esc><C-r>I
  356.  
  357.     " Disable Vim normal-mode undo/redo keys.
  358.     " Having a single key for undo is an accident waiting to happen, especially when 'u' and 'U' are also used as visual-mode character case toggles.
  359.     " SOURCE: https://stackoverflow.com/questions/57714401/vi-vim-remap-or-unmap-built-in-command-the-u-key-in-visual-mode
  360.     nnoremap u <NOP>
  361.     nnoremap <C-r> <NOP>
  362.  
  363.     " }}} Undo and redo functionality for normal, visual, and insert mode
  364.  
  365.     " Find and Replace functionality for normal, visual, and insert mode {{{
  366.  
  367.     nnoremap <silent> <C-f> :call SmartFind()<CR>
  368.     nnoremap <silent> <C-h> :call SmartReplace()<CR>
  369.  
  370.     " NOTE: <C-u> removes the '<,'> visual-selection from the command line. See :h c_CTRL-u
  371.     vnoremap <silent> <C-f> :<C-u>call SmartFind()<CR>
  372.     vnoremap <silent> <C-h> :<C-u>call SmartReplace()<CR>
  373.  
  374.     " NOTE: <C-o> executes a normal-mode command without leaving insert mode. See :help ins-special-special
  375.     inoremap <silent> <C-f> <C-o>:call SmartFind()<CR>
  376.     inoremap <silent> <C-h> <C-o>:call SmartReplace()<CR>
  377.  
  378.     " }}} Find and Replace functionality for normal, visual, and insert mode
  379. endif
  380.  
  381. " }}} Binds
  382.  
  383. " }}} Windows common keyboard shortcuts and pasting behavior
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement