├── README ├── autoload └── vis.vim ├── doc └── vis.txt └── plugin ├── cecutil.vim └── visPlugin.vim /README: -------------------------------------------------------------------------------- 1 | This is a mirror of http://www.vim.org/scripts/script.php?script_id=1195 2 | 3 | I'm hereby making the script, long available at http://www.drchip.org/astronaut/vim/index.html#VIS, also available here at vim.sf.net. There are two commands made available: B and S. 4 | 5 | 6 | ---------------- 7 | Visual Commands: 8 | ---------------- 9 | 10 | B 11 | 12 | Use V, v, or ctrl-v to visually mark some region. Then use 13 | :B cmd (this command will appear as: :'<,'>B cmd) 14 | 15 | The command will then be applied to just the visually selected region. 16 | For examples: 17 | 18 | Use ctrl-v to select a column and then do a substitute on just that column. 19 | ctrl-v ..move.. :B s/pattern/becomes/ 20 | 21 | Use ctrl-v to select a column, then apply an external filter to just that column. 22 | ctrl-v ..move.. :B !sort 23 | 24 | 25 | ---------------- 26 | Visual Searches: 27 | ---------------- 28 | 29 | S 30 | 31 | Use V, v, or ctrl-v to visually mark some region. Then use 32 | :S pattern (this search will appear as :'<,'>S pattern) 33 | 34 | The search will then be applied to just the visually selected region. 35 | It may be repeated with n and N commands, too (without having to 36 | re-mark the region). A plain S will apply the last :S-pattern 37 | to the latest selected region. 38 | 39 | 40 | ----------------- 41 | Related Subjects: 42 | ----------------- 43 | 44 | * For incrementing/decrementing numbers, dates, and letters in a column: see vimscript#670 and vimtip#150 45 | * For sorting based on a column (column-restricted, whole lines but column-keyed), see vimtip#588 46 | * For overwriting visual blocks with other visual blocks: see vimtip#808 47 | * For more on applying substitutes to a visual block: see vimtip#63 48 | * For swapping pairs of visual blocks: see vimtip#329 49 | 50 | (alpha/beta version available at http://www.drchip.org/astronaut/vim/index.html#VIS) 51 | 52 | -------------------------------------------------------------------------------- /autoload/vis.vim: -------------------------------------------------------------------------------- 1 | " vis.vim: 2 | " Function: Perform an Ex command on a visual highlighted block (CTRL-V). 3 | " Version: 20 4 | " Date: Mar 29, 2013 5 | " GetLatestVimScripts: 1066 1 cecutil.vim 6 | " GetLatestVimScripts: 1195 1 :AutoInstall: vis.vim 7 | " Verse: For am I now seeking the favor of men, or of God? Or am I striving 8 | " to please men? For if I were still pleasing men, I wouldn't be a servant 9 | " of Christ. (Gal 1:10, WEB) 10 | " 11 | " Author: Charles E. Campbell - NOSPAM 12 | " Based on idea of Stefan Roemer 13 | " 14 | " ------------------------------------------------------------------------------ 15 | " Initialization: {{{1 16 | " Exit quickly when has already been loaded or 17 | " when 'compatible' is set 18 | if &cp || exists("g:loaded_vis") 19 | finish 20 | endif 21 | let s:keepcpo = &cpo 22 | let g:loaded_vis = "v20" 23 | set cpo&vim 24 | 25 | " --------------------------------------------------------------------- 26 | " Support Functions: {{{1 27 | " ------------------------------------------------------------------------------ 28 | " vis#VisBlockCmd: {{{2 29 | fun! vis#VisBlockCmd(cmd) range 30 | " call Dfunc("vis#VisBlockCmd(cmd<".a:cmd.">") 31 | 32 | " retain and re-use same visual mode 33 | sil! keepj norm `< 34 | let curposn = SaveWinPosn(0) 35 | let vmode = visualmode() 36 | " call Decho("vmode<".vmode.">") 37 | 38 | call s:SaveUserSettings() 39 | 40 | if vmode == 'V' 41 | " call Decho("cmd<".a:cmd.">") 42 | exe "keepj '<,'>".a:cmd 43 | 44 | else " handle v and ctrl-v 45 | " Initialize so begcol") 48 | if vmode != 'v' 49 | if begcol > endcol 50 | let begcol = s:VirtcolM1(">") 51 | let endcol = s:VirtcolM1("<") 52 | endif 53 | endif 54 | 55 | " Initialize so that begline endline 59 | let begline = a:lastline 60 | let endline = a:firstline 61 | endif 62 | " call Decho('beg['.begline.','.begcol.'] end['.endline.','.endcol.']') 63 | 64 | " ======================= 65 | " Modify Selected Region: 66 | " ======================= 67 | " 1. delete selected region into register "a 68 | " call Decho("delete selected region into register a") 69 | sil! keepj norm! gv"ad 70 | 71 | " 2. put cut-out text at end-of-file 72 | " call Decho("put cut-out text at end-of-file") 73 | keepj $ 74 | keepj pu_ 75 | let lastline= line("$") 76 | sil! keepj norm! "ap 77 | " call Decho("reg-A<".@a.">") 78 | 79 | " 3. apply command to those lines 80 | let curline = line(".") 81 | ka 82 | keepj $ 83 | " call Decho("apply command<".a:cmd."> to those lines (curline=".line(".").")") 84 | exe "keepj ". curline.',$'.a:cmd 85 | 86 | " 4. visual-block select the modified text in those lines 87 | " call Decho("visual-block select modified text at end-of-file") 88 | exe "keepj ".lastline 89 | exe "keepj norm! 0".vmode."G$\"ad" 90 | 91 | " 5. delete excess lines 92 | " call Decho("delete excess lines") 93 | exe "sil! keepj ".lastline.',$d' 94 | 95 | " 6. put modified text back into file 96 | " call Decho("put modifed text back into file (beginning=".begline.".".begcol.")") 97 | exe "keepj ".begline 98 | if begcol > 1 99 | exe 'sil! keepj norm! '.begcol."\\"ap" 100 | elseif begcol == 1 101 | norm! 0"ap 102 | else 103 | norm! 0"aP 104 | endif 105 | 106 | " 7. attempt to restore gv -- this is limited, it will 107 | " select the same size region in the same place as before, 108 | " not necessarily the changed region 109 | let begcol= begcol+1 110 | let endcol= endcol+1 111 | exe "sil keepj ".begline 112 | exe 'sil keepj norm! '.begcol."\".vmode 113 | exe "sil keepj ".endline 114 | exe 'sil keepj norm! '.endcol."\\" 115 | exe "sil keepj ".begline 116 | exe 'sil keepj norm! '.begcol."\" 117 | endif 118 | 119 | call s:RestoreUserSettings() 120 | call RestoreWinPosn(curposn) 121 | 122 | " call Dret("vis#VisBlockCmd") 123 | endfun 124 | 125 | " ------------------------------------------------------------------------------ 126 | " vis#VisBlockSearch: {{{2 127 | fun! vis#VisBlockSearch(...) range 128 | " call Dfunc("vis#VisBlockSearch() a:0=".a:0." lines[".a:firstline.",".a:lastline."]") 129 | let keepic= &ic 130 | set noic 131 | 132 | if a:0 >= 1 && strlen(a:1) > 0 133 | let pattern = a:1 134 | let s:pattern = pattern 135 | " call Decho("a:0=".a:0.": pattern<".pattern.">") 136 | elseif exists("s:pattern") 137 | let pattern= s:pattern 138 | else 139 | let pattern = @/ 140 | let s:pattern = pattern 141 | endif 142 | let vmode= visualmode() 143 | 144 | " collect search restrictions 145 | let firstline = line("'<") 146 | let lastline = line("'>") 147 | let firstcolm1 = s:VirtcolM1("<") 148 | let lastcolm1 = s:VirtcolM1(">") 149 | " call Decho("1: firstline=".firstline." lastline=".lastline." firstcolm1=".firstcolm1." lastcolm1=".lastcolm1) 150 | 151 | if(firstline > lastline) 152 | let firstline = line("'>") 153 | let lastline = line("'<") 154 | if a:0 >= 1 155 | keepj norm! `> 156 | endif 157 | else 158 | if a:0 >= 1 159 | keepj norm! `< 160 | endif 161 | endif 162 | " call Decho("2: firstline=".firstline." lastline=".lastline." firstcolm1=".firstcolm1." lastcolm1=".lastcolm1) 163 | 164 | if vmode != 'v' 165 | if firstcolm1 > lastcolm1 166 | let tmp = firstcolm1 167 | let firstcolm1 = lastcolm1 168 | let lastcolm1 = tmp 169 | endif 170 | endif 171 | " call Decho("3: firstline=".firstline." lastline=".lastline." firstcolm1=".firstcolm1." lastcolm1=".lastcolm1) 172 | 173 | let firstlinem1 = firstline - 1 174 | let lastlinep1 = lastline + 1 175 | let firstcol = firstcolm1 + 1 176 | let lastcol = lastcolm1 + 1 177 | let lastcolp1 = lastcol + 1 178 | " call Decho("4: firstline=".firstline." lastline=".lastline." firstcolm1=".firstcolm1." lastcolp1=".lastcolp1) 179 | 180 | " construct search string 181 | if vmode == 'V' 182 | let srch= '\%(\%>'.firstlinem1.'l\%<'.lastlinep1.'l\)\&' 183 | " call Decho("V srch: ".srch) 184 | elseif vmode == 'v' 185 | if firstline == lastline || firstline == lastlinep1 186 | let srch= '\%(\%'.firstline.'l\%>'.firstcolm1.'v\%<'.lastcolp1.'v\)\&' 187 | else 188 | let srch= '\%(\%(\%'.firstline.'l\%>'.firstcolm1.'v\)\|\%(\%'.lastline.'l\%<'.lastcolp1.'v\)\|\%(\%>'.firstline.'l\%<'.lastline.'l\)\)\&' 189 | endif 190 | " call Decho("v srch: ".srch) 191 | else 192 | let srch= '\%(\%>'.firstlinem1.'l\%>'.firstcolm1.'v\%<'.lastlinep1.'l\%<'.lastcolp1.'v\)\&' 193 | " call Decho("^v srch: ".srch) 194 | endif 195 | 196 | " perform search 197 | if a:0 <= 1 198 | " call Decho("Search forward: <".srch.pattern.">") 199 | call search(srch.pattern) 200 | let @/= srch.pattern 201 | 202 | elseif a:0 == 2 203 | " call Decho("Search backward: <".srch.pattern.">") 204 | call search(srch.pattern,a:2) 205 | let @/= srch.pattern 206 | endif 207 | 208 | " restore ignorecase 209 | let &ic= keepic 210 | 211 | " call Dret("vis#VisBlockSearch <".srch.">") 212 | return srch 213 | endfun 214 | 215 | " ------------------------------------------------------------------------------ 216 | " s:VirtcolM1: usually a virtcol(mark)-1, but due to tabs this can be different {{{2 217 | fun! s:VirtcolM1(mark) 218 | " call Dfunc('s:VirtcolM1("'.a:mark.'")') 219 | 220 | if virtcol("'".a:mark) <= 1 221 | " call Dret("s:VirtcolM1 0") 222 | return 0 223 | endif 224 | 225 | if &ve == "block" 226 | " Works around a ve=all vs ve=block difference with virtcol(). 227 | " Since s:SaveUserSettings() changes ve to ve=all, this small 228 | " ve override only affects vis#VisBlockSearch(). 229 | set ve=all 230 | " call Decho("temporarily setting ve=all") 231 | endif 232 | 233 | " call Decho("exe norm! `".a:mark."h") 234 | exe "keepj norm! `".a:mark."h" 235 | 236 | let vekeep = &ve 237 | let vc = virtcol(".") 238 | let &ve = vekeep 239 | 240 | " call Dret("s:VirtcolM1 ".vc) 241 | return vc 242 | endfun 243 | 244 | " --------------------------------------------------------------------- 245 | " s:SaveUserSettings: save options which otherwise may interfere {{{2 246 | fun! s:SaveUserSettings() 247 | " call Dfunc("s:SaveUserSettings()") 248 | let s:keep_lz = &lz 249 | let s:keep_fen = &fen 250 | let s:keep_fo = &fo 251 | let s:keep_ic = &ic 252 | let s:keep_magic = &magic 253 | let s:keep_sol = &sol 254 | let s:keep_ve = &ve 255 | let s:keep_ww = &ww 256 | let s:keep_cedit = &cedit 257 | set lz magic nofen noic nosol ve=all ww= fo=nroql2 cedit& 258 | 259 | " Save any contents in register a 260 | let s:rega= @a 261 | 262 | " call Dret("s:SaveUserSettings") 263 | endfun 264 | 265 | " --------------------------------------------------------------------- 266 | " s:RestoreUserSettings: restore register a and options {{{2 267 | fun! s:RestoreUserSettings() 268 | " call Dfunc("s:RestoreUserSettings()") 269 | let @a = s:rega 270 | let &cedit = s:keep_cedit 271 | let &fen = s:keep_fen 272 | let &fo = s:keep_fo 273 | let &ic = s:keep_ic 274 | let &lz = s:keep_lz 275 | let &sol = s:keep_sol 276 | let &ve = s:keep_ve 277 | let &ww = s:keep_ww 278 | " call Dret("s:RestoreUserSettings") 279 | endfun 280 | 281 | let &cpo= s:keepcpo 282 | unlet s:keepcpo 283 | " ------------------------------------------------------------------------------ 284 | " Modelines: {{{1 285 | " vim: fdm=marker 286 | -------------------------------------------------------------------------------- /doc/vis.txt: -------------------------------------------------------------------------------- 1 | *vis.txt* The Visual Block Tool Mar 29, 2013 2 | 3 | Author: Charles E. Campbell 4 | (remove NOSPAM from Campbell's email first) 5 | Copyright: (c) 2004-2013 by Charles E. Campbell *vis-copyright* 6 | The VIM LICENSE applies to vis.vim and vis.txt 7 | (see |copyright|) except use "vis" instead of "Vim" 8 | No warranty, express or implied. Use At-Your-Own-Risk. 9 | 10 | 11 | ============================================================================== 12 | 1. Contents *vis* *vis-contents* *vis.vim* 13 | 14 | 1. Contents......................: |vis-contents| 15 | 2. Visual Block Manual...........: |vis-manual| 16 | 3. Visual Block Search...........: |vis-srch| 17 | 4. Required......................: |vis-required| 18 | 5. Sorting Examples..............: |vis-sort| 19 | 6. History.......................: |vis-history| 20 | 21 | 22 | ============================================================================== 23 | 2. Visual Block Manual *visman* *vismanual* *vis-manual* *v_:B* 24 | 25 | Performs an arbitrary Ex command on a visual highlighted block. 26 | 27 | Mark visual block (CTRL-V) or visual character (v), 28 | press ':B ' and enter an Ex command [cmd]. 29 | 30 | ex. Use ctrl-v to visually mark the block then use 31 | :B cmd (will appear as :'<,'>B cmd ) 32 | 33 | ex. Use v to visually mark the block then use 34 | :B cmd (will appear as :'<,'>B cmd ) 35 | 36 | Command-line completion is supported for Ex commands. 37 | 38 | There must be a space before the '!' when invoking external shell 39 | commands, eg. ':B !sort'. Otherwise an error is reported. 40 | 41 | Doesn't work as one might expect with Vim's ve option. That's 42 | because ve=all ended up leaving unwanted blank columns, so the 43 | solution chosen was to have the vis function turn ve off temporarily. 44 | 45 | The script works by deleting the selected region into register "a. 46 | The register "a itself is first saved and later restored. The text is 47 | then put at the end-of-file, modified by the user command, and then 48 | deleted back into register "a. Any excess lines are removed, and the 49 | modified text is then put back into the text at its original 50 | location. 51 | 52 | Popular uses for this command include: > 53 | 54 | :B s/pattern/output/ 55 | :B left 56 | :B right 57 | < 58 | 1: apply a substitute command to just the selected visual block, 59 | 2: left justify the selected block, and 60 | 3: right justify the selected block, respectively. 61 | 62 | The concept for this plugin is originally Stefan Roemer's 63 | ; however, both the implementation 64 | and methods used internally have completely changed since Roemer's 65 | version. 66 | 67 | 68 | ============================================================================== 69 | 3. Visual Block Search *vis-search* *vis-srch* *vis-S* 70 | 71 | Visual block search provides two ways to get visual-selection 72 | based searches. Both these methods work well with :set hls 73 | and searching may be repeated with the n or N commands. 74 | 75 | Using // and ?? after a visual selection (the // is only available 76 | if you have g:vis_WantSlashSlash=1 in your <.vimrc> file): 77 | > 78 | ex. select region via V, v, or ctrl-v 79 | //pattern 80 | < 81 | You'll actually get a long leader string of commands to restrict 82 | searches to the requested visual block first. You may then enter 83 | the pattern afterwards. For example, using "v" to select this 84 | paragraph, you'll see something like: > 85 | 86 | /\%(\%(\%80l\%>12v\)\|\%(\%83l\%<53v\)\|\%(\%>80l\%<83l\)\)\& 87 | < 88 | You may enter whatever pattern you want after the \&, and the 89 | pattern search will be restricted to the requested region. 90 | 91 | The "S" command in visual mode: 92 | > 93 | ex. select region via V, v, or ctrl-v 94 | :S pattern 95 | < 96 | The ":S pattern" will appear as ":'<,'>S pattern". This 97 | command will move the cursor to the next instance of the 98 | pattern, restricted to the visually selected block. 99 | 100 | An "R" command was contemplated, but I currently see no way to 101 | get it to continue to search backwards with n and N commands. 102 | 103 | 104 | ============================================================================== 105 | 4. Required *vis-required* 106 | 107 | The latest (v20f or later) now requires vim 7.0 (or later), 108 | as it has been split into plugin/ and an autoload/ sections for 109 | on-demand loading. 110 | 111 | Starting with version 11, required . It uses 112 | the SaveWinPosn() and RestoreWinPosn() functions therein. You may get 113 | from 114 | 115 | http://www.drchip.org/astronaut/vim/index.html#CECUTIL 116 | 117 | 118 | ============================================================================== 119 | 5. Sorting Examples *vis-sort* 120 | 121 | Assume we start with the following three lines: > 122 | 123 | one two three 124 | four five six 125 | seven eight nine 126 | < 127 | Example 1: Use visual-block mode to select the center three 128 | words: ctrl-v select two/five/eight, then :'<,'>sort: > 129 | 130 | four five six 131 | one two three 132 | seven eight nine 133 | < 134 | Note that the visual-block is ignored, other than as a way to 135 | select the three lines. The resulting sorting is done on the 136 | three words "one/four/seven". 137 | 138 | (this example presumed that you're using vim 7.0; if you're using 139 | an earlier version vim, try :'<,\> !sort instead) 140 | 141 | Example 2: Using vis.vim's B command: 142 | Again, use visual-block mode to select the center 143 | three words: ctrl-v select two/five/eight, then :'<,'>B sort: > 144 | 145 | one eight three 146 | four five six 147 | seven two nine 148 | < 149 | This operation sorts the selected three words (two/five/eight), 150 | leaving all characters outside the visual block alone. 151 | 152 | (this example presumed that you're using vim 7.0; if you're using 153 | an earlier version vim, try :'<,\> !sort instead) 154 | 155 | Example 3: Using vissort.vim's Vissort() function 156 | Use visual block mode to select the center three words; 157 | ctrl-v select two/five/eight, then :'<,'>Vissort: > 158 | 159 | seven eight nine 160 | four five six 161 | one two three 162 | < 163 | This time, the entire lines are sorted, but the sorting is done 164 | based on the visual-block selected region (ie. two/five/eight). 165 | 166 | 167 | ============================================================================== 168 | 6. History *vis-history* {{{1 169 | 170 | v20 : May 20, 2009 - cecutil bugfix 171 | May 19, 2010 - split into plugin/ and autoload/ for faster 172 | loading and on-demand loading. 173 | Mar 18, 2013 - (Gary Johnson) pointed out that changing 174 | cedit to caused problems with visincr; 175 | the cedit setting is now bypassed in vis, too. 176 | Mar 29, 2013 - Fixed a problem with vis#VisBlockCmd() where it 177 | missed substitutes due to a short last line. 178 | s:SaveUserSettings() now makes ve=all instead of 179 | ve= (see |'ve'|) 180 | v19 : Jan 06, 2006 - small modification included to allow AlignMaps 181 | maps to work (visual select, :B norm \somemap) 182 | - cecutil updated to use keepjumps 183 | Jan 24, 2006 - works around formatoption setting 184 | Jan 25, 2006 - uses SaveWinPosn(0) to avoid SWP stack use 185 | v18 : Jul 11, 2005 - vis.vim now works around a virtcol() behavior 186 | difference between ve=all vs ve=block 187 | v17 : Apr 25, 2005 - vis.vim now uses cecutil (SaveWinPosn, etc) so the 188 | tarball now includes a copy of cecutil.vim 189 | v16 : Feb 02, 2005 - fixed a bug with visual-block + S ; the first line 190 | was being omitted in the search 191 | Mar 01, 2005 - used instead of '' 192 | Apr 13, 2005 - :'<,'>S plus v had a bug with one or two line 193 | selections (tnx to Vigil for pointing this out) 194 | Apr 14, 2005 - set ignorecase caused visual-block searching 195 | to confuse visual modes "v" and "V" 196 | v15 : Feb 01, 2005 - includes some additions to the help 197 | v14 : Sep 28, 2004 - visual-block based searching now supported. One 198 | do this either with :'<,'>S pattern or with a / or ? 199 | Jan 31, 2005 - fixed help file 200 | v13 : Jul 16, 2004 - folding commands added to source 201 | - GetLatestVimScript hook added for automatic updating 202 | v12 : Jun 14, 2004 - bugfix (folding interfered) 203 | v11 : May 18, 2004 - Included calls to SaveWinPosn() and RestoreWinPosn() 204 | to prevent unwanted movement of the cursor and window. 205 | As a result, now requires 206 | (see |vis-required|). 207 | v10 : Feb 11, 2003 - bugfix (ignorecase option interfered with v) 208 | v9 : Sep 10, 2002 - bugfix (left Decho on, now commented out) 209 | v8 : Sep 09, 2002 - bugfix (first column problem) 210 | v7 : Sep 05, 2002 - bugfix (was forcing begcolG$\"ad 216 | - Fixed double-loading (was commented 217 | out for debugging purposes) 218 | v3 : Jun 20, 2002 - saves ve, unsets ve, restores ve 219 | v2 : June 19, 2002 - Charles Campbell's 220 | v? June 19, 2002 Complete rewrite - is now immune to 221 | the presence of tabs and is considerably faster. 222 | v1 Epoch - Stefan Roemer 223 | wrote the original . 224 | 225 | ============================================================================== 226 | Modelines: {{{1 227 | vim:tw=78:ts=8:ft=help:fdm=marker 228 | -------------------------------------------------------------------------------- /plugin/cecutil.vim: -------------------------------------------------------------------------------- 1 | " cecutil.vim : save/restore window position 2 | " save/restore mark position 3 | " save/restore selected user maps 4 | " Author: Charles E. Campbell 5 | " Version: 18h ASTRO-ONLY 6 | " Date: Oct 16, 2012 7 | " 8 | " Saving Restoring Destroying Marks: {{{1 9 | " call SaveMark(markname) let savemark= SaveMark(markname) 10 | " call RestoreMark(markname) call RestoreMark(savemark) 11 | " call DestroyMark(markname) 12 | " commands: SM RM DM 13 | " 14 | " Saving Restoring Destroying Window Position: {{{1 15 | " call SaveWinPosn() let winposn= SaveWinPosn() 16 | " call RestoreWinPosn() call RestoreWinPosn(winposn) 17 | " \swp : save current window/buffer's position 18 | " \rwp : restore current window/buffer's previous position 19 | " commands: SWP RWP 20 | " 21 | " Saving And Restoring User Maps: {{{1 22 | " call SaveUserMaps(mapmode,maplead,mapchx,suffix) 23 | " call RestoreUserMaps(suffix) 24 | " 25 | " GetLatestVimScripts: 1066 1 :AutoInstall: cecutil.vim 26 | " 27 | " You believe that God is one. You do well. The demons also {{{1 28 | " believe, and shudder. But do you want to know, vain man, that 29 | " faith apart from works is dead? (James 2:19,20 WEB) 30 | "redraw!|call inputsave()|call input("Press to continue")|call inputrestore() 31 | 32 | " --------------------------------------------------------------------- 33 | " Load Once: {{{1 34 | if &cp || exists("g:loaded_cecutil") 35 | finish 36 | endif 37 | let g:loaded_cecutil = "v18h" 38 | let s:keepcpo = &cpo 39 | set cpo&vim 40 | "DechoRemOn 41 | 42 | " ======================= 43 | " Public Interface: {{{1 44 | " ======================= 45 | 46 | " --------------------------------------------------------------------- 47 | " Map Interface: {{{2 48 | if !hasmapto('SaveWinPosn') 49 | map swp SaveWinPosn 50 | endif 51 | if !hasmapto('RestoreWinPosn') 52 | map rwp RestoreWinPosn 53 | endif 54 | nmap SaveWinPosn :call SaveWinPosn() 55 | nmap RestoreWinPosn :call RestoreWinPosn() 56 | 57 | " --------------------------------------------------------------------- 58 | " Command Interface: {{{2 59 | com! -bar -nargs=0 SWP call SaveWinPosn() 60 | com! -bar -nargs=? RWP call RestoreWinPosn() 61 | com! -bar -nargs=1 SM call SaveMark() 62 | com! -bar -nargs=1 RM call RestoreMark() 63 | com! -bar -nargs=1 DM call DestroyMark() 64 | 65 | com! -bar -nargs=1 WLR call s:WinLineRestore() 66 | 67 | if v:version < 630 68 | let s:modifier= "sil! " 69 | else 70 | let s:modifier= "sil! keepj " 71 | endif 72 | 73 | " =============== 74 | " Functions: {{{1 75 | " =============== 76 | 77 | " --------------------------------------------------------------------- 78 | " SaveWinPosn: {{{2 79 | " let winposn= SaveWinPosn() will save window position in winposn variable 80 | " call SaveWinPosn() will save window position in b:cecutil_winposn{b:cecutil_iwinposn} 81 | " let winposn= SaveWinPosn(0) will *only* save window position in winposn variable (no stacking done) 82 | fun! SaveWinPosn(...) 83 | " echomsg "Decho: SaveWinPosn() a:0=".a:0 84 | if line("$") == 1 && getline(1) == "" 85 | " echomsg "Decho: SaveWinPosn : empty buffer" 86 | return "" 87 | endif 88 | let so_keep = &l:so 89 | let siso_keep = &siso 90 | let ss_keep = &l:ss 91 | setlocal so=0 siso=0 ss=0 92 | 93 | let swline = line(".") " save-window line in file 94 | let swcol = col(".") " save-window column in file 95 | if swcol >= col("$") 96 | let swcol= swcol + virtcol(".") - virtcol("$") " adjust for virtual edit (cursor past end-of-line) 97 | endif 98 | let swwline = winline() - 1 " save-window window line 99 | let swwcol = virtcol(".") - wincol() " save-window window column 100 | let savedposn = "" 101 | " echomsg "Decho: sw[".swline.",".swcol."] sww[".swwline.",".swwcol."]" 102 | let savedposn = "call GoWinbufnr(".winbufnr(0).")" 103 | let savedposn = savedposn."|".s:modifier.swline 104 | let savedposn = savedposn."|".s:modifier."norm! 0z\" 105 | if swwline > 0 106 | let savedposn= savedposn.":".s:modifier."call s:WinLineRestore(".(swwline+1).")\" 107 | endif 108 | if swwcol > 0 109 | let savedposn= savedposn.":".s:modifier."norm! 0".swwcol."zl\" 110 | endif 111 | let savedposn = savedposn.":".s:modifier."call cursor(".swline.",".swcol.")\" 112 | 113 | " save window position in 114 | " b:cecutil_winposn_{iwinposn} (stack) 115 | " only when SaveWinPosn() is used 116 | if a:0 == 0 117 | if !exists("b:cecutil_iwinposn") 118 | let b:cecutil_iwinposn= 1 119 | else 120 | let b:cecutil_iwinposn= b:cecutil_iwinposn + 1 121 | endif 122 | " echomsg "Decho: saving posn to SWP stack" 123 | let b:cecutil_winposn{b:cecutil_iwinposn}= savedposn 124 | endif 125 | 126 | let &l:so = so_keep 127 | let &siso = siso_keep 128 | let &l:ss = ss_keep 129 | 130 | " if exists("b:cecutil_iwinposn") " Decho 131 | " echomsg "Decho: b:cecutil_winpos{".b:cecutil_iwinposn."}[".b:cecutil_winposn{b:cecutil_iwinposn}."]" 132 | " else " Decho 133 | " echomsg "Decho: b:cecutil_iwinposn doesn't exist" 134 | " endif " Decho 135 | " echomsg "Decho: SaveWinPosn [".savedposn."]" 136 | return savedposn 137 | endfun 138 | 139 | " --------------------------------------------------------------------- 140 | " RestoreWinPosn: {{{2 141 | " call RestoreWinPosn() 142 | " call RestoreWinPosn(winposn) 143 | fun! RestoreWinPosn(...) 144 | " echomsg "Decho: RestoreWinPosn() a:0=".a:0 145 | " echomsg "Decho: getline(1)<".getline(1).">" 146 | " echomsg "Decho: line(.)=".line(".") 147 | if line("$") == 1 && getline(1) == "" 148 | " echomsg "Decho: RestoreWinPosn : empty buffer" 149 | return "" 150 | endif 151 | let so_keep = &l:so 152 | let siso_keep = &l:siso 153 | let ss_keep = &l:ss 154 | setlocal so=0 siso=0 ss=0 155 | 156 | if a:0 == 0 || a:1 == "" 157 | " use saved window position in b:cecutil_winposn{b:cecutil_iwinposn} if it exists 158 | if exists("b:cecutil_iwinposn") && exists("b:cecutil_winposn{b:cecutil_iwinposn}") 159 | " echomsg "Decho: using stack b:cecutil_winposn{".b:cecutil_iwinposn."}<".b:cecutil_winposn{b:cecutil_iwinposn}.">" 160 | try 161 | exe s:modifier.b:cecutil_winposn{b:cecutil_iwinposn} 162 | catch /^Vim\%((\a\+)\)\=:E749/ 163 | " ignore empty buffer error messages 164 | endtry 165 | " normally drop top-of-stack by one 166 | " but while new top-of-stack doesn't exist 167 | " drop top-of-stack index by one again 168 | if b:cecutil_iwinposn >= 1 169 | unlet b:cecutil_winposn{b:cecutil_iwinposn} 170 | let b:cecutil_iwinposn= b:cecutil_iwinposn - 1 171 | while b:cecutil_iwinposn >= 1 && !exists("b:cecutil_winposn{b:cecutil_iwinposn}") 172 | let b:cecutil_iwinposn= b:cecutil_iwinposn - 1 173 | endwhile 174 | if b:cecutil_iwinposn < 1 175 | unlet b:cecutil_iwinposn 176 | endif 177 | endif 178 | else 179 | echohl WarningMsg 180 | echomsg "***warning*** need to SaveWinPosn first!" 181 | echohl None 182 | endif 183 | 184 | else " handle input argument 185 | " echomsg "Decho: using input a:1<".a:1.">" 186 | " use window position passed to this function 187 | exe a:1 188 | " remove a:1 pattern from b:cecutil_winposn{b:cecutil_iwinposn} stack 189 | if exists("b:cecutil_iwinposn") 190 | let jwinposn= b:cecutil_iwinposn 191 | while jwinposn >= 1 " search for a:1 in iwinposn..1 192 | if exists("b:cecutil_winposn{jwinposn}") " if it exists 193 | if a:1 == b:cecutil_winposn{jwinposn} " and the pattern matches 194 | unlet b:cecutil_winposn{jwinposn} " unlet it 195 | if jwinposn == b:cecutil_iwinposn " if at top-of-stack 196 | let b:cecutil_iwinposn= b:cecutil_iwinposn - 1 " drop stacktop by one 197 | endif 198 | endif 199 | endif 200 | let jwinposn= jwinposn - 1 201 | endwhile 202 | endif 203 | endif 204 | 205 | " Seems to be something odd: vertical motions after RWP 206 | " cause jump to first column. The following fixes that. 207 | " Note: was using wincol()>1, but with signs, a cursor 208 | " at column 1 yields wincol()==3. Beeping ensued. 209 | let vekeep= &ve 210 | set ve=all 211 | if virtcol('.') > 1 212 | exe s:modifier."norm! hl" 213 | elseif virtcol(".") < virtcol("$") 214 | exe s:modifier."norm! lh" 215 | endif 216 | let &ve= vekeep 217 | 218 | let &l:so = so_keep 219 | let &l:siso = siso_keep 220 | let &l:ss = ss_keep 221 | 222 | " echomsg "Decho: RestoreWinPosn" 223 | endfun 224 | 225 | " --------------------------------------------------------------------- 226 | " s:WinLineRestore: {{{2 227 | fun! s:WinLineRestore(swwline) 228 | " echomsg "Decho: s:WinLineRestore(swwline=".a:swwline.")" 229 | while winline() < a:swwline 230 | let curwinline= winline() 231 | exe s:modifier."norm! \" 232 | if curwinline == winline() 233 | break 234 | endif 235 | endwhile 236 | " echomsg "Decho: s:WinLineRestore" 237 | endfun 238 | 239 | " --------------------------------------------------------------------- 240 | " GoWinbufnr: go to window holding given buffer (by number) {{{2 241 | " Prefers current window; if its buffer number doesn't match, 242 | " then will try from topleft to bottom right 243 | fun! GoWinbufnr(bufnum) 244 | " call Dfunc("GoWinbufnr(".a:bufnum.")") 245 | if winbufnr(0) == a:bufnum 246 | " call Dret("GoWinbufnr : winbufnr(0)==a:bufnum") 247 | return 248 | endif 249 | winc t 250 | let first=1 251 | while winbufnr(0) != a:bufnum && (first || winnr() != 1) 252 | winc w 253 | let first= 0 254 | endwhile 255 | " call Dret("GoWinbufnr") 256 | endfun 257 | 258 | " --------------------------------------------------------------------- 259 | " SaveMark: sets up a string saving a mark position. {{{2 260 | " For example, SaveMark("a") 261 | " Also sets up a global variable, g:savemark_{markname} 262 | fun! SaveMark(markname) 263 | " call Dfunc("SaveMark(markname<".a:markname.">)") 264 | let markname= a:markname 265 | if strpart(markname,0,1) !~ '\a' 266 | let markname= strpart(markname,1,1) 267 | endif 268 | " call Decho("markname=".markname) 269 | 270 | let lzkeep = &lz 271 | set lz 272 | 273 | if 1 <= line("'".markname) && line("'".markname) <= line("$") 274 | let winposn = SaveWinPosn(0) 275 | exe s:modifier."norm! `".markname 276 | let savemark = SaveWinPosn(0) 277 | let g:savemark_{markname} = savemark 278 | let savemark = markname.savemark 279 | call RestoreWinPosn(winposn) 280 | else 281 | let g:savemark_{markname} = "" 282 | let savemark = "" 283 | endif 284 | 285 | let &lz= lzkeep 286 | 287 | " call Dret("SaveMark : savemark<".savemark.">") 288 | return savemark 289 | endfun 290 | 291 | " --------------------------------------------------------------------- 292 | " RestoreMark: {{{2 293 | " call RestoreMark("a") -or- call RestoreMark(savemark) 294 | fun! RestoreMark(markname) 295 | " call Dfunc("RestoreMark(markname<".a:markname.">)") 296 | 297 | if strlen(a:markname) <= 0 298 | " call Dret("RestoreMark : no such mark") 299 | return 300 | endif 301 | let markname= strpart(a:markname,0,1) 302 | if markname !~ '\a' 303 | " handles 'a -> a styles 304 | let markname= strpart(a:markname,1,1) 305 | endif 306 | " call Decho("markname=".markname." strlen(a:markname)=".strlen(a:markname)) 307 | 308 | let lzkeep = &lz 309 | set lz 310 | let winposn = SaveWinPosn(0) 311 | 312 | if strlen(a:markname) <= 2 313 | if exists("g:savemark_{markname}") && strlen(g:savemark_{markname}) != 0 314 | " use global variable g:savemark_{markname} 315 | " call Decho("use savemark list") 316 | call RestoreWinPosn(g:savemark_{markname}) 317 | exe "norm! m".markname 318 | endif 319 | else 320 | " markname is a savemark command (string) 321 | " call Decho("use savemark command") 322 | let markcmd= strpart(a:markname,1) 323 | call RestoreWinPosn(markcmd) 324 | exe "norm! m".markname 325 | endif 326 | 327 | call RestoreWinPosn(winposn) 328 | let &lz = lzkeep 329 | 330 | " call Dret("RestoreMark") 331 | endfun 332 | 333 | " --------------------------------------------------------------------- 334 | " DestroyMark: {{{2 335 | " call DestroyMark("a") -- destroys mark 336 | fun! DestroyMark(markname) 337 | " call Dfunc("DestroyMark(markname<".a:markname.">)") 338 | 339 | " save options and set to standard values 340 | let reportkeep= &report 341 | let lzkeep = &lz 342 | set lz report=10000 343 | 344 | let markname= strpart(a:markname,0,1) 345 | if markname !~ '\a' 346 | " handles 'a -> a styles 347 | let markname= strpart(a:markname,1,1) 348 | endif 349 | " call Decho("markname=".markname) 350 | 351 | let curmod = &mod 352 | let winposn = SaveWinPosn(0) 353 | 1 354 | let lineone = getline(".") 355 | exe "k".markname 356 | d 357 | put! =lineone 358 | let &mod = curmod 359 | call RestoreWinPosn(winposn) 360 | 361 | " restore options to user settings 362 | let &report = reportkeep 363 | let &lz = lzkeep 364 | 365 | " call Dret("DestroyMark") 366 | endfun 367 | 368 | " --------------------------------------------------------------------- 369 | " QArgSplitter: to avoid \ processing by , is needed. {{{2 370 | " However, doesn't split at all, so this one returns a list 371 | " with splits at all whitespace (only!), plus a leading length-of-list. 372 | " The resulting list: qarglist[0] corresponds to a:0 373 | " qarglist[i] corresponds to a:{i} 374 | fun! QArgSplitter(qarg) 375 | " call Dfunc("QArgSplitter(qarg<".a:qarg.">)") 376 | let qarglist = split(a:qarg) 377 | let qarglistlen = len(qarglist) 378 | let qarglist = insert(qarglist,qarglistlen) 379 | " call Dret("QArgSplitter ".string(qarglist)) 380 | return qarglist 381 | endfun 382 | 383 | " --------------------------------------------------------------------- 384 | " ListWinPosn: {{{2 385 | "fun! ListWinPosn() " Decho 386 | " if !exists("b:cecutil_iwinposn") || b:cecutil_iwinposn == 0 " Decho 387 | " call Decho("nothing on SWP stack") " Decho 388 | " else " Decho 389 | " let jwinposn= b:cecutil_iwinposn " Decho 390 | " while jwinposn >= 1 " Decho 391 | " if exists("b:cecutil_winposn{jwinposn}") " Decho 392 | " call Decho("winposn{".jwinposn."}<".b:cecutil_winposn{jwinposn}.">") " Decho 393 | " else " Decho 394 | " call Decho("winposn{".jwinposn."} -- doesn't exist") " Decho 395 | " endif " Decho 396 | " let jwinposn= jwinposn - 1 " Decho 397 | " endwhile " Decho 398 | " endif " Decho 399 | "endfun " Decho 400 | "com! -nargs=0 LWP call ListWinPosn() " Decho 401 | 402 | " --------------------------------------------------------------------- 403 | " SaveUserMaps: this function sets up a script-variable (s:restoremap) {{{2 404 | " which can be used to restore user maps later with 405 | " call RestoreUserMaps() 406 | " 407 | " mapmode - see :help maparg for details (n v o i c l "") 408 | " ex. "n" = Normal 409 | " The letters "b" and "u" are optional prefixes; 410 | " The "u" means that the map will also be unmapped 411 | " The "b" means that the map has a qualifier 412 | " ex. "un" = Normal + unmapping 413 | " ex. "bn" = Normal + 414 | " ex. "bun" = Normal + + unmapping 415 | " ex. "ubn" = Normal + + unmapping 416 | " maplead - see mapchx 417 | " mapchx - "" handled as a single map item. 418 | " ex. "" 419 | " - "string" a string of single letters which are actually 420 | " multiple two-letter maps (using the maplead: 421 | " maplead . each_character_in_string) 422 | " ex. maplead="\" and mapchx="abc" saves user mappings for 423 | " \a, \b, and \c 424 | " Of course, if maplead is "", then for mapchx="abc", 425 | " mappings for a, b, and c are saved. 426 | " - :something handled as a single map item, w/o the ":" 427 | " ex. mapchx= ":abc" will save a mapping for "abc" 428 | " suffix - a string unique to your plugin 429 | " ex. suffix= "DrawIt" 430 | fun! SaveUserMaps(mapmode,maplead,mapchx,suffix) 431 | " call Dfunc("SaveUserMaps(mapmode<".a:mapmode."> maplead<".a:maplead."> mapchx<".a:mapchx."> suffix<".a:suffix.">)") 432 | 433 | if !exists("s:restoremap_{a:suffix}") 434 | " initialize restoremap_suffix to null string 435 | let s:restoremap_{a:suffix}= "" 436 | endif 437 | 438 | " set up dounmap: if 1, then save and unmap (a:mapmode leads with a "u") 439 | " if 0, save only 440 | let mapmode = a:mapmode 441 | let dounmap = 0 442 | let dobuffer = "" 443 | while mapmode =~ '^[bu]' 444 | if mapmode =~ '^u' 445 | let dounmap = 1 446 | let mapmode = strpart(a:mapmode,1) 447 | elseif mapmode =~ '^b' 448 | let dobuffer = " " 449 | let mapmode = strpart(a:mapmode,1) 450 | endif 451 | endwhile 452 | " call Decho("dounmap=".dounmap." dobuffer<".dobuffer.">") 453 | 454 | " save single map :...something... 455 | if strpart(a:mapchx,0,1) == ':' 456 | " call Decho("save single map :...something...") 457 | let amap= strpart(a:mapchx,1) 458 | if amap == "|" || amap == "\" 459 | let amap= "\".amap 460 | endif 461 | let amap = a:maplead.amap 462 | let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|:sil! ".mapmode."unmap ".dobuffer.amap 463 | if maparg(amap,mapmode) != "" 464 | let maprhs = substitute(maparg(amap,mapmode),'|','','ge') 465 | let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|:".mapmode."map ".dobuffer.amap." ".maprhs 466 | endif 467 | if dounmap 468 | exe "sil! ".mapmode."unmap ".dobuffer.amap 469 | endif 470 | 471 | " save single map 472 | elseif strpart(a:mapchx,0,1) == '<' 473 | " call Decho("save single map ") 474 | let amap = a:mapchx 475 | if amap == "|" || amap == "\" 476 | let amap= "\".amap 477 | " call Decho("amap[[".amap."]]") 478 | endif 479 | let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|sil! ".mapmode."unmap ".dobuffer.amap 480 | if maparg(a:mapchx,mapmode) != "" 481 | let maprhs = substitute(maparg(amap,mapmode),'|','','ge') 482 | let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|".mapmode."map ".dobuffer.amap." ".maprhs 483 | endif 484 | if dounmap 485 | exe "sil! ".mapmode."unmap ".dobuffer.amap 486 | endif 487 | 488 | " save multiple maps 489 | else 490 | " call Decho("save multiple maps") 491 | let i= 1 492 | while i <= strlen(a:mapchx) 493 | let amap= a:maplead.strpart(a:mapchx,i-1,1) 494 | if amap == "|" || amap == "\" 495 | let amap= "\".amap 496 | endif 497 | let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|sil! ".mapmode."unmap ".dobuffer.amap 498 | if maparg(amap,mapmode) != "" 499 | let maprhs = substitute(maparg(amap,mapmode),'|','','ge') 500 | let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|".mapmode."map ".dobuffer.amap." ".maprhs 501 | endif 502 | if dounmap 503 | exe "sil! ".mapmode."unmap ".dobuffer.amap 504 | endif 505 | let i= i + 1 506 | endwhile 507 | endif 508 | " call Dret("SaveUserMaps : restoremap_".a:suffix.": ".s:restoremap_{a:suffix}) 509 | endfun 510 | 511 | " --------------------------------------------------------------------- 512 | " RestoreUserMaps: {{{2 513 | " Used to restore user maps saved by SaveUserMaps() 514 | fun! RestoreUserMaps(suffix) 515 | " call Dfunc("RestoreUserMaps(suffix<".a:suffix.">)") 516 | if exists("s:restoremap_{a:suffix}") 517 | let s:restoremap_{a:suffix}= substitute(s:restoremap_{a:suffix},'|\s*$','','e') 518 | if s:restoremap_{a:suffix} != "" 519 | " call Decho("exe ".s:restoremap_{a:suffix}) 520 | exe "sil! ".s:restoremap_{a:suffix} 521 | endif 522 | unlet s:restoremap_{a:suffix} 523 | endif 524 | " call Dret("RestoreUserMaps") 525 | endfun 526 | 527 | " ============== 528 | " Restore: {{{1 529 | " ============== 530 | let &cpo= s:keepcpo 531 | unlet s:keepcpo 532 | 533 | " ================ 534 | " Modelines: {{{1 535 | " ================ 536 | " vim: ts=4 fdm=marker 537 | -------------------------------------------------------------------------------- /plugin/visPlugin.vim: -------------------------------------------------------------------------------- 1 | " vis.vim: 2 | " Function: Perform an Ex command on a visual highlighted block (CTRL-V). 3 | " Date: May 18, 2010 4 | " GetLatestVimScripts: 1066 1 cecutil.vim 5 | " GetLatestVimScripts: 1195 1 :AutoInstall: vis.vim 6 | " Verse: For am I now seeking the favor of men, or of God? Or am I striving 7 | " to please men? For if I were still pleasing men, I wouldn't be a servant 8 | " of Christ. (Gal 1:10, WEB) 9 | 10 | " --------------------------------------------------------------------- 11 | " Details: {{{1 12 | " Requires: Requires 6.0 or later (this script is a plugin) 13 | " Requires (see :he vis-required) 14 | " 15 | " Usage: Mark visual block (CTRL-V) or visual character (v), 16 | " press ':B ' and enter an Ex command [cmd]. 17 | " 18 | " ex. Use ctrl-v to visually mark the block then use 19 | " :B cmd (will appear as :'<,'>B cmd ) 20 | " 21 | " ex. Use v to visually mark the block then use 22 | " :B cmd (will appear as :'<,'>B cmd ) 23 | " 24 | " Command-line completion is supported for Ex commands. 25 | " 26 | " Note: There must be a space before the '!' when invoking external shell 27 | " commands, eg. ':B !sort'. Otherwise an error is reported. 28 | " 29 | " Author: Charles E. Campbell - NOSPAM 30 | " Based on idea of Stefan Roemer 31 | " 32 | " ------------------------------------------------------------------------------ 33 | " Initialization: {{{1 34 | " Exit quickly when has already been loaded or 35 | " when 'compatible' is set 36 | if &cp 37 | finish 38 | endif 39 | let s:keepcpo= &cpo 40 | set cpo&vim 41 | 42 | " ------------------------------------------------------------------------------ 43 | " Public Interface: {{{1 44 | " -range : VisBlockCmd operates on the range itself 45 | " -com=command : Ex command and arguments 46 | " -nargs=+ : arguments may be supplied, up to any quantity 47 | com! -range -nargs=+ -com=command B silent ,call vis#VisBlockCmd() 48 | com! -range -nargs=* -com=expression S silent ,call vis#VisBlockSearch() 49 | 50 | " Suggested by Hari -- 51 | if exists("g:vis_WantSlashSlash") && g:vis_WantSlashSlash 52 | vn // /=vis#VisBlockSearch() 53 | endif 54 | vn ?? ?=vis#VisBlockSearch() 55 | 56 | " --------------------------------------------------------------------- 57 | " Modelines: {{{1 58 | " vim: fdm=marker 59 | --------------------------------------------------------------------------------