├── README.md ├── autoload └── fnr.vim ├── plugin └── fnr.vim └── test ├── fnr.vader └── run /README.md: -------------------------------------------------------------------------------- 1 | vim-fnr 2 | ======= 3 | 4 | Find-N-Replace in Vim with live preview (experimental) 5 | 6 | Installation 7 | ------------ 8 | 9 | Use your favorite plugin manager. vim-fnr requires 10 | [vim-pseudocl](https://github.com/junegunn/vim-pseudocl). 11 | 12 | With [vim-plug](https://github.com/junegunn/vim-plug): 13 | 14 | ```vim 15 | Plug 'junegunn/vim-pseudocl' 16 | Plug 'junegunn/vim-fnr' 17 | ``` 18 | 19 | Usage 20 | ----- 21 | 22 | - Normal mode 23 | - `r` 24 | - Substitution in the range 25 | - `R` 26 | - Substitution of the word under the cursor in the entire document 27 | - Visual mode 28 | - `r` 29 | - Substitution in the selected range 30 | - `R` 31 | - Substitution of the selected string in the entire document 32 | - Command line 33 | - `:FNR` 34 | 35 | The command is repeatable with `.` key if you have installed 36 | [repeat.vim](http://github.com/tpope/vim-repeat). 37 | 38 | ### Special keys 39 | 40 | - `Tab` 41 | - `i` - case-insensitive match 42 | - `w` - word-boundary match (`\`) 43 | - `g` - substitute all occurrences 44 | - `c` - confirm each substitution 45 | - `Tab` or `Enter` to return 46 | - `CTRL-N` or `CTRL-P` 47 | - Auto-completion 48 | 49 | Options 50 | ------- 51 | 52 | ```vim 53 | " Defaults 54 | let g:fnr_flags = 'gc' 55 | let g:fnr_hl_from = 'Todo' 56 | let g:fnr_hl_to = 'IncSearch' 57 | ``` 58 | 59 | Custom mappings 60 | --------------- 61 | 62 | ```vim 63 | nmap r (FNR) 64 | xmap r (FNR) 65 | nmap R (FNR%) 66 | xmap R (FNR%) 67 | ``` 68 | 69 | License 70 | ------- 71 | 72 | MIT 73 | 74 | -------------------------------------------------------------------------------- /autoload/fnr.vim: -------------------------------------------------------------------------------- 1 | " Copyright (c) 2014 Junegunn Choi 2 | " 3 | " MIT License 4 | " 5 | " Permission is hereby granted, free of charge, to any person obtaining 6 | " a copy of this software and associated documentation files (the 7 | " "Software"), to deal in the Software without restriction, including 8 | " without limitation the rights to use, copy, modify, merge, publish, 9 | " distribute, sublicense, and/or sell copies of the Software, and to 10 | " permit persons to whom the Software is furnished to do so, subject to 11 | " the following conditions: 12 | " 13 | " The above copyright notice and this permission notice shall be 14 | " included in all copies or substantial portions of the Software. 15 | " 16 | " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | " EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | " NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | " LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | " OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | " WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | let s:cpo_save = &cpo 25 | set cpo&vim 26 | 27 | hi FNRCursor term=inverse cterm=inverse gui=inverse 28 | 29 | let s:previous = '' 30 | let s:need_repeat = 0 31 | let s:repeat_entire = 0 32 | 33 | function! s:hide_cursor() 34 | if !exists('s:t_ve') 35 | let s:t_ve = &t_ve 36 | set t_ve= 37 | endif 38 | " TODO: GVIM 39 | endfunction 40 | 41 | function! s:display_cursor() 42 | if exists('s:t_ve') 43 | let &t_ve = s:t_ve 44 | unlet s:t_ve 45 | endif 46 | endfunction 47 | 48 | function! s:echo_cursor(hl, str) 49 | execute 'echohl ' . a:hl 50 | try 51 | if s:cursor == len(a:str) 52 | echon a:str 53 | echohl FNRCursor 54 | echon ' ' 55 | return 1 56 | else 57 | if s:cursor > 0 58 | echon strpart(a:str, 0, s:cursor) 59 | end 60 | echohl FNRCursor 61 | echon strpart(a:str, s:cursor, 1) 62 | 63 | execute 'echohl ' . a:hl 64 | echon strpart(a:str, s:cursor + 1) 65 | return 0 66 | endif 67 | finally 68 | echohl None 69 | endtry 70 | endfunction 71 | 72 | function! s:mode_string() 73 | let str = '' 74 | for m in ['i', 'w', 'g', 'c'] 75 | let str .= s:mode =~ m ? toupper(m) : m 76 | endfor 77 | return '('.str.')' 78 | endfunction 79 | 80 | function! s:toggle_mode(o) 81 | if s:mode =~ a:o | let s:mode = substitute(s:mode, a:o, '', 'g') 82 | else | let s:mode .= a:o 83 | endif 84 | endfunction 85 | 86 | function! s:input(prompt, default) 87 | try 88 | call s:display_cursor() 89 | return input(a:prompt, a:default) 90 | finally 91 | call s:hide_cursor() 92 | endtry 93 | endfunction 94 | 95 | function! s:contains(list, val) 96 | return index(a:list, a:val) >= 0 97 | endfunction 98 | 99 | function! g:_fnr_on_unknown_key(key, str, cursor) 100 | if a:key == "\" 101 | let ophase = s:phase 102 | let s:phase = s:phase.'m' 103 | while 1 104 | call g:_fnr_render('', '', '') 105 | let ch = nr2char(getchar()) 106 | if s:contains(['g', 'c', 'i', 'w'], ch) 107 | call s:toggle_mode(ch) 108 | elseif s:contains(["\", "\"], ch) 109 | let s:phase = ophase 110 | break 111 | elseif s:contains(["\", "\"], ch) 112 | throw 'exit' 113 | endif 114 | call g:_fnr_on_change(a:str, '', '') 115 | endwhile 116 | endif 117 | return [g:pseudocl#CONTINUE, a:str, a:cursor] 118 | endfunction 119 | 120 | function! s:char(from, to) 121 | for c in ['/', ',', ':', '@'] 122 | if stridx(a:from.a:to, c) < 0 123 | return c 124 | endif 125 | endfor 126 | return '#' 127 | endfunction 128 | 129 | function! g:_fnr_on_change(new, old, _cursor) 130 | if a:new != a:old 131 | let [ic, wb, we] = s:parse_mode(s:mode) 132 | if s:phase =~ 'f' 133 | let s:from = a:new 134 | call s:matchdelete() 135 | if !empty(a:new) 136 | call add(s:mids, matchadd(s:hl1, s:prefix.ic.wb.s:escape(a:new).we)) 137 | endif 138 | elseif s:phase =~ 't' 139 | " Preview 140 | if s:taint 141 | silent! undo 142 | endif 143 | 144 | let s:to = a:new 145 | let range = 146 | \ s:type == "\" ? "'<,'>" 147 | \ : (line('w0') > line("'<") ? line('w0') : "'<") 148 | \ . ',' 149 | \ . (line('w$') < line("'>") ? line('w$') : "'>") 150 | let c = s:char(s:from, s:to) 151 | let s:command = 's'.c.s:prefix.ic.wb.escape(s:escape(s:from), c).we.c.s:escape_nl_cr(escape(s:to, c.'&~\')).c 152 | silent! execute range.s:command.substitute(s:mode, '[^g]', '', 'g') 153 | let s:taint = 1 154 | 155 | " Update highlights 156 | call s:matchdelete() 157 | if !empty(s:to) 158 | let line = 0 159 | let nocc = 0 160 | let diff = len(s:to) - len(s:from) 161 | 162 | for [l, c] in s:matches 163 | if l == line 164 | let nocc += 1 165 | else 166 | let line = l 167 | let nocc = 0 168 | endif 169 | 170 | let col = c + nocc * diff 171 | call add(s:mids, matchadd(s:hl2, '\%'.l.'l\%'.col.'c\V'.ic.wb.escape(s:to, '\').we)) 172 | endfor 173 | endif 174 | call winrestview(s:view) 175 | endif 176 | redraw 177 | endif 178 | endfunction 179 | 180 | function! g:_fnr_render(_prompt, line, cursor) 181 | call pseudocl#render#clear() 182 | echohl None 183 | echon ':FNR ' 184 | if s:phase =~ 'm' | echohl Label | endif 185 | echon s:mode_string() 186 | echohl None 187 | echon ' { ' 188 | if s:phase == 'f' | echohl Label | endif 189 | echon 'find' 190 | echohl None 191 | echon ': ' 192 | if s:phase == 'f' 193 | call pseudocl#render#echo_line(a:line, a:cursor, 35) 194 | else 195 | echon s:from 196 | echon ' ' 197 | endif 198 | echohl None 199 | echon ', ' 200 | if s:phase == 't' | echohl Label | endif 201 | echon 'replace' 202 | echohl None 203 | echon ': ' 204 | if s:phase == 't' 205 | " TODO: trimming of overly lengthy s:from 206 | call pseudocl#render#echo_line(a:line, a:cursor, 35 + len(s:from)) 207 | else 208 | echon s:to 209 | echon ' ' 210 | endif 211 | echohl None 212 | echon '}' 213 | endfunction 214 | 215 | function! s:message(msg) 216 | echohl WarningMsg 217 | echon "\r" 218 | echon "\r".a:msg 219 | echohl None 220 | endfunction 221 | 222 | function! s:matchdelete() 223 | if !empty(s:mids) 224 | for mid in s:mids 225 | if mid > 0 226 | silent! call matchdelete(mid) 227 | endif 228 | endfor 229 | call remove(s:mids, 0, -1) 230 | endif 231 | endfunction 232 | 233 | function! s:sort(i1, i2) 234 | let [l1, l2] = [a:i1[0], a:i2[0]] 235 | let [c1, c2] = [a:i1[1], a:i2[1]] 236 | 237 | if l1 > l2 238 | return 1 239 | elseif l1 < l2 240 | return -1 241 | elseif c1 > c2 242 | return 1 243 | elseif c1 < c2 244 | return -1 245 | endif 246 | return 0 247 | endfunction 248 | 249 | function! s:parse_mode(mode) 250 | let ic = (a:mode =~# 'i' ? '\c' : '\C') 251 | let [wb, we] = (a:mode =~# 'w' ? ['\<', '\>'] : ['', '']) 252 | return [ic, wb, we] 253 | endfunction 254 | 255 | function! s:escape(pattern) 256 | return s:escape_nl(escape(a:pattern, '\')) 257 | endfunction 258 | 259 | function! s:escape_nl(pattern) 260 | return substitute(a:pattern, "\n", '\\n', 'g') 261 | endfunction 262 | 263 | function! s:escape_nl_cr(pattern) 264 | return substitute(a:pattern, "\n", '\\r', 'g') 265 | endfunction 266 | 267 | function! s:find_matches(pattern) 268 | let found = [] 269 | let matches = [] 270 | let first_occurence = {} 271 | while 1 272 | if empty(first_occurence) 273 | normal! 0 274 | let flag = 'wc' 275 | else 276 | let flag = 'w' 277 | endif 278 | 279 | let [l, c] = searchpos(a:pattern, flag) 280 | if l == 0 && c == 0 || index(found, [l, c]) >= 0 281 | break 282 | elseif empty(first_occurence) 283 | let first_occurence = winsaveview() 284 | endif 285 | call add(found, [l, c]) 286 | if l <= line('w$') && l >= line('w0') 287 | call add(matches, [l, c]) 288 | endif 289 | endwhile 290 | call sort(matches, 's:sort') 291 | 292 | if !empty(first_occurence) 293 | call winrestview(first_occurence) 294 | endif 295 | return [found, matches] 296 | endfunction 297 | 298 | function! s:save_undo() 299 | let &undolevels = &undolevels 300 | if exists(':wundo') 301 | let s:undofile = tempname() 302 | silent execute 'wundo! '.s:undofile 303 | endif 304 | endfunction 305 | 306 | function! s:restore_undo() 307 | if exists(':wundo') && filereadable(s:undofile) 308 | silent execute 'rundo '.s:undofile 309 | call delete(s:undofile) 310 | endif 311 | endfunction 312 | 313 | function! s:save_visual() 314 | let s:visual = [visualmode(), getpos("'<")[1:-1], getpos("'>")[1:-1]] 315 | endfunction 316 | 317 | function! s:restore_visual() 318 | let [mode, p1, p2] = s:visual 319 | let [l0, c0] = [line('.'), col('.')] 320 | let [l1, c1, o1] = p1 321 | let [l2, c2, o2] = p2 322 | if l1 == 0 || l2 == 0 323 | return 324 | endif 325 | let ve_save = &virtualedit 326 | try 327 | if mode == "\" 328 | set virtualedit=all 329 | endif 330 | execute printf("normal! %dG%d|%s%dG%d|\%dG%d|", l1, c1 + o1, mode, l2, c2 + o2, l0, c0) 331 | finally 332 | let &virtualedit = ve_save 333 | endtry 334 | endfunction 335 | 336 | function! fnr#fnr(type, ...) range 337 | silent! call pseudocl#nop() 338 | if !exists('*pseudocl#start') 339 | echoerr 'junegunn/vim-pseudocl not found' 340 | return 341 | endif 342 | let view = winsaveview() 343 | let s:type = a:type 344 | let s:mids = [] 345 | let s:prefix = '\%V\V' 346 | let s:hl1 = get(g:, 'fnr_hl_from', 'Todo') 347 | let s:hl2 = get(g:, 'fnr_hl_to', 'IncSearch') 348 | let s:from = get(g:, '_fnr_cword', '') 349 | let s:to = '?' 350 | let s:mode = get(g:, 'fnr_flags', 'gc') 351 | let s:phase = 'f' 352 | let s:matches = [] 353 | let s:taint = 0 354 | let entire = get(g:, '_fnr_entire', 0) 355 | 356 | call s:save_visual() 357 | let save_yank = [@", @f] 358 | if a:0 > 0 359 | if a:0 == 1 360 | normal! gv"fy 361 | if a:1 == 2 362 | let s:from = @f 363 | let entire = 1 364 | normal! ggVG"fy 365 | endif 366 | else 367 | silent execute printf("normal! %dGV%dG\"fy", a:1, a:2) 368 | endif 369 | else 370 | if s:type == 'line' 371 | silent execute "normal! '[V']\"fy" 372 | elseif s:type == 'block' 373 | silent execute "normal! `[\`]\"fy" 374 | else 375 | silent execute "normal! `[v`]\"fy" 376 | endif 377 | endif 378 | let content = @f 379 | let s:words = pseudocl#complete#extract_words(content) 380 | let [@", @f] = save_yank 381 | call winrestview(view) 382 | 383 | if s:need_repeat 384 | silent! execute "'<,'>". s:previous 385 | return 386 | endif 387 | 388 | let [ic, wb, we] = s:parse_mode(s:mode) 389 | 390 | let cl_save = &cursorline 391 | call s:hide_cursor() 392 | 393 | let opts = { 394 | \ 'renderer': function('g:_fnr_render'), 395 | \ 'words': s:words, 396 | \ 'map': 0, 397 | \ 'remap': { "\": "\", "\": "\" }, 398 | \ 'on_change': function('g:_fnr_on_change'), 399 | \ 'on_unknown_key': function('g:_fnr_on_unknown_key') } 400 | 401 | try 402 | " Find 403 | call g:_fnr_on_change(s:from, '', '') 404 | let s:from = pseudocl#start(extend(opts, { 'input': s:from, 'highlight': s:hl1 })) 405 | if empty(s:from) 406 | return s:message("Empty query") 407 | endif 408 | 409 | " Found 410 | let [ic, wb, we] = s:parse_mode(s:mode) 411 | let [found, s:matches] = s:find_matches(s:prefix.ic.wb.s:escape(s:from).we) 412 | if empty(found) 413 | return s:message("No matches") 414 | endif 415 | 416 | " Replace 417 | let s:phase = 't' 418 | let s:to = s:from 419 | let s:view = winsaveview() 420 | set cursorline 421 | call s:save_undo() 422 | call g:_fnr_on_change(s:to, '', '') 423 | let s:to = pseudocl#start(extend(opts, { 'input': s:to, 'highlight': s:hl2 })) 424 | 425 | silent! undo 426 | call s:restore_undo() 427 | let cmd = s:command.substitute(s:mode, '[^gc]', '', 'g') 428 | let range = "'<,'>" 429 | call histadd(':', entire ? '%'.substitute(cmd, '\\%V', '', '') : range.cmd) 430 | execute range.cmd 431 | " vim-repeat does not seem to support substitution confirmation 432 | let s:previous = s:command.substitute(s:mode, '[^g]', '', 'g') 433 | let s:repeat_entire = entire 434 | silent! call repeat#set("\(FNRRepeat)") 435 | catch /Pattern not found/ 436 | return s:message("No matches") 437 | catch 'exit' 438 | if s:taint 439 | silent! undo 440 | call s:restore_undo() 441 | endif 442 | call s:message("Cancelled") 443 | finally 444 | call s:matchdelete() 445 | call s:display_cursor() 446 | call s:restore_visual() 447 | unlet! g:_fnr_cword g:_fnr_entire s:in_getmode 448 | let &cursorline = cl_save 449 | call winrestview(view) 450 | endtry 451 | endfunction 452 | 453 | function! fnr#fnr_repeat() 454 | if s:repeat_entire 455 | silent! execute '%'.s:previous 456 | else 457 | try 458 | let s:need_repeat = 1 459 | normal! . 460 | finally 461 | let s:need_repeat = 0 462 | endtry 463 | endif 464 | silent! call repeat#set("\(FNRRepeat)") 465 | endfunction 466 | 467 | let &cpo = s:cpo_save 468 | unlet s:cpo_save 469 | 470 | -------------------------------------------------------------------------------- /plugin/fnr.vim: -------------------------------------------------------------------------------- 1 | " Copyright (c) 2014 Junegunn Choi 2 | " 3 | " MIT License 4 | " 5 | " Permission is hereby granted, free of charge, to any person obtaining 6 | " a copy of this software and associated documentation files (the 7 | " "Software"), to deal in the Software without restriction, including 8 | " without limitation the rights to use, copy, modify, merge, publish, 9 | " distribute, sublicense, and/or sell copies of the Software, and to 10 | " permit persons to whom the Software is furnished to do so, subject to 11 | " the following conditions: 12 | " 13 | " The above copyright notice and this permission notice shall be 14 | " included in all copies or substantial portions of the Software. 15 | " 16 | " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | " EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | " NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | " LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | " OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | " WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | nnoremap (FNR) :let [g:_fnr_cword, g:_fnr_entire] = [expand(''), 0]:set opfunc=fnr#fnrg@ 25 | xnoremap (FNR) :call fnr#fnr(visualmode(), 1) 26 | nnoremap (FNR%) :let [g:_fnr_cword, g:_fnr_entire] = [expand(''), 1]:%FNR 27 | xnoremap (FNR%) :call fnr#fnr(visualmode(), 2) 28 | nnoremap (FNRRepeat) :call fnr#fnr_repeat() 29 | 30 | command! -range FNR call fnr#fnr('line', , ) 31 | 32 | function! s:define_maps(leader) 33 | for m in ['n', 'v'] 34 | for [k, p] in items({'r': '(FNR)', 'R': '(FNR%)'}) 35 | if !hasmapto(p, m) && empty(mapcheck(a:leader.k, m)) 36 | execute m.printf('map %s %s', k, p) 37 | endif 38 | endfor 39 | endfor 40 | endfunction 41 | 42 | call s:define_maps(exists('mapleader') ? mapleader : '\') 43 | -------------------------------------------------------------------------------- /test/fnr.vader: -------------------------------------------------------------------------------- 1 | Execute (Setup): 2 | Save g:fnr_flags, mapleader 3 | 4 | " To test with default flags 5 | unlet! g:fnr_flags 6 | let mapleader = ' ' 7 | 8 | Given: 9 | MIT License 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining 12 | a copy of this software and associated documentation files (the 13 | "Software"), to deal in the Software without restriction, including 14 | without limitation the rights to use, copy, modify, merge, publish, 15 | distribute, sublicense, and/or sell copies of the Software, and to 16 | permit persons to whom the Software is furnished to do so, subject to 17 | the following conditions: 18 | 19 | Do (normal - R): 20 | \R 21 | L\ 22 | \\-L\y 23 | 24 | Expect: 25 | MIT-License 26 | 27 | Permission is hereby granted, free of charge, to any person obtaining 28 | a copy of this software and associated documentation files (the 29 | "Software"), to deal in the Software without restriction, including 30 | without limitation the rights to use, copy, modify, merge, publish, 31 | distribute, sublicense, and/or sell copies of the Software, and to 32 | permit persons to whom the Software is furnished to do so, subject to 33 | the following conditions: 34 | 35 | Do (normal - R - cword): 36 | w\R 37 | \ 38 | \LICENSE\y 39 | 40 | Expect: 41 | MIT LICENSE 42 | 43 | Permission is hereby granted, free of charge, to any person obtaining 44 | a copy of this software and associated documentation files (the 45 | "Software"), to deal in the Software without restriction, including 46 | without limitation the rights to use, copy, modify, merge, publish, 47 | distribute, sublicense, and/or sell copies of the Software, and to 48 | permit persons to whom the Software is furnished to do so, subject to 49 | the following conditions: 50 | 51 | Do (normal - R - insensitive): 52 | w\R 53 | \ 54 | \i\ 55 | \LICENSE\yy 56 | 57 | Expect: 58 | MIT LICENSE 59 | 60 | Permission is hereby granted, free of charge, to any person obtaining 61 | a copy of this software and associated documentation files (the 62 | "Software"), to deal in the Software without restriction, including 63 | without limitation the rights to use, copy, modify, merge, publish, 64 | distribute, subLICENSE, and/or sell copies of the Software, and to 65 | permit persons to whom the Software is furnished to do so, subject to 66 | the following conditions: 67 | 68 | Do (normal - R - word-boundary): 69 | \R 70 | \is\ 71 | \w\ 72 | \\wa\ny 73 | 74 | Expect: 75 | MIT License 76 | 77 | Permission is hereby granted, free of charge, to any person obtaining 78 | a copy of this software and associated documentation files (the 79 | "Software"), to deal in the Software without restriction, including 80 | without limitation the rights to use, copy, modify, merge, publish, 81 | distribute, sublicense, and/or sell copies of the Software, and to 82 | permit persons to whom the Software was furnished to do so, subject to 83 | the following conditions: 84 | 85 | Do (normal - R - word-boundary - no confirmation): 86 | \R 87 | \is\ 88 | \wc\ 89 | \\wa\ 90 | 91 | Expect: 92 | MIT License 93 | 94 | Permission was hereby granted, free of charge, to any person obtaining 95 | a copy of this software and associated documentation files (the 96 | "Software"), to deal in the Software without restriction, including 97 | without limitation the rights to use, copy, modify, merge, publish, 98 | distribute, sublicense, and/or sell copies of the Software, and to 99 | permit persons to whom the Software was furnished to do so, subject to 100 | the following conditions: 101 | 102 | Do (normal - s - inner paragraph): 103 | 2j 104 | \rip 105 | \i\ 106 | \LiCeNsE\ 107 | \a 108 | 109 | Expect: 110 | MIT License 111 | 112 | Permission is hereby granted, free of charge, to any person obtaining 113 | a copy of this software and associated documentation files (the 114 | "Software"), to deal in the Software without restriction, including 115 | without limitation the rights to use, copy, modify, merge, publish, 116 | distribute, subLiCeNsE, and/or sell copies of the Software, and to 117 | permit persons to whom the Software is furnished to do so, subject to 118 | the following conditions: 119 | 120 | Do (blockwise visual - r): 121 | 2j 122 | \3w6j 123 | \r 124 | is\ 125 | \z\nyyy 126 | 127 | Expect: 128 | MIT License 129 | 130 | Permission iz hereby granted, free of charge, to any person obtaining 131 | a copy of thiz software and associated documentation files (the 132 | "Software"), to deal in the Software without restriction, including 133 | without limitation the rights to use, copy, modify, merge, publish, 134 | diztribute, sublicense, and/or sell copies of the Software, and to 135 | permit persons to whom the Software is furnished to do so, subject to 136 | the following conditions: 137 | 138 | Do (visual - R - insensitive - 1st occurrence - no confirmation): 139 | 4jlv3l 140 | \R 141 | \ 142 | \giccc\ 143 | -\ 144 | 145 | Expect: 146 | MIT License 147 | 148 | Permission is hereby granted, free of charge, to any person obtaining 149 | a copy of this Soft-ware and associated documentation files (the 150 | "Soft-ware"), to deal in the Software without restriction, including 151 | without limitation the rights to use, copy, modify, merge, publish, 152 | distribute, sublicense, and/or sell copies of the Soft-ware, and to 153 | permit persons to whom the Soft-ware is furnished to do so, subject to 154 | the following conditions: 155 | 156 | Do (normal - sip): 157 | w\rip 158 | \i\ 159 | \ 160 | \\z\y 161 | 162 | Expect: 163 | MIT Licenze 164 | 165 | Permission is hereby granted, free of charge, to any person obtaining 166 | a copy of this software and associated documentation files (the 167 | "Software"), to deal in the Software without restriction, including 168 | without limitation the rights to use, copy, modify, merge, publish, 169 | distribute, sublicense, and/or sell copies of the Software, and to 170 | permit persons to whom the Software is furnished to do so, subject to 171 | the following conditions: 172 | 173 | Do (normal - sip - . (repeat.vim integration)): 174 | w\rip 175 | \i\ 176 | \ 177 | \\z\y 178 | 2j 179 | . 180 | 181 | Expect: 182 | MIT Licenze 183 | 184 | Permission is hereby granted, free of charge, to any person obtaining 185 | a copy of this software and associated documentation files (the 186 | "Software"), to deal in the Software without restriction, including 187 | without limitation the rights to use, copy, modify, merge, publish, 188 | distribute, subLicenze, and/or sell copies of the Software, and to 189 | permit persons to whom the Software is furnished to do so, subject to 190 | the following conditions: 191 | 192 | Do (visual - R - CTRL-W / CTRL-K / CTRL-B / CTRL-F / Left / Right): 193 | 2j 194 | v4e 195 | \R 196 | \ 197 | \\ 198 | \\\\ 199 | \\\ 200 | \\\ 201 | n isn't granted\a 202 | 203 | Expect: 204 | MIT License 205 | 206 | Permission isn't granted, free of charge, to any person obtaining 207 | a copy of this software and associated documentation files (the 208 | "Software"), to deal in the Software without restriction, including 209 | without limitation the rights to use, copy, modify, merge, publish, 210 | distribute, sublicense, and/or sell copies of the Software, and to 211 | permit persons to whom the Software is furnished to do so, subject to 212 | the following conditions: 213 | 214 | Do (normal - R - CTRL-R-" / CTRL-R-=): 215 | y2e 216 | G 217 | \R 218 | \ 219 | \" 220 | \ 221 | \ 222 | \" = 223 | \=@"\ 224 | \a 225 | 226 | Expect: 227 | MIT License = MIT License 228 | 229 | Permission is hereby granted, free of charge, to any person obtaining 230 | a copy of this software and associated documentation files (the 231 | "Software"), to deal in the Software without restriction, including 232 | without limitation the rights to use, copy, modify, merge, publish, 233 | distribute, sublicense, and/or sell copies of the Software, and to 234 | permit persons to whom the Software is furnished to do so, subject to 235 | the following conditions: 236 | 237 | # conditions copies copy 238 | Do (visual - R - CTRL-N / CTRL-P / CTRL-K): 239 | v2e 240 | \R\ 241 | \ 242 | co\ 243 | co\\ 244 | co\\\ 245 | co\\\\ 246 | co\\\\\ 247 | co\ 248 | co\\ 249 | co\\\ 250 | co\\\\ 251 | co\\\\\ 252 | co\\\\ 253 | co\\\ 254 | \\\\\ 255 | \ 256 | \a 257 | 258 | Expect: 259 | conditions copies copy co conditions copy copies conditions co copy co condi 260 | 261 | Permission is hereby granted, free of charge, to any person obtaining 262 | a copy of this software and associated documentation files (the 263 | "Software"), to deal in the Software without restriction, including 264 | without limitation the rights to use, copy, modify, merge, publish, 265 | distribute, sublicense, and/or sell copies of the Software, and to 266 | permit persons to whom the Software is furnished to do so, subject to 267 | the following conditions: 268 | 269 | Execute (g:fnr_flags): 270 | let g:fnr_flags = 'wi' 271 | 272 | Do (normal - R (wi)): 273 | \R 274 | \is\ 275 | n't\ 276 | 277 | Expect: 278 | MIT License 279 | 280 | Permission isn't hereby granted, free of charge, to any person obtaining 281 | a copy of this software and associated documentation files (the 282 | "Software"), to deal in the Software without restriction, including 283 | without limitation the rights to use, copy, modify, merge, publish, 284 | distribute, sublicense, and/or sell copies of the Software, and to 285 | permit persons to whom the Software isn't furnished to do so, subject to 286 | the following conditions: 287 | 288 | Execute: 289 | unlet! g:fnr_flags 290 | 291 | Do (visual - R - newline): 292 | V\R 293 | \ 294 | \Hello world 295 | \y 296 | 297 | Expect: 298 | Hello world 299 | Permission is hereby granted, free of charge, to any person obtaining 300 | a copy of this software and associated documentation files (the 301 | "Software"), to deal in the Software without restriction, including 302 | without limitation the rights to use, copy, modify, merge, publish, 303 | distribute, sublicense, and/or sell copies of the Software, and to 304 | permit persons to whom the Software is furnished to do so, subject to 305 | the following conditions: 306 | 307 | Do (Turn off ignorecase): 308 | \R 309 | \i\ 310 | \HEREBY\ 311 | \i\ 312 | THEREBY\ 313 | 314 | Expect: 315 | MIT License 316 | 317 | Permission is hereby granted, free of charge, to any person obtaining 318 | a copy of this software and associated documentation files (the 319 | "Software"), to deal in the Software without restriction, including 320 | without limitation the rights to use, copy, modify, merge, publish, 321 | distribute, sublicense, and/or sell copies of the Software, and to 322 | permit persons to whom the Software is furnished to do so, subject to 323 | the following conditions: 324 | 325 | Do (Remember visual selection): 326 | - Select the first two lines 327 | Vj\ 328 | - Go to is 329 | 3Gw 330 | - FNR 331 | \R\\w\ 332 | \was\a 333 | gvd 334 | 335 | Expect: 336 | Permission was hereby granted, free of charge, to any person obtaining 337 | a copy of this software and associated documentation files (the 338 | "Software"), to deal in the Software without restriction, including 339 | without limitation the rights to use, copy, modify, merge, publish, 340 | distribute, sublicense, and/or sell copies of the Software, and to 341 | permit persons to whom the Software was furnished to do so, subject to 342 | the following conditions: 343 | 344 | Given (backslash, trailing slash): 345 | \^_^/ 346 | 347 | Do (visual - R - backslash): 348 | viW\R 349 | \ 350 | \\(-_-)~ 351 | \y 352 | 353 | Expect: 354 | \(-_-)~ 355 | 356 | Given (Sharp, ouch!): 357 | Hello#World 358 | 359 | Do (visual - R - sharp): 360 | viW\R 361 | \ 362 | \Goodbye#World 363 | \y 364 | 365 | Expect: 366 | Goodbye#World 367 | 368 | Execute (Restore): 369 | Restore 370 | 371 | -------------------------------------------------------------------------------- /test/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $(dirname $BASH_SOURCE) 4 | 5 | vim -Nu <(cat << EOF 6 | syntax on 7 | let mapleader = ' ' 8 | for dep in ['vader.vim', 'vim-pseudocl', 'vim-repeat'] 9 | execute 'set rtp+=' . finddir(dep, expand('~/.vim').'/**') 10 | endfor 11 | set rtp+=.. 12 | EOF) +'Vader*' 13 | 14 | --------------------------------------------------------------------------------