Advertisement
FocusedWolf

Vim: Windows common keyboard shortcuts

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