diff --git a/README.md b/README.md index ddf3389..61436ab 100644 --- a/README.md +++ b/README.md @@ -1,231 +1,231 @@ -vim-easyclip -============= -### Simplified clipboard functionality for Vim.### - -Author: [Steve Vermeulen] (https://github.com/svermeulen), based on work by [Max Brunsfeld] (http://www.github.com/maxbrunsfeld) - -A good starting point for the motivation behind this Vim plugin can be found in Drew Neil's post [Registers: The Good, the Bad, and the Ugly Parts](http://vimcasts.org/blog/2013/11/25/registers-the-good-the-bad-and-the-ugly-parts) - -### Installation ### - -I recommend loading your plugins with [neobundle](https://github.com/Shougo/neobundle.vim) or [vundle](https://github.com/gmarik/vundle) or [pathogen](https://github.com/tpope/vim-pathogen) - -This plugin also requires that you have Tim Pope's [repeat.vim](https://github.com/tpope/vim-repeat) plugin installed. - -### Black Hole Redirection ### - -By default, Vim's built-in delete operator will yank the deleted text in addition to just deleting it. This works great when you want to cut text and paste it somewhere else, but in many other cases it can make things more difficult. For example, if you want to make some tiny edit to fix formatting after cutting some text, you either have to have had the foresight to use a named register, or specify the black hole register explicitly to do your formatting. This plugin solves that problem by redirecting all change and delete operations to the black hole register and introducing a new operator, 'cut' (by default this is mapped to the `m` key for 'move'). - -There is simply no need to clutter up the yank history with every single edit, when you almost always know at the time you are deleting text whether it's something that is worth keeping around or not. - -**NOTE** As a result of the above, by default easyclip will shadow an import vim function: The Add Mark key (`m`). Therefore either you will want to use a different key for the 'cut' operator (see options section below for this) or remap something else to 'add mark'. For example, to use `gm` for 'add mark' instead of `m`, include the following in your vimrc: - - nnoremap gm m - -### Substitution Operator ### - -Because replacing text is such a common operation, EasyClip includes a motion for it. It is essentially equivalent to doing a change operation then pasting using the specified register. For example, assuming you have mapped this motion to the `s` key, to paste over the word under the cursor you would type `siw`, or to paste inside brackets, `si(`, etc. - -It can also take a register to use for the substitution (eg. `"asip`), and is fully repeatable using the `.` key. - -**NOTE** This feature is off by default. To use, you have to either enable the option `g:EasyClipUseSubstituteDefaults` (in which case it will be mapped to the `s` key) or map the key/keys of your choice to the `` mappings found in substitute.vim. - -### Yank Buffer ### - -EasyClip allows you to yank and cut things without worrying about losing text that you copied previously. It achieves this by storing all yanks into a buffer, which you can cycle through forward or backwards to choose the yank that you want - -This works very similar to the way [YankRing](https://github.com/vim-scripts/YankRing.vim) and [YankStack](https://github.com/maxbrunsfeld/vim-yankstack) work, in that you can use a key binding to toggle between different yanks immediately after triggering a paste or substitute. (Most of the functionality is actually taken and adapted from Yankstack, with changes to make it work with substitute) - -By default, the keys to toggle the paste are mapped to `` and `` (similar to yankring). For example, executing `p` will paste, then toggle it to the most recent yank before that. You can continue toggling forwards/backwards in the yank history to replace the most recent paste as much as you want. Note that the toggle action will of course not be included in the undo history. That is, pressing undo after any number of swaps will undo the paste and not each swap. - -This method of toggling the chosen yank after paste will probably be your primary method of digging back into the yank buffer. Note that in this case the yank buffer is unchanged. What this means for example is that you can toggle a given paste back using `` 10 times, then if you perform a new paste in a different location it will still use the most recent yank (and not the final yank you arrived at after 10 swaps). - -Alternatively, you can execute (by default) keys `[y` or `]y` to navigate the yank buffer 'head' forwards or backwards. In this case the change will be permanent. That is, pressing `[y[yp` will paste the third most recent yank. Subsequent pastes will use the same yank, until you go forwards again using `]y`. - -You can view the full list of yanks at any time by running the command `:Yanks` - -Note that you can swap substitution operations in the same way as paste. - -Every time the yank buffer changes, it also populates all the numbered registers. `"1` is therefore the previous yank, `"2` is the yank before that, etc. This is similar to how the numbered registers work by default (but a bit more sane). (Credit to Drew Neil for the suggestion) - -Also, see `g:EasyClipPreserveCursorPositionAfterYank` option below for an optional non standard customization to yank - -### Paste ### - -By default EasyClip preserves the default vim paste behaviour, which is the following: - -* `p` (lowercase) pastes text after the current line if the pasted text is multiline (or after the current character if non-multiline) -* `P` (uppercase) behaves the same except acts before the current line (or before the current character if non-multiline) - -When the text is multi-line, the cursor is placed at the start of the new text. When the paste is non-multiline, the cursor is placed at the end. - -Alternatively, you can enable the option `g:EasyClipAlwaysMoveCursorToEndOfPaste` to have the cursor positioned at the end in both cases (off by default). Note that when this option is enabled, the beginning of the multi-line text is added to the jumplist, so you can still return to the start of the paste by pressing `` (and this applies to multi-line substitutions as well) - -Another non-standard option is `g:EasyClipAutoFormat` (off by default), which will automatically format text immediately after it is pasted. This can be useful when pasting text from one indent level to another. - -Easy Clip also includes a mapping for insert mode paste, which automatically turns on 'paste' mode for the duration of the paste. Using 'paste' mode will work much more intuitively when pasting text with multiple lines while in insert mode. You can enable this by including something similar to the following in your .vimrc: - - imap EasyClipInsertModePaste - -### System Clipboard Sync ### - -EasyClip will also automatically sync with your system clipboard. - -Every time you leave and return to vim, easy clip will check whether you copied anything from outside Vim and add it to the yank history. - -### Options ### - -EasyClip can be easily customized to whatever mapping you wish, using the following options: - -`g:EasyClipAutoFormat` - Default: 0. Set this to 1 to enable auto-formatting pasting text - -`g:EasyClipYankHistorySize` - Default: 50. Change this to limit yank history - -`g:EasyClipAlwaysMoveCursorToEndOfPaste` - Default: 0. Set this to 1 to always position cursor at the end of the pasted text for both multi-line and non-multiline pastes. - -`g:EasyClipDoSystemSync` - Default: 1. Set this to zero to disable system clipboard sync. - -`g:EasyClipPreserveCursorPositionAfterYank` - Default 0 (ie. disabled). Vim's default behaviour is to position the cursor at the beginning of the yanked text, which is consistent with other motions. However if you prefer the cursor position to remain unchanged when performing yanks, enable this option. - -You can also disable the default mappings by setting one or more of the following to zero. By default they are set to 1 (ie. enabled) - - `g:EasyClipUseYankDefaults` - - `g:EasyClipUseCutDefaults` - - `g:EasyClipUsePasteDefaults` - - `g:EasyClipEnableBlackHoleRedirect` - - `g:EasyClipUsePasteToggleDefaults` - -One exception to the above is substitute, which is 0 by default (ie. disabled) - - `g:EasyClipUseSubstituteDefaults` - -To change from the default mappings, you can disable one of the options above and then map to the specific `` mappings of your choice. For example, to change the mapping for cut (by default set to `m`) to `x`, include the following in your vimrc:` - - let g:EasyClipUseCutDefaults = 0 - - nmap x MoveMotionPlug - xmap x MoveMotionXPlug - nmap xx MoveMotionLinePlug - -Or to change the bindings for toggling paste from `` and `` to `` and `` include the following: - - let g:EasyClipUsePasteToggleDefaults = 0 - - nmap EasyClipSwapPasteForward - nmap EasyClipSwapPasteBackwards - -Or to use `gs` for substitute include the following: (in this case you don't need to turn off the default since the default is already disabled) - - nmap gs SubstituteOverMotionMap - nmap gss SubstituteLine - xmap gs XEasyClipPaste - -For reference, or other kinds of mappings, see the Plugs section of the file with the name of the operation you wish to remap (vim-easy-clip/autoload/substitute.vim / move.vim / yank.vim /etc.) - -Note that EasyClip will only enable a default mapping if it hasn't already been mapped to something in your .vimrc. - -### Default Key Mappings ### - -`d` - Delete over the given motion and *do not* change clipboard - -`dd` - Delete the line and *do not* change clipboard - -`D` - Delete from cursor to the end of the line and *do not* change clipboard - -`dD` - Delete the contents of line except the newline character (that is, make it blank) and *do not* change clipboard - -`x` - Delete the character under cursor and *do not* change clipboard - -`s` - Delete the character under cursor then enter insert mode and *do not* change clipboard - -`S` - Delete the line under cursor then enter insert mode and *do not* change clipboard - -`c` - Enter insert mode over top the given area and *do not* change clipboard - -`cc` - Enter insert mode over top the current line and *do not* change clipboard - -`C` - Enter insert mode from cursor to the end of the line and *do not* change clipboard - -`p` - Paste from specified register. Inserts after current line if text is multiline, after current character if text is non-multiline. Leaves cursor at end of pasted text. - -`P` - Same as p except inserts text before current line/character - -`p` - Same as `p` except does not auto-format text. This is only relevant if the auto-format option is enabled - -`P` - Same as `P` except does not auto-format text. This is only relevant if the auto-format option is enabled - -`gp` - Same as p but preserves the current cursor position - -`gP` - Same as P but preserves the current cursor position - -`gP` - Same as `P` but preserves the current cursor position - -`gp` - Same as `p` but preserves the current cursor position - -`m` - Delete over the given motion and copy text to clipboard - -`mm` - Delete the current line and copy text to clipboard - -`` - Rotate the previous paste forward in yank buffer. Note that this binding will only work if executed immediately after a paste - -`` - Rotate the previous paste backward in yank buffer. Note that this binding will only work if executed immediately after a paste - -`[y` - Go backward in the yank buffer. This can be executed at any time to modify order of yanks in the yank buffer (though I would recommend just using `` instead) - -`]y` - Go forward in the yank buffer. This can be executed at any time to modify order of yanks in the yank buffer (though I would recommend just using `` instead) - -`Y` - Copy text from cursor position to the end of line to the clipboard - -**When the option `g:EasyClipUseSubstituteDefaults` is enabled, the following mappings are added:** - -`s` - Substitute over the given motion with specified register (or default register if unspecified). Note that this only applies if the `g:EasyClipUseSubstituteDefaults` option is set. - -`ss` - Substitute over the current line with specified register (or default register if unspecified). Note that this only applies if the `g:EasyClipUseSubstituteDefaults` option is set. - -`gs` - Same as s but preserves the current cursor position. - -### Custom Yanks ### - -If you have custom yanks that occur in your vimrc or elsewhere and would like them to be included in the yank history, you can either call EasyClip#Yank() to record the string or call the command `EasyClipBeforeYank` before the yank occurs. For example, to yank the current file name you could do either of the following: - -`nnoremap yfn :EasyClipBeforeYank:let @*=expand('%')` - -`nnoremap yfn :call EasyClip#Yank(expand('%'))` - -### Feedback ### - -Feel free to email all feedback/criticism/suggestions to sfvermeulen@gmail.com. Or, feel free to create a github issue. - -### Todo ### - -- `:Yanks` command should maybe open up the list of yanks in a scratch buffer so that it is searchable - -### Changelog ### - -2.1 (2013-12-06) - - Bug fixes - - Disabled substitution operator by default - - Added numbered registers - -2.0 (2013-09-22) - - Many bug fixes - - Yankring/Yankstack style post-paste swap - - RSPEC unit tests added for stability - -1.2 (2013-09-22) - - More bug fixes - -1.1 (2013-09-03) - - Bunch of bug fixes - -1.0 (2013-07-08) - - Initial release - -### License ### - -Distributed under the same terms as Vim itself. See the vim license. - +vim-easyclip +============= +### Simplified clipboard functionality for Vim.### + +Author: [Steve Vermeulen] (https://github.com/svermeulen), based on work by [Max Brunsfeld] (http://www.github.com/maxbrunsfeld) + +A good starting point for the motivation behind this Vim plugin can be found in Drew Neil's post [Registers: The Good, the Bad, and the Ugly Parts](http://vimcasts.org/blog/2013/11/25/registers-the-good-the-bad-and-the-ugly-parts) + +### Installation ### + +I recommend loading your plugins with [neobundle](https://github.com/Shougo/neobundle.vim) or [vundle](https://github.com/gmarik/vundle) or [pathogen](https://github.com/tpope/vim-pathogen) + +This plugin also requires that you have Tim Pope's [repeat.vim](https://github.com/tpope/vim-repeat) plugin installed. + +### Black Hole Redirection ### + +By default, Vim's built-in delete operator will yank the deleted text in addition to just deleting it. This works great when you want to cut text and paste it somewhere else, but in many other cases it can make things more difficult. For example, if you want to make some tiny edit to fix formatting after cutting some text, you either have to have had the foresight to use a named register, or specify the black hole register explicitly to do your formatting. This plugin solves that problem by redirecting all change and delete operations to the black hole register and introducing a new operator, 'cut' (by default this is mapped to the `m` key for 'move'). + +There is simply no need to clutter up the yank history with every single edit, when you almost always know at the time you are deleting text whether it's something that is worth keeping around or not. + +**NOTE** As a result of the above, by default easyclip will shadow an import vim function: The Add Mark key (`m`). Therefore either you will want to use a different key for the 'cut' operator (see options section below for this) or remap something else to 'add mark'. For example, to use `gm` for 'add mark' instead of `m`, include the following in your vimrc: + + nnoremap gm m + +### Substitution Operator ### + +Because replacing text is such a common operation, EasyClip includes a motion for it. It is essentially equivalent to doing a change operation then pasting using the specified register. For example, assuming you have mapped this motion to the `s` key, to paste over the word under the cursor you would type `siw`, or to paste inside brackets, `si(`, etc. + +It can also take a register to use for the substitution (eg. `"asip`), and is fully repeatable using the `.` key. + +**NOTE** This feature is off by default. To use, you have to either enable the option `g:EasyClipUseSubstituteDefaults` (in which case it will be mapped to the `s` key) or map the key/keys of your choice to the `` mappings found in substitute.vim. + +### Yank Buffer ### + +EasyClip allows you to yank and cut things without worrying about losing text that you copied previously. It achieves this by storing all yanks into a buffer, which you can cycle through forward or backwards to choose the yank that you want + +This works very similar to the way [YankRing](https://github.com/vim-scripts/YankRing.vim) and [YankStack](https://github.com/maxbrunsfeld/vim-yankstack) work, in that you can use a key binding to toggle between different yanks immediately after triggering a paste or substitute. (Most of the functionality is actually taken and adapted from Yankstack, with changes to make it work with substitute) + +By default, the keys to toggle the paste are mapped to `` and `` (similar to yankring). For example, executing `p` will paste, then toggle it to the most recent yank before that. You can continue toggling forwards/backwards in the yank history to replace the most recent paste as much as you want. Note that the toggle action will of course not be included in the undo history. That is, pressing undo after any number of swaps will undo the paste and not each swap. + +This method of toggling the chosen yank after paste will probably be your primary method of digging back into the yank buffer. Note that in this case the yank buffer is unchanged. What this means for example is that you can toggle a given paste back using `` 10 times, then if you perform a new paste in a different location it will still use the most recent yank (and not the final yank you arrived at after 10 swaps). + +Alternatively, you can execute (by default) keys `[y` or `]y` to navigate the yank buffer 'head' forwards or backwards. In this case the change will be permanent. That is, pressing `[y[yp` will paste the third most recent yank. Subsequent pastes will use the same yank, until you go forwards again using `]y`. + +You can view the full list of yanks at any time by running the command `:Yanks` + +Note that you can swap substitution operations in the same way as paste. + +Every time the yank buffer changes, it also populates all the numbered registers. `"1` is therefore the previous yank, `"2` is the yank before that, etc. This is similar to how the numbered registers work by default (but a bit more sane). (Credit to Drew Neil for the suggestion) + +Also, see `g:EasyClipPreserveCursorPositionAfterYank` option below for an optional non standard customization to yank + +### Paste ### + +By default EasyClip preserves the default vim paste behaviour, which is the following: + +* `p` (lowercase) pastes text after the current line if the pasted text is multiline (or after the current character if non-multiline) +* `P` (uppercase) behaves the same except acts before the current line (or before the current character if non-multiline) + +When the text is multi-line, the cursor is placed at the start of the new text. When the paste is non-multiline, the cursor is placed at the end. + +Alternatively, you can enable the option `g:EasyClipAlwaysMoveCursorToEndOfPaste` to have the cursor positioned at the end in both cases (off by default). Note that when this option is enabled, the beginning of the multi-line text is added to the jumplist, so you can still return to the start of the paste by pressing `` (and this applies to multi-line substitutions as well) + +Another non-standard option is `g:EasyClipAutoFormat` (off by default), which will automatically format text immediately after it is pasted. This can be useful when pasting text from one indent level to another. + +Easy Clip also includes a mapping for insert mode paste, which automatically turns on 'paste' mode for the duration of the paste. Using 'paste' mode will work much more intuitively when pasting text with multiple lines while in insert mode. You can enable this by including something similar to the following in your .vimrc: + + imap EasyClipInsertModePaste + +### System Clipboard Sync ### + +EasyClip will also automatically sync with your system clipboard. + +Every time you leave and return to vim, easy clip will check whether you copied anything from outside Vim and add it to the yank history. + +### Options ### + +EasyClip can be easily customized to whatever mapping you wish, using the following options: + +`g:EasyClipAutoFormat` - Default: 0. Set this to 1 to enable auto-formatting pasting text + +`g:EasyClipYankHistorySize` - Default: 50. Change this to limit yank history + +`g:EasyClipAlwaysMoveCursorToEndOfPaste` - Default: 0. Set this to 1 to always position cursor at the end of the pasted text for both multi-line and non-multiline pastes. + +`g:EasyClipDoSystemSync` - Default: 1. Set this to zero to disable system clipboard sync. + +`g:EasyClipPreserveCursorPositionAfterYank` - Default 0 (ie. disabled). Vim's default behaviour is to position the cursor at the beginning of the yanked text, which is consistent with other motions. However if you prefer the cursor position to remain unchanged when performing yanks, enable this option. + +You can also disable the default mappings by setting one or more of the following to zero. By default they are set to 1 (ie. enabled) + + `g:EasyClipUseYankDefaults` + + `g:EasyClipUseCutDefaults` + + `g:EasyClipUsePasteDefaults` + + `g:EasyClipEnableBlackHoleRedirect` + + `g:EasyClipUsePasteToggleDefaults` + +One exception to the above is substitute, which is 0 by default (ie. disabled) + + `g:EasyClipUseSubstituteDefaults` + +To change from the default mappings, you can disable one of the options above and then map to the specific `` mappings of your choice. For example, to change the mapping for cut (by default set to `m`) to `x`, include the following in your vimrc:` + + let g:EasyClipUseCutDefaults = 0 + + nmap x MoveMotionPlug + xmap x MoveMotionXPlug + nmap xx MoveMotionLinePlug + +Or to change the bindings for toggling paste from `` and `` to `` and `` include the following: + + let g:EasyClipUsePasteToggleDefaults = 0 + + nmap EasyClipSwapPasteForward + nmap EasyClipSwapPasteBackwards + +Or to use `gs` for substitute include the following: (in this case you don't need to turn off the default since the default is already disabled) + + nmap gs SubstituteOverMotionMap + nmap gss SubstituteLine + xmap gs XEasyClipPaste + +For reference, or other kinds of mappings, see the Plugs section of the file with the name of the operation you wish to remap (vim-easy-clip/autoload/substitute.vim / move.vim / yank.vim /etc.) + +Note that EasyClip will only enable a default mapping if it hasn't already been mapped to something in your .vimrc. + +### Default Key Mappings ### + +`d` - Delete over the given motion and *do not* change clipboard + +`dd` - Delete the line and *do not* change clipboard + +`D` - Delete from cursor to the end of the line and *do not* change clipboard + +`dD` - Delete the contents of line except the newline character (that is, make it blank) and *do not* change clipboard + +`x` - Delete the character under cursor and *do not* change clipboard + +`s` - Delete the character under cursor then enter insert mode and *do not* change clipboard + +`S` - Delete the line under cursor then enter insert mode and *do not* change clipboard + +`c` - Enter insert mode over top the given area and *do not* change clipboard + +`cc` - Enter insert mode over top the current line and *do not* change clipboard + +`C` - Enter insert mode from cursor to the end of the line and *do not* change clipboard + +`p` - Paste from specified register. Inserts after current line if text is multiline, after current character if text is non-multiline. Leaves cursor at end of pasted text. + +`P` - Same as p except inserts text before current line/character + +`p` - Same as `p` except does not auto-format text. This is only relevant if the auto-format option is enabled + +`P` - Same as `P` except does not auto-format text. This is only relevant if the auto-format option is enabled + +`gp` - Same as p but preserves the current cursor position + +`gP` - Same as P but preserves the current cursor position + +`gP` - Same as `P` but preserves the current cursor position + +`gp` - Same as `p` but preserves the current cursor position + +`m` - Delete over the given motion and copy text to clipboard + +`mm` - Delete the current line and copy text to clipboard + +`` - Rotate the previous paste forward in yank buffer. Note that this binding will only work if executed immediately after a paste + +`` - Rotate the previous paste backward in yank buffer. Note that this binding will only work if executed immediately after a paste + +`[y` - Go backward in the yank buffer. This can be executed at any time to modify order of yanks in the yank buffer (though I would recommend just using `` instead) + +`]y` - Go forward in the yank buffer. This can be executed at any time to modify order of yanks in the yank buffer (though I would recommend just using `` instead) + +`Y` - Copy text from cursor position to the end of line to the clipboard + +**When the option `g:EasyClipUseSubstituteDefaults` is enabled, the following mappings are added:** + +`s` - Substitute over the given motion with specified register (or default register if unspecified). Note that this only applies if the `g:EasyClipUseSubstituteDefaults` option is set. + +`ss` - Substitute over the current line with specified register (or default register if unspecified). Note that this only applies if the `g:EasyClipUseSubstituteDefaults` option is set. + +`gs` - Same as s but preserves the current cursor position. + +### Custom Yanks ### + +If you have custom yanks that occur in your vimrc or elsewhere and would like them to be included in the yank history, you can either call EasyClip#Yank() to record the string or call the command `EasyClipBeforeYank` before the yank occurs. For example, to yank the current file name you could do either of the following: + +`nnoremap yfn :EasyClipBeforeYank:let @*=expand('%')` + +`nnoremap yfn :call EasyClip#Yank(expand('%'))` + +### Feedback ### + +Feel free to email all feedback/criticism/suggestions to sfvermeulen@gmail.com. Or, feel free to create a github issue. + +### Todo ### + +- `:Yanks` command should maybe open up the list of yanks in a scratch buffer so that it is searchable + +### Changelog ### + +2.1 (2013-12-06) + - Bug fixes + - Disabled substitution operator by default + - Added numbered registers + +2.0 (2013-09-22) + - Many bug fixes + - Yankring/Yankstack style post-paste swap + - RSPEC unit tests added for stability + +1.2 (2013-09-22) + - More bug fixes + +1.1 (2013-09-03) + - Bunch of bug fixes + +1.0 (2013-07-08) + - Initial release + +### License ### + +Distributed under the same terms as Vim itself. See the vim license. + diff --git a/autoload/EasyClip.vim b/autoload/EasyClip.vim index 8061114..697df2b 100644 --- a/autoload/EasyClip.vim +++ b/autoload/EasyClip.vim @@ -1,74 +1,74 @@ - -""""""""""""""""""""""" -" Global Options -""""""""""""""""""""""" -let g:EasyClipYankHistorySize = get(g:, 'EasyClipYankHistorySize', 50) -let g:EasyClipAutoFormat = get(g:, 'EasyClipAutoFormat', 0) -let g:EasyClipEnableBlackHoleRedirect = get(g:, 'EasyClipEnableBlackHoleRedirect', 1) -let g:EasyClipUseCutDefaults = get(g:, 'EasyClipUseCutDefaults', 1) -let g:EasyClipUseSubstituteDefaults = get(g:, 'EasyClipUseSubstituteDefaults', 0) -let g:EasyClipUsePasteToggleDefaults = get(g:, 'EasyClipUsePasteToggleDefaults', 1) -let g:EasyClipUsePasteDefaults = get(g:, 'EasyClipUsePasteDefaults', 1) -let g:EasyClipAlwaysMoveCursorToEndOfPaste = get(g:, 'EasyClipAlwaysMoveCursorToEndOfPaste', 0) -let g:EasyClipUseYankDefaults = get(g:, 'EasyClipUseYankDefaults', 1) -let g:EasyClipDoSystemSync = get(g:, 'EasyClipDoSystemSync', 1) -let g:EasyClipPreserveCursorPositionAfterYank = get(g:, 'EasyClipPreserveCursorPositionAfterYank', 0) - -let g:EasyClipEnableBlackHoleRedirectForChangeOperator = get(g:, 'EasyClipEnableBlackHoleRedirectForChangeOperator', 1) -let g:EasyClipEnableBlackHoleRedirectForDeleteOperator = get(g:, 'EasyClipEnableBlackHoleRedirectForDeleteOperator', 1) -let g:EasyClipEnableBlackHoleRedirectForSelectOperator = get(g:, 'EasyClipEnableBlackHoleRedirectForSelectOperator', 1) - -""""""""""""""""""""""" -" Functions -""""""""""""""""""""""" -function! EasyClip#GetDefaultReg() - let clipboard_flags = split(&clipboard, ',') - if index(clipboard_flags, 'unnamedplus') >= 0 - return "+" - elseif index(clipboard_flags, 'unnamed') >= 0 - return "*" - else - return "\"" - endif -endfunction - -" Only add the given mapping if it doesn't already exist -function! EasyClip#AddWeakMapping(left, right, modes, ...) - - let recursive = a:0 > 0 ? a:1 : 0 - - for mode in split(a:modes, '\zs') - if !EasyClip#HasMapping(a:left, mode) - exec mode . (recursive ? "map" : "noremap") . " " . a:left . " " . a:right - endif - endfor -endfunction - -function! EasyClip#HasMapping(mapping, mode) - return maparg(a:mapping, a:mode) != '' -endfunction - -function! EasyClip#GetCurrentYank() - return getreg(EasyClip#GetDefaultReg()) -endfunction - -function! EasyClip#SetCurrentYank(yank) - call setreg(EasyClip#GetDefaultReg(), a:yank) -endfunction - -function! EasyClip#Yank(str) - EasyClipBeforeYank - exec "let @". EasyClip#GetDefaultReg() . "='". a:str . "'" -endfunction - -function! EasyClip#Init() - - call EasyClip#Paste#Init() - call EasyClip#Move#Init() - call EasyClip#Substitute#Init() - call EasyClip#Yank#Init() - - " Add black hole bindings last so that it only - " adds bindings if they are not taken - call EasyClip#BlackHole#Init() -endfunction + +""""""""""""""""""""""" +" Global Options +""""""""""""""""""""""" +let g:EasyClipYankHistorySize = get(g:, 'EasyClipYankHistorySize', 50) +let g:EasyClipAutoFormat = get(g:, 'EasyClipAutoFormat', 0) +let g:EasyClipEnableBlackHoleRedirect = get(g:, 'EasyClipEnableBlackHoleRedirect', 1) +let g:EasyClipUseCutDefaults = get(g:, 'EasyClipUseCutDefaults', 1) +let g:EasyClipUseSubstituteDefaults = get(g:, 'EasyClipUseSubstituteDefaults', 0) +let g:EasyClipUsePasteToggleDefaults = get(g:, 'EasyClipUsePasteToggleDefaults', 1) +let g:EasyClipUsePasteDefaults = get(g:, 'EasyClipUsePasteDefaults', 1) +let g:EasyClipAlwaysMoveCursorToEndOfPaste = get(g:, 'EasyClipAlwaysMoveCursorToEndOfPaste', 0) +let g:EasyClipUseYankDefaults = get(g:, 'EasyClipUseYankDefaults', 1) +let g:EasyClipDoSystemSync = get(g:, 'EasyClipDoSystemSync', 1) +let g:EasyClipPreserveCursorPositionAfterYank = get(g:, 'EasyClipPreserveCursorPositionAfterYank', 0) + +let g:EasyClipEnableBlackHoleRedirectForChangeOperator = get(g:, 'EasyClipEnableBlackHoleRedirectForChangeOperator', 1) +let g:EasyClipEnableBlackHoleRedirectForDeleteOperator = get(g:, 'EasyClipEnableBlackHoleRedirectForDeleteOperator', 1) +let g:EasyClipEnableBlackHoleRedirectForSelectOperator = get(g:, 'EasyClipEnableBlackHoleRedirectForSelectOperator', 1) + +""""""""""""""""""""""" +" Functions +""""""""""""""""""""""" +function! EasyClip#GetDefaultReg() + let clipboard_flags = split(&clipboard, ',') + if index(clipboard_flags, 'unnamedplus') >= 0 + return "+" + elseif index(clipboard_flags, 'unnamed') >= 0 + return "*" + else + return "\"" + endif +endfunction + +" Only add the given mapping if it doesn't already exist +function! EasyClip#AddWeakMapping(left, right, modes, ...) + + let recursive = a:0 > 0 ? a:1 : 0 + + for mode in split(a:modes, '\zs') + if !EasyClip#HasMapping(a:left, mode) + exec mode . (recursive ? "map" : "noremap") . " " . a:left . " " . a:right + endif + endfor +endfunction + +function! EasyClip#HasMapping(mapping, mode) + return maparg(a:mapping, a:mode) != '' +endfunction + +function! EasyClip#GetCurrentYank() + return getreg(EasyClip#GetDefaultReg()) +endfunction + +function! EasyClip#SetCurrentYank(yank) + call setreg(EasyClip#GetDefaultReg(), a:yank) +endfunction + +function! EasyClip#Yank(str) + EasyClipBeforeYank + exec "let @". EasyClip#GetDefaultReg() . "='". a:str . "'" +endfunction + +function! EasyClip#Init() + + call EasyClip#Paste#Init() + call EasyClip#Move#Init() + call EasyClip#Substitute#Init() + call EasyClip#Yank#Init() + + " Add black hole bindings last so that it only + " adds bindings if they are not taken + call EasyClip#BlackHole#Init() +endfunction diff --git a/autoload/EasyClip/BlackHole.vim b/autoload/EasyClip/BlackHole.vim index 3322cb9..8b4986d 100644 --- a/autoload/EasyClip/BlackHole.vim +++ b/autoload/EasyClip/BlackHole.vim @@ -1,70 +1,70 @@ - -function! EasyClip#BlackHole#AddSelectBindings() - - let i = 33 - - " Add a map for every printable character to copy to black hole register - " I see no easier way to do this - while i <= 126 - if i !=# 124 - let char = nr2char(i) - exec 'snoremap '. char .' "_c'. char - endif - - let i = i + 1 - endwhile - - snoremap "_c - snoremap "_c - snoremap \| "_c| -endfunction - -function! EasyClip#BlackHole#AddDeleteBindings() - - let bindings = - \ [ - \ ['d', '"_d', 'nx'], - \ ['dd', '"_dd', 'n'], - \ ['dD', '0"_d$', 'n'], - \ ['D', '"_D', 'nx'], - \ ['x', '"_x', 'nx'], - \ ] - - for binding in bindings - call call("EasyClip#AddWeakMapping", binding) - endfor -endfunction - -function! EasyClip#BlackHole#AddChangeBindings() - - let bindings = - \ [ - \ ['c', '"_c', 'nx'], - \ ['cc', '"_S', 'n'], - \ ['C', '"_C', 'nx'], - \ ['s', '"_s', 'nx'], - \ ['S', '"_S', 'nx'], - \ ] - - for binding in bindings - call call("EasyClip#AddWeakMapping", binding) - endfor -endfunction - -function! EasyClip#BlackHole#Init() - - if g:EasyClipEnableBlackHoleRedirect - - if g:EasyClipEnableBlackHoleRedirectForChangeOperator - call EasyClip#BlackHole#AddChangeBindings() - endif - - if g:EasyClipEnableBlackHoleRedirectForDeleteOperator - call EasyClip#BlackHole#AddDeleteBindings() - endif - - if g:EasyClipEnableBlackHoleRedirectForSelectOperator - call EasyClip#BlackHole#AddSelectBindings() - endif - endif -endfunction + +function! EasyClip#BlackHole#AddSelectBindings() + + let i = 33 + + " Add a map for every printable character to copy to black hole register + " I see no easier way to do this + while i <= 126 + if i !=# 124 + let char = nr2char(i) + exec 'snoremap '. char .' "_c'. char + endif + + let i = i + 1 + endwhile + + snoremap "_c + snoremap "_c + snoremap \| "_c| +endfunction + +function! EasyClip#BlackHole#AddDeleteBindings() + + let bindings = + \ [ + \ ['d', '"_d', 'nx'], + \ ['dd', '"_dd', 'n'], + \ ['dD', '0"_d$', 'n'], + \ ['D', '"_D', 'nx'], + \ ['x', '"_x', 'nx'], + \ ] + + for binding in bindings + call call("EasyClip#AddWeakMapping", binding) + endfor +endfunction + +function! EasyClip#BlackHole#AddChangeBindings() + + let bindings = + \ [ + \ ['c', '"_c', 'nx'], + \ ['cc', '"_S', 'n'], + \ ['C', '"_C', 'nx'], + \ ['s', '"_s', 'nx'], + \ ['S', '"_S', 'nx'], + \ ] + + for binding in bindings + call call("EasyClip#AddWeakMapping", binding) + endfor +endfunction + +function! EasyClip#BlackHole#Init() + + if g:EasyClipEnableBlackHoleRedirect + + if g:EasyClipEnableBlackHoleRedirectForChangeOperator + call EasyClip#BlackHole#AddChangeBindings() + endif + + if g:EasyClipEnableBlackHoleRedirectForDeleteOperator + call EasyClip#BlackHole#AddDeleteBindings() + endif + + if g:EasyClipEnableBlackHoleRedirectForSelectOperator + call EasyClip#BlackHole#AddSelectBindings() + endif + endif +endfunction diff --git a/autoload/EasyClip/Move.vim b/autoload/EasyClip/Move.vim index 3f32ddc..8b694d0 100644 --- a/autoload/EasyClip/Move.vim +++ b/autoload/EasyClip/Move.vim @@ -1,81 +1,81 @@ - -""""""""""""""""""""""" -" Variables -""""""""""""""""""""""" -let s:activeRegister = EasyClip#GetDefaultReg() - -""""""""""""""""""""""" -" Plugs -""""""""""""""""""""""" -nnoremap MoveMotionEndOfLinePlug :EasyClipBeforeYanky$"_d$:call repeat#set("\MoveMotionEndOfLinePlug") -nnoremap MoveMotionReplaceLinePlug :EasyClipBeforeYank0y$"_d$:call repeat#set("\MoveMotionReplaceLinePlug") -nnoremap MoveMotionLinePlug ':EasyClipBeforeYank'. v:count .'yy'. v:count . '"_dd:call repeat#set("\MoveMotionLinePlug")' -xnoremap MoveMotionXPlug :call VisualModeMoveMotion(v:register) -nnoremap MoveMotionPlug ":call EasyClip#Move#PreMoveMotion():set opfunc=EasyClip#Move#MoveMotion" . (v:count > 0 ? v:count : 1) . "g@" - -""""""""""""""""""""""" -" Functions -""""""""""""""""""""""" -function! s:VisualModeMoveMotion(reg) - - if a:reg == EasyClip#GetDefaultReg() - EasyClipBeforeYank - normal! gvy - normal! gv"_d - else - " If register is specified explicitly then do not change default register - " or add to yank history - exec "normal! gv\"" . a:reg . "y" - normal! gv"_d - endif -endfunction - -function! EasyClip#Move#PreMoveMotion( ) - let s:activeRegister = v:register - - " This is necessary to get around a bug in vim where the active register persists to - " the next command. Repro by doing "_d and then a command that uses v:register - if s:activeRegister ==# "_" - let s:activeRegister = EasyClip#GetDefaultReg( ) - endif -endfunction - -function! EasyClip#Move#MoveMotion(type) - - let oldVisualStart = getpos("'<") - let oldVisualEnd = getpos("'>") - - call EasyClip#Yank#_YankLastChangedText(a:type, s:activeRegister) - - exec "normal! gv" - exec "normal! \"_d" - - call setpos("'<", oldVisualStart) - call setpos("'>", oldVisualEnd) - -endfunction - -function! EasyClip#Move#SetDefaultBindings() - - let bindings = - \ [ - \ ['m', 'MoveMotionPlug', 'n', 1], - \ ['mm', 'MoveMotionLinePlug', 'n', 1], - \ ['m', 'MoveMotionXPlug', 'x', 1], - \ ] - - " Leave these commented to avoid shadowing M (go to middle of screen) - "\ ['M', 'MoveMotionEndOfLinePlug', 'n', 1], - "\ ['mM', 'MoveMotionReplaceLinePlug', 'n', 1], - - for binding in bindings - call call("EasyClip#AddWeakMapping", binding) - endfor -endfunction - -function! EasyClip#Move#Init() - - if g:EasyClipUseCutDefaults - call EasyClip#Move#SetDefaultBindings() - endif -endfunction + +""""""""""""""""""""""" +" Variables +""""""""""""""""""""""" +let s:activeRegister = EasyClip#GetDefaultReg() + +""""""""""""""""""""""" +" Plugs +""""""""""""""""""""""" +nnoremap MoveMotionEndOfLinePlug :EasyClipBeforeYanky$"_d$:call repeat#set("\MoveMotionEndOfLinePlug") +nnoremap MoveMotionReplaceLinePlug :EasyClipBeforeYank0y$"_d$:call repeat#set("\MoveMotionReplaceLinePlug") +nnoremap MoveMotionLinePlug ':EasyClipBeforeYank'. v:count .'yy'. v:count . '"_dd:call repeat#set("\MoveMotionLinePlug")' +xnoremap MoveMotionXPlug :call VisualModeMoveMotion(v:register) +nnoremap MoveMotionPlug ":call EasyClip#Move#PreMoveMotion():set opfunc=EasyClip#Move#MoveMotion" . (v:count > 0 ? v:count : 1) . "g@" + +""""""""""""""""""""""" +" Functions +""""""""""""""""""""""" +function! s:VisualModeMoveMotion(reg) + + if a:reg == EasyClip#GetDefaultReg() + EasyClipBeforeYank + normal! gvy + normal! gv"_d + else + " If register is specified explicitly then do not change default register + " or add to yank history + exec "normal! gv\"" . a:reg . "y" + normal! gv"_d + endif +endfunction + +function! EasyClip#Move#PreMoveMotion( ) + let s:activeRegister = v:register + + " This is necessary to get around a bug in vim where the active register persists to + " the next command. Repro by doing "_d and then a command that uses v:register + if s:activeRegister ==# "_" + let s:activeRegister = EasyClip#GetDefaultReg( ) + endif +endfunction + +function! EasyClip#Move#MoveMotion(type) + + let oldVisualStart = getpos("'<") + let oldVisualEnd = getpos("'>") + + call EasyClip#Yank#_YankLastChangedText(a:type, s:activeRegister) + + exec "normal! gv" + exec "normal! \"_d" + + call setpos("'<", oldVisualStart) + call setpos("'>", oldVisualEnd) + +endfunction + +function! EasyClip#Move#SetDefaultBindings() + + let bindings = + \ [ + \ ['m', 'MoveMotionPlug', 'n', 1], + \ ['mm', 'MoveMotionLinePlug', 'n', 1], + \ ['m', 'MoveMotionXPlug', 'x', 1], + \ ] + + " Leave these commented to avoid shadowing M (go to middle of screen) + "\ ['M', 'MoveMotionEndOfLinePlug', 'n', 1], + "\ ['mM', 'MoveMotionReplaceLinePlug', 'n', 1], + + for binding in bindings + call call("EasyClip#AddWeakMapping", binding) + endfor +endfunction + +function! EasyClip#Move#Init() + + if g:EasyClipUseCutDefaults + call EasyClip#Move#SetDefaultBindings() + endif +endfunction diff --git a/autoload/EasyClip/Paste.vim b/autoload/EasyClip/Paste.vim index 0094de2..62e7c3e 100644 --- a/autoload/EasyClip/Paste.vim +++ b/autoload/EasyClip/Paste.vim @@ -1,290 +1,290 @@ -""""""""""""""""""""""" -" Variables -""""""""""""""""""""""" -let s:pasteOverrideRegister = '' -let s:lastPasteRegister ='' -let s:lastPasteChangedtick = -1 -let s:offsetSum = 0 -let s:isSwapping = 0 -let s:IgnoreAutoFormat = 0 - -""""""""""""""""""""""" -" Plugs -""""""""""""""""""""""" - -set pastetoggle=PasteToggle - -" Always toggle to 'paste mode' before pasting in insert mode -imap EasyClipInsertModePaste 'PasteToggle' . EasyClip#GetDefaultReg() . 'PasteToggle' - -cnoremap EasyClipCommandModePaste '' . EasyClip#GetDefaultReg() - -nnoremap EasyClipSwapPasteForward :call EasyClip#Paste#SwapPaste(1) -nnoremap EasyClipSwapPasteBackwards :call EasyClip#Paste#SwapPaste(0) - -nnoremap EasyClipPasteAfter :call EasyClip#Paste#PasteText(v:register, v:count, 'p', 1, "EasyClipPasteAfter") -nnoremap EasyClipPasteBefore :call EasyClip#Paste#PasteText(v:register, v:count, 'P', 1, "EasyClipPasteBefore") - -xnoremap XEasyClipPaste ':call EasyClip#Paste#PasteTextVisualMode(''' . v:register . ''',' . v:count . ')' - -nnoremap G_EasyClipPasteAfter :call EasyClip#Paste#PasteText(v:register, v:count, 'gp', 1, "G_EasyClipPasteAfter") -nnoremap G_EasyClipPasteBefore :call EasyClip#Paste#PasteText(v:register, v:count, 'gP', 1, "G_EasyClipPasteBefore") -xnoremap XG_EasyClipPaste "_d:call EasyClip#Paste#PasteText(v:register, v:count, 'gP', 1, "G_EasyClipPasteBefore") - -nnoremap EasyClipPasteUnformattedAfter :call EasyClip#Paste#PasteText(v:register, v:count, 'p', 0, "EasyClipPasteUnformattedAfter") -nnoremap EasyClipPasteUnformattedBefore :call EasyClip#Paste#PasteText(v:register, v:count, 'P', 0, "EasyClipPasteUnformattedBefore") - -nnoremap G_EasyClipPasteUnformattedAfter :call EasyClip#Paste#PasteText(v:register, v:count, 'gp', 0, "G_EasyClipPasteUnformattedAfter") -nnoremap G_EasyClipPasteUnformattedBefore :call EasyClip#Paste#PasteText(v:register, v:count, 'gP', 0, "G_EasyClipPasteUnformattedBefore") - -nnoremap XEasyClipPasteUnformatted "_d:call EasyClip#Paste#PasteText(v:register, v:count, 'P', 0, "EasyClipPasteUnformattedBefore") - -xnoremap XG_EasyClipPasteUnformatted "_d:call EasyClip#Paste#PasteText(v:register, v:count, 'gP', 0, "G_EasyClipPasteUnformattedBefore") - -nnoremap EasyClipToggleFormattedPaste :call EasyClip#Paste#ToggleFormattedPaste() - -""""""""""""""""""""""" -" Functions -""""""""""""""""""""""" - -" Adds the following functionality to paste: -" - add position of cursor before pasting to jumplist -" - optionally auto format, preserving the marks `[ and `] in the process -" - always position the cursor directly after the text for P and p versions -" - do not move the cursor for gp and gP versions -" -" op = either P or p -" format = 1 if we should autoformat -" inline = 1 if we should paste multiline text inline. -" That is, add the newline wherever the cursor is rather than above/below the current line -function! EasyClip#Paste#Paste(op, format, reg, inline) - - let reg = empty(s:pasteOverrideRegister) ? a:reg : s:pasteOverrideRegister - - let text = getreg(reg) - - if text ==# '' - " Necessary to avoid error - return - endif - - let s:lastPasteRegister = reg - let isMultiLine = (text =~# "\n") - let line = getline(".") - let isEmptyLine = (line =~# '^\s*$') - let oldPos = getpos('.') - - if a:inline - " Do not save to jumplist when pasting inline - exec "normal! ". (a:op ==# 'p' ? 'a' : 'i') . "\". reg . "\" - else - let hasMoreThanOneLine = (text =~# "\n.*\n") - " Save their old position to jumplist - " Except for gp since the cursor pos shouldn't change - " in that case - if hasMoreThanOneLine && g:EasyClipAlwaysMoveCursorToEndOfPaste - if a:op ==# 'P' - " just doing m` doesn't work in this case so do it one line above - exec "normal! km`j" - elseif a:op == 'p' - exec "normal! m`" - endif - endif - - exec "normal! \"".reg.a:op - endif - - if (isMultiLine || isEmptyLine) && a:format && g:EasyClipAutoFormat && get(b:, 'EasyClipAutoFormat', 1) && !s:IgnoreAutoFormat - " Only auto-format if it's multiline or pasting into an empty line - - keepjumps normal! `] - let startPos = getpos('.') - normal! ^ - let numFromStart = startPos[2] - col('.') - - " Suppress 'x lines indented' message - silent exec "keepjumps normal! `[=`]" - call setpos('.', startPos) - normal! ^ - - if numFromStart > 0 - " Preserve cursor position so that it is placed at the last pasted character - exec "normal! ". numFromStart . "l" - endif - - normal! m] - endif - - if a:op ==# 'gp' - call setpos('.', oldPos) - - elseif a:op ==# 'gP' - exec "keepjumps normal! `[" - - else - if isMultiLine - if g:EasyClipAlwaysMoveCursorToEndOfPaste - exec "keepjumps normal! `]" - else - exec "keepjumps normal! `[" - endif - - normal! ^ - else - exec "keepjumps normal! `]" - endif - endif - -endfunction - -function! s:EndSwapPaste() - - if !s:isSwapping - " Should never happen - throw "Unknown Error detected during EasyClip paste" - endif - - let s:isSwapping = 0 - - augroup SwapPasteMoveDetect - autocmd! - augroup END - - " Return yank positions to their original state before we started swapping - call EasyClip#Yank#Rotate(-s:offsetSum) -endfunction - -function! EasyClip#Paste#WasLastChangePaste() - return b:changedtick == s:lastPasteChangedtick || b:changedtick == g:lastSubChangedtick -endfunction - -function! EasyClip#Paste#PasteTextVisualMode(reg, count) - - normal! gv - - " If we're pasting a single line yank in visual block mode then repeat paste for each line - if mode() ==# '' && getreg(a:reg) !~# '\n' - exec "normal! \"_c\" . EasyClip#GetDefaultReg() - else - normal! "_d - call EasyClip#Paste#PasteText(a:reg, a:count, "P", 1, "EasyClipPasteBefore") - endif -endfunction - -function! EasyClip#Paste#PasteText(reg, count, op, format, plugName) - let reg = a:reg - - " This is necessary to get around a bug in vim where the active register persists to - " the next command. Repro by doing "_d and then a command that uses v:register - if reg == "_" - let reg = EasyClip#GetDefaultReg() - end - - let i = 0 - let cnt = a:count > 0 ? a:count : 1 - - while i < cnt - call EasyClip#Paste#Paste(a:op, a:format, reg, 0) - let i = i + 1 - endwhile - - let s:lastPasteChangedtick = b:changedtick - - if !empty(a:plugName) - let fullPlugName = "\". a:plugName - silent! call repeat#setreg(fullPlugName, reg) - silent! call repeat#set(fullPlugName, a:count) - endif -endfunction - -function! EasyClip#Paste#ToggleFormattedPaste() - - if !EasyClip#Paste#WasLastChangePaste() - echo 'Last action was not paste, toggle unformat command ignored' - return - endif - - let s:IgnoreAutoFormat = 1 - let s:pasteOverrideRegister = s:lastPasteRegister - exec "normal u." - let s:pasteOverrideRegister = '' - let s:IgnoreAutoFormat = 0 - -endfunction - -function! EasyClip#Paste#SwapPaste(forward) - if !EasyClip#Paste#WasLastChangePaste() - echo 'Last action was not paste, swap ignored' - return - endif - - if s:isSwapping - " Stop checking to end the swap session - augroup SwapPasteMoveDetect - autocmd! - augroup END - else - let s:isSwapping = 1 - let s:offsetSum = 0 - endif - - if s:lastPasteRegister == EasyClip#GetDefaultReg() - let offset = (a:forward ? 1 : -1) - - call EasyClip#Yank#Rotate(offset) - let s:offsetSum += offset - endif - - let s:pasteOverrideRegister = EasyClip#GetDefaultReg() - exec "normal u." - let s:pasteOverrideRegister = '' - - augroup SwapPasteMoveDetect - autocmd! - " Wait an extra CursorMoved event since there always seems to be one fired after this function ends - autocmd CursorMoved autocmd SwapPasteMoveDetect CursorMoved call EndSwapPaste() - augroup END -endfunction - -" Default Paste Behaviour is: -" p - paste after newline if multiline, paste after character if non-multiline -" P - paste before newline if multiline, paste before character if non-multiline -" gp - same as p but keep old cursor position -" gP - same as P but keep old cursor position -" - same as p but does not auto-format -" - same as P but does not auto-format -" g - same as c-p but keeps cursor position -" g - same as c-p but keeps cursor position -function! EasyClip#Paste#SetDefaultMappings() - - let bindings = - \ [ - \ ['p', 'XEasyClipPaste', 'x', 1], - \ ['P', 'XEasyClipPaste', 'x', 1], - \ ['gp', 'XG_EasyClipPaste', 'x', 1], - \ ['gP', 'XG_EasyClipPaste', 'x', 1], - \ ['p', 'XEasyClipPasteUnformatted', 'x', 1], - \ ['P', 'XEasyClipPasteUnformatted', 'x', 1], - \ ['P', 'EasyClipPasteBefore', 'n', 1], - \ ['p', 'EasyClipPasteAfter', 'n', 1], - \ ['gp', 'G_EasyClipPasteAfter', 'n', 1], - \ ['gP', 'G_EasyClipPasteBefore', 'n', 1], - \ ['p', 'EasyClipPasteUnformattedAfter', 'n', 1], - \ ['P', 'EasyClipPasteUnformattedBefore', 'n', 1], - \ ['gp', 'G_EasyClipPasteUnformattedAfter', 'n', 1], - \ ['gP', 'G_EasyClipPasteUnformattedBefore', 'n', 1], - \ ['', 'EasyClipSwapPasteForward', 'n', 1], - \ ['', 'EasyClipSwapPasteBackwards', 'n', 1], - \ ] - - for binding in bindings - call call("EasyClip#AddWeakMapping", binding) - endfor -endfunction - -function! EasyClip#Paste#Init() - - if g:EasyClipUsePasteDefaults - call EasyClip#Paste#SetDefaultMappings() - endif -endfunction +""""""""""""""""""""""" +" Variables +""""""""""""""""""""""" +let s:pasteOverrideRegister = '' +let s:lastPasteRegister ='' +let s:lastPasteChangedtick = -1 +let s:offsetSum = 0 +let s:isSwapping = 0 +let s:IgnoreAutoFormat = 0 + +""""""""""""""""""""""" +" Plugs +""""""""""""""""""""""" + +set pastetoggle=PasteToggle + +" Always toggle to 'paste mode' before pasting in insert mode +imap EasyClipInsertModePaste 'PasteToggle' . EasyClip#GetDefaultReg() . 'PasteToggle' + +cnoremap EasyClipCommandModePaste '' . EasyClip#GetDefaultReg() + +nnoremap EasyClipSwapPasteForward :call EasyClip#Paste#SwapPaste(1) +nnoremap EasyClipSwapPasteBackwards :call EasyClip#Paste#SwapPaste(0) + +nnoremap EasyClipPasteAfter :call EasyClip#Paste#PasteText(v:register, v:count, 'p', 1, "EasyClipPasteAfter") +nnoremap EasyClipPasteBefore :call EasyClip#Paste#PasteText(v:register, v:count, 'P', 1, "EasyClipPasteBefore") + +xnoremap XEasyClipPaste ':call EasyClip#Paste#PasteTextVisualMode(''' . v:register . ''',' . v:count . ')' + +nnoremap G_EasyClipPasteAfter :call EasyClip#Paste#PasteText(v:register, v:count, 'gp', 1, "G_EasyClipPasteAfter") +nnoremap G_EasyClipPasteBefore :call EasyClip#Paste#PasteText(v:register, v:count, 'gP', 1, "G_EasyClipPasteBefore") +xnoremap XG_EasyClipPaste "_d:call EasyClip#Paste#PasteText(v:register, v:count, 'gP', 1, "G_EasyClipPasteBefore") + +nnoremap EasyClipPasteUnformattedAfter :call EasyClip#Paste#PasteText(v:register, v:count, 'p', 0, "EasyClipPasteUnformattedAfter") +nnoremap EasyClipPasteUnformattedBefore :call EasyClip#Paste#PasteText(v:register, v:count, 'P', 0, "EasyClipPasteUnformattedBefore") + +nnoremap G_EasyClipPasteUnformattedAfter :call EasyClip#Paste#PasteText(v:register, v:count, 'gp', 0, "G_EasyClipPasteUnformattedAfter") +nnoremap G_EasyClipPasteUnformattedBefore :call EasyClip#Paste#PasteText(v:register, v:count, 'gP', 0, "G_EasyClipPasteUnformattedBefore") + +nnoremap XEasyClipPasteUnformatted "_d:call EasyClip#Paste#PasteText(v:register, v:count, 'P', 0, "EasyClipPasteUnformattedBefore") + +xnoremap XG_EasyClipPasteUnformatted "_d:call EasyClip#Paste#PasteText(v:register, v:count, 'gP', 0, "G_EasyClipPasteUnformattedBefore") + +nnoremap EasyClipToggleFormattedPaste :call EasyClip#Paste#ToggleFormattedPaste() + +""""""""""""""""""""""" +" Functions +""""""""""""""""""""""" + +" Adds the following functionality to paste: +" - add position of cursor before pasting to jumplist +" - optionally auto format, preserving the marks `[ and `] in the process +" - always position the cursor directly after the text for P and p versions +" - do not move the cursor for gp and gP versions +" +" op = either P or p +" format = 1 if we should autoformat +" inline = 1 if we should paste multiline text inline. +" That is, add the newline wherever the cursor is rather than above/below the current line +function! EasyClip#Paste#Paste(op, format, reg, inline) + + let reg = empty(s:pasteOverrideRegister) ? a:reg : s:pasteOverrideRegister + + let text = getreg(reg) + + if text ==# '' + " Necessary to avoid error + return + endif + + let s:lastPasteRegister = reg + let isMultiLine = (text =~# "\n") + let line = getline(".") + let isEmptyLine = (line =~# '^\s*$') + let oldPos = getpos('.') + + if a:inline + " Do not save to jumplist when pasting inline + exec "normal! ". (a:op ==# 'p' ? 'a' : 'i') . "\". reg . "\" + else + let hasMoreThanOneLine = (text =~# "\n.*\n") + " Save their old position to jumplist + " Except for gp since the cursor pos shouldn't change + " in that case + if hasMoreThanOneLine && g:EasyClipAlwaysMoveCursorToEndOfPaste + if a:op ==# 'P' + " just doing m` doesn't work in this case so do it one line above + exec "normal! km`j" + elseif a:op == 'p' + exec "normal! m`" + endif + endif + + exec "normal! \"".reg.a:op + endif + + if (isMultiLine || isEmptyLine) && a:format && g:EasyClipAutoFormat && get(b:, 'EasyClipAutoFormat', 1) && !s:IgnoreAutoFormat + " Only auto-format if it's multiline or pasting into an empty line + + keepjumps normal! `] + let startPos = getpos('.') + normal! ^ + let numFromStart = startPos[2] - col('.') + + " Suppress 'x lines indented' message + silent exec "keepjumps normal! `[=`]" + call setpos('.', startPos) + normal! ^ + + if numFromStart > 0 + " Preserve cursor position so that it is placed at the last pasted character + exec "normal! ". numFromStart . "l" + endif + + normal! m] + endif + + if a:op ==# 'gp' + call setpos('.', oldPos) + + elseif a:op ==# 'gP' + exec "keepjumps normal! `[" + + else + if isMultiLine + if g:EasyClipAlwaysMoveCursorToEndOfPaste + exec "keepjumps normal! `]" + else + exec "keepjumps normal! `[" + endif + + normal! ^ + else + exec "keepjumps normal! `]" + endif + endif + +endfunction + +function! s:EndSwapPaste() + + if !s:isSwapping + " Should never happen + throw "Unknown Error detected during EasyClip paste" + endif + + let s:isSwapping = 0 + + augroup SwapPasteMoveDetect + autocmd! + augroup END + + " Return yank positions to their original state before we started swapping + call EasyClip#Yank#Rotate(-s:offsetSum) +endfunction + +function! EasyClip#Paste#WasLastChangePaste() + return b:changedtick == s:lastPasteChangedtick || b:changedtick == g:lastSubChangedtick +endfunction + +function! EasyClip#Paste#PasteTextVisualMode(reg, count) + + normal! gv + + " If we're pasting a single line yank in visual block mode then repeat paste for each line + if mode() ==# '' && getreg(a:reg) !~# '\n' + exec "normal! \"_c\" . EasyClip#GetDefaultReg() + else + normal! "_d + call EasyClip#Paste#PasteText(a:reg, a:count, "P", 1, "EasyClipPasteBefore") + endif +endfunction + +function! EasyClip#Paste#PasteText(reg, count, op, format, plugName) + let reg = a:reg + + " This is necessary to get around a bug in vim where the active register persists to + " the next command. Repro by doing "_d and then a command that uses v:register + if reg == "_" + let reg = EasyClip#GetDefaultReg() + end + + let i = 0 + let cnt = a:count > 0 ? a:count : 1 + + while i < cnt + call EasyClip#Paste#Paste(a:op, a:format, reg, 0) + let i = i + 1 + endwhile + + let s:lastPasteChangedtick = b:changedtick + + if !empty(a:plugName) + let fullPlugName = "\". a:plugName + silent! call repeat#setreg(fullPlugName, reg) + silent! call repeat#set(fullPlugName, a:count) + endif +endfunction + +function! EasyClip#Paste#ToggleFormattedPaste() + + if !EasyClip#Paste#WasLastChangePaste() + echo 'Last action was not paste, toggle unformat command ignored' + return + endif + + let s:IgnoreAutoFormat = 1 + let s:pasteOverrideRegister = s:lastPasteRegister + exec "normal u." + let s:pasteOverrideRegister = '' + let s:IgnoreAutoFormat = 0 + +endfunction + +function! EasyClip#Paste#SwapPaste(forward) + if !EasyClip#Paste#WasLastChangePaste() + echo 'Last action was not paste, swap ignored' + return + endif + + if s:isSwapping + " Stop checking to end the swap session + augroup SwapPasteMoveDetect + autocmd! + augroup END + else + let s:isSwapping = 1 + let s:offsetSum = 0 + endif + + if s:lastPasteRegister == EasyClip#GetDefaultReg() + let offset = (a:forward ? 1 : -1) + + call EasyClip#Yank#Rotate(offset) + let s:offsetSum += offset + endif + + let s:pasteOverrideRegister = EasyClip#GetDefaultReg() + exec "normal u." + let s:pasteOverrideRegister = '' + + augroup SwapPasteMoveDetect + autocmd! + " Wait an extra CursorMoved event since there always seems to be one fired after this function ends + autocmd CursorMoved autocmd SwapPasteMoveDetect CursorMoved call EndSwapPaste() + augroup END +endfunction + +" Default Paste Behaviour is: +" p - paste after newline if multiline, paste after character if non-multiline +" P - paste before newline if multiline, paste before character if non-multiline +" gp - same as p but keep old cursor position +" gP - same as P but keep old cursor position +" - same as p but does not auto-format +" - same as P but does not auto-format +" g - same as c-p but keeps cursor position +" g - same as c-p but keeps cursor position +function! EasyClip#Paste#SetDefaultMappings() + + let bindings = + \ [ + \ ['p', 'XEasyClipPaste', 'x', 1], + \ ['P', 'XEasyClipPaste', 'x', 1], + \ ['gp', 'XG_EasyClipPaste', 'x', 1], + \ ['gP', 'XG_EasyClipPaste', 'x', 1], + \ ['p', 'XEasyClipPasteUnformatted', 'x', 1], + \ ['P', 'XEasyClipPasteUnformatted', 'x', 1], + \ ['P', 'EasyClipPasteBefore', 'n', 1], + \ ['p', 'EasyClipPasteAfter', 'n', 1], + \ ['gp', 'G_EasyClipPasteAfter', 'n', 1], + \ ['gP', 'G_EasyClipPasteBefore', 'n', 1], + \ ['p', 'EasyClipPasteUnformattedAfter', 'n', 1], + \ ['P', 'EasyClipPasteUnformattedBefore', 'n', 1], + \ ['gp', 'G_EasyClipPasteUnformattedAfter', 'n', 1], + \ ['gP', 'G_EasyClipPasteUnformattedBefore', 'n', 1], + \ ['', 'EasyClipSwapPasteForward', 'n', 1], + \ ['', 'EasyClipSwapPasteBackwards', 'n', 1], + \ ] + + for binding in bindings + call call("EasyClip#AddWeakMapping", binding) + endfor +endfunction + +function! EasyClip#Paste#Init() + + if g:EasyClipUsePasteDefaults + call EasyClip#Paste#SetDefaultMappings() + endif +endfunction diff --git a/autoload/EasyClip/Substitute.vim b/autoload/EasyClip/Substitute.vim index dffec10..a3c59e8 100644 --- a/autoload/EasyClip/Substitute.vim +++ b/autoload/EasyClip/Substitute.vim @@ -1,153 +1,153 @@ - -""""""""""""""""""""""" -" Variables -""""""""""""""""""""""" - -" This is made global because it's changed in paste.vim -let g:lastSubChangedtick = -1 - -let s:activeRegister = EasyClip#GetDefaultReg() -let s:moveCursor = 0 - -""""""""""""""""""""""" -" Plugs -""""""""""""""""""""""" -nnoremap SubstituteOverMotionMap :call EasyClip#Substitute#OnPreSubstitute(v:register, 1):set opfunc=EasyClip#Substitute#SubstituteMotiong@ -nnoremap G_SubstituteOverMotionMap :call EasyClip#Substitute#OnPreSubstitute(v:register, 0):set opfunc=EasyClip#Substitute#SubstituteMotiong@ - -nnoremap SubstituteToEndOfLine :call EasyClip#Substitute#SubstituteToEndOfLine(v:register, 1):call repeat#set("\SubstituteToEndOfLine") -nnoremap G_SubstituteToEndOfLine :call EasyClip#Substitute#SubstituteToEndOfLine(v:register, 0):call repeat#set("\G_SubstituteToEndOfLine") - -nnoremap SubstituteLine :call EasyClip#Substitute#SubstituteLine(v:register, v:count):call repeat#set("\SubstituteLine") - -""""""""""""""""""""""" -" Functions -""""""""""""""""""""""" -function! EasyClip#Substitute#OnPreSubstitute(register, moveCursor) - let s:activeRegister = a:register - - " This is necessary to get around a bug in vim where the active register persists to - " the next command. Repro by doing "_d and then a command that uses v:register - if a:register == "_" - let s:activeRegister = EasyClip#GetDefaultReg() - endif - - let s:moveCursor = a:moveCursor -endfunction - -function! EasyClip#Substitute#SubstituteMotion(type, ...) - - let startPos = getpos('.') - - if &selection ==# 'exclusive' - let excl_right = "\" - else - let excl_right = "" - endif - - let oldVirtualEdit=&virtualedit - set virtualedit=onemore - - " use keepjumps since we only want to change jumplist - " if it's multiline - if a:type ==# 'line' - exe "keepjump normal! '[V']".excl_right - elseif a:type ==# 'char' - exe "keepjump normal! `[v`]".excl_right - else - echom "Unexpected selection type" - exec "set virtualedit=". oldVirtualEdit - return - endif - - let reg = s:activeRegister - - if (getreg(reg) =~# "\n") - if s:moveCursor - " Record the start of the substitution to the jump list - exec "normal! m`" - endif - endif - - " Using "c" change doesn't work correctly for multiline, - " Adds an extra line at the end, so delete instead - exe "normal! \"_d" - - " Use our own version of paste so it autoformats and positions the cursor correctly - call EasyClip#Paste#Paste("P", 1, reg, 0) - exec "set virtualedit=". oldVirtualEdit - - let g:lastSubChangedtick = b:changedtick - - if !s:moveCursor - call setpos('.', startPos) - - " For some reason this is necessary otherwise doing gS and then hitting 'j' does not work as you'd expect (jumps to end of next line) - normal! hl - end -endfunction - -function! EasyClip#Substitute#SubstituteLine(reg, count) - - " Check for black hole register to get around a bug in vim where the active - " register persists to the next command - let reg = (a:reg == "_" ? EasyClip#GetDefaultReg() : a:reg) - - if getreg(reg) !~ '\n' - - exec "normal! 0\"_d$" - " Use our own version of paste so it autoformats and positions the cursor correctly - call EasyClip#Paste#Paste("P", 1, reg, 0) - else - let isLastLine = (line(".") == line("$")) - - let cnt = a:count > 0 ? a:count : 1 - exe "normal! ". cnt . "\"_dd" - - let i = 0 - while i < cnt - " Use our own version of paste so it autoformats and positions the cursor correctly - call EasyClip#Paste#Paste(isLastLine ? "p" : "P", 1, reg, 0) - - let i = i + 1 - endwhile - endif - - let g:lastSubChangedtick = b:changedtick -endfunction - -function! EasyClip#Substitute#SubstituteToEndOfLine(reg, moveCursor) - let startPos = getpos('.') - exec "normal! \"_d$" - - " Use our own version of paste so it autoformats and positions the cursor correctly - call EasyClip#Paste#Paste("p", 1, a:reg, 0) - - if !a:moveCursor - call setpos('.', startPos) - endif -endfunction - -function! EasyClip#Substitute#SetDefaultBindings() - - let bindings = - \ [ - \ ['s', 'SubstituteOverMotionMap', 'n', 1], - \ ['gs', 'G_SubstituteOverMotionMap', 'n', 1], - \ ['ss', 'SubstituteLine', 'n', 1], - \ ['s', 'XEasyClipPaste', 'x', 1], - \ ['S', 'SubstituteToEndOfLine', 'n', 1], - \ ['gS', 'G_SubstituteToEndOfLine', 'n', 1], - \ ] - - for binding in bindings - call call("EasyClip#AddWeakMapping", binding) - endfor -endfunction - -function! EasyClip#Substitute#Init() - - if g:EasyClipUseSubstituteDefaults - call EasyClip#Substitute#SetDefaultBindings() - endif -endfunction + +""""""""""""""""""""""" +" Variables +""""""""""""""""""""""" + +" This is made global because it's changed in paste.vim +let g:lastSubChangedtick = -1 + +let s:activeRegister = EasyClip#GetDefaultReg() +let s:moveCursor = 0 + +""""""""""""""""""""""" +" Plugs +""""""""""""""""""""""" +nnoremap SubstituteOverMotionMap :call EasyClip#Substitute#OnPreSubstitute(v:register, 1):set opfunc=EasyClip#Substitute#SubstituteMotiong@ +nnoremap G_SubstituteOverMotionMap :call EasyClip#Substitute#OnPreSubstitute(v:register, 0):set opfunc=EasyClip#Substitute#SubstituteMotiong@ + +nnoremap SubstituteToEndOfLine :call EasyClip#Substitute#SubstituteToEndOfLine(v:register, 1):call repeat#set("\SubstituteToEndOfLine") +nnoremap G_SubstituteToEndOfLine :call EasyClip#Substitute#SubstituteToEndOfLine(v:register, 0):call repeat#set("\G_SubstituteToEndOfLine") + +nnoremap SubstituteLine :call EasyClip#Substitute#SubstituteLine(v:register, v:count):call repeat#set("\SubstituteLine") + +""""""""""""""""""""""" +" Functions +""""""""""""""""""""""" +function! EasyClip#Substitute#OnPreSubstitute(register, moveCursor) + let s:activeRegister = a:register + + " This is necessary to get around a bug in vim where the active register persists to + " the next command. Repro by doing "_d and then a command that uses v:register + if a:register == "_" + let s:activeRegister = EasyClip#GetDefaultReg() + endif + + let s:moveCursor = a:moveCursor +endfunction + +function! EasyClip#Substitute#SubstituteMotion(type, ...) + + let startPos = getpos('.') + + if &selection ==# 'exclusive' + let excl_right = "\" + else + let excl_right = "" + endif + + let oldVirtualEdit=&virtualedit + set virtualedit=onemore + + " use keepjumps since we only want to change jumplist + " if it's multiline + if a:type ==# 'line' + exe "keepjump normal! '[V']".excl_right + elseif a:type ==# 'char' + exe "keepjump normal! `[v`]".excl_right + else + echom "Unexpected selection type" + exec "set virtualedit=". oldVirtualEdit + return + endif + + let reg = s:activeRegister + + if (getreg(reg) =~# "\n") + if s:moveCursor + " Record the start of the substitution to the jump list + exec "normal! m`" + endif + endif + + " Using "c" change doesn't work correctly for multiline, + " Adds an extra line at the end, so delete instead + exe "normal! \"_d" + + " Use our own version of paste so it autoformats and positions the cursor correctly + call EasyClip#Paste#Paste("P", 1, reg, 0) + exec "set virtualedit=". oldVirtualEdit + + let g:lastSubChangedtick = b:changedtick + + if !s:moveCursor + call setpos('.', startPos) + + " For some reason this is necessary otherwise doing gS and then hitting 'j' does not work as you'd expect (jumps to end of next line) + normal! hl + end +endfunction + +function! EasyClip#Substitute#SubstituteLine(reg, count) + + " Check for black hole register to get around a bug in vim where the active + " register persists to the next command + let reg = (a:reg == "_" ? EasyClip#GetDefaultReg() : a:reg) + + if getreg(reg) !~ '\n' + + exec "normal! 0\"_d$" + " Use our own version of paste so it autoformats and positions the cursor correctly + call EasyClip#Paste#Paste("P", 1, reg, 0) + else + let isLastLine = (line(".") == line("$")) + + let cnt = a:count > 0 ? a:count : 1 + exe "normal! ". cnt . "\"_dd" + + let i = 0 + while i < cnt + " Use our own version of paste so it autoformats and positions the cursor correctly + call EasyClip#Paste#Paste(isLastLine ? "p" : "P", 1, reg, 0) + + let i = i + 1 + endwhile + endif + + let g:lastSubChangedtick = b:changedtick +endfunction + +function! EasyClip#Substitute#SubstituteToEndOfLine(reg, moveCursor) + let startPos = getpos('.') + exec "normal! \"_d$" + + " Use our own version of paste so it autoformats and positions the cursor correctly + call EasyClip#Paste#Paste("p", 1, a:reg, 0) + + if !a:moveCursor + call setpos('.', startPos) + endif +endfunction + +function! EasyClip#Substitute#SetDefaultBindings() + + let bindings = + \ [ + \ ['s', 'SubstituteOverMotionMap', 'n', 1], + \ ['gs', 'G_SubstituteOverMotionMap', 'n', 1], + \ ['ss', 'SubstituteLine', 'n', 1], + \ ['s', 'XEasyClipPaste', 'x', 1], + \ ['S', 'SubstituteToEndOfLine', 'n', 1], + \ ['gS', 'G_SubstituteToEndOfLine', 'n', 1], + \ ] + + for binding in bindings + call call("EasyClip#AddWeakMapping", binding) + endfor +endfunction + +function! EasyClip#Substitute#Init() + + if g:EasyClipUseSubstituteDefaults + call EasyClip#Substitute#SetDefaultBindings() + endif +endfunction diff --git a/autoload/EasyClip/Yank.vim b/autoload/EasyClip/Yank.vim index 269e5ef..85e4027 100644 --- a/autoload/EasyClip/Yank.vim +++ b/autoload/EasyClip/Yank.vim @@ -1,284 +1,284 @@ -" A lot of this is based on yankstack by Max Brunsfeld -" See originally code here: https://github.com/maxbrunsfeld/vim-yankstack - -""""""""""""""""""""""" -" Variables -""""""""""""""""""""""" -let s:activeRegister = EasyClip#GetDefaultReg() -let s:yankstackTail = [] -let s:isFirstYank = 1 -let s:preYankPos = [] -let s:yankCount = 0 -let s:lastSystemClipboard = '' - -""""""""""""""""""""""" -" Commands -""""""""""""""""""""""" -command! EasyClipBeforeYank :call EasyClip#Yank#OnBeforeYank() -command! -nargs=0 Yanks call EasyClip#Yank#ShowYanks() -command! -nargs=0 ClearYanks call EasyClip#Yank#ClearYanks() - -""""""""""""""""""""""" -" Plugs -""""""""""""""""""""""" -nnoremap EasyClipRotateYanksForward :call EasyClip#Yank#ManuallyRotateYanks(1) -nnoremap EasyClipRotateYanksBackward :call EasyClip#Yank#ManuallyRotateYanks(-1) - -nnoremap YankLinePreserveCursorPosition :call EasyClip#Yank#PreYankMotion():call EasyClip#Yank#YankLine() -nnoremap YankPreserveCursorPosition :call EasyClip#Yank#PreYankMotion():set opfunc=EasyClip#Yank#YankMotiong@ - -xnoremap VisualModeYank :call VisualModeYank(v:register) - -""""""""""""""""""""""" -" Functions -""""""""""""""""""""""" -function! s:VisualModeYank(reg) - if a:reg == EasyClip#GetDefaultReg() - EasyClipBeforeYank - normal! gvy - else - " If register is specified explicitly then do not change default register - " or add to yank history - exec "normal! gv\"" . a:reg . "y" - endif -endfunction - -function! EasyClip#Yank#EasyClipGetNumYanks() - return len(s:yankstackTail) + 1 -endfunction - -function! EasyClip#Yank#OnBeforeYank() - if s:isFirstYank - let s:isFirstYank = 0 - return - endif - - let head = EasyClip#Yank#GetYankstackHead() - - if !empty(head.text) && (empty(s:yankstackTail) || (head != s:yankstackTail[0])) - call insert(s:yankstackTail, head) - let s:yankstackTail = s:yankstackTail[: g:EasyClipYankHistorySize-1] - endif - - call s:OnYankBufferChanged() -endfunction - -function! s:OnYankBufferChanged() - for i in range(1, min([len(s:yankstackTail), 9])) - let entry = s:yankstackTail[i-1] - - call setreg(i, entry.text, entry.type) - endfor -endfunction - -function! EasyClip#Yank#Rotate(offset) - - if empty(s:yankstackTail) - return - endif - - let offset_left = a:offset - - while offset_left != 0 - let head = EasyClip#Yank#GetYankstackHead() - - if offset_left > 0 - let entry = remove(s:yankstackTail, 0) - call add(s:yankstackTail, head) - let offset_left -= 1 - elseif offset_left < 0 - let entry = remove(s:yankstackTail, -1) - call insert(s:yankstackTail, head) - let offset_left += 1 - endif - - call EasyClip#Yank#SetYankStackHead(entry) - endwhile - - call s:OnYankBufferChanged() -endfunction - -function! EasyClip#Yank#ClearYanks() - let s:yankstackTail = [] - let s:isFirstYank = 1 -endfunction - -function! EasyClip#Yank#GetYankstackHead() - let reg = EasyClip#GetDefaultReg() - - return { 'text': getreg(reg), 'type': getregtype(reg) } -endfunction - -function! EasyClip#Yank#SetYankStackHead(entry) - let reg = EasyClip#GetDefaultReg() - call setreg(reg, a:entry.text, a:entry.type) -endfunction - -function! EasyClip#Yank#ShowYanks() - echohl WarningMsg | echo "--- Yanks ---" | echohl None - let i = 0 - for yank in EasyClip#Yank#EasyClipGetAllYanks() - call EasyClip#Yank#ShowYank(yank, i) - let i += 1 - endfor -endfunction - -function! EasyClip#Yank#ShowYank(yank, index) - let index = printf("%-4d", a:index) - let line = substitute(a:yank.text, '\V\n', '^M', 'g') - - if len(line) > 80 - let line = line[: 80] . '…' - endif - - echohl Directory | echo index - echohl None | echon line - echohl None -endfunction - -function! EasyClip#Yank#PreYankMotion() - let s:yankCount = v:count > 0 ? v:count : 1 - let s:activeRegister = v:register - - " This is necessary to get around a bug in vim where the active register persists to - " the next command. Repro by doing "_d and then a command that uses v:register - if s:activeRegister ==# "_" - let s:activeRegister = EasyClip#GetDefaultReg() - endif - - let s:preYankPos = getpos('.') -endfunction - -function! EasyClip#Yank#_YankLastChangedText(type, reg) - - if &selection ==# 'exclusive' - let excl_right = "\" - else - let excl_right = "" - endif - - let oldDefaultReg = '' - - if a:reg ==# EasyClip#GetDefaultReg() - " If register is declared explicitly then don't add it to yank history - EasyClipBeforeYank - else - let oldDefaultReg = EasyClip#GetCurrentYank() - endif - - if a:type !=# 'line' && a:type !=# 'char' - echoerr "Unexpected selection type '" . a:type . "'" - return - endif - - exe "keepjumps normal! `[" . (a:type ==# 'line' ? 'V' : 'v') - \ . "`]".excl_right."\"".a:reg."y" - - " When an explict register is specified it also clobbers the default register, so - " restore that - if a:reg !=# EasyClip#GetDefaultReg() - call EasyClip#SetCurrentYank(oldDefaultReg) - endif -endfunction - -function! EasyClip#Yank#YankMotion(type) - - let oldVisualStart = getpos("'<") - let oldVisualEnd = getpos("'>") - - call EasyClip#Yank#_YankLastChangedText(a:type, s:activeRegister) - - call setpos("'<", oldVisualStart) - call setpos("'>", oldVisualEnd) - - if g:EasyClipPreserveCursorPositionAfterYank && !empty(s:preYankPos) - call setpos('.', s:preYankPos) - let s:preYankPos = [] - " This is necessary for some reason otherwise if you go down a line it will - " jump to the column where the yank normally positions the cursor by default - " To repro just remove this line, run yiq inside quotes, then go down a line - if col('.') == col('$')-1 - normal! hl - else - normal! lh - endif - endif -endfunction - -function! EasyClip#Yank#YankLine() - EasyClipBeforeYank - exec 'normal! '. s:yankCount . '"'. s:activeRegister .'yy' - - call setpos('.', s:preYankPos) -endfunction - -function! EasyClip#Yank#EasyClipGetAllYanks() - return [EasyClip#Yank#GetYankstackHead()] + s:yankstackTail -endfunction - -function! EasyClip#Yank#ManuallyRotateYanks(offset) - - call EasyClip#Yank#Rotate(a:offset) - echo "Current Yank: " . split(EasyClip#Yank#GetYankstackHead().text, '\n')[0] . "..." -endfunction - -function! EasyClip#Yank#SetDefaultMappings() - - let bindings = - \ [ - \ ['[y', 'EasyClipRotateYanksForward', 'n', 1], - \ [']y', 'EasyClipRotateYanksBackward', 'n', 1], - \ ['Y', ':EasyClipBeforeYanky$', 'n', 0], - \ ['y', 'YankPreserveCursorPosition', 'n', 1], - \ ['yy', 'YankLinePreserveCursorPosition', 'n', 1], - \ ['y', 'VisualModeYank', 'x', 1], - \ ] - - for binding in bindings - call call("EasyClip#AddWeakMapping", binding) - endfor -endfunction - -function! EasyClip#Yank#OnFocusLost() - if EasyClip#GetDefaultReg() ==# '"' - call setreg('*', EasyClip#GetCurrentYank()) - endif - - let s:lastSystemClipboard = @* -endfunction - -" Just automatically copy system clipboard to the default -" register -function! EasyClip#Yank#OnFocusGained() - let newClipboardValue = @* - - " If the clipboard contains binary information then 'newClipboardValue' will be empty - if newClipboardValue !=# '' && s:lastSystemClipboard !=# newClipboardValue - EasyClipBeforeYank - let s:lastSystemClipboard = newClipboardValue - exec 'let @'. EasyClip#GetDefaultReg() .' = newClipboardValue' - endif -endfunction - -function! EasyClip#Yank#InitSystemSync() - - " Check whether the system clipboard changed while focus was lost and - " add it to our yank buffer - augroup _sync_clipboard - au! - autocmd FocusGained * call EasyClip#Yank#OnFocusGained() - autocmd FocusLost * call EasyClip#Yank#OnFocusLost() - augroup END -endfunction - -function! EasyClip#Yank#Init() - - if g:EasyClipUseYankDefaults - call EasyClip#Yank#SetDefaultMappings() - endif - - if g:EasyClipDoSystemSync - call EasyClip#Yank#InitSystemSync() - endif -endfunction - +" A lot of this is based on yankstack by Max Brunsfeld +" See originally code here: https://github.com/maxbrunsfeld/vim-yankstack + +""""""""""""""""""""""" +" Variables +""""""""""""""""""""""" +let s:activeRegister = EasyClip#GetDefaultReg() +let s:yankstackTail = [] +let s:isFirstYank = 1 +let s:preYankPos = [] +let s:yankCount = 0 +let s:lastSystemClipboard = '' + +""""""""""""""""""""""" +" Commands +""""""""""""""""""""""" +command! EasyClipBeforeYank :call EasyClip#Yank#OnBeforeYank() +command! -nargs=0 Yanks call EasyClip#Yank#ShowYanks() +command! -nargs=0 ClearYanks call EasyClip#Yank#ClearYanks() + +""""""""""""""""""""""" +" Plugs +""""""""""""""""""""""" +nnoremap EasyClipRotateYanksForward :call EasyClip#Yank#ManuallyRotateYanks(1) +nnoremap EasyClipRotateYanksBackward :call EasyClip#Yank#ManuallyRotateYanks(-1) + +nnoremap YankLinePreserveCursorPosition :call EasyClip#Yank#PreYankMotion():call EasyClip#Yank#YankLine() +nnoremap YankPreserveCursorPosition :call EasyClip#Yank#PreYankMotion():set opfunc=EasyClip#Yank#YankMotiong@ + +xnoremap VisualModeYank :call VisualModeYank(v:register) + +""""""""""""""""""""""" +" Functions +""""""""""""""""""""""" +function! s:VisualModeYank(reg) + if a:reg == EasyClip#GetDefaultReg() + EasyClipBeforeYank + normal! gvy + else + " If register is specified explicitly then do not change default register + " or add to yank history + exec "normal! gv\"" . a:reg . "y" + endif +endfunction + +function! EasyClip#Yank#EasyClipGetNumYanks() + return len(s:yankstackTail) + 1 +endfunction + +function! EasyClip#Yank#OnBeforeYank() + if s:isFirstYank + let s:isFirstYank = 0 + return + endif + + let head = EasyClip#Yank#GetYankstackHead() + + if !empty(head.text) && (empty(s:yankstackTail) || (head != s:yankstackTail[0])) + call insert(s:yankstackTail, head) + let s:yankstackTail = s:yankstackTail[: g:EasyClipYankHistorySize-1] + endif + + call s:OnYankBufferChanged() +endfunction + +function! s:OnYankBufferChanged() + for i in range(1, min([len(s:yankstackTail), 9])) + let entry = s:yankstackTail[i-1] + + call setreg(i, entry.text, entry.type) + endfor +endfunction + +function! EasyClip#Yank#Rotate(offset) + + if empty(s:yankstackTail) + return + endif + + let offset_left = a:offset + + while offset_left != 0 + let head = EasyClip#Yank#GetYankstackHead() + + if offset_left > 0 + let entry = remove(s:yankstackTail, 0) + call add(s:yankstackTail, head) + let offset_left -= 1 + elseif offset_left < 0 + let entry = remove(s:yankstackTail, -1) + call insert(s:yankstackTail, head) + let offset_left += 1 + endif + + call EasyClip#Yank#SetYankStackHead(entry) + endwhile + + call s:OnYankBufferChanged() +endfunction + +function! EasyClip#Yank#ClearYanks() + let s:yankstackTail = [] + let s:isFirstYank = 1 +endfunction + +function! EasyClip#Yank#GetYankstackHead() + let reg = EasyClip#GetDefaultReg() + + return { 'text': getreg(reg), 'type': getregtype(reg) } +endfunction + +function! EasyClip#Yank#SetYankStackHead(entry) + let reg = EasyClip#GetDefaultReg() + call setreg(reg, a:entry.text, a:entry.type) +endfunction + +function! EasyClip#Yank#ShowYanks() + echohl WarningMsg | echo "--- Yanks ---" | echohl None + let i = 0 + for yank in EasyClip#Yank#EasyClipGetAllYanks() + call EasyClip#Yank#ShowYank(yank, i) + let i += 1 + endfor +endfunction + +function! EasyClip#Yank#ShowYank(yank, index) + let index = printf("%-4d", a:index) + let line = substitute(a:yank.text, '\V\n', '^M', 'g') + + if len(line) > 80 + let line = line[: 80] . '…' + endif + + echohl Directory | echo index + echohl None | echon line + echohl None +endfunction + +function! EasyClip#Yank#PreYankMotion() + let s:yankCount = v:count > 0 ? v:count : 1 + let s:activeRegister = v:register + + " This is necessary to get around a bug in vim where the active register persists to + " the next command. Repro by doing "_d and then a command that uses v:register + if s:activeRegister ==# "_" + let s:activeRegister = EasyClip#GetDefaultReg() + endif + + let s:preYankPos = getpos('.') +endfunction + +function! EasyClip#Yank#_YankLastChangedText(type, reg) + + if &selection ==# 'exclusive' + let excl_right = "\" + else + let excl_right = "" + endif + + let oldDefaultReg = '' + + if a:reg ==# EasyClip#GetDefaultReg() + " If register is declared explicitly then don't add it to yank history + EasyClipBeforeYank + else + let oldDefaultReg = EasyClip#GetCurrentYank() + endif + + if a:type !=# 'line' && a:type !=# 'char' + echoerr "Unexpected selection type '" . a:type . "'" + return + endif + + exe "keepjumps normal! `[" . (a:type ==# 'line' ? 'V' : 'v') + \ . "`]".excl_right."\"".a:reg."y" + + " When an explict register is specified it also clobbers the default register, so + " restore that + if a:reg !=# EasyClip#GetDefaultReg() + call EasyClip#SetCurrentYank(oldDefaultReg) + endif +endfunction + +function! EasyClip#Yank#YankMotion(type) + + let oldVisualStart = getpos("'<") + let oldVisualEnd = getpos("'>") + + call EasyClip#Yank#_YankLastChangedText(a:type, s:activeRegister) + + call setpos("'<", oldVisualStart) + call setpos("'>", oldVisualEnd) + + if g:EasyClipPreserveCursorPositionAfterYank && !empty(s:preYankPos) + call setpos('.', s:preYankPos) + let s:preYankPos = [] + " This is necessary for some reason otherwise if you go down a line it will + " jump to the column where the yank normally positions the cursor by default + " To repro just remove this line, run yiq inside quotes, then go down a line + if col('.') == col('$')-1 + normal! hl + else + normal! lh + endif + endif +endfunction + +function! EasyClip#Yank#YankLine() + EasyClipBeforeYank + exec 'normal! '. s:yankCount . '"'. s:activeRegister .'yy' + + call setpos('.', s:preYankPos) +endfunction + +function! EasyClip#Yank#EasyClipGetAllYanks() + return [EasyClip#Yank#GetYankstackHead()] + s:yankstackTail +endfunction + +function! EasyClip#Yank#ManuallyRotateYanks(offset) + + call EasyClip#Yank#Rotate(a:offset) + echo "Current Yank: " . split(EasyClip#Yank#GetYankstackHead().text, '\n')[0] . "..." +endfunction + +function! EasyClip#Yank#SetDefaultMappings() + + let bindings = + \ [ + \ ['[y', 'EasyClipRotateYanksForward', 'n', 1], + \ [']y', 'EasyClipRotateYanksBackward', 'n', 1], + \ ['Y', ':EasyClipBeforeYanky$', 'n', 0], + \ ['y', 'YankPreserveCursorPosition', 'n', 1], + \ ['yy', 'YankLinePreserveCursorPosition', 'n', 1], + \ ['y', 'VisualModeYank', 'x', 1], + \ ] + + for binding in bindings + call call("EasyClip#AddWeakMapping", binding) + endfor +endfunction + +function! EasyClip#Yank#OnFocusLost() + if EasyClip#GetDefaultReg() ==# '"' + call setreg('*', EasyClip#GetCurrentYank()) + endif + + let s:lastSystemClipboard = @* +endfunction + +" Just automatically copy system clipboard to the default +" register +function! EasyClip#Yank#OnFocusGained() + let newClipboardValue = @* + + " If the clipboard contains binary information then 'newClipboardValue' will be empty + if newClipboardValue !=# '' && s:lastSystemClipboard !=# newClipboardValue + EasyClipBeforeYank + let s:lastSystemClipboard = newClipboardValue + exec 'let @'. EasyClip#GetDefaultReg() .' = newClipboardValue' + endif +endfunction + +function! EasyClip#Yank#InitSystemSync() + + " Check whether the system clipboard changed while focus was lost and + " add it to our yank buffer + augroup _sync_clipboard + au! + autocmd FocusGained * call EasyClip#Yank#OnFocusGained() + autocmd FocusLost * call EasyClip#Yank#OnFocusLost() + augroup END +endfunction + +function! EasyClip#Yank#Init() + + if g:EasyClipUseYankDefaults + call EasyClip#Yank#SetDefaultMappings() + endif + + if g:EasyClipDoSystemSync + call EasyClip#Yank#InitSystemSync() + endif +endfunction + diff --git a/doc/easyclip.txt b/doc/easyclip.txt index 239b250..77e8d6d 100644 --- a/doc/easyclip.txt +++ b/doc/easyclip.txt @@ -1,337 +1,337 @@ -*easyclip.txt* Simplified clipboard functionality for Vim. - -Author: Steve Vermeulen , based on work by Max -Brunsfeld - -|easyclip-introduction| Introduction -|easyclip-installation| Installation -|easyclip-cut| Black hole redirection / cut -|easyclip-substitute| Substitute operator -|easyclip-yankbuffer| Yank Buffer -|easyclip-paste| Paste -|easyclip-ossync| OS Sync -|easyclip-options| Options -|easyclip-mappings| Mappings -|easyclip-custom-yanks| Custom Yanks -|easyclip-feedback| Feedback -|easyclip-changelog| Changelog -|easyclip-license| License - -INTRODUCTION *easyclip-introduction* - -Author: Steve Vermeulen (https://github.com/svermeulen), based on work by -Max Brunsfeld (http://www.github.com/maxbrunsfeld) - -EasyClip is a plugin for Vim which contains a collection of clipboard related -functionality with the goal of making using Vim simpler and more intuitive -without losing any of its power. - -A good starting point for the motivation behind this plugin can be found in Drew -Neil's post: -Registers: The Good, the Bad, and the Ugly Parts -(http://vimcasts.org/blog/2013/11/25/registers-the-good-the-bad-and-the-ugly-parts) - -The most recent version of this plugin can be found at -https://github.com/svermeulen/vim-easyclip - -INSTALLATION *easyclip-installation* - -I recommend loading your plugins with neobundle -(https://github.com/Shougo/neobundle.vim) or vundle -(https://github.com/gmarik/vundle) or pathogen -(https://github.com/tpope/vim-pathogen) - -This plugin also requires that you have Tim Pope's repeat.vim -(https://github.com/tpope/vim-repeat) plugin installed. - -BLACK HOLE REDIRECTION *easyclip-cut* - -By default, Vim's built-in delete operator will yank the deleted text in -addition to just deleting it. This works great when you want to cut text and -paste it somewhere else, but in many other cases it can make things more -difficult. For example, if you want to make some tiny edit to fix formatting -after cutting some text, you either have to have had the foresight to use a -named register, or specify the black hole register explicitly to do your -formatting. This plugin solves that problem by redirecting all change and -delete operations to the black hole register and introducing a new operator, -'cut' (by default this is mapped to the 'm' key). - -There is simply no need to clutter up the yank history with every single edit, -when you almost always know at the time you are deleting text whether it's -something that is worth keeping around or not. - -SUBSTITUTION OPERATOR *easyclip-substitute* - -Because replacing text is such a common operation, EasyClip includes a motion -for it. It is essentially equivalent to doing a change operation then pasting -using the specified register. For example, assuming you have mapped this motion -to the 's' key, to paste over the word under the cursor you would type 'siw', or -to paste inside brackets, 'si(', etc. - -It can also take a register to use for the substitution (eg. '"asip'), and is -fully repeatable using the '.' key. - -NOTE // This feature is off by default. To use, you have to either enable the -option |g:EasyClipUseSubstituteDefaults| (in which case it will be mapped to the -'s' key) or map the key/keys of your choice to the '' mappings found -in substitute.vim. - -YANK BUFFER *easyclip-yankbuffer* - -EasyClip allows you to yank and cut things without worrying about losing text -that you copied previously. It achieves this by storing all yanks into a -buffer, which you can cycle through forward or backwards to choose the yank that -you want - -This works very similar to the way YankRing -(https://github.com/vim-scripts/YankRing.vim) and YankStack -(https://github.com/maxbrunsfeld/vim-yankstack) work, in that you can use a key -binding to toggle between different yanks immediately after triggering a paste -or substitute. (Most of the functionality is actually taken and adapted from -Yankstack, with changes to make it work with substitute) - -By default, the keys to toggle the paste are mapped to '' and '' -(similar to yankring). For example, executing 'p' will paste, then toggle -it to the most recent yank before that. You can continue toggling -forwards/backwards in the yank history to replace the most recent paste as much -as you want. Note that the toggle action will of course not be included in the -undo history. That is, pressing undo after any number of swaps will undo the -paste and not each swap. - -This method of toggling the chosen yank after paste will probably be your -primary method of digging back into the yank buffer. Note that in this case the -yank buffer is unchanged. What this means for example is that you can toggle a -given paste back using '' 10 times, then if you perform a new paste in a -different location it will still use the most recent yank (and not the final -yank you arrived at after 10 swaps). - -Alternatively, you can execute (by default) keys '[y' or ']y' to navigate the -yank buffer 'head' forwards or backwards. In this case the change will be -permanent. That is, pressing '[y[yp' will paste the third most recent yank. -Subsequent pastes will use the same yank, until you go forwards again using -']y'. - -You can view the full list of yanks at any time by running the command ':Yanks' - -Note that you can swap substitution operations in the same way as paste. - -Every time the yank buffer changes, it also populates all the numbered -registers. "1 is therefore the previous yank, "2 is the yank before that, etc. -This is similar to how the numbered registers work by default (but a bit more -sane). (Credit to Drew Neil for the suggestion) - -Also, see |g:EasyClipPreserveCursorPositionAfterYank| option below for an -optional non standard customization to yank - -PASTE *easyclip-paste* - -By default EasyClip preserves the default vim paste behaviour, which is the -following: - -* 'p' (lowercase) pastes text after the current line if the pasted text is -multiline (or after the current character if non-multiline) - -* 'P' (uppercase) behaves the same except acts before the current line -(or before the current character if non-multiline) - -When the text is multi-line, the cursor is placed at the start of the new text. -When the paste is non-multiline, the cursor is placed at the end. - -Alternatively, you can enable the option -|g:EasyClipAlwaysMoveCursorToEndOfPaste| to have the cursor positioned at the -end in both cases (off by default). Note that when this option is enabled, the -beginning of the multi-line text is added to the jumplist, so you can still -return to the start of the paste by pressing '' (and this applies to -multi-line substitutions as well) - -Another non-standard option is |g:EasyClipAutoFormat| (see below) - -Easy Clip also includes a mapping for insert mode paste, which automatically -turns on 'paste' mode for the duration of the paste. Using 'paste' mode will -work much more intuitively when pasting text with multiple lines while in insert -mode. You can enable this by including something similar to the following in -your .vimrc: - - imap EasyClipInsertModePaste - -SYSTEM CLIPBOARD SYNC *easyclip-ossync* - -EasyClip will also automatically sync with your system clipboard. - -Every time you leave and return to vim, easy clip will check whether you copied -anything from outside Vim and add it to the yank history. - -OPTIONS *easyclip-options* - -EasyClip can be easily customized to whatever mapping you wish, using the -following options: - -*g:EasyClipAlwaysMoveCursorToEndOfPaste* Default: 0. Set this to 1 to always -position cursor at the end of the pasted text for both multi-line and -non-multiline pastes. - -*g:EasyClipAutoFormat* Default: 0. Set this to 1 to enable -auto-formatting. This can be useful when pasting text from one indent level to -another. - -*g:EasyClipYankHistorySize* Default: 50. Change this to limit yank history - -*g:EasyClipDoSystemSync* Default: 1. Set this to zero to disable system -clipboard sync. - -*g:EasyClipPreserveCursorPositionAfterYank* - Default 0 (ie. disabled). Vim's -default behaviour is to position the cursor at the beginning of the yanked text, -which is consistent with other motions. However if you prefer the -cursor position to remain unchanged when performing yanks, enable this -option. - -You can also disable the default mappings by setting one or more of the -following to zero. By default they are set to 1 (ie. enabled) - - *g:EasyClipUseYankDefaults* - - *g:EasyClipUseCutDefaults* - - *g:EasyClipUsePasteDefaults* - - *g:EasyClipEnableBlackHoleRedirect* - - *g:EasyClipUsePasteToggleDefaults* - -One exception to the above is substitute, which is 0 by default (ie. disabled) - - *g:EasyClipUseSubstituteDefaults* - -To change from the default mappings, you can disable one of the options above -and then map to the specific mappings of your choice. For example, to -change the mapping for cut (by default set to `m`) to `x`, include the following -in your vimrc:` - - let g:EasyClipUseCutDefaults = 0 - - nmap x MoveMotionPlug xmap x MoveMotionXPlug nmap xx - MoveMotionLinePlug - -Or to change the bindings for toggling paste from '' and '' to '' -and '' include the following: - - let g:EasyClipUsePasteToggleDefaults = 0 - - nmap EasyClipSwapPasteForward nmap - EasyClipSwapPasteBackwards - -Or to use 'gs' for substitute include the following: (in this case you don't -need to turn off the default since the default is already disabled) - - nmap gs SubstituteOverMotionMap nmap gss SubstituteLine - xmap gs XEasyClipPaste - -For reference, or other kinds of mappings, see the bottom of the file with the -name of the operation you wish to remap (vim-easy-clip/autoload/substitute.vim / -move.vim / yank.vim /etc.) - -Note that EasyClip will only enable a default mapping if it hasn't already been -mapped to something in your .vimrc. - -KEY MAPPINGS *easyclip-mappings* - -*d* - Delete over the given motion and *do not* change clipboard - -*dd* - Delete the line and *do not* change clipboard - -*D* - Delete from cursor to the end of the line and *do not* change clipboard - -*dD* - Delete the contents of line except the newline character (that is, make it blank) and *do not* change clipboard - -*x* - Delete the character under cursor and *do not* change clipboard - -*s* - Delete the character under cursor then enter insert mode and *do not* change clipboard - -*S* - Delete the line under cursor then enter insert mode and *do not* change clipboard - -*c* - Enter insert mode over top the given area and *do not* change clipboard - -*cc* - Enter insert mode over top the current line and *do not* change clipboard - -*C* - Enter insert mode from cursor to the end of the line and *do not* change clipboard - -*p* - Paste from specified register. Inserts after current line if text is multiline, after current character if text is non-multiline. Leaves cursor at end of pasted text. - -*P* - Same as p except inserts text before current line/character - -*p* - Same as 'p' except does not auto-format text. This is only relevant if the auto-format option is enabled - -*P* - Same as 'P' except does not auto-format text. This is only relevant if the auto-format option is enabled - -*gp* - Same as p but preserves the current cursor position - -*gP* - Same as P but preserves the current cursor position - -*gP* - Same as 'P' but preserves the current cursor position - -*gp* - Same as 'p' but preserves the current cursor position - -*m* - Delete over the given motion and copy text to clipboard - -*mm* - Delete the current line and copy text to clipboard - -** -p>' - Rotate the previous paste forward in yank buffer. Note that this binding will only work if executed immediately after a paste - -** -n>' - Rotate the previous paste backward in yank buffer. Note that this binding will only work if executed immediately after a paste - -*[y* - Go backward in the yank buffer. This can be executed at any time to modify order of yanks in the yank buffer (though I would recommend just using '' instead) - -*]y* - Go forward in the yank buffer. This can be executed at any time to modify order of yanks in the yank buffer (though I would recommend just using '' instead) - -*Y* - Copy text from cursor position to the end of line to the clipboard - -When the option |g:EasyClipUseSubstituteDefaults| is enabled, the following mappings are added: - -s - Substitute over the given motion with specified register (or default register if unspecified). - -ss - Substitute over the current line with specified register (or default register if unspecified). - -gs - Same as s but preserves the current cursor position. - -CUSTOM YANKS *easyclip-custom-yanks* - -If you have custom yanks that occur in your vimrc or elsewhere and would like -them to be included in the yank history, you can either call EasyClip#Yank() to -record the string or call the command *EasyClipBeforeYank* before the yank -occurs. For example, to yank the current file name you could do either of the -following: - - nnoremap yfn :EasyClipBeforeYank:let @*=expand('%') - - nnoremap yfn :call EasyClip#Yank(expand('%')) - -FEEDBACK *easyclip-feedback* - -Feel free to email all feedback/criticism/suggestions to sfvermeulen@gmail.com. -Or, feel free to create a github issue. - -CHANGELOG *easyclip-changelog* - -2.1 (2013-12-06) - - Bug fixes - - Disabled substitution operator by default - -2.0 (2013-09-22) - - Many bug fixes - - Yankring/Yankstack style post-paste swap - - RSPEC unit tests added for stability - -1.2 (2013-09-22) - - More bug fixes - -1.1 (2013-09-03) - - Bunch of bug fixes - -1.0 (2013-07-08) - - Initial release - - *easyclip-license* -Distributed under the same terms as Vim itself. -See |license|. - - vim:tw=78:ts=8:ft=help:norl: +*easyclip.txt* Simplified clipboard functionality for Vim. + +Author: Steve Vermeulen , based on work by Max +Brunsfeld + +|easyclip-introduction| Introduction +|easyclip-installation| Installation +|easyclip-cut| Black hole redirection / cut +|easyclip-substitute| Substitute operator +|easyclip-yankbuffer| Yank Buffer +|easyclip-paste| Paste +|easyclip-ossync| OS Sync +|easyclip-options| Options +|easyclip-mappings| Mappings +|easyclip-custom-yanks| Custom Yanks +|easyclip-feedback| Feedback +|easyclip-changelog| Changelog +|easyclip-license| License + +INTRODUCTION *easyclip-introduction* + +Author: Steve Vermeulen (https://github.com/svermeulen), based on work by +Max Brunsfeld (http://www.github.com/maxbrunsfeld) + +EasyClip is a plugin for Vim which contains a collection of clipboard related +functionality with the goal of making using Vim simpler and more intuitive +without losing any of its power. + +A good starting point for the motivation behind this plugin can be found in Drew +Neil's post: +Registers: The Good, the Bad, and the Ugly Parts +(http://vimcasts.org/blog/2013/11/25/registers-the-good-the-bad-and-the-ugly-parts) + +The most recent version of this plugin can be found at +https://github.com/svermeulen/vim-easyclip + +INSTALLATION *easyclip-installation* + +I recommend loading your plugins with neobundle +(https://github.com/Shougo/neobundle.vim) or vundle +(https://github.com/gmarik/vundle) or pathogen +(https://github.com/tpope/vim-pathogen) + +This plugin also requires that you have Tim Pope's repeat.vim +(https://github.com/tpope/vim-repeat) plugin installed. + +BLACK HOLE REDIRECTION *easyclip-cut* + +By default, Vim's built-in delete operator will yank the deleted text in +addition to just deleting it. This works great when you want to cut text and +paste it somewhere else, but in many other cases it can make things more +difficult. For example, if you want to make some tiny edit to fix formatting +after cutting some text, you either have to have had the foresight to use a +named register, or specify the black hole register explicitly to do your +formatting. This plugin solves that problem by redirecting all change and +delete operations to the black hole register and introducing a new operator, +'cut' (by default this is mapped to the 'm' key). + +There is simply no need to clutter up the yank history with every single edit, +when you almost always know at the time you are deleting text whether it's +something that is worth keeping around or not. + +SUBSTITUTION OPERATOR *easyclip-substitute* + +Because replacing text is such a common operation, EasyClip includes a motion +for it. It is essentially equivalent to doing a change operation then pasting +using the specified register. For example, assuming you have mapped this motion +to the 's' key, to paste over the word under the cursor you would type 'siw', or +to paste inside brackets, 'si(', etc. + +It can also take a register to use for the substitution (eg. '"asip'), and is +fully repeatable using the '.' key. + +NOTE // This feature is off by default. To use, you have to either enable the +option |g:EasyClipUseSubstituteDefaults| (in which case it will be mapped to the +'s' key) or map the key/keys of your choice to the '' mappings found +in substitute.vim. + +YANK BUFFER *easyclip-yankbuffer* + +EasyClip allows you to yank and cut things without worrying about losing text +that you copied previously. It achieves this by storing all yanks into a +buffer, which you can cycle through forward or backwards to choose the yank that +you want + +This works very similar to the way YankRing +(https://github.com/vim-scripts/YankRing.vim) and YankStack +(https://github.com/maxbrunsfeld/vim-yankstack) work, in that you can use a key +binding to toggle between different yanks immediately after triggering a paste +or substitute. (Most of the functionality is actually taken and adapted from +Yankstack, with changes to make it work with substitute) + +By default, the keys to toggle the paste are mapped to '' and '' +(similar to yankring). For example, executing 'p' will paste, then toggle +it to the most recent yank before that. You can continue toggling +forwards/backwards in the yank history to replace the most recent paste as much +as you want. Note that the toggle action will of course not be included in the +undo history. That is, pressing undo after any number of swaps will undo the +paste and not each swap. + +This method of toggling the chosen yank after paste will probably be your +primary method of digging back into the yank buffer. Note that in this case the +yank buffer is unchanged. What this means for example is that you can toggle a +given paste back using '' 10 times, then if you perform a new paste in a +different location it will still use the most recent yank (and not the final +yank you arrived at after 10 swaps). + +Alternatively, you can execute (by default) keys '[y' or ']y' to navigate the +yank buffer 'head' forwards or backwards. In this case the change will be +permanent. That is, pressing '[y[yp' will paste the third most recent yank. +Subsequent pastes will use the same yank, until you go forwards again using +']y'. + +You can view the full list of yanks at any time by running the command ':Yanks' + +Note that you can swap substitution operations in the same way as paste. + +Every time the yank buffer changes, it also populates all the numbered +registers. "1 is therefore the previous yank, "2 is the yank before that, etc. +This is similar to how the numbered registers work by default (but a bit more +sane). (Credit to Drew Neil for the suggestion) + +Also, see |g:EasyClipPreserveCursorPositionAfterYank| option below for an +optional non standard customization to yank + +PASTE *easyclip-paste* + +By default EasyClip preserves the default vim paste behaviour, which is the +following: + +* 'p' (lowercase) pastes text after the current line if the pasted text is +multiline (or after the current character if non-multiline) + +* 'P' (uppercase) behaves the same except acts before the current line +(or before the current character if non-multiline) + +When the text is multi-line, the cursor is placed at the start of the new text. +When the paste is non-multiline, the cursor is placed at the end. + +Alternatively, you can enable the option +|g:EasyClipAlwaysMoveCursorToEndOfPaste| to have the cursor positioned at the +end in both cases (off by default). Note that when this option is enabled, the +beginning of the multi-line text is added to the jumplist, so you can still +return to the start of the paste by pressing '' (and this applies to +multi-line substitutions as well) + +Another non-standard option is |g:EasyClipAutoFormat| (see below) + +Easy Clip also includes a mapping for insert mode paste, which automatically +turns on 'paste' mode for the duration of the paste. Using 'paste' mode will +work much more intuitively when pasting text with multiple lines while in insert +mode. You can enable this by including something similar to the following in +your .vimrc: + + imap EasyClipInsertModePaste + +SYSTEM CLIPBOARD SYNC *easyclip-ossync* + +EasyClip will also automatically sync with your system clipboard. + +Every time you leave and return to vim, easy clip will check whether you copied +anything from outside Vim and add it to the yank history. + +OPTIONS *easyclip-options* + +EasyClip can be easily customized to whatever mapping you wish, using the +following options: + +*g:EasyClipAlwaysMoveCursorToEndOfPaste* Default: 0. Set this to 1 to always +position cursor at the end of the pasted text for both multi-line and +non-multiline pastes. + +*g:EasyClipAutoFormat* Default: 0. Set this to 1 to enable +auto-formatting. This can be useful when pasting text from one indent level to +another. + +*g:EasyClipYankHistorySize* Default: 50. Change this to limit yank history + +*g:EasyClipDoSystemSync* Default: 1. Set this to zero to disable system +clipboard sync. + +*g:EasyClipPreserveCursorPositionAfterYank* - Default 0 (ie. disabled). Vim's +default behaviour is to position the cursor at the beginning of the yanked text, +which is consistent with other motions. However if you prefer the +cursor position to remain unchanged when performing yanks, enable this +option. + +You can also disable the default mappings by setting one or more of the +following to zero. By default they are set to 1 (ie. enabled) + + *g:EasyClipUseYankDefaults* + + *g:EasyClipUseCutDefaults* + + *g:EasyClipUsePasteDefaults* + + *g:EasyClipEnableBlackHoleRedirect* + + *g:EasyClipUsePasteToggleDefaults* + +One exception to the above is substitute, which is 0 by default (ie. disabled) + + *g:EasyClipUseSubstituteDefaults* + +To change from the default mappings, you can disable one of the options above +and then map to the specific mappings of your choice. For example, to +change the mapping for cut (by default set to `m`) to `x`, include the following +in your vimrc:` + + let g:EasyClipUseCutDefaults = 0 + + nmap x MoveMotionPlug xmap x MoveMotionXPlug nmap xx + MoveMotionLinePlug + +Or to change the bindings for toggling paste from '' and '' to '' +and '' include the following: + + let g:EasyClipUsePasteToggleDefaults = 0 + + nmap EasyClipSwapPasteForward nmap + EasyClipSwapPasteBackwards + +Or to use 'gs' for substitute include the following: (in this case you don't +need to turn off the default since the default is already disabled) + + nmap gs SubstituteOverMotionMap nmap gss SubstituteLine + xmap gs XEasyClipPaste + +For reference, or other kinds of mappings, see the bottom of the file with the +name of the operation you wish to remap (vim-easy-clip/autoload/substitute.vim / +move.vim / yank.vim /etc.) + +Note that EasyClip will only enable a default mapping if it hasn't already been +mapped to something in your .vimrc. + +KEY MAPPINGS *easyclip-mappings* + +*d* - Delete over the given motion and *do not* change clipboard + +*dd* - Delete the line and *do not* change clipboard + +*D* - Delete from cursor to the end of the line and *do not* change clipboard + +*dD* - Delete the contents of line except the newline character (that is, make it blank) and *do not* change clipboard + +*x* - Delete the character under cursor and *do not* change clipboard + +*s* - Delete the character under cursor then enter insert mode and *do not* change clipboard + +*S* - Delete the line under cursor then enter insert mode and *do not* change clipboard + +*c* - Enter insert mode over top the given area and *do not* change clipboard + +*cc* - Enter insert mode over top the current line and *do not* change clipboard + +*C* - Enter insert mode from cursor to the end of the line and *do not* change clipboard + +*p* - Paste from specified register. Inserts after current line if text is multiline, after current character if text is non-multiline. Leaves cursor at end of pasted text. + +*P* - Same as p except inserts text before current line/character + +*p* - Same as 'p' except does not auto-format text. This is only relevant if the auto-format option is enabled + +*P* - Same as 'P' except does not auto-format text. This is only relevant if the auto-format option is enabled + +*gp* - Same as p but preserves the current cursor position + +*gP* - Same as P but preserves the current cursor position + +*gP* - Same as 'P' but preserves the current cursor position + +*gp* - Same as 'p' but preserves the current cursor position + +*m* - Delete over the given motion and copy text to clipboard + +*mm* - Delete the current line and copy text to clipboard + +** -p>' - Rotate the previous paste forward in yank buffer. Note that this binding will only work if executed immediately after a paste + +** -n>' - Rotate the previous paste backward in yank buffer. Note that this binding will only work if executed immediately after a paste + +*[y* - Go backward in the yank buffer. This can be executed at any time to modify order of yanks in the yank buffer (though I would recommend just using '' instead) + +*]y* - Go forward in the yank buffer. This can be executed at any time to modify order of yanks in the yank buffer (though I would recommend just using '' instead) + +*Y* - Copy text from cursor position to the end of line to the clipboard + +When the option |g:EasyClipUseSubstituteDefaults| is enabled, the following mappings are added: + +s - Substitute over the given motion with specified register (or default register if unspecified). + +ss - Substitute over the current line with specified register (or default register if unspecified). + +gs - Same as s but preserves the current cursor position. + +CUSTOM YANKS *easyclip-custom-yanks* + +If you have custom yanks that occur in your vimrc or elsewhere and would like +them to be included in the yank history, you can either call EasyClip#Yank() to +record the string or call the command *EasyClipBeforeYank* before the yank +occurs. For example, to yank the current file name you could do either of the +following: + + nnoremap yfn :EasyClipBeforeYank:let @*=expand('%') + + nnoremap yfn :call EasyClip#Yank(expand('%')) + +FEEDBACK *easyclip-feedback* + +Feel free to email all feedback/criticism/suggestions to sfvermeulen@gmail.com. +Or, feel free to create a github issue. + +CHANGELOG *easyclip-changelog* + +2.1 (2013-12-06) + - Bug fixes + - Disabled substitution operator by default + +2.0 (2013-09-22) + - Many bug fixes + - Yankring/Yankstack style post-paste swap + - RSPEC unit tests added for stability + +1.2 (2013-09-22) + - More bug fixes + +1.1 (2013-09-03) + - Bunch of bug fixes + +1.0 (2013-07-08) + - Initial release + + *easyclip-license* +Distributed under the same terms as Vim itself. +See |license|. + + vim:tw=78:ts=8:ft=help:norl: diff --git a/plugin/EasyClip.vim b/plugin/EasyClip.vim index 6a903e9..218f466 100644 --- a/plugin/EasyClip.vim +++ b/plugin/EasyClip.vim @@ -1,2 +1,2 @@ - -call EasyClip#Init() + +call EasyClip#Init() diff --git a/spec/fixtures/repeat.vim b/spec/fixtures/repeat.vim index 520723c..e8fe723 100644 --- a/spec/fixtures/repeat.vim +++ b/spec/fixtures/repeat.vim @@ -1,115 +1,115 @@ -" repeat.vim - Let the repeat command repeat plugin maps -" Maintainer: Tim Pope -" Version: 1.1 -" GetLatestVimScripts: 2136 1 :AutoInstall: repeat.vim - -" Installation: -" Place in either ~/.vim/plugin/repeat.vim (to load at start up) or -" ~/.vim/autoload/repeat.vim (to load automatically as needed). -" -" License: -" Copyright (c) Tim Pope. Distributed under the same terms as Vim itself. -" See :help license -" -" Developers: -" Basic usage is as follows: -" -" silent! call repeat#set("\MappingToRepeatCommand",3) -" -" The first argument is the mapping that will be invoked when the |.| key is -" pressed. Typically, it will be the same as the mapping the user invoked. -" This sequence will be stuffed into the input queue literally. Thus you must -" encode special keys by prefixing them with a backslash inside double quotes. -" -" The second argument is the default count. This is the number that will be -" prefixed to the mapping if no explicit numeric argument was given. The -" value of the v:count variable is usually correct and it will be used if the -" second parameter is omitted. If your mapping doesn't accept a numeric -" argument and you never want to receive one, pass a value of -1. -" -" Make sure to call the repeat#set function _after_ making changes to the -" file. -" -" For mappings that use a register and want the same register used on -" repetition, use: -" -" silent! call repeat#setreg("\MappingToRepeatCommand", v:register) -" -" This function can (and probably needs to be) called before making changes to -" the file (as those typically clear v:register). Therefore, the call sequence -" in your mapping will look like this: -" -" nnoremap MyMap -" \ :execute 'silent! call repeat#setreg("\Plug>MyMap", v:register)' -" \ call MyFunction(v:register, ...) -" \ silent! call repeat#set("\Plug>MyMap") - -if exists("g:loaded_repeat") || &cp || v:version < 700 - finish -endif -let g:loaded_repeat = 1 - -let g:repeat_tick = -1 -let g:repeat_reg = ['', ''] - -" Special function to avoid spurious repeats in a related, naturally repeating -" mapping when your repeatable mapping doesn't increase b:changedtick. -function! repeat#invalidate() - let g:repeat_tick = -1 -endfunction - -function! repeat#set(sequence,...) - let g:repeat_sequence = a:sequence - let g:repeat_count = a:0 ? a:1 : v:count - let g:repeat_tick = b:changedtick -endfunction - -function! repeat#setreg(sequence,register) - let g:repeat_reg = [a:sequence, a:register] -endfunction - -function! repeat#run(count) - if g:repeat_tick == b:changedtick - let r = '' - if g:repeat_reg[0] ==# g:repeat_sequence && !empty(g:repeat_reg[1]) - if g:repeat_reg[1] ==# '=' - " This causes a re-evaluation of the expression on repeat, which - " is what we want. - let r = '"=' . getreg('=', 1) . "\" - else - let r = '"' . g:repeat_reg[1] - endif - endif - - let c = g:repeat_count - let s = g:repeat_sequence - let cnt = c == -1 ? "" : (a:count ? a:count : (c ? c : '')) - call feedkeys(r . cnt, 'n') - call feedkeys(s) - else - call feedkeys((a:count ? a:count : '') . '.', 'n') - endif -endfunction - -function! repeat#wrap(command,count) - let preserve = (g:repeat_tick == b:changedtick) - exe 'norm! '.(a:count ? a:count : '').a:command . (&foldopen =~# 'undo' ? 'zv' : '') - if preserve - let g:repeat_tick = b:changedtick - endif -endfunction - -nnoremap . :call repeat#run(v:count) -nnoremap u :call repeat#wrap('u',v:count) -if maparg('U','n') ==# '' - nnoremap U :call repeat#wrap('U',v:count) -endif -nnoremap :call repeat#wrap("\C-R>",v:count) - -augroup repeatPlugin - autocmd! - autocmd BufLeave,BufWritePre,BufReadPre * let g:repeat_tick = (g:repeat_tick == b:changedtick || g:repeat_tick == 0) ? 0 : -1 - autocmd BufEnter,BufWritePost * if g:repeat_tick == 0|let g:repeat_tick = b:changedtick|endif -augroup END - -" vim:set ft=vim et sw=4 sts=4: +" repeat.vim - Let the repeat command repeat plugin maps +" Maintainer: Tim Pope +" Version: 1.1 +" GetLatestVimScripts: 2136 1 :AutoInstall: repeat.vim + +" Installation: +" Place in either ~/.vim/plugin/repeat.vim (to load at start up) or +" ~/.vim/autoload/repeat.vim (to load automatically as needed). +" +" License: +" Copyright (c) Tim Pope. Distributed under the same terms as Vim itself. +" See :help license +" +" Developers: +" Basic usage is as follows: +" +" silent! call repeat#set("\MappingToRepeatCommand",3) +" +" The first argument is the mapping that will be invoked when the |.| key is +" pressed. Typically, it will be the same as the mapping the user invoked. +" This sequence will be stuffed into the input queue literally. Thus you must +" encode special keys by prefixing them with a backslash inside double quotes. +" +" The second argument is the default count. This is the number that will be +" prefixed to the mapping if no explicit numeric argument was given. The +" value of the v:count variable is usually correct and it will be used if the +" second parameter is omitted. If your mapping doesn't accept a numeric +" argument and you never want to receive one, pass a value of -1. +" +" Make sure to call the repeat#set function _after_ making changes to the +" file. +" +" For mappings that use a register and want the same register used on +" repetition, use: +" +" silent! call repeat#setreg("\MappingToRepeatCommand", v:register) +" +" This function can (and probably needs to be) called before making changes to +" the file (as those typically clear v:register). Therefore, the call sequence +" in your mapping will look like this: +" +" nnoremap MyMap +" \ :execute 'silent! call repeat#setreg("\Plug>MyMap", v:register)' +" \ call MyFunction(v:register, ...) +" \ silent! call repeat#set("\Plug>MyMap") + +if exists("g:loaded_repeat") || &cp || v:version < 700 + finish +endif +let g:loaded_repeat = 1 + +let g:repeat_tick = -1 +let g:repeat_reg = ['', ''] + +" Special function to avoid spurious repeats in a related, naturally repeating +" mapping when your repeatable mapping doesn't increase b:changedtick. +function! repeat#invalidate() + let g:repeat_tick = -1 +endfunction + +function! repeat#set(sequence,...) + let g:repeat_sequence = a:sequence + let g:repeat_count = a:0 ? a:1 : v:count + let g:repeat_tick = b:changedtick +endfunction + +function! repeat#setreg(sequence,register) + let g:repeat_reg = [a:sequence, a:register] +endfunction + +function! repeat#run(count) + if g:repeat_tick == b:changedtick + let r = '' + if g:repeat_reg[0] ==# g:repeat_sequence && !empty(g:repeat_reg[1]) + if g:repeat_reg[1] ==# '=' + " This causes a re-evaluation of the expression on repeat, which + " is what we want. + let r = '"=' . getreg('=', 1) . "\" + else + let r = '"' . g:repeat_reg[1] + endif + endif + + let c = g:repeat_count + let s = g:repeat_sequence + let cnt = c == -1 ? "" : (a:count ? a:count : (c ? c : '')) + call feedkeys(r . cnt, 'n') + call feedkeys(s) + else + call feedkeys((a:count ? a:count : '') . '.', 'n') + endif +endfunction + +function! repeat#wrap(command,count) + let preserve = (g:repeat_tick == b:changedtick) + exe 'norm! '.(a:count ? a:count : '').a:command . (&foldopen =~# 'undo' ? 'zv' : '') + if preserve + let g:repeat_tick = b:changedtick + endif +endfunction + +nnoremap . :call repeat#run(v:count) +nnoremap u :call repeat#wrap('u',v:count) +if maparg('U','n') ==# '' + nnoremap U :call repeat#wrap('U',v:count) +endif +nnoremap :call repeat#wrap("\C-R>",v:count) + +augroup repeatPlugin + autocmd! + autocmd BufLeave,BufWritePre,BufReadPre * let g:repeat_tick = (g:repeat_tick == b:changedtick || g:repeat_tick == 0) ? 0 : -1 + autocmd BufEnter,BufWritePost * if g:repeat_tick == 0|let g:repeat_tick = b:changedtick|endif +augroup END + +" vim:set ft=vim et sw=4 sts=4: diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8f5e52c..44e9233 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,12 +1,12 @@ - -$LOAD_PATH.unshift("C:/Projects/Libraries/vimbot/lib") - -require "vimbot" - -PLUGIN_ROOT = File.expand_path("../..", __FILE__) -VIM_REPEAT_PATH = File.expand_path("spec/fixtures/repeat.vim", PLUGIN_ROOT) - -RSpec.configure do |c| - c.alias_it_should_behave_like_to :it_has_behavior, 'has behavior:' -end - + +$LOAD_PATH.unshift("C:/Projects/Libraries/vimbot/lib") + +require "vimbot" + +PLUGIN_ROOT = File.expand_path("../..", __FILE__) +VIM_REPEAT_PATH = File.expand_path("spec/fixtures/repeat.vim", PLUGIN_ROOT) + +RSpec.configure do |c| + c.alias_it_should_behave_like_to :it_has_behavior, 'has behavior:' +end +