" multiselect.vim " Author: Hari Krishna (hari_vim at yahoo dot com) " Last Change: 20-Oct-2004 @ 14:47 " Created: 21-Jan-2004 " Requires: Vim-6.2, multvals.vim(3.9), genutils.vim(1.12) " Version: 1.1.1 " Licence: This program is free software; you can redistribute it and/or " modify it under the terms of the GNU General Public License. " See http://www.gnu.org/copyleft/gpl.txt " Acknowledgements: " - This plugin is based on the multipleRanges.vim script (vimscript#352) " version 1.7 by Salman Halim (salmanhalim at hotmail dot com). I first " started with the idea of adding additional features to this plugin, but " I quickly realized that implementing many of those ideas will be a lot " more work unless I use a full featured array functionality, which is why " I have rewritten it to use multvals.vim. Though most of the code has " been modified and a lot of new code has been added (so there is hardly " any code that you would see as same, except that it still has some " structural similarity), I give a lot of credit to Salman Halim for the " original ideas and to get me quickly started with this new plugin. " Download From: " http://www.vim.org/script.php?script_id=953 " Description: " - This plugin extends the Vim's visual mode functionality by allowing you " to define multiple selections before executing a command on them. " - Currently it is limited to the visual-by-line mode. There are other " limitations that exist, e.g., the selection is remembered by line " numbers, so insertions and deletions above the selections will not be " automatically taken care oflinsertions and deletions above the " selections will not be automatically taken care of. " - Here is a set of mappings (with applicable modes) and the equivalent " command that this plugin defines for each operation (for brevity, names " do not exclude the common prefix of MS and defaults do not include " the common prefix of ): " " Mapping Name Default Description~ " AddSelection msa n,v Add current selection to the " selection list (MSAdd). " v if unused. " Ctrl+LeftMouse Make multiple selections using mouse. " DeleteSelection msd n Delete current selection (MSDelete). " ClearSelection msc n,v Clear selections in the given range or " the entire buffer (MSClear). " RestoreSelections msr n Restore previous state of the " selections (MSRestore). After a " ClearSelection, this works like |gv|. " RefreshSelections msf n Refresh/Redraw selections (MSRefresh). " HideSelections msh n Hide the selections (MSHide). Use " MSRefresh to show the sections again. " InvertSelections msi n,v Invert the entire or selected " selection (MSInvert). " ExecCmdOnSelection ms: n Execute a ex mode command on all the " selections (MSExecCmd). " ExecNormalCmdOnSelection msn n Execute a normal mode command on all " the selections (MSExecNormalCmd). " ShowSelections mss n Dump all the current selections on " the screen as "startline,endline" " pairs (MSShow). " NextSelection ms] n Take cursor to the next selection " (MSNext). " PrevSelection ms[ n Take cursor to the previous selection " (MSPrev). " MatchAddSelection msm n,v Add matched lines to the selection " (MSMatchAdd). " VMatchAddSelection msv n,v Add unmatched lines to the selection " (MSVMatchAdd). " " Note that the ex-mode commands that work on selections can also take " arbitrary ranges (see |:range|). " " - To make it easier and quicker to add selections, the plugin unless " disabled by setting the g:no_multiselect_mousemaps, map the Ctrl+Mouse " combination to automatically add the current selection and start a new " one. Just keep the Ctrl key pressed and use left mouse to make " selections. If you are selecting single lines you don't even need to " drag mouse. " " If you instead use keyboard to create visual selections, the plugin " automatically maps (if it is not already mapped) such that you " can just press to add the current selection. The cursor is " placed in the direction of the selection such that it is easier to " continue moving the cursor for making further selections. If you prefer, " you can also add the following mapping in your vimrc to use key " to quickly make multiple single-line selections. " " nnoremap :MSAdd " " - To allow other plugins access selections programmatically, the plugin " defines the following global functions (with prototypes): " " boolean MSSelectionExists() " int MSNumberOfSelections() " void MSStartSelectionIter() " void MSStopSelectionIter() " boolean MSHasNextSelection() " String MSNextSelection() " " First line in the given selection. " int MSFL(String sel) " " Last line in the given selection. " int MSLL(String sel) " " If the plugin is current executing a command on the selection. " boolean MSIsExecuting() " " However the operations are not limited to the above as the selections " themselves are stored as a multvals array in the buffer local variable " called b:multiselRanges (which may not exist if there are no selections " yet in the current buffer), with ":" as the separator and each element " as a "firstline,lastline" pair. You can use any multvals function to " manipulate this array. However it is recommended to stick with the " plugin API as far as possible, as the format of the array could be " changed in the future. " " If your plugin depends on the existence of multiselect, it is " recommended to check the compatibility by comparing the value of " loaded_multiselect with what is expected. The format of this value is " exactly same as the |v:version|. " " Ex: " Delete all the lines in the current selections " MSExecCmd d " Convert all the characters in the current selections to upper case. " MSExecNormalCmd gU " " Installation And Configuration: " - Drop the plugin in a plugin directory under your 'runtimepath'. " - Install the dependent multvals and genutils plugins. " - Configure any key bindings in the above table. " - Set g:multiselTmpMark if you don't like the default value 't'. This " specifies the mark name to be used internaly for keeping track of the " substitutions that split or join lines. " - Set g:multiselUseSynHi to 1 if you prefer using syntax highlighting over " :match highlight to highlight the selections. They both have advantages " and disadvantages, e.g., you can have multiple syntax highlighting rules " coexist, but only one :match highlighting can exist at any time in a " window (so if you have other plugins that depend on :match highlighting, " then you have a collision). However, highlighting selections by syntax " rules is not perfected yet, so in most cases, :match highlighting should " work better than syntax highlighting. " - Set g:multiselAbortOnErrors to 0 if you don't want the plugin to abort " on errors while executing commands on the selections. Alternatively, you " can pass in the appropriate flag/option to avoid generating an error " (such as 'e' flag to :substitute or :silent command in general) " - Customize MultiSelections highlighting group if you don't like the " default "reverse" video. E.g.: " " hi MultiSelections guifg=grey90 guibg=black " " - If you feel that the default mappings defined by the plugin are too " long, consider installing execmap.vim plugin from vim.org scripts " section. " - If you would like to change the modifiers that are used to add " selections through mouse (from the default Alt(or Meta)), use " g:multiselMouseSelAddMod variable. E.g. to use Alt+Shift (or Meta+Shift) " as the modifiers, " " let g:multiselMouseSelAddMod = 'M-S-' " " You can also change the mouse key that is to be used (Right instead of " Left, e.g.) by setting the g:multiselMouseSelAddKey variable. E.g. to " use Alt+RightMouse, you would set: " " let g:multiselMouseSelAddMod = 'M-' " let g:multiselMouseSelAddKey = 'Right' " " Of course, you could also remove the need to press modifiers by " setting g:multiselMouseSelAddMod to an empty string. You will then " essentially replace the normal Vim selection mechanism with that of the " plugin (not advisable if you use Vim's v and ^V modes very much). " TODO: " - While executing commands on multiple ranges, there should be a way " to execute at least normal commands on each line in the range instead of " each range (useful for running on plugin windows). " - Implement yank and paste selections (\msy, \msp), but how should they " really work? " - Support different visual modes. The block mode could be quite " complicated to implement. if exists('loaded_multiselect') finish endif if v:version < 602 echomsg 'multiselect: You need at least Vim 6.2' finish endif " Dependency checks. if !exists('loaded_multvals') runtime plugin/multvals.vim endif if !exists('loaded_multvals') || loaded_multvals < 309 echomsg "multiselect: You need a newer version of multvals.vim plugin" finish endif if !exists('loaded_genutils') runtime plugin/genutils.vim endif if !exists('loaded_genutils') || loaded_genutils < 112 echomsg "multiselect: You need a newer version of genutils.vim plugin" finish endif let loaded_multiselect = 101 " Initializations {{{ if !exists('g:multiselTmpMark') let g:multiselTmpMark = 't' endif if !exists('g:multiselUseSynHi') let g:multiselUseSynHi = 0 endif if !exists('g:multiselAbortOnErrors') let g:multiselAbortOnErrors = 1 endif if !exists('g:multiselMouseSelAddMod') let g:multiselMouseSelAddMod = 'C-' endif if !exists('g:multiselMouseSelAddKey') let g:multiselMouseSelAddKey = 'Left' endif command! -range MSAdd :call AddSelection(, ) command! MSDelete :call DeleteSelection() command! -range=% MSClear :call ClearSelection(, ) command! MSRestore :call RestoreSelections() command! MSRefresh :call RefreshSelections() command! -range=% MSInvert :call InvertSelections(, ) command! MSHide :call HideSelections() command! -nargs=1 -complete=command MSExecCmd \ :call ExecCmdOnSelection(, 0) command! -nargs=1 -complete=command MSExecNormalCmd \ :call s:ExecCmdOnSelection(, 1) command! MSShow :call ShowSelections() command! MSNext :call NextSelection(1) command! MSPrev :call NextSelection(-1) command! -range=% -nargs=1 MSMatchAdd :call AddSelectionsByMatch(, \ , , 0) command! -range=% -nargs=1 MSVMatchAdd :call AddSelectionsByMatch(, \ , , 1) if (! exists("no_plugin_maps") || ! no_plugin_maps) && \ (! exists("no_multiselect_maps") || ! no_multiselect_maps) " [-2f] if (! exists("no_multiselect_mousemaps") || ! no_multiselect_mousemaps) exec 'noremap <'.g:multiselMouseSelAddMod. \ 'LeftMouse> <'.g:multiselMouseSelAddKey.'Mouse>V' exec 'noremap <'.g:multiselMouseSelAddMod. \ 'LeftDrag> <'.g:multiselMouseSelAddKey.'Drag>' exec 'noremap <'.g:multiselMouseSelAddMod. \ 'LeftRelease> :MSAdd<'.g:multiselMouseSelAddKey.'Release>' endif if maparg('', 'v') == '' vnoremap m`:MSAdd`` endif function! s:AddMap(name, map, cmd, mode, silent) if (!hasmapto('MS'.a:name, a:mode)) exec a:mode.'map '.a:map.' MS'.a:name endif exec a:mode.'map '.(a:silent?' ':'').'