diff --git a/.vim/autoload/pathogen.vim b/.vim/autoload/pathogen.vim new file mode 100644 index 0000000..dbe07f0 --- /dev/null +++ b/.vim/autoload/pathogen.vim @@ -0,0 +1,289 @@ +" pathogen.vim - path option manipulation +" Maintainer: Tim Pope +" Version: 2.4 + +" Install in ~/.vim/autoload (or ~\vimfiles\autoload). +" +" For management of individually installed plugins in ~/.vim/bundle (or +" ~\vimfiles\bundle), adding `execute pathogen#infect()` to the top of your +" .vimrc is the only other setup necessary. +" +" The API is documented inline below. + +if exists("g:loaded_pathogen") || &cp + finish +endif +let g:loaded_pathogen = 1 + +" Point of entry for basic default usage. Give a relative path to invoke +" pathogen#interpose() (defaults to "bundle/{}"), or an absolute path to invoke +" pathogen#surround(). Curly braces are expanded with pathogen#expand(): +" "bundle/{}" finds all subdirectories inside "bundle" inside all directories +" in the runtime path. +function! pathogen#infect(...) abort + for path in a:0 ? filter(reverse(copy(a:000)), 'type(v:val) == type("")') : ['bundle/{}'] + if path =~# '^\%({\=[$~\\/]\|{\=\w:[\\/]\).*[{}*]' + call pathogen#surround(path) + elseif path =~# '^\%([$~\\/]\|\w:[\\/]\)' + call s:warn('Change pathogen#infect('.string(path).') to pathogen#infect('.string(path.'/{}').')') + call pathogen#surround(path . '/{}') + elseif path =~# '[{}*]' + call pathogen#interpose(path) + else + call s:warn('Change pathogen#infect('.string(path).') to pathogen#infect('.string(path.'/{}').')') + call pathogen#interpose(path . '/{}') + endif + endfor + call pathogen#cycle_filetype() + if pathogen#is_disabled($MYVIMRC) + return 'finish' + endif + return '' +endfunction + +" Split a path into a list. +function! pathogen#split(path) abort + if type(a:path) == type([]) | return a:path | endif + if empty(a:path) | return [] | endif + let split = split(a:path,'\\\@]','\\&','') + endif +endfunction + +" Like findfile(), but hardcoded to use the runtimepath. +function! pathogen#runtime_findfile(file,count) abort + let rtp = pathogen#join(1,pathogen#split(&rtp)) + let file = findfile(a:file,rtp,a:count) + if file ==# '' + return '' + else + return fnamemodify(file,':p') + endif +endfunction + +" Section: Deprecated + +function! s:warn(msg) abort + echohl WarningMsg + echomsg a:msg + echohl NONE +endfunction + +" Prepend all subdirectories of path to the rtp, and append all 'after' +" directories in those subdirectories. Deprecated. +function! pathogen#runtime_prepend_subdirectories(path) abort + call s:warn('Change pathogen#runtime_prepend_subdirectories('.string(a:path).') to pathogen#infect('.string(a:path.'/{}').')') + return pathogen#surround(a:path . pathogen#slash() . '{}') +endfunction + +function! pathogen#incubate(...) abort + let name = a:0 ? a:1 : 'bundle/{}' + call s:warn('Change pathogen#incubate('.(a:0 ? string(a:1) : '').') to pathogen#infect('.string(name).')') + return pathogen#interpose(name) +endfunction + +" Deprecated alias for pathogen#interpose(). +function! pathogen#runtime_append_all_bundles(...) abort + if a:0 + call s:warn('Change pathogen#runtime_append_all_bundles('.string(a:1).') to pathogen#infect('.string(a:1.'/{}').')') + else + call s:warn('Change pathogen#runtime_append_all_bundles() to pathogen#infect()') + endif + return pathogen#interpose(a:0 ? a:1 . '/{}' : 'bundle/{}') +endfunction + +" vim:set et sw=2 foldmethod=expr foldexpr=getline(v\:lnum)=~'^\"\ Section\:'?'>1'\:getline(v\:lnum)=~#'^fu'?'a1'\:getline(v\:lnum)=~#'^endf'?'s1'\:'=': diff --git a/.vim/bundle/goyo.vim/README.md b/.vim/bundle/goyo.vim/README.md new file mode 100644 index 0000000..0e1475b --- /dev/null +++ b/.vim/bundle/goyo.vim/README.md @@ -0,0 +1,130 @@ +goyo.vim ([고요](http://en.wiktionary.org/wiki/고요하다)) +========================================================= + +Distraction-free writing in Vim. + +![](https://raw.github.com/junegunn/i/master/goyo.png) + +(Color scheme: [seoul256](https://github.com/junegunn/seoul256.vim)) + +Best served with [limelight.vim](https://github.com/junegunn/limelight.vim). + +Installation +------------ + +Use your favorite plugin manager. + +- [vim-plug](https://github.com/junegunn/vim-plug) + 1. Add `Plug 'junegunn/goyo.vim'` to .vimrc + 2. Run `:PlugInstall` + +Usage +----- + +- `:Goyo` + - Toggle Goyo +- `:Goyo [dimension]` + - Turn on or resize Goyo +- `:Goyo!` + - Turn Goyo off + +The window can be resized with the usual `[count]` + `>`, `<`, `+`, +`-` keys. + +### Dimension expression + +The expected format of a dimension expression is +`[WIDTH][XOFFSET][x[HEIGHT][YOFFSET]]`. `XOFFSET` and `YOFFSET` should be +prefixed by `+` or `-`. Each component can be given in percentage. + +```vim +" Width +Goyo 120 + +" Height +Goyo x30 + +" Both +Goyo 120x30 + +" In percentage +Goyo 120x50% + +" With offsets +Goyo 50%+25%x50%-25% +``` + +Configuration +------------- + +- `g:goyo_width` (default: 80) +- `g:goyo_height` (default: 85%) +- `g:goyo_linenr` (default: 0) + +### Callbacks + +By default, [vim-airline](https://github.com/bling/vim-airline), +[vim-powerline](https://github.com/Lokaltog/vim-powerline), +[powerline](https://github.com/Lokaltog/powerline), +[lightline.vim](https://github.com/itchyny/lightline.vim), +[vim-signify](https://github.com/mhinz/vim-signify), +and [vim-gitgutter](https://github.com/airblade/vim-gitgutter) are temporarily +disabled while in Goyo mode. + +If you have other plugins that you want to disable/enable, or if you want to +change the default settings of Goyo window, you can set up custom routines +to be triggered on `GoyoEnter` and `GoyoLeave` events. + +```vim +function! s:goyo_enter() + silent !tmux set status off + silent !tmux list-panes -F '\#F' | grep -q Z || tmux resize-pane -Z + set noshowmode + set noshowcmd + set scrolloff=999 + Limelight + " ... +endfunction + +function! s:goyo_leave() + silent !tmux set status on + silent !tmux list-panes -F '\#F' | grep -q Z && tmux resize-pane -Z + set showmode + set showcmd + set scrolloff=5 + Limelight! + " ... +endfunction + +autocmd! User GoyoEnter nested call goyo_enter() +autocmd! User GoyoLeave nested call goyo_leave() +``` + +More examples can be found here: +[Customization](https://github.com/junegunn/goyo.vim/wiki/Customization) + +Inspiration +----------- + +- [LiteDFM](https://github.com/bilalq/lite-dfm) +- [VimRoom](http://projects.mikewest.org/vimroom/) + +Pros. +----- + +1. Works well with splits. Doesn't mess up with the current window arrangement +1. Works well with popular statusline plugins +1. Prevents accessing the empty windows around the central buffer +1. Can be closed with any of `:q[uit]`, `:clo[se]`, `:tabc[lose]`, or `:Goyo` +1. Can dynamically change the width of the window +1. Adjusts its colors when color scheme is changed +1. Realigns the window when the terminal (or window) is resized or when the size + of the font is changed +1. Correctly hides colorcolumns and Emojis in statusline +1. Highly customizable with callbacks + +License +------- + +MIT + diff --git a/.vim/bundle/goyo.vim/autoload/goyo.vim b/.vim/bundle/goyo.vim/autoload/goyo.vim new file mode 100644 index 0000000..735c950 --- /dev/null +++ b/.vim/bundle/goyo.vim/autoload/goyo.vim @@ -0,0 +1,447 @@ +" Copyright (c) 2015 Junegunn Choi +" +" MIT License +" +" Permission is hereby granted, free of charge, to any person obtaining +" a copy of this software and associated documentation files (the +" "Software"), to deal in the Software without restriction, including +" without limitation the rights to use, copy, modify, merge, publish, +" distribute, sublicense, and/or sell copies of the Software, and to +" permit persons to whom the Software is furnished to do so, subject to +" the following conditions: +" +" The above copyright notice and this permission notice shall be +" included in all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +let s:cpo_save = &cpo +set cpo&vim + +function! s:const(val, min, max) + return min([max([a:val, a:min]), a:max]) +endfunction + +function! s:get_color(group, attr) + return synIDattr(synIDtrans(hlID(a:group)), a:attr) +endfunction + +function! s:set_color(group, attr, color) + let gui = a:color =~ '^#' + execute printf('hi %s %s%s=%s', a:group, gui ? 'gui' : 'cterm', a:attr, a:color) +endfunction + +function! s:blank(repel) + if bufwinnr(t:goyo_pads.r) <= bufwinnr(t:goyo_pads.l) + 1 + \ || bufwinnr(t:goyo_pads.b) <= bufwinnr(t:goyo_pads.t) + 3 + call s:goyo_off() + endif + execute 'wincmd' a:repel +endfunction + +function! s:init_pad(command) + execute a:command + + setlocal buftype=nofile bufhidden=wipe nomodifiable nobuflisted noswapfile + \ nonu nocursorline nocursorcolumn winfixwidth winfixheight statusline=\ + if exists('&rnu') + setlocal nornu + endif + if exists('&colorcolumn') + setlocal colorcolumn= + endif + let bufnr = winbufnr(0) + + execute winnr('#') . 'wincmd w' + return bufnr +endfunction + +function! s:setup_pad(bufnr, vert, size, repel) + let win = bufwinnr(a:bufnr) + execute win . 'wincmd w' + execute (a:vert ? 'vertical ' : '') . 'resize ' . max([0, a:size]) + augroup goyop + execute 'autocmd WinEnter,CursorMoved nested call s:blank("'.a:repel.'")' + autocmd WinLeave call s:hide_statusline() + augroup END + + " To hide scrollbars of pad windows in GVim + let diff = winheight(0) - line('$') - (has('gui_running') ? 2 : 0) + if diff > 0 + setlocal modifiable + call append(0, map(range(1, diff), '""')) + normal! gg + setlocal nomodifiable + endif + execute winnr('#') . 'wincmd w' +endfunction + +function! s:resize_pads() + augroup goyop + autocmd! + augroup END + + let t:goyo_dim.width = s:const(t:goyo_dim.width, 2, &columns) + let t:goyo_dim.height = s:const(t:goyo_dim.height, 2, &lines) + + let vmargin = max([0, (&lines - t:goyo_dim.height) / 2 - 1]) + let yoff = s:const(t:goyo_dim.yoff, - vmargin, vmargin) + let top = vmargin + yoff + let bot = vmargin - yoff - 1 + call s:setup_pad(t:goyo_pads.t, 0, top, 'j') + call s:setup_pad(t:goyo_pads.b, 0, bot, 'k') + + let nwidth = max([len(string(line('$'))) + 1, &numberwidth]) + let width = t:goyo_dim.width + (&number ? nwidth : 0) + let hmargin = max([0, (&columns - width) / 2 - 1]) + let xoff = s:const(t:goyo_dim.xoff, - hmargin, hmargin) + call s:setup_pad(t:goyo_pads.l, 1, hmargin + xoff, 'l') + call s:setup_pad(t:goyo_pads.r, 1, hmargin - xoff, 'h') +endfunction + +function! s:tranquilize() + let bg = s:get_color('Normal', 'bg#') + for grp in ['NonText', 'FoldColumn', 'ColorColumn', 'VertSplit', + \ 'StatusLine', 'StatusLineNC', 'SignColumn'] + " -1 on Vim / '' on GVim + if bg == -1 || empty(bg) + call s:set_color(grp, 'fg', get(g:, 'goyo_bg', 'black')) + call s:set_color(grp, 'bg', 'NONE') + else + call s:set_color(grp, 'fg', bg) + call s:set_color(grp, 'bg', bg) + endif + call s:set_color(grp, '', 'NONE') + endfor +endfunction + +function! s:hide_statusline() + setlocal statusline=\ +endfunction + +function! s:hide_linenr() + if !get(g:, 'goyo_linenr', 0) + setlocal nonu + if exists('&rnu') + setlocal nornu + endif + endif + if exists('&colorcolumn') + setlocal colorcolumn= + endif +endfunction + +function! s:maps_nop() + let mapped = filter(['R', 'H', 'J', 'K', 'L', '|', '_'], + \ "empty(maparg(\"\\".v:val, 'n'))") + for c in mapped + execute 'nnoremap '.escape(c, '|').' ' + endfor + return mapped +endfunction + +function! s:maps_resize() + let commands = { + \ '=': ':let t:goyo_dim = parse_arg(t:goyo_dim_expr) call resize_pads()', + \ '>': ':let t:goyo_dim.width = winwidth(0) + 2 * v:count1 call resize_pads()', + \ '<': ':let t:goyo_dim.width = winwidth(0) - 2 * v:count1 call resize_pads()', + \ '+': ':let t:goyo_dim.height += 2 * v:count1 call resize_pads()', + \ '-': ':let t:goyo_dim.height -= 2 * v:count1 call resize_pads()' + \ } + let mapped = filter(keys(commands), "empty(maparg(\"\\".v:val, 'n'))") + for c in mapped + execute 'nnoremap '.c.' '.commands[c] + endfor + return mapped +endfunction + +nnoremap (goyo-resize) :call resize_pads() + +function! s:goyo_on(dim) + let dim = s:parse_arg(a:dim) + if empty(dim) + return + endif + + let s:orig_tab = tabpagenr() + let settings = + \ { 'laststatus': &laststatus, + \ 'showtabline': &showtabline, + \ 'fillchars': &fillchars, + \ 'winminwidth': &winminwidth, + \ 'winwidth': &winwidth, + \ 'winminheight': &winminheight, + \ 'winheight': &winheight, + \ 'ruler': &ruler, + \ 'sidescroll': &sidescroll, + \ 'sidescrolloff': &sidescrolloff + \ } + + " New tab + tab split + + let t:goyo_master = winbufnr(0) + let t:goyo_dim = dim + let t:goyo_dim_expr = a:dim + let t:goyo_pads = {} + let t:goyo_revert = settings + let t:goyo_maps = extend(s:maps_nop(), s:maps_resize()) + if has('gui_running') + let t:goyo_revert.guioptions = &guioptions + endif + + " vim-gitgutter + let t:goyo_disabled_gitgutter = get(g:, 'gitgutter_enabled', 0) + if t:goyo_disabled_gitgutter + silent! GitGutterDisable + endif + + " vim-signify + let t:goyo_disabled_signify = exists('b:sy') && b:sy.active + if t:goyo_disabled_signify + SignifyToggle + endif + + " vim-airline + let t:goyo_disabled_airline = exists('#airline') + if t:goyo_disabled_airline + AirlineToggle + endif + + " vim-powerline + let t:goyo_disabled_powerline = exists('#PowerlineMain') + if t:goyo_disabled_powerline + augroup PowerlineMain + autocmd! + augroup END + augroup! PowerlineMain + endif + + " lightline.vim + let t:goyo_disabled_lightline = exists('#lightline') + if t:goyo_disabled_lightline + silent! call lightline#disable() + endif + + call s:hide_linenr() + " Global options + let &winheight = max([&winminheight, 1]) + set winminheight=1 + set winheight=1 + set winminwidth=1 winwidth=1 + set laststatus=0 + set showtabline=0 + set noruler + set fillchars+=vert:\ + set fillchars+=stl:\ + set fillchars+=stlnc:\ + set sidescroll=1 + set sidescrolloff=0 + + " Hide left-hand scrollbars + if has('gui_running') + set guioptions-=l + set guioptions-=L + endif + + let t:goyo_pads.l = s:init_pad('vertical topleft new') + let t:goyo_pads.r = s:init_pad('vertical botright new') + let t:goyo_pads.t = s:init_pad('topleft new') + let t:goyo_pads.b = s:init_pad('botright new') + + call s:resize_pads() + call s:tranquilize() + + augroup goyo + autocmd! + autocmd TabLeave * call s:goyo_off() + autocmd VimResized * call s:resize_pads() + autocmd ColorScheme * call s:tranquilize() + autocmd BufWinEnter * call s:hide_linenr() | call s:hide_statusline() + autocmd WinEnter,WinLeave * call s:hide_statusline() + if has('nvim') + autocmd TermClose * call feedkeys("\(goyo-resize)") + endif + augroup END + + call s:hide_statusline() + if exists('g:goyo_callbacks[0]') + call g:goyo_callbacks[0]() + endif + if exists('#User#GoyoEnter') + doautocmd User GoyoEnter + endif +endfunction + +function! s:goyo_off() + if !exists('#goyo') + return + endif + + " Oops, not this tab + if !exists('t:goyo_revert') + return + endif + + " Clear auto commands + augroup goyo + autocmd! + augroup END + augroup! goyo + augroup goyop + autocmd! + augroup END + augroup! goyop + + for c in t:goyo_maps + execute 'nunmap '.escape(c, '|') + endfor + + let goyo_revert = t:goyo_revert + let goyo_disabled_gitgutter = t:goyo_disabled_gitgutter + let goyo_disabled_signify = t:goyo_disabled_signify + let goyo_disabled_airline = t:goyo_disabled_airline + let goyo_disabled_powerline = t:goyo_disabled_powerline + let goyo_disabled_lightline = t:goyo_disabled_lightline + let goyo_orig_buffer = t:goyo_master + let [line, col] = [line('.'), col('.')] + + if tabpagenr() == 1 + tabnew + normal! gt + bd + endif + tabclose + execute 'normal! '.s:orig_tab.'gt' + if winbufnr(0) == goyo_orig_buffer + " Doesn't work if window closed with `q` + execute printf('normal! %dG%d|', line, col) + endif + + let wmw = remove(goyo_revert, 'winminwidth') + let ww = remove(goyo_revert, 'winwidth') + let &winwidth = ww + let &winminwidth = wmw + let wmh = remove(goyo_revert, 'winminheight') + let wh = remove(goyo_revert, 'winheight') + let &winheight = max([wmh, 1]) + let &winminheight = wmh + let &winheight = wh + + for [k, v] in items(goyo_revert) + execute printf('let &%s = %s', k, string(v)) + endfor + execute 'colo '. get(g:, 'colors_name', 'default') + + if goyo_disabled_gitgutter + silent! GitGutterEnable + endif + + if goyo_disabled_signify + silent! if !b:sy.active + SignifyToggle + endif + endif + + if goyo_disabled_airline && !exists('#airline') + AirlineToggle + " For some reason, Airline requires two refreshes to avoid display + " artifacts + silent! AirlineRefresh + silent! AirlineRefresh + endif + + if goyo_disabled_powerline && !exists('#PowerlineMain') + doautocmd PowerlineStartup VimEnter + silent! PowerlineReloadColorscheme + endif + + if goyo_disabled_lightline + silent! call lightline#enable() + endif + + if exists('#Powerline') + doautocmd Powerline ColorScheme + endif + + if exists('g:goyo_callbacks[1]') + call g:goyo_callbacks[1]() + endif + if exists('#User#GoyoLeave') + doautocmd User GoyoLeave + endif +endfunction + +function! s:relsz(expr, limit) + if a:expr !~ '%$' + return str2nr(a:expr) + endif + return a:limit * str2nr(a:expr[:-2]) / 100 +endfunction + +function! s:parse_arg(arg) + if exists('g:goyo_height') || !exists('g:goyo_margin_top') && !exists('g:goyo_margin_bottom') + let height = s:relsz(get(g:, 'goyo_height', '85%'), &lines) + let yoff = 0 + else + let top = max([0, s:relsz(get(g:, 'goyo_margin_top', 4), &lines)]) + let bot = max([0, s:relsz(get(g:, 'goyo_margin_bottom', 4), &lines)]) + let height = &lines - top - bot + let yoff = top - bot + endif + + let dim = { 'width': s:relsz(get(g:, 'goyo_width', 80), &columns), + \ 'height': height, + \ 'xoff': 0, + \ 'yoff': yoff } + if empty(a:arg) + return dim + endif + let parts = matchlist(a:arg, '^\s*\([0-9]\+%\?\)\?\([+-][0-9]\+%\?\)\?\%(x\([0-9]\+%\?\)\?\([+-][0-9]\+%\?\)\?\)\?\s*$') + if empty(parts) + echohl WarningMsg + echo 'Invalid dimension expression: '.a:arg + echohl None + return {} + endif + if !empty(parts[1]) | let dim.width = s:relsz(parts[1], &columns) | endif + if !empty(parts[2]) | let dim.xoff = s:relsz(parts[2], &columns) | endif + if !empty(parts[3]) | let dim.height = s:relsz(parts[3], &lines) | endif + if !empty(parts[4]) | let dim.yoff = s:relsz(parts[4], &lines) | endif + return dim +endfunction + +function! goyo#execute(bang, dim) + if a:bang + if exists('#goyo') + call s:goyo_off() + endif + else + if exists('#goyo') == 0 + call s:goyo_on(a:dim) + elseif !empty(a:dim) + if winnr('$') < 5 + call s:goyo_off() + return goyo#execute(a:bang, a:dim) + endif + let dim = s:parse_arg(a:dim) + if !empty(dim) + let t:goyo_dim = dim + let t:goyo_dim_expr = a:dim + call s:resize_pads() + endif + else + call s:goyo_off() + end + end +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + diff --git a/.vim/bundle/goyo.vim/plugin/goyo.vim b/.vim/bundle/goyo.vim/plugin/goyo.vim new file mode 100644 index 0000000..af4793a --- /dev/null +++ b/.vim/bundle/goyo.vim/plugin/goyo.vim @@ -0,0 +1,24 @@ +" Copyright (c) 2015 Junegunn Choi +" +" MIT License +" +" Permission is hereby granted, free of charge, to any person obtaining +" a copy of this software and associated documentation files (the +" "Software"), to deal in the Software without restriction, including +" without limitation the rights to use, copy, modify, merge, publish, +" distribute, sublicense, and/or sell copies of the Software, and to +" permit persons to whom the Software is furnished to do so, subject to +" the following conditions: +" +" The above copyright notice and this permission notice shall be +" included in all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +command! -nargs=? -bar -bang Goyo call goyo#execute(0, ) diff --git a/.vim/bundle/vim-multiple-cursors/.rspec b/.vim/bundle/vim-multiple-cursors/.rspec new file mode 100644 index 0000000..397921f --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/.rspec @@ -0,0 +1,2 @@ +--color +--format d diff --git a/.vim/bundle/vim-multiple-cursors/.travis.yml b/.vim/bundle/vim-multiple-cursors/.travis.yml new file mode 100644 index 0000000..cfb198a --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/.travis.yml @@ -0,0 +1,11 @@ +sudo: false +language: ruby + +addons: + apt: + packages: + - vim-gtk + +before_script: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" diff --git a/.vim/bundle/vim-multiple-cursors/CHANGELOG.md b/.vim/bundle/vim-multiple-cursors/CHANGELOG.md new file mode 100644 index 0000000..265b39f --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/CHANGELOG.md @@ -0,0 +1,109 @@ +## 2.2 (06/10/2013) +Bugfixes: + - Fix plugin break in PASTE mode. This fixes #44. + +## 2.1 (04/26/2013) + +Bugfixes: + - Fix 1 regression where cursors could potentially get out of sync in insert mode + +Features: + - Added some logic to debug latency. Fanning out to 30 cursors in insert mode with my vimrc took over 300ms. It's like than 20ms with a plain vimrc. Need to debug what setting is causing the slowing down in insert mode and inform users. + +## 2.0 (04/24/2013) + +Bugfixes: + - Fix inconsistent undo behavior. Changes made in multicursor insert mode are now undone together. This fixes #22. + - Single key commands that do not terminate properly no longer cause ghostly cursors to linger on screen. An error message is now displayed informing the user the number of cursor locations that the input cannot be properly played back at. This fixes #28. + +## 1.16 (04/23/2013) + +Features: + - Add integration tests using vimrunner. Hook up travis-ci to run continous integration on commit. + +## 1.15 (04/22/2013) + +Bugfixes: + - Fix plugin causing error bell. This fixes #29. + +## 1.14 (04/22/2013) + +Features: + - Allow users to separate start key from next key. (credit: @xanderman) + +## 1.13 (04/22/2013) + +Bugfixes: + - Add support for switching to visual line mode from inside multicursor mode + - Fix highlight issue where extra character at end of line is highlighted for visual selections covering more than 2 lines. + +## 1.12 (04/19/2013) + +Bugfixes: + - Fix tab character causing highlight errors. This fixes #18 and fixes #32 + +## 1.11 (04/18/2013) + +Bugfixes: + - Fix regression where `C-n` doesn't exhibit correct behavior when all matches have been found + - Clear echo messages when a new input is received + +## 1.10 (04/17/2013) + +Bugfixes: + - `O` works now in normal mode. This fixes #24 + - Turn on `lazyredraw` during multicursor mode to prevent the sluggish screen redraws + +Features: + - Add command **MultipleCursorsFind** to add multiple virtual cursors using regexp. This closes #20 + +## 1.9 (04/17/2013) + +Bugfixes: + - Fix starting multicursor mode in visual line mode. This fixes #25 + - Major refactoring to avoid getting in and out of visual mode as much as possible + +## 1.8 (04/16/2013) + +Bugfixes: + - Fix regression that causes call stack to explode with too many cursors + +## 1.7 (04/15/2013) + +Bugfixes: + - Finally fix the annoying highlighting problem when the last virtual cursor is on the last character of the line. The solution is a hack, but it should be harmless + +## 1.6 (04/15/2013) + +Bugfixes: + - Stop chaining dictionary function calls. This fixes #10 and #11 + +## 1.5 (04/15/2013) + +Bugfixes: + - Exit Vim's visual mode before waiting for user's next input. This fixes #14 + +## 1.4 (04/14/2013) + +Bugfixes: + - Don't use clearmatches(). It clears highlighting from other plugins. This fixes #13 + +## 1.3 (04/14/2013) + +Bugfixes: + - Change mapping from using expression-quote syntax to using raw strings + +## 1.2 (04/14/2013) + +Bugfixes: + - Restore view when exiting from multicursor mode. This fixes #5 + - Remove the unnecessary user level mapping for 'prev' and 'skip' in visual mode, since we can purely detect those keys from multicursor mode + +## 1.1 (04/14/2013) + +Bugfixes: + - Stop hijacking escape key in normal mode. This fixes #1, #2, and #3 + +## 1.0 (04/13/2013) + +Initial release diff --git a/.vim/bundle/vim-multiple-cursors/CONTRIBUTING.md b/.vim/bundle/vim-multiple-cursors/CONTRIBUTING.md new file mode 100644 index 0000000..878aa59 --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Problems summary + +## Expected + +## Environment Information + * OS: + * Neovim/Vim/Gvim version: + +## Provide a minimal .vimrc with less than 50 lines + + " Your minimal.vimrc + +## Generate a logfile if appropriate + + 1. export NVIM_PYTHON_LOG_FILE=/tmp/log + 2. export NVIM_PYTHON_LOG_LEVEL=DEBUG + 3. nvim -u minimal.vimrc + 4. recreate your issue + 5. cat /tmp/log_{PID} + +## Screen shot (if possible) + +## Upload the log file diff --git a/.vim/bundle/vim-multiple-cursors/Gemfile b/.vim/bundle/vim-multiple-cursors/Gemfile new file mode 100644 index 0000000..7658cb9 --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' +gem 'vimrunner' +gem 'rake' +gem 'rspec' diff --git a/.vim/bundle/vim-multiple-cursors/Gemfile.lock b/.vim/bundle/vim-multiple-cursors/Gemfile.lock new file mode 100644 index 0000000..e833b24 --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/Gemfile.lock @@ -0,0 +1,30 @@ +GEM + remote: https://rubygems.org/ + specs: + diff-lcs (1.2.5) + rake (10.4.2) + rspec (3.4.0) + rspec-core (~> 3.4.0) + rspec-expectations (~> 3.4.0) + rspec-mocks (~> 3.4.0) + rspec-core (3.4.1) + rspec-support (~> 3.4.0) + rspec-expectations (3.4.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.4.0) + rspec-mocks (3.4.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.4.0) + rspec-support (3.4.1) + vimrunner (0.3.1) + +PLATFORMS + ruby + +DEPENDENCIES + rake + rspec + vimrunner + +BUNDLED WITH + 1.10.6 diff --git a/.vim/bundle/vim-multiple-cursors/MIT-LICENSE.txt b/.vim/bundle/vim-multiple-cursors/MIT-LICENSE.txt new file mode 100644 index 0000000..dade7aa --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/MIT-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright 2013 Terry Ma + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.vim/bundle/vim-multiple-cursors/README.md b/.vim/bundle/vim-multiple-cursors/README.md new file mode 100644 index 0000000..8ed8c11 --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/README.md @@ -0,0 +1,247 @@ +# vim-multiple-cursors +[![Build Status](https://travis-ci.org/terryma/vim-multiple-cursors.svg)](https://travis-ci.org/terryma/vim-multiple-cursors) +[![Issue Stats](http://issuestats.com/github/terryma/vim-multiple-cursors/badge/pr?style=flat)](http://issuestats.com/github/terryma/vim-multiple-cursors) +[![Issue Stats](http://issuestats.com/github/terryma/vim-multiple-cursors/badge/issue?style=flat)](http://issuestats.com/github/terryma/vim-multiple-cursors) +## Contents + - [About](#about) + - [Features](#features) + - [Installation](#installation) + - [Quick Start](#quick-start) + - [Mapping](#mapping) + - [Settings](#settings) + - [Interactions with other plugins](#interactions-with-other-plugins) + - [Highlight](#highlight) + - *[FAQ](#faq)* + - *[Known issues](#known-issues)* + - *[Issue creation requirements](#issue-creation-requirements)* + - [Changelog](#changelog) + - [Contributing](#contributing) + - [Credit](#credit) + +### Contributors +- [eapache](https://github.com/eapache) +- [aschrab](https://github.com/aschrab) +- [kristijanhusak](https://github.com/kristijanhusak) +- [faceleg](https://github.com/faceleg) + +## About +[There](https://github.com/paradigm/vim-multicursor) [have](https://github.com/felixr/vim-multiedit) [been](https://github.com/hlissner/vim-multiedit) [many](https://github.com/adinapoli/vim-markmultiple) [attempts](https://github.com/AndrewRadev/multichange.vim) at bringing Sublime Text's awesome [multiple selection][sublime-multiple-selection] feature into Vim, but none so far have been in my opinion a faithful port that is simplistic to use, yet powerful and intuitive enough for an existing Vim user. [vim-multiple-cursors] is yet another attempt at that. + +### It's great for quick refactoring +![Example1](assets/example1.gif?raw=true) + +Vim command sequence: `2Gfpcname` + +### Add a cursor to each line of your visual selection +![Example2](assets/example2.gif?raw=true) + +Vim command sequence: `2Gvipi"",vipJ$r]Idays = [` + +### Do it backwards too! This is not just a replay of the above gif :) +![Example3](assets/example3.gif?raw=true) + +Vim command sequence: `2Gdf[$r,0f,vc` + +### Add multiple cursors using regexes +![Example4](assets/example4.gif?raw=true) + +To see what keystrokes are used for the above examples, see [the wiki page](https://github.com/terryma/vim-multiple-cursors/wiki/Keystrokes-for-example-gifs). + +## Features +- Live update in Insert mode +- One key to rule it all! See [Quick Start](#quick-start) on what the key does in different scenarios +- Works in Normal, Insert, and Visual mode for any commands (including + multi-key commands, assuming you set `g:multicursor_insert_maps` and + `g:multicursor_normal_maps`; see Settings below for details) + +## Installation +Install using [Pathogen], [Vundle], [Neobundle], or your favorite Vim package manager. +Requires vim 7.4 or later for full functionality. + +## Quick Start +Out of the box, all you need to know is a single key `Ctrl-n`. Pressing the key in Normal mode highlights the current word under the cursor in Visual mode and places a virtual cursor at the end of it. Pressing it again finds the next occurrence and places another virtual cursor at the end of the visual selection. If you select multiple lines in Visual mode, pressing the key puts a virtual cursor at every line and leaves you in Normal mode. + +After you've marked all your locations with `Ctrl-n`, you can change the visual selection with normal Vim motion commands in Visual mode. You could go to Normal mode by pressing `v` and wield your motion commands there. Single key command to switch to Insert mode such as `c` or `s` from Visual mode or `i`, `a`, `I`, `A` in Normal mode should work without any issues. + +At any time, you can press `` to exit back to regular Vim. + +Two additional keys are also mapped: +- `Ctrl-p` in Visual mode will remove the current virtual cursor and go back to the previous virtual cursor location. This is useful if you are trigger happy with `Ctrl-n` and accidentally went too far. +- `Ctrl-x` in Visual mode will remove the current virtual cursor and skip to the next virtual cursor location. This is useful if you don't want the current selection to be a candidate to operate on later. + +You can also add multiple cursors using a regular expression. The command `MultipleCursorsFind` accepts a range and a pattern, and it will create a virtual cursor at the end of every match within the range. If no range is passed in, then it defaults to the entire buffer. + +**NOTE:** If at any time you have lingering cursors on screen, you can press `Ctrl-n` in Normal mode and it will remove all prior cursors before starting a new one. + +## Mapping +Out of the box, only the single key `Ctrl-n` is mapped in regular Vim's Normal mode and Visual mode to provide the functionality mentioned above. `Ctrl-n`, `Ctrl-p`, `Ctrl-x`, and `` are mapped in the special multicursor mode once you've added at least one virtual cursor to the buffer. If you don't like the plugin taking over your favorite key bindings, you can turn off the default with +```viml +let g:multi_cursor_use_default_mapping=0 +``` + +You can then map the 'next', 'previous', 'skip', and 'exit' keys like the following: +```viml +" Default mapping +let g:multi_cursor_next_key='' +let g:multi_cursor_prev_key='' +let g:multi_cursor_skip_key='' +let g:multi_cursor_quit_key='' +``` + +By default, the 'next' key is also used to enter multicursor mode. If you want to use a different key to start multicursor mode than for selecting the next location, do like the following: +```viml +" Map start key separately from next key +let g:multi_cursor_start_key='' +``` + +Note that when multicursor mode is started, it selects current word with boundaries, i.e. it behaves like `*`. If you want to avoid word boundaries in Normal mode (as `g*` does) but still have old behaviour up your sleeve, you can do the following: +```viml +let g:multi_cursor_start_key='' +let g:multi_cursor_start_word_key='g' +``` +In this configuration `` will start multicursor mode without word boundaries (but only in Normal mode, as it does not make much sense to use it in Visual mode). Old behaviour with word boundaries is still available using `g`. + +**IMPORTANT:** Please note that currently only single keystrokes and special keys can be mapped. This means that a mapping like `n` will NOT work correctly. For a list of special keys that are supported, see `help :key-notation` + +**NOTE:** Please make sure to always map something to `g:multi_cursor_quit_key`, otherwise you'll have a tough time quitting from multicursor mode. + +**NOTE:** Prior to version 1.3, the recommended way to map the keys is using the expression quote syntax in Vim, using something like `"\"` or `"\"` (see h: expr-quote). After 1.3, the recommended way is to use a raw string like above. If your key mappings don't appear to work, give the new syntax a try. + +You can also map your own keys to quit, if ``g:multi_cursor_quit_key`` won't work: + +``` +let g:multi_cursor_quit_key='' +nnoremap :call multiple_cursors#quit() +``` + +## Settings +Currently there are four additional global settings one can tweak: + +### ```g:multi_cursor_exit_from_visual_mode``` (Default: 1) +If set to 0, then pressing `g:multi_cursor_quit_key` in _Visual_ mode will not quit and delete all existing cursors. This is useful if you want to press Escape and go back to Normal mode, and still be able to operate on all the cursors. + +### ```g:multi_cursor_exit_from_insert_mode``` (Default: 1) +If set to 0, then pressing `g:multi_cursor_quit_key` in _Insert_ mode will not quit and delete all existing cursors. This is useful if you want to press Escape and go back to Normal mode, and still be able to operate on all the cursors. + +### ```g:multi_cursor_insert_maps``` (Default: `{}`) +Any key in this map (values are ignored) will cause multi-cursor _Insert_ mode +to pause for `timeoutlen` waiting for map completion just like normal vim. +Otherwise keys mapped in insert mode are ignored when multiple cursors are +active. For example, setting it to `{'\':1}` will make insert-mode mappings +beginning with the default leader key work in multi-cursor mode. You have to +manually set this because vim doesn't provide a way to see which keys _start_ +mappings. + +### ```g:multi_cursor_normal_maps``` (Default: see below) +Default value: `{'!':1, '@':1, '=':1, 'q':1, 'r':1, 't':1, 'T':1, 'y':1, '[':1, ']':1, '\':1, 'd':1, 'f':1, 'F':1, 'g':1, '"':1, 'z':1, 'c':1, 'm':1, '<':1, '>':1}` + +Any key in this map (values are ignored) will cause multi-cursor _Normal_ mode +to pause for map completion just like normal vim. Otherwise keys mapped in +normal mode will "fail to replay" when multiple cursors are active. For example, +changing it from `{}` to `{'d':1}` makes normal-mode mappings beginning with `d` +(such as `dw` to delete a word) work in multi-cursor mode. + +### ```g:multi_cursor_visual_maps``` (Default: see below) +Default value: `{'i':1, 'a':1, 'f':1, 'F':1, 't':1, 'T':1}` + +Any key in this map (values are ignored) will cause multi-cursor _Visual_ mode +to pause for map completion just like normal vim. Otherwise keys mapped in +visual mode will "fail to replay" when multiple cursors are active. For example, +changing it from `{}` to `{'i':1}` makes visual-mode mappings beginning with `i` +(such as `it` to select an "inner tag block") work in multi-cursor mode. + +The default list contents should work for anybody, unless they have remapped a +key from an operator-pending command to a non-operator-pending command or +vice versa. + +These keys must be manually listed because vim doesn't provide a way to +automatically see which keys _start_ mappings, and trying to run motion commands +such as `j` as if they were operator-pending commands can break things. + +### Interactions with other plugins + +### ```Multiple_cursors_before/Multiple_cursors_after``` (Default: `nothing`) + +Other plugins may trigger on keypresses when in insert mode. These plugins +generally provide a means to toggle their active state. These hooks allow +the user to provide functions in their .vimrc to do this when multiple-cursor-mode +is entered. + +For example, if you are using [Neocomplete](https://github.com/Shougo/neocomplete.vim), +add this to your vimrc to prevent conflict: + +```viml +" Called once right before you start selecting multiple cursors +function! Multiple_cursors_before() + if exists(':NeoCompleteLock')==2 + exe 'NeoCompleteLock' + endif +endfunction + +" Called once only when the multiple selection is canceled (default ) +function! Multiple_cursors_after() + if exists(':NeoCompleteUnlock')==2 + exe 'NeoCompleteUnlock' + endif +endfunction +``` + +With this locking and unlocking we prevent neocomplete to trigger it's function calls until we are finished with multiple cursors editing. + +Plugins themselves can register `User` autocommands on `MultipleCursorsPre` and +`MultipleCursorsPost` for automatic integration. + +### Highlight +The plugin uses the highlight group `multiple_cursors_cursor` and `multiple_cursors_visual` to highlight the virtual cursors and their visual selections respectively. You can customize them by putting something similar like the following in your vimrc: + +```viml +" Default highlighting (see help :highlight and help :highlight-link) +highlight multiple_cursors_cursor term=reverse cterm=reverse gui=reverse +highlight link multiple_cursors_visual Visual +``` + +## FAQ + +#### **Q** CTRL+n doesn't seem to work in gVIM? + +**A** Try setting `set selection=inclusive` in your `~/.gvimrc` + +#### **Q** How can I select `n` keywords with several keystrokes? I have tried `200` which does not work. + +**A** You can use :MultipleCursorsFind keyword. I have this binding in my vimrc: + +```VimL +nnoremap :MultipleCursorsFind / +vnoremap :MultipleCursorsFind / +``` + +This allows one to a) search for the keyword using `*` b) turn search results into cursors with `Alt-j`. + +## Known Issues +- Select mode is not implemented + +## Issue Creation Requirements + +This is a community supported project. Contributor's time is precious and limited. To ensure your issue is not closed out of hand, please ensure it meets the requirements outlined in [CONTRIBUTING.md](CONTRIBUTING.md). + +## Changelog +See [CHANGELOG.md](CHANGELOG.md) + +## Contributing +As one can see, there're still many issues to be resolved, patches and suggestions are always welcome! A list of open feature requests can be found [here](../../issues?labels=enhancement&state=open). + +Running the test suite requires ruby and rake as well as vim of course. On Mac +OS, [MacVim](https://code.google.com/p/macvim/) is known to work. + +## Credit +Obviously inspired by Sublime Text's [multiple selection][sublime-multiple-selection] feature, also encouraged by Emac's [multiple cursors][emacs-multiple-cursors] implementation by Magnar Sveen + +[vim-multiple-cursors]:http://github.com/terryma/vim-multiple-cursors +[sublime-multiple-selection]:http://www.sublimetext.com/docs/2/multiple_selection_with_the_keyboard.html +[Pathogen]:http://github.com/tpope/vim-pathogen +[Vundle]:http://github.com/gmarik/vundle +[Neobundle]:http://github.com/Shougo/neobundle.vim +[emacs-multiple-cursors]:https://github.com/magnars/multiple-cursors.el + + +[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/terryma/vim-multiple-cursors/trend.png)](https://bitdeli.com/free "Bitdeli Badge") diff --git a/.vim/bundle/vim-multiple-cursors/Rakefile b/.vim/bundle/vim-multiple-cursors/Rakefile new file mode 100644 index 0000000..7150a28 --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/Rakefile @@ -0,0 +1,11 @@ +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new(:spec) do |t| + t.pattern = 'spec/multiple_cursors_spec.rb' +end + +RSpec::Core::RakeTask.new(:benchmark) do |t| + t.pattern = 'spec/benchmark_spec.rb' +end + +task :default => :spec diff --git a/.vim/bundle/vim-multiple-cursors/autoload/multiple_cursors.vim b/.vim/bundle/vim-multiple-cursors/autoload/multiple_cursors.vim new file mode 100644 index 0000000..36d267f --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/autoload/multiple_cursors.vim @@ -0,0 +1,1256 @@ +"=============================================================================== +" Initialization +"=============================================================================== + +" Tweak key settings. If the key is set using 'expr-quote' (h: expr-quote), then +" there's nothing that we need to do. If it's set using raw strings, then we +" need to convert it. We need to resort to such voodoo exec magic here to get +" it to work the way we like. '' is converted to '\' by the end and +" the global vars are replaced by their new value. This is ok since the mapping +" using '' should already have completed in the plugin file. +for s:key in [ 'g:multi_cursor_next_key', + \ 'g:multi_cursor_prev_key', + \ 'g:multi_cursor_skip_key', + \ 'g:multi_cursor_quit_key' ] + if exists(s:key) + " Translate raw strings like "" into key code like "\" + exec 'let s:temp = '.s:key + if s:temp =~ '^<.*>$' + exec 'let '.s:key.' = "\'.s:temp.'"' + endif + else + " If the user didn't define it, initialize it to an empty string so the + " logic later don't break + exec 'let '.s:key.' = ""' + endif +endfor +unlet! s:key s:temp + +" These keys will not be replicated at every cursor location. Make sure that +" this assignment happens AFTER the key tweak setting above +let s:special_keys = { + \ 'v': [ g:multi_cursor_next_key, g:multi_cursor_prev_key, g:multi_cursor_skip_key ], + \ 'n': [ g:multi_cursor_next_key ], + \ } + +" The highlight group we use for all the cursors +let s:hi_group_cursor = 'multiple_cursors_cursor' + +" The highlight group we use for all the visual selection +let s:hi_group_visual = 'multiple_cursors_visual' + +" Used for preventing multiple calls on before function +let s:before_function_called = 0 + +" Used for searching whole words (search pattern is wrapped with \< and \>) +" Keep old behaviour by default (act like g*) +let s:use_word_boundary = 1 + +" Set up highlighting +if !hlexists(s:hi_group_cursor) + exec "highlight ".s:hi_group_cursor." term=reverse cterm=reverse gui=reverse" +endif +if !hlexists(s:hi_group_visual) + exec "highlight link ".s:hi_group_visual." Visual" +endif + +" Temporary buffer that is used for individual paste buffer save/restore +" operations +let s:paste_buffer_temporary_text = '' +let s:paste_buffer_temporary_type = '' + +"=============================================================================== +" Internal Mappings +"=============================================================================== + +inoremap (multiple-cursors-input) :call process_user_input() +nnoremap (multiple-cursors-input) :call process_user_input() +xnoremap (multiple-cursors-input) :call process_user_input() + +inoremap (multiple-cursors-apply) :call apply_user_input_next('i') +nnoremap (multiple-cursors-apply) :call apply_user_input_next('n') +xnoremap (multiple-cursors-apply) :call apply_user_input_next('v') + +inoremap (multiple-cursors-detect) :call detect_bad_input() +nnoremap (multiple-cursors-detect) :call detect_bad_input() +xnoremap (multiple-cursors-detect) :call detect_bad_input() + +inoremap (multiple-cursors-wait) :call wait_for_user_input('') +nnoremap (multiple-cursors-wait) :call wait_for_user_input('') +xnoremap (multiple-cursors-wait) :call wait_for_user_input('') + +" Note that although these mappings are seemingly triggerd from Visual mode, +" they are in fact triggered from Normal mode. We quit visual mode to allow the +" virtual highlighting to take over +nnoremap (multiple-cursors-prev) :call multiple_cursors#prev() +nnoremap (multiple-cursors-skip) :call multiple_cursors#skip() +nnoremap (multiple-cursors-new) :call multiple_cursors#new('v', 0) +nnoremap (multiple-cursors-new-word) :call multiple_cursors#new('v', 1) + +"=============================================================================== +" Public Functions +"=============================================================================== + +" Print some debugging info +function! multiple_cursors#debug() + call s:cm.debug() +endfunction + +function! multiple_cursors#get_latency_debug_file() + return s:latency_debug_file +endfunction + + +function! s:fire_pre_triggers() + if !s:before_function_called + doautocmd User MultipleCursorsPre + if exists('*Multiple_cursors_before') + exe "call Multiple_cursors_before()" + endif + let s:before_function_called = 1 + endif +endfunction + +" Creates a new cursor. Different logic applies depending on the mode the user +" is in and the current state of the buffer. +" 1. In normal mode, a new cursor is created at the end of the word under Vim's +" normal cursor +" 2. In visual mode, if the visual selection covers more than one line, a new +" cursor is created at the beginning of each line +" 3. In visual mode, if the visual selection covers a single line, a new cursor +" is created at the end of the visual selection. Another cursor will be +" attempted to be created at the next occurrence of the visual selection +function! multiple_cursors#new(mode, word_boundary) + " Call before function if exists only once until it is canceled () + call s:fire_pre_triggers() + let s:use_word_boundary = a:word_boundary + if a:mode ==# 'n' + " Reset all existing cursors, don't restore view and setting + call s:cm.reset(0, 0) + + " Select the word under cursor to set the '< and '> marks + exec "normal! viw" + call s:exit_visual_mode() + + " Add cursor with the current visual selection + call s:cm.add(s:pos("'>"), s:region("'<", "'>")) + call s:wait_for_user_input('v') + elseif a:mode ==# 'v' + " If the visual area covers the same line, then do a search for next + " occurrence + let start = line("'<") + let finish = line("'>") + if start != finish + call s:cm.reset(0, 0) + let col = col("'<") + for line in range(line("'<"), line("'>")) + let pos = [line, col] + call s:cm.add(pos) + endfor + " Start in normal mode + call s:wait_for_user_input('n') + else + " Came directly from visual mode + if s:cm.is_empty() + call s:cm.reset(0, 0) + + if visualmode() ==# 'V' + let left = [line('.'), 1] + let right = [line('.'), col('$')-1] + if right[1] == 0 " empty line + return + endif + call s:cm.add(right, [left, right]) + else + call s:cm.add(s:pos("'>"), s:region("'<", "'>")) + endif + endif + let content = s:get_text(s:region("'<", "'>")) + let next = s:find_next(content) + if s:cm.add(next[1], next) + call s:update_visual_markers(next) + else + call cursor(s:cm.get_current().position) + echohl WarningMsg | echo 'No more matches' | echohl None + endif + call s:wait_for_user_input('v') + endif + endif +endfunction + +" Quit out of multicursor mode, fixes #27. +function! multiple_cursors#quit() + call s:exit() +endfunction + +" Delete the current cursor. If there's no more cursors, stop the loop +function! multiple_cursors#prev() + call s:cm.delete_current() + if !s:cm.is_empty() + call s:update_visual_markers(s:cm.get_current().visual) + call cursor(s:cm.get_current().position) + call s:wait_for_user_input('v') + endif +endfunction + +" Skip the current cursor and move to the next cursor +function! multiple_cursors#skip() + call s:cm.delete_current() + let content = s:get_text(s:region("'<", "'>")) + let next = s:find_next(content) + call s:cm.add(next[1], next) + call s:update_visual_markers(next) + call s:wait_for_user_input('v') +endfunction + +" Search for pattern between the start and end line number. For each match, add +" a virtual cursor at the end and start multicursor mode +" This function is called from a command. User commands in Vim do not support +" passing in column ranges. If the user selects a block of text in visual mode, +" but not visual line mode, we only want to match patterns within the actual +" visual selection. We get around this by checking the last visual selection and +" see if its start and end lines match the input. If so, we assume that the user +" did a normal visual selection and we use the '< and '> marks to define the +" region instead of start and end from the method parameter. +function! multiple_cursors#find(start, end, pattern) + let s:cm.saved_winview = winsaveview() + let s:cm.start_from_find = 1 + if visualmode() ==# 'v' && a:start == line("'<") && a:end == line("'>") + let pos1 = s:pos("'<") + let pos2 = s:pos("'>") + else + let pos1 = [a:start, 1] + let pos2 = [a:end, col([a:end, '$'])] + endif + call cursor(pos1) + let first = 1 + while 1 + if first + " Set `virtualedit` to 'onemore' for the first search to consistently + " match patterns like '$' + let saved_virtualedit = &virtualedit + let &virtualedit = "onemore" + " First search starts from the current position + let match = search(a:pattern, 'cW') + else + let match = search(a:pattern, 'W') + endif + if !match + break + endif + let left = s:pos('.') + " Perform an intermediate backward search to correctly match patterns like + " '^' and '$' + let match = search(a:pattern, 'bceW') + let right = s:pos('.') + " Reset the cursor and perform a normal search if the intermediate search + " wasn't successful + if !match || s:compare_pos(right, left) != 0 + call cursor(left) + call search(a:pattern, 'ceW') + let right = s:pos('.') + endif + if first + let &virtualedit = saved_virtualedit + let first = 0 + endif + if s:compare_pos(right, pos2) > 0 + " Position the cursor at the end of the previous match so it'll be on a + " virtual cursor when multicursor mode is started. The `winrestview()` + " call below 'undoes' unnecessary repositionings + call search(a:pattern, 'be') + break + endif + call s:cm.add(right, [left, right]) + " Redraw here forces the cursor movement to be updated. This prevents the + " jerky behavior when doing any action once the cursors are added. But it + " also slows down adding the cursors dramatically. We need to a better + " solution here + " redraw + endwhile + if s:cm.is_empty() + call winrestview(s:cm.saved_winview) + echohl ErrorMsg | echo 'No match found' | echohl None + return + else + echohl Normal | echo 'Added '.s:cm.size().' cursor'.(s:cm.size()>1?'s':'') | echohl None + + " If we've created any cursors, we need to call the before function, end + " function will be called via normal routes + call s:fire_pre_triggers() + + call s:wait_for_user_input('v') + endif +endfunction + +"=============================================================================== +" Cursor class +"=============================================================================== +let s:Cursor = {} + +" Create a new cursor. Highlight it and save the current line length +function! s:Cursor.new(position) + let obj = copy(self) + let obj.position = copy(a:position) + let obj.visual = [] + let obj.saved_visual = [] + " Stores text that was yanked after any commands in Normal or Visual mode + let obj.paste_buffer_text = getreg('"') + let obj.paste_buffer_type = getregtype('"') + let obj.cursor_hi_id = s:highlight_cursor(a:position) + let obj.visual_hi_id = 0 + let obj.line_length = col([a:position[0], '$']) + if has('folding') + silent! execute a:position[0] . "foldopen!" + endif + return obj +endfunction + +" Return the line the cursor is on +function! s:Cursor.line() dict + return self.position[0] +endfunction + +" Return the column the cursor is on +function! s:Cursor.column() dict + return self.position[1] +endfunction + +" Move the cursor location by the number of lines and columns specified in the +" input. The input can be negative. +function! s:Cursor.move(line, column) dict + let self.position[0] += a:line + let self.position[1] += a:column + if !empty(self.visual) + let self.visual[0][0] += a:line + let self.visual[0][1] += a:column + let self.visual[1][0] += a:line + let self.visual[1][1] += a:column + endif + call self.update_highlight() +endfunction + +" Update the current position of the cursor +function! s:Cursor.update_position(pos) dict + let self.position[0] = a:pos[0] + let self.position[1] = a:pos[1] + call self.update_highlight() +endfunction + +" Reapply the highlight on the cursor +function! s:Cursor.update_highlight() dict + call s:cm.remove_highlight(self.cursor_hi_id) + let self.cursor_hi_id = s:highlight_cursor(self.position) +endfunction + +" Refresh the length of the line the cursor is on. This could change from +" underneath +function! s:Cursor.update_line_length() dict + let self.line_length = col([self.line(), '$']) +endfunction + +" Update the visual selection and its highlight +function! s:Cursor.update_visual_selection(region) dict + let self.visual = deepcopy(a:region) + call s:cm.remove_highlight(self.visual_hi_id) + let self.visual_hi_id = s:highlight_region(a:region) +endfunction + +" Remove the visual selection and its highlight +function! s:Cursor.remove_visual_selection() dict + let self.saved_visual = deepcopy(self.visual) + let self.visual = [] + " TODO(terryma): Move functionality into separate class + call s:cm.remove_highlight(self.visual_hi_id) + let self.visual_hi_id = 0 +endfunction + +" Restore unnamed register from paste buffer +function! s:Cursor.restore_unnamed_register() dict + call setreg('"', self.paste_buffer_text, self.paste_buffer_type) +endfunction + +" Save contents of the unnamed register into paste buffer +function! s:Cursor.save_unnamed_register() dict + let self.paste_buffer_text = getreg('"') + let self.paste_buffer_type = getregtype('"') +endfunction + +"=============================================================================== +" CursorManager class +"=============================================================================== +let s:CursorManager = {} + +" Constructor +function! s:CursorManager.new() + let obj = copy(self) + " List of Cursors we're managing + let obj.cursors = [] + " Current index into the s:cursors array + let obj.current_index = -1 + " This marks the starting cursor index into the s:cursors array + let obj.starting_index = -1 + " We save some user settings when the plugin loads initially + let obj.saved_settings = { + \ 'virtualedit': &virtualedit, + \ 'cursorline': &cursorline, + \ 'lazyredraw': &lazyredraw, + \ 'paste': &paste, + \ 'clipboard': &clipboard, + \ } + " We save the window view when multicursor mode is entered + let obj.saved_winview = [] + " Track whether we started multicursor mode from calling multiple_cursors#find + let obj.start_from_find = 0 + return obj +endfunction + +" Clear all cursors and their highlights +function! s:CursorManager.reset(restore_view, restore_setting, ...) dict + if a:restore_view + " Return the view back to the beginning + if !empty(self.saved_winview) + call winrestview(self.saved_winview) + endif + + " If the cursor moved, just restoring the view could get confusing, let's + " put the cursor at where the user left it. Only do this if we didn't start + " from find mode + if !self.is_empty() && !self.start_from_find + call cursor(self.get(0).position) + endif + endif + + " Delete all cursors and clear their highlights. Don't do clearmatches() as + " that will potentially interfere with other plugins + if !self.is_empty() + for i in range(self.size()) + call self.remove_highlight(self.get(i).cursor_hi_id) + call self.remove_highlight(self.get(i).visual_hi_id) + endfor + endif + + let self.cursors = [] + let self.current_index = -1 + let self.starting_index = -1 + let self.saved_winview = [] + let self.start_from_find = 0 + let s:char = '' + let s:saved_char = '' + if a:restore_setting + call self.restore_user_settings() + endif + " Call after function if exists and only if action is canceled () + if a:0 && s:before_function_called + if exists('*Multiple_cursors_after') + exe "call Multiple_cursors_after()" + endif + doautocmd User MultipleCursorsPost + let s:before_function_called = 0 + endif +endfunction + +" Returns 0 if it's not managing any cursors at the moment +function! s:CursorManager.is_empty() dict + return self.size() == 0 +endfunction + +" Returns the number of cursors it's managing +function! s:CursorManager.size() dict + return len(self.cursors) +endfunction + +" Returns the current cursor +function! s:CursorManager.get_current() dict + return self.cursors[self.current_index] +endfunction + +" Returns the cursor at index i +function! s:CursorManager.get(i) dict + return self.cursors[a:i] +endfunction + +" Removes the current cursor and all its associated highlighting. Also update +" the current index +function! s:CursorManager.delete_current() dict + call self.remove_highlight(self.get_current().cursor_hi_id) + call self.remove_highlight(self.get_current().visual_hi_id) + call remove(self.cursors, self.current_index) + let self.current_index -= 1 +endfunction + +" Remove the highlighting if its matchid exists +function! s:CursorManager.remove_highlight(hi_id) dict + if a:hi_id + " If the user did a matchdelete or a clearmatches, we don't want to barf if + " the matchid is no longer valid + silent! call matchdelete(a:hi_id) + endif +endfunction + +function! s:CursorManager.debug() dict + let i = 0 + for c in self.cursors + echom 'cursor #'.i.': pos='.string(c.position).' visual='.string(c.visual) + let i+=1 + endfor + echom 'input = '.s:char + echom 'index = '.self.current_index + echom 'pos = '.string(s:pos('.')) + echom '''< = '.string(s:pos("'<")) + echom '''> = '.string(s:pos("'>")) + echom 'to mode = '.s:to_mode + echom 'from mode = '.s:from_mode + " echom 'special keys = '.string(s:special_keys) + echom ' ' +endfunction + +" Sync the current cursor to the current Vim cursor. This includes updating its +" location, its highlight, and potentially its visual region. Return true if the +" position changed, false otherwise +function! s:CursorManager.update_current() dict + let cur = self.get_current() + if s:to_mode ==# 'v' || s:to_mode ==# 'V' + " If we're in visual line mode, we need to go to visual mode before we can + " update the visual region + if s:to_mode ==# 'V' + exec "normal! gvv\" + endif + + " Sets the cursor at the right place + exec "normal! gv\" + call cur.update_visual_selection(s:get_visual_region(s:pos('.'))) + elseif s:from_mode ==# 'v' || s:from_mode ==# 'V' + " Save contents of unnamed register after each operation in Visual mode. + " This should be executed after user input is processed, when unnamed + " register already contains the text. + call cur.save_unnamed_register() + + call cur.remove_visual_selection() + elseif s:from_mode ==# 'i' && s:to_mode ==# 'n' && self.current_index != self.size() - 1 + normal! h + elseif s:from_mode ==# 'n' + " Save contents of unnamed register after each operation in Normal mode. + call cur.save_unnamed_register() + endif + let vdelta = line('$') - s:saved_linecount + " If the total number of lines changed in the buffer, we need to potentially + " adjust other cursor locations + if vdelta != 0 + if self.current_index != self.size() - 1 + let cur_column_offset = (cur.column() - col('.')) * -1 + let new_line_length = len(getline('.')) + for i in range(self.current_index+1, self.size()-1) + let hdelta = 0 + " Note: some versions of Vim don't like chaining function calls like + " a.b().c(). For compatibility reasons, don't do it + let c = self.get(i) + " If there're other cursors on the same line, we need to adjust their + " columns. This needs to happen before we adjust their line! + if cur.line() == c.line() + if vdelta > 0 + " Added a line + let hdelta = cur_column_offset + else + " Removed a line + let hdelta = new_line_length + endif + endif + call c.move(vdelta, hdelta) + endfor + endif + else + " If the line length changes, for all the other cursors on the same line as + " the current one, update their cursor location as well + let hdelta = col('$') - cur.line_length + " Only do this if we're still on the same line as before + if hdelta != 0 && cur.line() == line('.') + " Update all the cursor's positions that occur after the current cursor on + " the same line + if self.current_index != self.size() - 1 + for i in range(self.current_index+1, self.size()-1) + let c = self.get(i) + " Only do it for cursors on the same line + if cur.line() == c.line() + call c.move(0, hdelta) + else + " Early exit, if we're not on the same line, neither will any cursor + " that come after this + break + endif + endfor + endif + endif + endif + + let pos = s:pos('.') + if cur.position == pos + return 0 + endif + call cur.update_position(pos) + return 1 +endfunction + +" Advance to the next cursor +function! s:CursorManager.next() dict + let self.current_index = (self.current_index + 1) % self.size() +endfunction + +" Start tracking cursor updates +function! s:CursorManager.start_loop() dict + let self.starting_index = self.current_index +endfunction + +" Returns true if we're cycled through all the cursors +function! s:CursorManager.loop_done() dict + return self.current_index == self.starting_index +endfunction + +" Tweak some user settings, and save our current window view. This is called +" every time multicursor mode is entered. +" virtualedit needs to be set to onemore for updates to work correctly +" cursorline needs to be turned off for the cursor highlight to work on the line +" where the real vim cursor is +" lazyredraw needs to be turned on to prevent jerky screen behavior with many +" cursors on screen +" paste mode needs to be switched off since it turns off a bunch of features +" that's critical for the plugin to function +" clipboard should not have unnamed and unnamedplus otherwise plugin cannot +" reliably use unnamed register ('"') +function! s:CursorManager.initialize() dict + let self.saved_settings['virtualedit'] = &virtualedit + let self.saved_settings['cursorline'] = &cursorline + let self.saved_settings['lazyredraw'] = &lazyredraw + let self.saved_settings['paste'] = &paste + let self.saved_settings['clipboard'] = &clipboard + let &virtualedit = "onemore" + let &cursorline = 0 + let &lazyredraw = 1 + let &paste = 0 + set clipboard-=unnamed clipboard-=unnamedplus + " We could have already saved the view from multiple_cursors#find + if !self.start_from_find + let self.saved_winview = winsaveview() + endif + + " Save contents and type of unnamed register upon entering multicursor mode + " to restore it later when leaving mode + let s:paste_buffer_temporary_text = getreg('"') + let s:paste_buffer_temporary_type = getregtype('"') +endfunction + +" Restore user settings. +function! s:CursorManager.restore_user_settings() dict + if !empty(self.saved_settings) + let &virtualedit = self.saved_settings['virtualedit'] + let &cursorline = self.saved_settings['cursorline'] + let &lazyredraw = self.saved_settings['lazyredraw'] + let &paste = self.saved_settings['paste'] + let &clipboard = self.saved_settings['clipboard'] + endif + + " Restore original contents and type of unnamed register. This method is + " called from reset, which calls us only when restore_setting argument is + " true, which happens only when we leave multicursor mode. This should be + " symmetrical to saving of unnamed register upon the start of multicursor + " mode. + call setreg('"', s:paste_buffer_temporary_text, s:paste_buffer_temporary_type) +endfunction + +" Reposition all cursors to the start or end of their region +function! s:CursorManager.reposition_all_within_region(start) dict + for c in self.cursors + call c.update_position(c.saved_visual[a:start ? 0 : 1]) + endfor +endfunction + +" Reselect the current cursor's region in visual mode +function! s:CursorManager.reapply_visual_selection() dict + call s:select_in_visual_mode(self.get_current().visual) +endfunction + +" Creates a new virtual cursor as 'pos' +" Optionally a 'region' object can be passed in as second argument. If set, the +" visual region of the cursor will be set to it +" Return true if the cursor has been successfully added, false otherwise +" Mode change: Normal -> Normal +" Cursor change: None (TODO Should we set Vim's cursor to pos?) +function! s:CursorManager.add(pos, ...) dict + " Lazy init + if self.is_empty() + call self.initialize() + endif + + " Don't add duplicates + let i = 0 + for c in self.cursors + if c.position == a:pos + return 0 + endif + let i+=1 + endfor + + let cursor = s:Cursor.new(a:pos) + + " Save the visual selection + if a:0 > 0 + call cursor.update_visual_selection(a:1) + endif + + call add(self.cursors, cursor) + let self.current_index += 1 + return 1 +endfunction + +"=============================================================================== +" Variables +"=============================================================================== + +" This is the last user input that we're going to replicate, in its string form +let s:char = '' +" This is either `I` or `A`, as input in Visual mode, that we're going to use +" to make the appropriate transition into Insert mode +let s:saved_char = '' +" This is the mode the user is in before s:char +let s:from_mode = '' +" This is the mode the user is in after s:char +let s:to_mode = '' +" This is the total number of lines in the buffer before processing s:char +let s:saved_linecount = -1 +" This is used to apply the highlight fix. See s:apply_highight_fix() +let s:saved_line = 0 +" This is the number of cursor locations where we detected an input that we +" cannot play back +let s:bad_input = 0 +" Singleton cursor manager instance +let s:cm = s:CursorManager.new() + +"=============================================================================== +" Utility functions +"=============================================================================== + +" Return the position of the input marker as a two element array. First element +" is the line number, second element is the column number +function! s:pos(mark) + let pos = getpos(a:mark) + return [pos[1], pos[2]] +endfunction + +" Return the region covered by the input markers as a two element array. First +" element is the position of the start marker, second element is the position of +" the end marker +function! s:region(start_mark, end_mark) + return [s:pos(a:start_mark), s:pos(a:end_mark)] +endfunction + +" Exit visual mode and go back to normal mode +" The reason for the additional gv\ is that it allows the cursor to stay +" on where it was before exiting +" Mode change: Normal -> Normal or Visual -> Normal +" Cursor change: If in visual mode, changed to exactly where it was on screen in +" visual mode. If in normal mode, changed to where the cursor was when the last +" visual selection ended +function! s:exit_visual_mode() + exec "normal! \gv\" + + " Call before function if exists only once until it is canceled () + if exists('*Multiple_cursors_before') && !s:before_function_called + exe "call Multiple_cursors_before()" + let s:before_function_called = 1 + endif +endfunction + +" Visually select input region, where region is an array containing the start +" and end position. If start is after end, the selection simply goes backwards. +" Typically m<, m>, and gv would be a simple way of accomplishing this, but on +" some systems, the m< and m> marks are not supported. Note that v`` has random +" behavior if `` is the same location as the cursor location. +" Mode change: Normal -> Visual +" Cursor change: Set to end of region +" TODO: Refactor this and s:update_visual_markers +" FIXME: By using m` we're destroying the user's jumplist. We should use a +" different mark and use :keepjump +function! s:select_in_visual_mode(region) + if a:region[0] == a:region[1] + normal! v + else + call cursor(a:region[1]) + normal! m` + call cursor(a:region[0]) + normal! v`` + endif + + " Unselect and reselect it again to properly set the '< and '> markers + exec "normal! \gv" +endfunction + +" Update '< and '> to the input region +" Mode change: Normal -> Normal +" Cursor change: Set to the end of the region +function! s:update_visual_markers(region) + if a:region[0] == a:region[1] + normal! v + else + call cursor(a:region[1]) + normal! m` + call cursor(a:region[0]) + normal! v`` + endif + call s:exit_visual_mode() +endfunction + +" Finds the next occurrence of the input text in the current buffer. +" Search is case sensitive +" Mode change: Normal -> Normal +" Cursor change: Set to the end of the match +function! s:find_next(text) + let pattern = substitute(escape(a:text, '\'), '\n', '\\n', 'g') + if s:use_word_boundary == 1 + let pattern = '\<'.pattern.'\>' + endif + let pattern = '\V\C'.pattern + call search(pattern) + let start = s:pos('.') + call search(pattern, 'ce') + let end = s:pos('.') + return [start, end] +endfunction + +" Highlight the position using the cursor highlight group +function! s:highlight_cursor(pos) + " Give cursor highlight high priority, to overrule visual selection + return matchadd(s:hi_group_cursor, '\%'.a:pos[0].'l\%'.a:pos[1].'c', 99999) +endfunction + +" Compare two position arrays. Return a negative value if lhs occurs before rhs, +" positive value if after, and 0 if they are the same. +function! s:compare_pos(l, r) + " If number lines are the same, compare columns + return a:l[0] ==# a:r[0] ? a:l[1] - a:r[1] : a:l[0] - a:r[0] +endfunction + +" Highlight the area bounded by the input region. The logic here really stinks, +" it's frustrating that Vim doesn't have a built in easier way to do this. None +" of the \%V or \%'m solutions work because we need the highlighting to stay for +" multiple places. +function! s:highlight_region(region) + let s = sort(copy(a:region), "s:compare_pos") + if s:to_mode ==# 'V' + let pattern = '\%>'.(s[0][0]-1).'l\%<'.(s[1][0]+1).'l.*\ze.\_$' + else + if (s[0][0] == s[1][0]) + " Same line + let pattern = '\%'.s[0][0].'l\%>'.(s[0][1]-1).'c.*\%<'.(s[1][1]+1).'c.' + else + " Two lines + let s1 = '\%'.s[0][0].'l.\%>'.s[0][1].'c.*' + let s2 = '\%'.s[1][0].'l.*\%<'.s[1][1].'c..' + let pattern = s1.'\|'.s2 + " More than two lines + if (s[1][0] - s[0][0] > 1) + let pattern = pattern.'\|\%>'.s[0][0].'l\%<'.s[1][0].'l.*\ze.\_$' + endif + endif + endif + return matchadd(s:hi_group_visual, pattern) +endfunction + +" Perform the operation that's necessary to revert us from one mode to another +function! s:revert_mode(from, to) + if a:to ==# 'v' + call s:cm.reapply_visual_selection() + elseif a:to ==# 'V' + call s:cm.reapply_visual_selection() + normal! V + elseif a:to ==# 'n' && a:from ==# 'i' + stopinsert + endif +endfunction + +" Consume all the additional character the user typed between the last +" getchar() and here, to avoid potential race condition. +let s:saved_keys = "" +function! s:feedkeys(keys) + while 1 + let c = getchar(0) + let char_type = type(c) + " Checking type is important, when strings are compared with integers, + " strings are always converted to ints, and all strings are equal to 0 + if char_type == 0 + if c == 0 + break + else + let s:saved_keys .= nr2char(c) + endif + elseif char_type == 1 " char with more than 8 bits (as string) + let s:saved_keys .= c + endif + endwhile + call feedkeys(a:keys) +endfunction + +" Take the user input and apply it at every cursor +function! s:process_user_input() + " Grr this is frustrating. In Insert mode, between the feedkey call and here, + " the current position could actually CHANGE for some odd reason. Forcing a + " position reset here + let cursor_position = s:cm.get_current() + call cursor(cursor_position.position) + + " Before applying the user input, we need to revert back to the mode the user + " was in when the input was entered + call s:revert_mode(s:to_mode, s:from_mode) + + " Update the line length BEFORE applying any actions. TODO(terryma): Is there + " a better place to do this? + " let cursor_position = s:cm.get_current() + call cursor_position.update_line_length() + let s:saved_linecount = line('$') + + " Restore unnamed register only in Normal mode. This should happen before user + " input is processed. + if s:from_mode ==# 'n' || s:from_mode ==# 'v' || s:from_mode ==# 'V' + call cursor_position.restore_unnamed_register() + endif + + " Apply the user input. Note that the above could potentially change mode, we + " use the mapping below to help us determine what the new mode is + " Note that it's possible that \(multiple-cursors-apply) never gets called, we have a + " detection mechanism using \(multiple-cursors-detect). See its documentation for more details + + " Assume that input is not valid + let s:valid_input = 0 + + " If we're coming from insert mode or going into insert mode, always chain the + " undos together. + " FIXME(terryma): Undo always places the cursor at the beginning of the line. + " Figure out why. + if s:from_mode ==# 'i' || s:to_mode ==# 'i' + silent! undojoin | call s:feedkeys(s:char."\(multiple-cursors-apply)") + else + call s:feedkeys(s:char."\(multiple-cursors-apply)") + endif + + " Even when s:char produces invalid input, this method is always called. The + " 't' here is important + call feedkeys("\(multiple-cursors-detect)", 't') +endfunction + +" This method is always called during fanout, even when a bad user input causes +" s:apply_user_input_next to not be called. We detect that and force the method +" to be called to continue the fanout process +function! s:detect_bad_input() + if !s:valid_input + " To invoke the appropriate `(multiple-cursors-apply)` mapping, we + " need to revert back to the mode the user was in when the input was entered + call s:revert_mode(s:to_mode, s:from_mode) + " We ignore the bad input and force invoke s:apply_user_input_next + call feedkeys("\(multiple-cursors-apply)") + let s:bad_input += 1 + endif +endfunction + +" Complete transition into Insert mode when `I` or `A` is input in Visual mode +function! s:handle_visual_IA_to_insert() + if !empty(s:saved_char) && s:char =~# 'v\|V' && s:to_mode ==# 'n' + if s:saved_char ==# 'I' + call s:cm.reposition_all_within_region(1) + endif + call feedkeys(tolower(s:saved_char)) + let s:saved_char = '' + endif +endfunction + +" Begin transition into Insert mode when `I` or `A` is input in Visual mode +function! s:handle_visual_IA_to_normal() + if s:char =~# 'I\|A' && s:from_mode =~# 'v\|V' + let s:saved_char = s:char + let s:char = s:from_mode " spoof a 'v' or 'V' input to transiton from Visual into Normal mode + endif +endfunction + +" Apply the user input at the next cursor location +function! s:apply_user_input_next(mode) + let s:valid_input = 1 + + " Save the current mode, only if we haven't already + if empty(s:to_mode) + let s:to_mode = a:mode + if s:to_mode ==# 'v' + if visualmode() ==# 'V' + let s:to_mode = 'V' + endif + endif + endif + + " Update the current cursor's information + let changed = s:cm.update_current() + + " Advance the cursor index + call s:cm.next() + + " We're done if we're made the full round + if s:cm.loop_done() + if s:to_mode ==# 'v' || s:to_mode ==# 'V' + " This is necessary to set the "'<" and "'>" markers properly + call s:update_visual_markers(s:cm.get_current().visual) + endif + call feedkeys("\(multiple-cursors-wait)") + call s:handle_visual_IA_to_insert() + else + " Continue to next + call feedkeys("\(multiple-cursors-input)") + endif +endfunction + +" If pos is equal to the left side of the visual selection, the region start +" from end to start +function! s:get_visual_region(pos) + let left = s:pos("'<") + let right = s:pos("'>") + if a:pos == left + let region = [right, left] + else + let region = [left, right] + endif + return region +endfunction + +function! s:strpart(s, i, l) + if a:l == 0 + return '' + endif + let [s, l] = ['', 0] + for c in split(a:s[a:i :], '\zs') + let s .= c + let l += len(c) + if l >= a:l + break + endif + endfor + return s +endfunction + +" Return the content of the buffer between the input region. This is used to +" find the next match in the buffer +" Mode change: Normal -> Normal +" Cursor change: None +function! s:get_text(region) + let lines = getline(a:region[0][0], a:region[1][0]) + let lines[-1] = s:strpart(lines[-1], 0, a:region[1][1]) + let lines[0] = lines[0][a:region[0][1] - 1:] + return join(lines, "\n") +endfunction + +" Wrapper around getchar() that returns the string representation of the user +" input +function! s:get_char() + let c = getchar() + " If the character is a number, then it's not a special key + if type(c) == 0 + let c = nr2char(c) + endif + return c +endfunction + +" Quits multicursor mode and clears all cursors. Return true if exited +" successfully. +function! s:exit() + if s:last_char() !=# g:multi_cursor_quit_key + return 0 + endif + let exit = 0 + if s:from_mode ==# 'n' + let exit = 1 + elseif (s:from_mode ==# 'v' || s:from_mode ==# 'V') && + \ g:multi_cursor_exit_from_visual_mode + let exit = 1 + elseif s:from_mode ==# 'i' && g:multi_cursor_exit_from_insert_mode + stopinsert + let exit = 1 + endif + if exit + call s:cm.reset(1, 1, 1) + return 1 + endif + return 0 +endfunction + +" These keys don't get faned out to all cursor locations. Instead, they're used +" to add new / remove existing cursors +" Precondition: The function is only called when the keys and mode respect the +" setting in s:special_keys +function! s:handle_special_key(key, mode) + " Use feedkeys here instead of calling the function directly to prevent + " increasing the call stack, since feedkeys execute after the current call + " finishes + if a:key == g:multi_cursor_next_key + if s:use_word_boundary == 1 + call s:feedkeys("\(multiple-cursors-new-word)") + else + call s:feedkeys("\(multiple-cursors-new)") + endif + elseif a:key == g:multi_cursor_prev_key + call s:feedkeys("\(multiple-cursors-prev)") + elseif a:key == g:multi_cursor_skip_key + call s:feedkeys("\(multiple-cursors-skip)") + endif +endfunction + +" The last line where the normal Vim cursor is always seems to highlighting +" issues if the cursor is on the last column. Vim's cursor seems to override the +" highlight of the virtual cursor. This won't happen if the virtual cursor isn't +" the last character on the line. This is a hack to add an empty space on the +" Vim cursor line right before we do the redraw, we'll revert the change +" immedidately after the redraw so the change should not be intrusive to the +" user's buffer content +function! s:apply_highlight_fix() + " Only do this if we're on the last character of the line + if col('.') == col('$') + let s:saved_line = getline('.') + if s:from_mode ==# 'i' + silent! undojoin | call setline('.', s:saved_line.' ') + else + call setline('.', s:saved_line.' ') + endif + endif +endfunction + +" Revert the fix if it was applied earlier +function! s:revert_highlight_fix() + if type(s:saved_line) == 1 + if s:from_mode ==# 'i' + silent! undojoin | call setline('.', s:saved_line) + else + call setline('.', s:saved_line) + endif + endif + let s:saved_line = 0 +endfunction + +let s:retry_keys = "" +function! s:display_error() + if s:bad_input == s:cm.size() + \ && ((s:from_mode ==# 'n' && has_key(g:multi_cursor_normal_maps, s:char[0])) + \ || (s:from_mode =~# 'v\|V' && has_key(g:multi_cursor_visual_maps, s:char[0]))) + " we couldn't replay it anywhere but we're told it's the beginning of a + " multi-character map like the `d` in `dw` + let s:retry_keys = s:char + else + let s:retry_keys = "" + if s:bad_input > 0 + echohl ErrorMsg | + \ echo "Key '".s:char."' cannot be replayed at ". + \ s:bad_input." cursor location".(s:bad_input == 1 ? '' : 's') | + \ echohl Normal + endif + endif + let s:bad_input = 0 +endfunction + +let s:latency_debug_file = '' +function! s:start_latency_measure() + if g:multi_cursor_debug_latency + let s:start_time = reltime() + endif +endfunction + +function! s:skip_latency_measure() + if g:multi_cursor_debug_latency + let s:skip_latency_measure = 1 + endif +endfunction + +function! s:end_latency_measure() + if g:multi_cursor_debug_latency && !empty(s:char) + if empty(s:latency_debug_file) + let s:latency_debug_file = tempname() + exec 'redir >> '.s:latency_debug_file + silent! echom "Starting latency debug at ".reltimestr(reltime()) + redir END + endif + + if !s:skip_latency_measure + exec 'redir >> '.s:latency_debug_file + silent! echom "Processing '".s:char."' took ".string(str2float(reltimestr(reltime(s:start_time)))*1000).' ms in '.s:cm.size().' cursors. mode = '.s:from_mode + redir END + endif + endif + let s:skip_latency_measure = 0 +endfunction + +function! s:last_char() + return s:char[len(s:char)-1] +endfunction + +function! s:wait_for_user_input(mode) + call s:display_error() + + let s:from_mode = a:mode + if empty(a:mode) + let s:from_mode = s:to_mode + endif + let s:to_mode = '' + + " Right before redraw, apply the highlighting bug fix + call s:apply_highlight_fix() + + redraw + + " Immediately revert the change to leave the user's buffer unchanged + call s:revert_highlight_fix() + + call s:end_latency_measure() + + let s:char = s:retry_keys . s:saved_keys + if len(s:saved_keys) == 0 + let s:char .= s:get_char() + call s:handle_visual_IA_to_normal() + else + let s:saved_keys = "" + endif + + if s:from_mode ==# 'i' && has_key(g:multi_cursor_insert_maps, s:last_char()) + let c = getchar(0) + let char_type = type(c) + let poll_count = 0 + while char_type == 0 && c == 0 && poll_count < &timeoutlen + sleep 1m + let c = getchar(0) + let char_type = type(c) + let poll_count += 1 + endwhile + + if char_type == 0 && c != 0 + let s:char .= nr2char(c) + elseif char_type == 1 " char with more than 8 bits (as string) + let s:char .= c + endif + elseif s:from_mode !=# 'i' && s:char[0] ==# ":" + call feedkeys(s:char) + call s:cm.reset(1, 1) + return + elseif s:from_mode ==# 'n' + while match(s:last_char(), "\\d") == 0 + let s:char .= s:get_char() + endwhile + endif + + call s:start_latency_measure() + + " Clears any echoes we might've added + normal! : + + if s:exit() + return + endif + + " If the key is a special key and we're in the right mode, handle it + if index(get(s:special_keys, s:from_mode, []), s:last_char()) != -1 + call s:handle_special_key(s:last_char(), s:from_mode) + call s:skip_latency_measure() + else + call s:cm.start_loop() + call s:feedkeys("\(multiple-cursors-input)") + endif +endfunction diff --git a/.vim/bundle/vim-multiple-cursors/doc/multiple_cursors.txt b/.vim/bundle/vim-multiple-cursors/doc/multiple_cursors.txt new file mode 100644 index 0000000..422d5cf --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/doc/multiple_cursors.txt @@ -0,0 +1,253 @@ +*vim-multiple-cursors.txt* True Sublime Text multiple selection in Vim + + ____ _ __ + ____ ___ __ __/ / /_(_)___ / /__ _______ ________________ __________ + / __ `__ \/ / / / / __/ / __ \/ / _ \ / ___/ / / / ___/ ___/ __ \/ ___/ ___/ + / / / / / / /_/ / / /_/ / /_/ / / __/ / /__/ /_/ / / (__ ) /_/ / / (__ ) +/_/ /_/ /_/\__,_/_/\__/_/ .___/_/\___/ \___/\__,_/_/ /____/\____/_/ /____/ + /_/ + + + Reference Manual~ + + +============================================================================== + +CONTENTS *multiple-cursors-contents* + 1.Intro...................................|multiple-cursors-intro| + 2.Usage...................................|multiple-cursors-usage| + 3.Mappings................................|multiple-cursors-mappings| + 4.Global Options..........................|multiple-cursors-global-options| + 5.Issues..................................|multiple-cursors-issues| + 6.Contributing............................|multiple-cursors-contributing| + 7.License.................................|multiple-cursors-license| + 8.Credit..................................|multiple-cursors-credit| + 9.References..............................|multiple-cursors-references| + +============================================================================== +1. Intro *multiple-cursors-intro* + +There [1] have [2] been [3] many [4] attempts [5] at bringing Sublime Text's +awesome multiple selection [6] feature into Vim, but none so far have been in +my opinion a faithful port that is simplistic to use, yet powerful and +intuitive enough for an existing Vim user. *vim-multiple-cursors* is yet +another attempt at that. + +============================================================================== +2. Usage *multiple-cursors-usage* + +Out of the box, all you need to know is a single key CTRL-N. Pressing the key +in Normal mode highlights the current word under the cursor in Visual mode and +places a virtual cursor at the end of it. Pressing it again finds the next +ocurrence and places another virtual cursor at the end of the visual +selection. If you select multiple lines in Visual mode, pressing the key puts +a virtual cursor at every line and leaves you in Normal mode. + +After you've marked all your locations with CTRL-N, you can change the visual +selection with normal Vim motion commands in Visual mode. You could go to +Normal mode by pressing v and wield your motion commands there. Single key +command to switch to Insert mode such as `c` or `s` from Visual mode or `i`, +`a`, `I`, `A` in Normal mode should work without any issues. + +At any time, you can press to exit back to regular Vim. + +Two additional keys are also mapped: + +CTRL-P in Visual mode will remove the current virtual cursor and go back to +the previous virtual cursor location. This is useful if you are trigger happy +with Ctrl-n and accidentally went too far. + +CTRL-X in Visual mode will remove the current virtual cursor and skip to the +next virtual cursor location. This is useful if you don't want the current +selection to be a candidate to operate on later. + +You can also add multiple cursors using a regular expression. The command +*MultipleCursorsFind* accepts a range and a pattern, and it will create a +virtual cursor at the end of every match within the range. If no range is +passed in, then it defaults to the entire buffer. + +NOTE: If at any time you have lingering cursors on screen, you can press +CTRL-N in Normal mode and it will remove all prior cursors before starting a +new one. + +============================================================================== +3. Mappings *multiple-cursors-mappings* + +*g:multi_cursor_use_default_mapping* (Default: 1) + +Out of the box, only the single key CTRL-N is mapped in regular Vim's Normal +mode and Visual mode to provide the functionality mentioned above. CTRL-N, +CTRL-P, CTRL-X, and are mapped in the special multicursor mode once +you've added at least one virtual cursor to the buffer. If you don't like the +plugin taking over your favorite key bindings, you can turn off the default +with > + + let g:multi_cursor_use_default_mapping=0 +< + +*g:multi_cursor_next_key* (Default: '') +*g:multi_cursor_prev_key* (Default: '') +*g:multi_cursor_skip_key* (Default: '') +*g:multi_cursor_quit_key* (Default: '') +You can map the 'next', 'previous', 'skip', and 'exit' keys like the +following: > + + " Default mapping + let g:multi_cursor_next_key='' + let g:multi_cursor_prev_key='' + let g:multi_cursor_skip_key='' + let g:multi_cursor_quit_key='' +< + +*g:multi_cursor_start_key* (Default: 'g:multi_cursor_next_key') +By default, the same key is used to enter multicursor mode as to select the +next cursor location. If you want to use a different key to start multicursor +mode than for selecting the next location, do like the following: > + + " Map start key separately from next key + let g:multi_cursor_start_key='' +< + +*g:multi_cursor_start_word_key* +When multicursor mode is started, it selects current word without +boundaries, i.e. it behaves like `g*`. If you want to use word boundaries in +Normal mode (as `*` does) but still have old behaviour up your sleeve, you can +do the following: > + + let g:multi_cursor_start_key='g' + let g:multi_cursor_start_word_key='' +< + +In this configuration will start multicursor mode using word boundaries +(but only in Normal mode, as it does not make much sense to use it in Visual +mode). Old behaviour without word boundaries is still available using +g. + +IMPORTANT: Please note that currently only single keystrokes and special +keys can be mapped. This contraint is also the reason why multikey commands +such as `ciw` do not work and cause unexpected behavior in Normal mode. This +means that a mapping like `n` will NOT work correctly. For a list of +special keys that are supported, see |key-notation| + +NOTE: Please make sure to always map something to |g:multi_cursor_quit_key|, +otherwise you'll have a tough time quitting from multicursor mode. + +NOTE: Prior to version 1.3, the recommended way to map the keys is using the +expression quote syntax in Vim, using something like `"\"` or `"\"` +(see h: expr-quote). After 1.3, the recommended way is to use a raw string +like above. If your key mappings don't appear to work, give the new syntax a +try. + +============================================================================== +4. Global Options *multiple-cursors-global-options* + +Currently there are four additional global settings one can tweak: + +*g:multi_cursor_exit_from_visual_mode* (Default: 1) + +If set to 0, then pressing |g:multi_cursor_quit_key| in Visual mode will not +quit and delete all existing cursors. This is useful if you want to press +Escape and go back to Normal mode, and still be able to operate on all the +cursors. + +*g:multi_cursor_exit_from_insert_mode* (Default: 1) + +If set to 0, then pressing |g:multi_cursor_quit_key| in Insert mode will not +quit and delete all existing cursors. This is useful if you want to press +Escape and go back to Normal mode, and still be able to operate on all the +cursors. + +*g:multi_cursor_insert_maps* (Default: `{}`) + +Any key in this map (values are ignored) will cause multi-cursor _Insert_ mode +to pause for `timeoutlen` waiting for map completion just like normal vim. +Otherwise keys mapped in insert mode are ignored when multiple cursors are +active. For example, setting it to `{'\':1}` will make insert-mode mappings +beginning with the default leader key work in multi-cursor mode. You have to +manually set this because vim doesn't provide a way to see which keys _start_ +mappings. + +*g:multi_cursor_normal_maps* (Default: see below) + +Default value: `{'!':1, '@':1, '=':1, 'q':1, 'r':1, 't':1, 'T':1, 'y':1, '[':1, ']':1, '\':1, 'd':1, 'f':1, 'F':1, 'g':1, '"':1, 'z':1, 'c':1, 'm':1, '<':1, '>':1}` + +Any key in this map (values are ignored) will cause multi-cursor _Normal_ mode +to pause for map completion just like normal vim. Otherwise keys mapped in +normal mode will "fail to replay" when multiple cursors are active. For example, +changing it from `{}` to `{'d':1}` makes normal-mode mappings beginning with `d` +(such as `dw` to delete a word) work in multi-cursor mode. + +*g:multi_cursor_visual_maps* (Default: ) + +Default value: `{'i':1, 'a':1, 'f':1, 'F':1, 't':1, 'T':1}` + +Any key in this map (values are ignored) will cause multi-cursor _Visual_ mode +to pause for map completion just like normal vim. Otherwise keys mapped in +visual mode will "fail to replay" when multiple cursors are active. For example, +changing it from `{}` to `{'i':1}` makes visual-mode mappings beginning with `i` +(such as `it` to select an "inner tag block") work in multi-cursor mode. + +The default list contents should work for anybody, unless they have remapped a +key from an operator-pending command to a non-operator-pending command or +vice versa. + +These keys must be manually listed because vim doesn't provide a way to +automatically see which keys _start_ mappings, and trying to run motion commands +such as `j` as if they were operator-pending commands can break things. + + +The plugin uses the highlight group `multiple_cursors_cursor` and +`multiple_cursors_visual` to highlight the virtual cursors and their visual +selections respectively. You can customize them by putting something similar +like the following in your vimrc: > + + " Default highlighting (see help :highlight and help :highlight-link) + highlight multiple_cursors_cursor term=reverse cterm=reverse gui=reverse + highlight link multiple_cursors_visual Visual + +< + +============================================================================== +5. Issues *multiple-cursors-issues* + +- Multi key commands like ciw do not work at the moment +- All user input typed before Vim is able to fan out the last operation to all + cursors is lost. This is a implementation decision to keep the input + perfectly synced in all locations, at the cost of potentially losing user + input. +- Select mode is not implemented + +============================================================================== +6. Contributing *multiple-cursors-contributing* + +The project is hosted on Github. Patches, feature requests and suggestions are +always welcome! + +Find the latest version of the plugin here: + http://github.com/terryma/vim-multiple-cursors + +============================================================================== +7. License *multiple-cursors-license* + +The project is licensed under the MIT license [7]. Copyrigth 2013 Terry Ma + +============================================================================== +8. Credit *multiple-cursors-credit* + +The plugin is obviously inspired by Sublime Text's awesome multiple selection +[6] feature. Some inspiration was also taken from Emac's multiple cursors [8] +implementation. + +============================================================================== +9. References *multiple-cursors-references* + +[1] https://github.com/paradigm/vim-multicursor +[2] https://github.com/felixr/vim-multiedit +[3] https://github.com/hlissner/vim-multiedit +[4] https://github.com/adinapoli/vim-markmultiple +[5] https://github.com/AndrewRadev/multichange.vim +[6] http://www.sublimetext.com/docs/2/multiple_selection_with_the_keyboard.html +[7] http://opensource.org/licenses/MIT +[8] https://github.com/magnars/multiple-cursors.el + + vim:tw=78:sw=4:ft=help:norl: diff --git a/.vim/bundle/vim-multiple-cursors/doc/tags b/.vim/bundle/vim-multiple-cursors/doc/tags new file mode 100644 index 0000000..0a5893b --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/doc/tags @@ -0,0 +1,25 @@ +MultipleCursorsFind multiple_cursors.txt /*MultipleCursorsFind* +g:multi_cursor_exit_from_insert_mode multiple_cursors.txt /*g:multi_cursor_exit_from_insert_mode* +g:multi_cursor_exit_from_visual_mode multiple_cursors.txt /*g:multi_cursor_exit_from_visual_mode* +g:multi_cursor_insert_maps multiple_cursors.txt /*g:multi_cursor_insert_maps* +g:multi_cursor_next_key multiple_cursors.txt /*g:multi_cursor_next_key* +g:multi_cursor_normal_maps multiple_cursors.txt /*g:multi_cursor_normal_maps* +g:multi_cursor_prev_key multiple_cursors.txt /*g:multi_cursor_prev_key* +g:multi_cursor_quit_key multiple_cursors.txt /*g:multi_cursor_quit_key* +g:multi_cursor_skip_key multiple_cursors.txt /*g:multi_cursor_skip_key* +g:multi_cursor_start_key multiple_cursors.txt /*g:multi_cursor_start_key* +g:multi_cursor_start_word_key multiple_cursors.txt /*g:multi_cursor_start_word_key* +g:multi_cursor_use_default_mapping multiple_cursors.txt /*g:multi_cursor_use_default_mapping* +g:multi_cursor_visual_maps multiple_cursors.txt /*g:multi_cursor_visual_maps* +multiple-cursors-contents multiple_cursors.txt /*multiple-cursors-contents* +multiple-cursors-contributing multiple_cursors.txt /*multiple-cursors-contributing* +multiple-cursors-credit multiple_cursors.txt /*multiple-cursors-credit* +multiple-cursors-global-options multiple_cursors.txt /*multiple-cursors-global-options* +multiple-cursors-intro multiple_cursors.txt /*multiple-cursors-intro* +multiple-cursors-issues multiple_cursors.txt /*multiple-cursors-issues* +multiple-cursors-license multiple_cursors.txt /*multiple-cursors-license* +multiple-cursors-mappings multiple_cursors.txt /*multiple-cursors-mappings* +multiple-cursors-references multiple_cursors.txt /*multiple-cursors-references* +multiple-cursors-usage multiple_cursors.txt /*multiple-cursors-usage* +vim-multiple-cursors multiple_cursors.txt /*vim-multiple-cursors* +vim-multiple-cursors.txt multiple_cursors.txt /*vim-multiple-cursors.txt* diff --git a/.vim/bundle/vim-multiple-cursors/plugin/multiple_cursors.vim b/.vim/bundle/vim-multiple-cursors/plugin/multiple_cursors.vim new file mode 100644 index 0000000..6595bc3 --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/plugin/multiple_cursors.vim @@ -0,0 +1,89 @@ +"=============================================================================== +" File: multiple_cursors.vim +" Author: Terry Ma +" Description: Emulate Sublime Text's multi selection feature +" Potential Features: +" - Create a blinking cursor effect? Good place to do it would be instead of +" waiting for user input, cycle through the highlight +" - Integrate with the status line? Maybe show a special multicursor mode? +" - Support mouse? Ctrl/Cmd click to set cursor? +"=============================================================================== +let s:save_cpo = &cpo +set cpo&vim + +function! s:init_settings(settings) + for [key, value] in items(a:settings) + let sub = '' + if type(value) == 0 + let sub = '%d' + elseif type(value) == 1 + let sub = '"%s"' + endif + let fmt = printf("let g:multi_cursor_%%s=get(g:, 'multi_cursor_%%s', %s)", + \ sub) + exec printf(fmt, key, key, value) + endfor +endfunction + +" Settings +let s:settings = { + \ 'exit_from_visual_mode': 1, + \ 'exit_from_insert_mode': 1, + \ 'use_default_mapping': 1, + \ 'debug_latency': 0, + \ } + +let s:settings_if_default = { + \ 'quit_key': '', + \ 'next_key': '', + \ 'prev_key': '', + \ 'skip_key': '', + \ } + +let s:default_insert_maps = {} +let s:default_normal_maps = {'!':1, '@':1, '=':1, 'q':1, 'r':1, 't':1, 'T':1, 'y':1, '[':1, ']':1, '\':1, 'd':1, 'f':1, 'F':1, 'g':1, '"':1, 'z':1, 'c':1, 'm':1, '<':1, '>':1} +let s:default_visual_maps = {'i':1, 'a':1, 'f':1, 'F':1, 't':1, 'T':1} + +let g:multi_cursor_insert_maps = + \ get(g:, 'multi_cursor_insert_maps', s:default_insert_maps) +let g:multi_cursor_normal_maps = + \ get(g:, 'multi_cursor_normal_maps', s:default_normal_maps) +let g:multi_cursor_visual_maps = + \ get(g:, 'multi_cursor_visual_maps', s:default_visual_maps) + +call s:init_settings(s:settings) + +if g:multi_cursor_use_default_mapping + call s:init_settings(s:settings_if_default) +endif + +if !exists('g:multi_cursor_start_word_key') + if exists('g:multi_cursor_start_key') + let g:multi_cursor_start_word_key = g:multi_cursor_start_key + elseif exists('g:multi_cursor_next_key') + let g:multi_cursor_start_word_key = g:multi_cursor_next_key + endif +endif + +" External mappings +if exists('g:multi_cursor_start_key') + exec 'nnoremap '.g:multi_cursor_start_key. + \' :call multiple_cursors#new("n", 0)' + exec 'xnoremap '.g:multi_cursor_start_key. + \' :call multiple_cursors#new("v", 0)' +endif + +if exists('g:multi_cursor_start_word_key') + exec 'nnoremap '.g:multi_cursor_start_word_key. + \' :call multiple_cursors#new("n", 1)' + " In Visual mode word boundary is not used + exec 'xnoremap '.g:multi_cursor_start_word_key. + \' :call multiple_cursors#new("v", 0)' +endif + +" Commands +command! -nargs=1 -range=% MultipleCursorsFind + \ call multiple_cursors#find(, , ) + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/.vim/bundle/vim-multiple-cursors/spec/benchmark_spec.rb b/.vim/bundle/vim-multiple-cursors/spec/benchmark_spec.rb new file mode 100644 index 0000000..73c81c5 --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/spec/benchmark_spec.rb @@ -0,0 +1,142 @@ +require 'vimrunner' +require 'vimrunner/rspec' + +Vimrunner::RSpec.configure do |config| + + # Use a single Vim instance for the test suite. Set to false to use an + # instance per test (slower, but can be easier to manage). + config.reuse_server = false + + # Decide how to start a Vim instance. In this block, an instance should be + # spawned and set up with anything project-specific. + config.start_vim do + # vim = Vimrunner.start + # vim = Vimrunner::Server.new("/usr/local/bin/vim").start + + # Or, start a GUI instance: + vim = Vimrunner.start_gvim + + # Setup your plugin in the Vim instance + plugin_path = File.expand_path('../..', __FILE__) + vim.add_plugin(plugin_path, 'plugin/multiple_cursors.vim') + + # The returned value is the Client available in the tests. + vim + end +end + +def set_file_content(string) + string = normalize_string_indent(string) + File.open(filename, 'w'){ |f| f.write(string) } + vim.edit filename +end + +def get_file_content() + vim.write + IO.read(filename).strip +end + +def before(string) + set_file_content(string) +end + +def after(string) + get_file_content().should eq normalize_string_indent(string) + type ":q" +end + +def type(string) + string.scan(/<.*?>|./).each do |key| + if /<.*>/.match(key) + vim.feedkeys "\\#{key}" + else + vim.feedkeys key + end + end + sleep 0.2 +end + +describe "Multiple Cursors" do + let(:filename) { 'test.txt' } + let(:options) { [] } + + specify "#benchmark" do + before <<-EOF + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + hello + EOF + + # type ':profile start /tmp/test.result' + # type ':profile! file *multiple_cursors.vim' + type ':let g:multi_cursor_debug_latency=1' + + type 'VGVchellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello' + + type ':echo multiple_cursors#get_latency_debug_file()' + sleep 3 + latency_file = vim.command 'echo multiple_cursors#get_latency_debug_file()' + puts 'latency file = ' + latency_file + + after <<-EOF + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello + EOF + end + +end diff --git a/.vim/bundle/vim-multiple-cursors/spec/multiple_cursors_spec.rb b/.vim/bundle/vim-multiple-cursors/spec/multiple_cursors_spec.rb new file mode 100644 index 0000000..2d92e5a --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/spec/multiple_cursors_spec.rb @@ -0,0 +1,817 @@ +# -*- encoding: utf-8 -*- +require 'spec_helper' + +def set_file_content(string) + string = normalize_string_indent(string) + File.open(filename, 'w'){ |f| f.write(string) } + vim.edit filename +end + +def get_file_content() + vim.write + IO.read(filename).strip +end + +def before(string) + options.each { |x| vim.command(x) } + set_file_content(string) +end + +def after(string) + expect(get_file_content()).to eq normalize_string_indent(string) +end + +def type(string) + string.scan(/<.*?>|./).each do |key| + if /<.*>/.match(key) + vim.feedkeys "\\#{key}" + else + vim.feedkeys key + end + end +end + +describe "Multiple Cursors op pending & exit from insert|visual mode" do + let(:filename) { 'test.txt' } + let(:options) { ['let g:multi_cursor_exit_from_insert_mode = 0', + 'let g:multi_cursor_exit_from_visual_mode = 0'] } + # the default value of g:multi_cursor_normal_maps already works + # for testing operator-pending + + specify "#paste from unnamed register to 3 cursors" do + before <<-EOF + yankme + a b c + a b c + a b c + EOF + + type 'yiwjvwwp' + + after <<-EOF + yankme + a b cyankme + a b cyankme + a b cyankme + EOF + end + + specify "#paste buffer normal caw then p" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'vwcawbP' + + after <<-EOF + jan hello world + feb hello world + mar hello world + EOF + end + + specify "#paste buffer normal C then ABC then p" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'vwCABC p' + + after <<-EOF + hello ABC jan world + hello ABC feb world + hello ABC mar world + EOF + end + + specify "#paste buffer normal daw then P" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'vwdawbP' + + after <<-EOF + jan hello world + feb hello world + mar hello world + EOF + end + + specify "#paste buffer normal D then P" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'vwwhDbhP' + + after <<-EOF + hello world jan + hello world feb + hello world mar + EOF + end + + specify "#paste buffer normal s then p" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'vws1p' + + after <<-EOF + hello 1jan world + hello 1feb world + hello 1mar world + EOF + end + +end + +describe "Multiple Cursors when normal_maps is empty" do + let(:filename) { 'test.txt' } + let(:options) { ['let g:multi_cursor_normal_maps = {}'] } + + # Operator-pending commands are handled correctly thanks to their inclusion + # in `g:multi_cursor_normal_maps`. + # + # When an operator-pending command like 'd' is missing from that setting's + # value, then it should result in a no-op, but we should still remain in + # multicursor mode. + specify "#normal mode 'd'" do + before <<-EOF + hello + hello + EOF + + type 'vdx' + + after <<-EOF + hell + hell + EOF + end + +end + +describe "Multiple Cursors when visual_maps is empty" do + let(:filename) { 'test.txt' } + let(:options) { ['let g:multi_cursor_visual_maps = {}'] } + + # Operator-pending commands are handled correctly thanks to their inclusion + # in `g:multi_cursor_visual_maps`. + # + # When an operator-pending command like 'f' is missing from that setting's + # value, then it should result in a no-op, but we should still remain in + # multicursor mode. + specify "#visual mode 'i'" do + before <<-EOF + hello world x + hello world x + EOF + + type 'fwfx' + + after <<-EOF + hello x + hello x + EOF + end + +end + +describe "Multiple Cursors" do + let(:filename) { 'test.txt' } + let(:options) { ['set autoindent'] } + + specify "#paste buffer normal x then p" do + before <<-EOF + jan + feb + mar + EOF + + type 'jjxp' + + after <<-EOF + ajn + efb + amr + EOF + end + + specify "#paste buffer visual y then p" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'vwvelywhp' + + after <<-EOF + hello jan jan world + hello feb feb world + hello mar mar world + EOF + end + + specify "#paste buffer initial visual y then P" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'wywbp' + + after <<-EOF + jan jan world + jan feb world + jan mar world + EOF + end + + specify "#paste buffer visual y then P" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'vwvely^P' + + after <<-EOF + jan hello jan world + feb hello feb world + mar hello mar world + EOF + end + + specify "#paste buffer visual Y then P" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'vwvY^P' + + after <<-EOF + hello jan world + hello jan world + hello feb world + hello feb world + hello mar world + hello mar world + EOF + end + + specify "#multiline replacement" do + before <<-EOF + hello + hello + hello + EOF + + type 'cworld' + + after <<-EOF + world + world + world + EOF + end + + specify "#single line replacement" do + before <<-EOF + hello hello hello + EOF + + type 'cworld' + + after <<-EOF + world world world + EOF + end + + specify "#mixed line replacement" do + before <<-EOF + hello hello + hello + EOF + + type 'cworld' + + after <<-EOF + world world + world + EOF + end + + specify "#new line in insert mode" do + before <<-EOF + hello + hello + EOF + + type 'chelloworld' + + after <<-EOF + hello + world + hello + world + EOF + end + + specify "#new line in insert mode middle of line" do + before <<-EOF + hello world + hello world + EOF + + type 'vlxi' + + after <<-EOF + hello + world + hello + world + EOF + end + + specify "#multiple new lines on one line in insert mode" do + before <<-EOF + 'a','b','c','d','e' + EOF + + type 'f,vc' + + after <<-EOF + 'a' + 'b' + 'c' + 'd' + 'e' + EOF + end + + specify "#multiple new lines on one line in insert mode with indents" do + before <<-EOF + 'a','b','c','d','e' + EOF + + type '4if,vc:%s/^/^' + + after <<-EOF + ^ 'a' + ^ 'b' + ^ 'c' + ^ 'd' + ^ 'e' + EOF + end + + specify "#normal mode 'o'" do + before <<-EOF + hello + hello + EOF + + type 'voworld' + + after <<-EOF + hello + world + hello + world + EOF + end + + specify "#normal mode 'O'" do + before <<-EOF + hello + hello + EOF + + type 'vOworld' + + after <<-EOF + world + hello + world + hello + EOF + end + + specify "#find command basic" do + before <<-EOF + hello + hello + EOF + + vim.normal ':MultipleCursorsFind hello' + type 'cworld' + + after <<-EOF + world + world + EOF + end + + specify "#find command start-of-line" do + before <<-EOF + hello + world + + hello + world + EOF + + vim.normal ':MultipleCursorsFind ^' + type 'Ibegin' + + after <<-EOF + beginhello + beginworld + begin + beginhello + beginworld + EOF + end + + specify "#find command end-of-line" do + before <<-EOF + hello + world + + hello + world + EOF + + vim.normal ':MultipleCursorsFind $' + type 'Iend' + + after <<-EOF + helloend + worldend + end + helloend + worldend + EOF + end + + specify "#visual line mode replacement" do + before <<-EOF + hello world + hello world + EOF + + type 'Vchi!' + + after <<-EOF + hi! + hi! + EOF + end + + specify "#skip key" do + before <<-EOF + hello + hello + hello + EOF + + type 'cworld' + + after <<-EOF + world + hello + world + EOF + end + + specify "#prev key" do + before <<-EOF + hello + hello + hello + EOF + + type 'cworld' + + after <<-EOF + world + world + hello + EOF + end + + specify "#visual mode 'i'" do + before <<-EOF + hi (hello world jan) bye + hi (hello world feb) bye + hi (hello world mar) bye + EOF + + type 'fwibcone' + + after <<-EOF + hi (one) bye + hi (one) bye + hi (one) bye + EOF + end + + specify "#visual mode 'a'" do + before <<-EOF + hi (hello world jan) bye + hi (hello world feb) bye + hi (hello world mar) bye + EOF + + type 'fwabcone' + + after <<-EOF + hi one bye + hi one bye + hi one bye + EOF + end + + specify "#visual mode 'f'" do + before <<-EOF + hi (hello world jan) bye + hi (hello world feb) bye + hi (hello world mar) bye + EOF + + type 'fwf)cone' + + after <<-EOF + hi (hello one bye + hi (hello one bye + hi (hello one bye + EOF + end + + specify "#visual mode 'F'" do + before <<-EOF + hi (hello world jan) bye + hi (hello world feb) bye + hi (hello world mar) bye + EOF + + type 'fwF(cbefore' + + after <<-EOF + hi beforeorld jan) bye + hi beforeorld feb) bye + hi beforeorld mar) bye + EOF + end + + specify "#visual mode 't'" do + before <<-EOF + hello.jan + hello hi.feb + hello hi bye.mar + EOF + + type 't.cone' + + after <<-EOF + one.jan + one.feb + one.mar + EOF + end + + specify "#visual mode 'T'" do + before <<-EOF + jan.world + feb.hi world + mar.bye hi world + EOF + + type 'fwT.cbefore' + + after <<-EOF + jan.beforeorld + feb.beforeorld + mar.beforeorld + EOF + end + + specify "#visual line mode 'f'" do + before <<-EOF + hello jan world + hello feb world + hello mar world + EOF + + type 'VfwvAafter' + + after <<-EOF + hello jan wafterorld + hello feb wafterorld + hello mar wafterorld + EOF + end + + specify "#visual mode 'I'" do + before <<-EOF + hello world jan + hello world feb + hello world mar + EOF + + type 'wIbefore' + + after <<-EOF + hello beforeworld jan + hello beforeworld feb + hello beforeworld mar + EOF + end + + specify "#visual mode 'A'" do + before <<-EOF + hello world jan + hello world feb + hello world mar + EOF + + type 'wAafter' + + after <<-EOF + hello worldafter jan + hello worldafter feb + hello worldafter mar + EOF + end + + specify "#resize regions visual mode 'I'" do + before <<-EOF + hello world jan + hello world feb + hello world mar + EOF + + type 'whhhIbefore' + + after <<-EOF + hello beforeworld jan + hello beforeworld feb + hello beforeworld mar + EOF + end + + specify "#resize regions visual mode 'A'" do + before <<-EOF + hello world jan + hello world feb + hello world mar + EOF + + type 'whhhAbefore' + + after <<-EOF + hello wobeforerld jan + hello wobeforerld feb + hello wobeforerld mar + EOF + end + + specify "#no word boundries visual mode 'I'" do + before <<-EOF + hello hibye world + hello hibye world + hello hibye world + EOF + + vim.normal ':MultipleCursorsFind bye' + type 'Ibefore' + + after <<-EOF + hello hibeforebye world + hello hibeforebye world + hello hibeforebye world + EOF + end + + specify "#variable-length regions visual mode 'I'" do + before <<-EOF + hello hii world + hello hiiii world + hello hiiiiii world + EOF + + vim.normal ':MultipleCursorsFind \' + type 'Ibefore' + + after <<-EOF + hello beforehii world + hello beforehiiii world + hello beforehiiiiii world + EOF + end + + specify "#normal mode 'I'" do + before <<-EOF + hello + hello + EOF + + type 'vIworld ' + + after <<-EOF + world hello + world hello + EOF + end + + specify "#normal mode 'A'" do + before <<-EOF + hello + hello + EOF + + type 'vA world' + + after <<-EOF + hello world + hello world + EOF + end + + specify "#undo" do + before <<-EOF + hello + hello + EOF + + type 'cworldu' + + after <<-EOF + hello + hello + EOF + end + + specify "#multiline visual mode" do + before <<-EOF + hello + hello + EOF + + type 'VjA world' + + after <<-EOF + hello world + hello world + EOF + end + + specify "#set paste mode" do + before <<-EOF + hello + hello + EOF + + type ':set pastecworld:set nopaste' + + after <<-EOF + world + world + EOF + end + + specify "#multi-byte strings" do + before <<-EOF + こんにちわビム + 世界の中心でビムを叫ぶ + ビム大好き + EOF + + type '/ビムcヴィム' + + after <<-EOF + こんにちわヴィム + 世界の中心でヴィムを叫ぶ + ヴィム大好き + EOF + end + +end diff --git a/.vim/bundle/vim-multiple-cursors/spec/spec_helper.rb b/.vim/bundle/vim-multiple-cursors/spec/spec_helper.rb new file mode 100644 index 0000000..4e0ad99 --- /dev/null +++ b/.vim/bundle/vim-multiple-cursors/spec/spec_helper.rb @@ -0,0 +1,25 @@ +require 'vimrunner' +require 'vimrunner/rspec' + +Vimrunner::RSpec.configure do |config| + + # Use a single Vim instance for the test suite. Set to false to use an + # instance per test (slower, but can be easier to manage). + config.reuse_server = false + + # Decide how to start a Vim instance. In this block, an instance should be + # spawned and set up with anything project-specific. + config.start_vim do + # vim = Vimrunner.start + + # Or, start a GUI instance: + vim = Vimrunner.start_gvim + + # Setup your plugin in the Vim instance + plugin_path = File.expand_path('../..', __FILE__) + vim.add_plugin(plugin_path, 'plugin/multiple_cursors.vim') + + # The returned value is the Client available in the tests. + vim + end +end diff --git a/.vim/bundle/vim-surround/README.markdown b/.vim/bundle/vim-surround/README.markdown new file mode 100644 index 0000000..fef61a8 --- /dev/null +++ b/.vim/bundle/vim-surround/README.markdown @@ -0,0 +1,97 @@ +surround.vim +============ + +Surround.vim is all about "surroundings": parentheses, brackets, quotes, +XML tags, and more. The plugin provides mappings to easily delete, +change and add such surroundings in pairs. + +It's easiest to explain with examples. Press `cs"'` inside + + "Hello world!" + +to change it to + + 'Hello world!' + +Now press `cs'` to change it to + + Hello world! + +To go full circle, press `cst"` to get + + "Hello world!" + +To remove the delimiters entirely, press `ds"`. + + Hello world! + +Now with the cursor on "Hello", press `ysiw]` (`iw` is a text object). + + [Hello] world! + +Let's make that braces and add some space (use `}` instead of `{` for no +space): `cs]{` + + { Hello } world! + +Now wrap the entire line in parentheses with `yssb` or `yss)`. + + ({ Hello } world!) + +Revert to the original text: `ds{ds)` + + Hello world! + +Emphasize hello: `ysiw` + + Hello world! + +Finally, let's try out visual mode. Press a capital V (for linewise +visual mode) followed by `S

`. + +

+ Hello world! +

+ +This plugin is very powerful for HTML and XML editing, a niche which +currently seems underfilled in Vim land. (As opposed to HTML/XML +*inserting*, for which many plugins are available). Adding, changing, +and removing pairs of tags simultaneously is a breeze. + +The `.` command will work with `ds`, `cs`, and `yss` if you install +[repeat.vim](https://github.com/tpope/vim-repeat). + +Installation +------------ + +If you don't have a preferred installation method, I recommend +installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and +then simply copy and paste: + + cd ~/.vim/bundle + git clone git://github.com/tpope/vim-surround.git + +Once help tags have been generated, you can view the manual with +`:help surround`. + +Contributing +------------ + +See the contribution guidelines for +[pathogen.vim](https://github.com/tpope/vim-pathogen#readme). + +Self-Promotion +-------------- + +Like surround.vim? Follow the repository on +[GitHub](https://github.com/tpope/vim-surround) and vote for it on +[vim.org](http://www.vim.org/scripts/script.php?script_id=1697). And if +you're feeling especially charitable, follow [tpope](http://tpo.pe/) on +[Twitter](http://twitter.com/tpope) and +[GitHub](https://github.com/tpope). + +License +------- + +Copyright (c) Tim Pope. Distributed under the same terms as Vim itself. +See `:help license`. diff --git a/.vim/bundle/vim-surround/doc/surround.txt b/.vim/bundle/vim-surround/doc/surround.txt new file mode 100644 index 0000000..674b6a9 --- /dev/null +++ b/.vim/bundle/vim-surround/doc/surround.txt @@ -0,0 +1,207 @@ +*surround.txt* Plugin for deleting, changing, and adding "surroundings" + +Author: Tim Pope +License: Same terms as Vim itself (see |license|) + +This plugin is only available if 'compatible' is not set. + +INTRODUCTION *surround* + +This plugin is a tool for dealing with pairs of "surroundings." Examples +of surroundings include parentheses, quotes, and HTML tags. They are +closely related to what Vim refers to as |text-objects|. Provided +are mappings to allow for removing, changing, and adding surroundings. + +Details follow on the exact semantics, but first, consider the following +examples. An asterisk (*) is used to denote the cursor position. + + Old text Command New text ~ + "Hello *world!" ds" Hello world! + [123+4*56]/2 cs]) (123+456)/2 + "Look ma, I'm *HTML!" cs" Look ma, I'm HTML! + if *x>3 { ysW( if ( x>3 ) { + my $str = *whee!; vllllS' my $str = 'whee!'; + +While a few features of this plugin will work in older versions of Vim, +Vim 7 is recommended for full functionality. + +MAPPINGS *surround-mappings* + +Delete surroundings is *ds* . The next character given determines the target +to delete. The exact nature of the target is explained in |surround-targets| +but essentially it is the last character of a |text-object|. This mapping +deletes the difference between the "i"nner object and "a"n object. This is +easiest to understand with some examples: + + Old text Command New text ~ + "Hello *world!" ds" Hello world! + (123+4*56)/2 ds) 123+456/2 +
Yo!*
dst Yo! + +Change surroundings is *cs* . It takes two arguments, a target like with +|ds|, and a replacement. *cS* changes surroundings, placing the surrounded +text on its own line(s) like |yS|. Details about the second argument can be +found below in |surround-replacements|. Once again, examples are in order. + + Old text Command New text ~ + "Hello *world!" cs"' 'Hello world!' + "Hello *world!" cs" Hello world! + (123+4*56)/2 cs)] [123+456]/2 + (123+4*56)/2 cs)[ [ 123+456 ]/2 +
Yo!*
cst

Yo!

+ +*ys* takes a valid Vim motion or text object as the first object, and wraps +it using the second argument as with |cs|. (It's a stretch, but a good +mnemonic for "ys" is "you surround".) + + Old text Command New text ~ + Hello w*orld! ysiw) Hello (world)! + +As a special case, *yss* operates on the current line, ignoring leading +whitespace. + + Old text Command New text ~ + Hello w*orld! yssB {Hello world!} + +There is also *yS* and *ySS* which indent the surrounded text and place it +on a line of its own. + +In visual mode, a simple "S" with an argument wraps the selection. This is +referred to as the *vS* mapping, although ordinarily there will be +additional keystrokes between the v and S. In linewise visual mode, the +surroundings are placed on separate lines and indented. In blockwise visual +mode, each line is surrounded. + +A "gS" in visual mode, known as *vgS* , behaves similarly. In linewise visual +mode, the automatic indenting is suppressed. In blockwise visual mode, this +enables surrounding past the end of the line with 'virtualedit' set (there +seems to be no way in Vim Script to differentiate between a jagged end of line +selection and a virtual block selected past the end of the line, so two maps +were needed). + + *i_CTRL-G_s* *i_CTRL-G_S* +Finally, there is an experimental insert mode mapping on s and . +Beware that the latter won't work on terminals with flow control (if you +accidentally freeze your terminal, use to unfreeze it). The mapping +inserts the specified surroundings and puts the cursor between them. If, +immediately after the mapping and before the replacement, a second or +carriage return is pressed, the prefix, cursor, and suffix will be placed on +three separate lines. S (not s) also exhibits this behavior. + +TARGETS *surround-targets* + +The |ds| and |cs| commands both take a target as their first argument. The +possible targets are based closely on the |text-objects| provided by Vim. +All targets are currently just one character. + +Eight punctuation marks, (, ), {, }, [, ], <, and >, represent themselves +and their counterparts. If the opening mark is used, contained whitespace is +also trimmed. The targets b, B, r, and a are aliases for ), }, ], and > +(the first two mirror Vim; the second two are completely arbitrary and +subject to change). + +Three quote marks, ', ", `, represent themselves, in pairs. They are only +searched for on the current line. + +A t is a pair of HTML or XML tags. See |tag-blocks| for details. Remember +that you can specify a numerical argument if you want to get to a tag other +than the innermost one. + +The letters w, W, and s correspond to a |word|, a |WORD|, and a |sentence|, +respectively. These are special in that they have nothing to delete, and +used with |ds| they are a no-op. With |cs|, one could consider them a +slight shortcut for ysi (cswb == ysiwb, more or less). + +A p represents a |paragraph|. This behaves similarly to w, W, and s above; +however, newlines are sometimes added and/or removed. + +REPLACEMENTS *surround-replacements* + +A replacement argument is a single character, and is required by |cs|, |ys|, +and |vS|. Undefined replacement characters (with the exception of alphabetic +characters) default to placing themselves at the beginning and end of the +destination, which can be useful for characters like / and |. + +If either ), }, ], or > is used, the text is wrapped in the appropriate pair +of characters. Similar behavior can be found with (, {, and [ (but not <), +which append an additional space to the inside. Like with the targets above, +b, B, r, and a are aliases for ), }, ], and >. To fulfill the common need for +code blocks in C-style languages, (which is really ) adds braces on +lines separate from the content. + +If t or < is used, Vim prompts for an HTML/XML tag to insert. You may specify +attributes here and they will be stripped from the closing tag. If replacing a +tag, its attributes are kept in the new tag. End your input with > to discard +the those attributes. If is used, the tags will appear on lines by +themselves. + +If s is used, a leading but not trailing space is added. This is useful for +removing parentheses from a function call with csbs. + +CUSTOMIZING *surround-customizing* + +The following adds a potential replacement on "-" (ASCII 45) in PHP files. +(To determine the ASCII code to use, :echo char2nr("-")). The carriage +return will be replaced by the original text. +> + autocmd FileType php let b:surround_45 = "" +< +This can be used in a PHP file as in the following example. + + Old text Command New text ~ + print "Hello *world!" yss- + +Additionally, one can use a global variable for globally available +replacements. +> + let g:surround_45 = "<% \r %>" + let g:surround_61 = "<%= \r %>" +< +Advanced, experimental, and subject to change: One can also prompt for +replacement text. The syntax for this is to surround the replacement in pairs +of low numbered control characters. If this sounds confusing, that's because +it is (but it makes the parsing easy). Consider the following example for a +LaTeX environment on the "l" replacement. +> + let g:surround_108 = "\\begin{\1environment: \1}\r\\end{\1\1}" +< +When this replacement is used, the user is prompted with an "environment: " +prompt for input. This input is inserted between each set of \1's. +Additional inputs up to \7 can be used. + +Furthermore, one can specify a regular expression substitution to apply. +> + let g:surround_108 = "\\begin{\1environment: \1}\r\\end{\1\r}.*\r\1}" +< +This will remove anything after the first } in the input when the text is +placed within the \end{} slot. The first \r marks where the pattern begins, +and the second where the replacement text begins. + +Here's a second example for creating an HTML
. The substitution cleverly +prompts for an id, but only adds id="" if it is non-blank. You may have to +read this one a few times slowly before you understand it. +> + let g:surround_{char2nr("d")} = "\r
" +< +Inputting text replacements is a proof of concept at this point. The ugly, +unintuitive interface and the brevity of the documentation reflect this. + +Finally, It is possible to always append a string to surroundings in insert +mode (and only insert mode). This is useful with certain plugins and mappings +that allow you to jump to such markings. +> + let g:surround_insert_tail = "<++>" +< +ISSUES *surround-issues* + +Vim could potentially get confused when deleting/changing occurs at the very +end of the line. Please report any repeatable instances of this. + +Do we need to use |inputsave()|/|inputrestore()| with the tag replacement? + +Indenting is handled haphazardly. Need to decide the most appropriate +behavior and implement it. Right now one can do :let b:surround_indent = 1 +(or the global equivalent) to enable automatic re-indenting by Vim via |=|; +should this be the default? + + vim:tw=78:ts=8:ft=help:norl: diff --git a/.vim/bundle/vim-surround/doc/tags b/.vim/bundle/vim-surround/doc/tags new file mode 100644 index 0000000..6935d68 --- /dev/null +++ b/.vim/bundle/vim-surround/doc/tags @@ -0,0 +1,18 @@ +cS surround.txt /*cS* +cs surround.txt /*cs* +ds surround.txt /*ds* +i_CTRL-G_S surround.txt /*i_CTRL-G_S* +i_CTRL-G_s surround.txt /*i_CTRL-G_s* +surround surround.txt /*surround* +surround-customizing surround.txt /*surround-customizing* +surround-issues surround.txt /*surround-issues* +surround-mappings surround.txt /*surround-mappings* +surround-replacements surround.txt /*surround-replacements* +surround-targets surround.txt /*surround-targets* +surround.txt surround.txt /*surround.txt* +vS surround.txt /*vS* +vgS surround.txt /*vgS* +yS surround.txt /*yS* +ySS surround.txt /*ySS* +ys surround.txt /*ys* +yss surround.txt /*yss* diff --git a/.vim/bundle/vim-surround/plugin/surround.vim b/.vim/bundle/vim-surround/plugin/surround.vim new file mode 100644 index 0000000..46f3252 --- /dev/null +++ b/.vim/bundle/vim-surround/plugin/surround.vim @@ -0,0 +1,598 @@ +" surround.vim - Surroundings +" Author: Tim Pope +" Version: 2.1 +" GetLatestVimScripts: 1697 1 :AutoInstall: surround.vim + +if exists("g:loaded_surround") || &cp || v:version < 700 + finish +endif +let g:loaded_surround = 1 + +" Input functions {{{1 + +function! s:getchar() + let c = getchar() + if c =~ '^\d\+$' + let c = nr2char(c) + endif + return c +endfunction + +function! s:inputtarget() + let c = s:getchar() + while c =~ '^\d\+$' + let c .= s:getchar() + endwhile + if c == " " + let c .= s:getchar() + endif + if c =~ "\\|\\|\0" + return "" + else + return c + endif +endfunction + +function! s:inputreplacement() + let c = s:getchar() + if c == " " + let c .= s:getchar() + endif + if c =~ "\" || c =~ "\" + return "" + else + return c + endif +endfunction + +function! s:beep() + exe "norm! \" + return "" +endfunction + +function! s:redraw() + redraw + return "" +endfunction + +" }}}1 + +" Wrapping functions {{{1 + +function! s:extractbefore(str) + if a:str =~ '\r' + return matchstr(a:str,'.*\ze\r') + else + return matchstr(a:str,'.*\ze\n') + endif +endfunction + +function! s:extractafter(str) + if a:str =~ '\r' + return matchstr(a:str,'\r\zs.*') + else + return matchstr(a:str,'\n\zs.*') + endif +endfunction + +function! s:fixindent(str,spc) + let str = substitute(a:str,'\t',repeat(' ',&sw),'g') + let spc = substitute(a:spc,'\t',repeat(' ',&sw),'g') + let str = substitute(str,'\(\n\|\%^\).\@=','\1'.spc,'g') + if ! &et + let str = substitute(str,'\s\{'.&ts.'\}',"\t",'g') + endif + return str +endfunction + +function! s:process(string) + let i = 0 + for i in range(7) + let repl_{i} = '' + let m = matchstr(a:string,nr2char(i).'.\{-\}\ze'.nr2char(i)) + if m != '' + let m = substitute(strpart(m,1),'\r.*','','') + let repl_{i} = input(match(m,'\w\+$') >= 0 ? m.': ' : m) + endif + endfor + let s = "" + let i = 0 + while i < strlen(a:string) + let char = strpart(a:string,i,1) + if char2nr(char) < 8 + let next = stridx(a:string,char,i+1) + if next == -1 + let s .= char + else + let insertion = repl_{char2nr(char)} + let subs = strpart(a:string,i+1,next-i-1) + let subs = matchstr(subs,'\r.*') + while subs =~ '^\r.*\r' + let sub = matchstr(subs,"^\r\\zs[^\r]*\r[^\r]*") + let subs = strpart(subs,strlen(sub)+1) + let r = stridx(sub,"\r") + let insertion = substitute(insertion,strpart(sub,0,r),strpart(sub,r+1),'') + endwhile + let s .= insertion + let i = next + endif + else + let s .= char + endif + let i += 1 + endwhile + return s +endfunction + +function! s:wrap(string,char,type,removed,special) + let keeper = a:string + let newchar = a:char + let s:input = "" + let type = a:type + let linemode = type ==# 'V' ? 1 : 0 + let before = "" + let after = "" + if type ==# "V" + let initspaces = matchstr(keeper,'\%^\s*') + else + let initspaces = matchstr(getline('.'),'\%^\s*') + endif + let pairs = "b()B{}r[]a<>" + let extraspace = "" + if newchar =~ '^ ' + let newchar = strpart(newchar,1) + let extraspace = ' ' + endif + let idx = stridx(pairs,newchar) + if newchar == ' ' + let before = '' + let after = '' + elseif exists("b:surround_".char2nr(newchar)) + let all = s:process(b:surround_{char2nr(newchar)}) + let before = s:extractbefore(all) + let after = s:extractafter(all) + elseif exists("g:surround_".char2nr(newchar)) + let all = s:process(g:surround_{char2nr(newchar)}) + let before = s:extractbefore(all) + let after = s:extractafter(all) + elseif newchar ==# "p" + let before = "\n" + let after = "\n\n" + elseif newchar ==# 's' + let before = ' ' + let after = '' + elseif newchar ==# ':' + let before = ':' + let after = '' + elseif newchar =~# "[tT\<]" + let dounmapp = 0 + let dounmapb = 0 + if !maparg(">","c") + let dounmapb = 1 + " Hide from AsNeeded + exe "cn"."oremap > >" + endif + let default = "" + if newchar ==# "T" + if !exists("s:lastdel") + let s:lastdel = "" + endif + let default = matchstr(s:lastdel,'<\zs.\{-\}\ze>') + endif + let tag = input("<",default) + if dounmapb + silent! cunmap > + endif + let s:input = tag + if tag != "" + let keepAttributes = ( match(tag, ">$") == -1 ) + let tag = substitute(tag,'>*$','','') + let attributes = "" + if keepAttributes + let attributes = matchstr(a:removed, '<[^ \t\n]\+\zs\_.\{-\}\ze>') + endif + let s:input = tag . '>' + if tag =~ '/$' + let tag = substitute(tag, '/$', '', '') + let before = '<'.tag.attributes.' />' + let after = '' + else + let before = '<'.tag.attributes.'>' + let after = '' + endif + if newchar == "\" + if type ==# "v" || type ==# "V" + let before .= "\n\t" + endif + if type ==# "v" + let after = "\n". after + endif + endif + endif + elseif newchar ==# 'l' || newchar == '\' + " LaTeX + let env = input('\begin{') + if env != "" + let s:input = env."\" + let env = '{' . env + let env .= s:closematch(env) + echo '\begin'.env + let before = '\begin'.env + let after = '\end'.matchstr(env,'[^}]*').'}' + endif + elseif newchar ==# 'f' || newchar ==# 'F' + let fnc = input('function: ') + if fnc != "" + let s:input = fnc."\" + let before = substitute(fnc,'($','','').'(' + let after = ')' + if newchar ==# 'F' + let before .= ' ' + let after = ' ' . after + endif + endif + elseif newchar ==# "\" + let fnc = input('function: ') + let s:input = fnc."\" + let before = '('.fnc.' ' + let after = ')' + elseif idx >= 0 + let spc = (idx % 3) == 1 ? " " : "" + let idx = idx / 3 * 3 + let before = strpart(pairs,idx+1,1) . spc + let after = spc . strpart(pairs,idx+2,1) + elseif newchar == "\" || newchar == "\" + let before = "{\n\t" + let after = "\n}" + elseif newchar !~ '\a' + let before = newchar + let after = newchar + else + let before = '' + let after = '' + endif + let after = substitute(after ,'\n','\n'.initspaces,'g') + if type ==# 'V' || (a:special && type ==# "v") + let before = substitute(before,' \+$','','') + let after = substitute(after ,'^ \+','','') + if after !~ '^\n' + let after = initspaces.after + endif + if keeper !~ '\n$' && after !~ '^\n' + let keeper .= "\n" + elseif keeper =~ '\n$' && after =~ '^\n' + let after = strpart(after,1) + endif + if before !~ '\n\s*$' + let before .= "\n" + if a:special + let before .= "\t" + endif + endif + endif + if type ==# 'V' + let before = initspaces.before + endif + if before =~ '\n\s*\%$' + if type ==# 'v' + let keeper = initspaces.keeper + endif + let padding = matchstr(before,'\n\zs\s\+\%$') + let before = substitute(before,'\n\s\+\%$','\n','') + let keeper = s:fixindent(keeper,padding) + endif + if type ==# 'V' + let keeper = before.keeper.after + elseif type =~ "^\" + " Really we should be iterating over the buffer + let repl = substitute(before,'[\\~]','\\&','g').'\1'.substitute(after,'[\\~]','\\&','g') + let repl = substitute(repl,'\n',' ','g') + let keeper = substitute(keeper."\n",'\(.\{-\}\)\(\n\)',repl.'\n','g') + let keeper = substitute(keeper,'\n\%$','','') + else + let keeper = before.extraspace.keeper.extraspace.after + endif + return keeper +endfunction + +function! s:wrapreg(reg,char,removed,special) + let orig = getreg(a:reg) + let type = substitute(getregtype(a:reg),'\d\+$','','') + let new = s:wrap(orig,a:char,type,a:removed,a:special) + call setreg(a:reg,new,type) +endfunction +" }}}1 + +function! s:insert(...) " {{{1 + " Optional argument causes the result to appear on 3 lines, not 1 + let linemode = a:0 ? a:1 : 0 + let char = s:inputreplacement() + while char == "\" || char == "\" + " TODO: use total count for additional blank lines + let linemode += 1 + let char = s:inputreplacement() + endwhile + if char == "" + return "" + endif + let cb_save = &clipboard + set clipboard-=unnamed clipboard-=unnamedplus + let reg_save = @@ + call setreg('"',"\r",'v') + call s:wrapreg('"',char,"",linemode) + " If line mode is used and the surrounding consists solely of a suffix, + " remove the initial newline. This fits a use case of mine but is a + " little inconsistent. Is there anyone that would prefer the simpler + " behavior of just inserting the newline? + if linemode && match(getreg('"'),'^\n\s*\zs.*') == 0 + call setreg('"',matchstr(getreg('"'),'^\n\s*\zs.*'),getregtype('"')) + endif + " This can be used to append a placeholder to the end + if exists("g:surround_insert_tail") + call setreg('"',g:surround_insert_tail,"a".getregtype('"')) + endif + if col('.') >= col('$') + norm! ""p + else + norm! ""P + endif + if linemode + call s:reindent() + endif + norm! `] + call search('\r','bW') + let @@ = reg_save + let &clipboard = cb_save + return "\" +endfunction " }}}1 + +function! s:reindent() " {{{1 + if exists("b:surround_indent") ? b:surround_indent : (!exists("g:surround_indent") || g:surround_indent) + silent norm! '[='] + endif +endfunction " }}}1 + +function! s:dosurround(...) " {{{1 + let scount = v:count1 + let char = (a:0 ? a:1 : s:inputtarget()) + let spc = "" + if char =~ '^\d\+' + let scount = scount * matchstr(char,'^\d\+') + let char = substitute(char,'^\d\+','','') + endif + if char =~ '^ ' + let char = strpart(char,1) + let spc = 1 + endif + if char == 'a' + let char = '>' + endif + if char == 'r' + let char = ']' + endif + let newchar = "" + if a:0 > 1 + let newchar = a:2 + if newchar == "\" || newchar == "\" || newchar == "" + return s:beep() + endif + endif + let cb_save = &clipboard + set clipboard-=unnamed clipboard-=unnamedplus + let append = "" + let original = getreg('"') + let otype = getregtype('"') + call setreg('"',"") + let strcount = (scount == 1 ? "" : scount) + if char == '/' + exe 'norm! '.strcount.'[/d'.strcount.']/' + elseif char =~# '[[:punct:][:space:]]' && char !~# '[][(){}<>"''`]' + exe 'norm! T'.char + if getline('.')[col('.')-1] == char + exe 'norm! l' + endif + exe 'norm! dt'.char + else + exe 'norm! d'.strcount.'i'.char + endif + let keeper = getreg('"') + let okeeper = keeper " for reindent below + if keeper == "" + call setreg('"',original,otype) + let &clipboard = cb_save + return "" + endif + let oldline = getline('.') + let oldlnum = line('.') + if char ==# "p" + call setreg('"','','V') + elseif char ==# "s" || char ==# "w" || char ==# "W" + " Do nothing + call setreg('"','') + elseif char =~ "[\"'`]" + exe "norm! i \d2i".char + call setreg('"',substitute(getreg('"'),' ','','')) + elseif char == '/' + norm! "_x + call setreg('"','/**/',"c") + let keeper = substitute(substitute(keeper,'^/\*\s\=','',''),'\s\=\*$','','') + elseif char =~# '[[:punct:][:space:]]' && char !~# '[][(){}<>]' + exe 'norm! F'.char + exe 'norm! df'.char + else + " One character backwards + call search('\m.', 'bW') + exe "norm! da".char + endif + let removed = getreg('"') + let rem2 = substitute(removed,'\n.*','','') + let oldhead = strpart(oldline,0,strlen(oldline)-strlen(rem2)) + let oldtail = strpart(oldline, strlen(oldline)-strlen(rem2)) + let regtype = getregtype('"') + if char =~# '[\[({ 2 ? a:3 : 0 + call s:wrapreg('"',newchar,removed,special) + endif + silent exe 'norm! ""'.pcmd.'`[' + if removed =~ '\n' || okeeper =~ '\n' || getreg('"') =~ '\n' + call s:reindent() + endif + if getline('.') =~ '^\s\+$' && keeper =~ '^\s*\n' + silent norm! cc + endif + call setreg('"',original,otype) + let s:lastdel = removed + let &clipboard = cb_save + if newchar == "" + silent! call repeat#set("\Dsurround".char,scount) + else + silent! call repeat#set("\C".(a:0 > 2 && a:3 ? "S" : "s")."urround".char.newchar.s:input,scount) + endif +endfunction " }}}1 + +function! s:changesurround(...) " {{{1 + let a = s:inputtarget() + if a == "" + return s:beep() + endif + let b = s:inputreplacement() + if b == "" + return s:beep() + endif + call s:dosurround(a,b,a:0 && a:1) +endfunction " }}}1 + +function! s:opfunc(type,...) " {{{1 + let char = s:inputreplacement() + if char == "" + return s:beep() + endif + let reg = '"' + let sel_save = &selection + let &selection = "inclusive" + let cb_save = &clipboard + set clipboard-=unnamed clipboard-=unnamedplus + let reg_save = getreg(reg) + let reg_type = getregtype(reg) + let type = a:type + if a:type == "char" + silent exe 'norm! v`[o`]"'.reg.'y' + let type = 'v' + elseif a:type == "line" + silent exe 'norm! `[V`]"'.reg.'y' + let type = 'V' + elseif a:type ==# "v" || a:type ==# "V" || a:type ==# "\" + let &selection = sel_save + let ve = &virtualedit + if !(a:0 && a:1) + set virtualedit= + endif + silent exe 'norm! gv"'.reg.'y' + let &virtualedit = ve + elseif a:type =~ '^\d\+$' + let type = 'v' + silent exe 'norm! ^v'.a:type.'$h"'.reg.'y' + if mode() ==# 'v' + norm! v + return s:beep() + endif + else + let &selection = sel_save + let &clipboard = cb_save + return s:beep() + endif + let keeper = getreg(reg) + if type ==# "v" && a:type !=# "v" + let append = matchstr(keeper,'\_s\@Y".(a:0 && a:1 ? "S" : "s")."surround".char.s:input,a:type) + else + silent! call repeat#set("\SurroundRepeat".char.s:input) + endif +endfunction + +function! s:opfunc2(arg) + call s:opfunc(a:arg,1) +endfunction " }}}1 + +function! s:closematch(str) " {{{1 + " Close an open (, {, [, or < on the command line. + let tail = matchstr(a:str,'.[^\[\](){}<>]*$') + if tail =~ '^\[.\+' + return "]" + elseif tail =~ '^(.\+' + return ")" + elseif tail =~ '^{.\+' + return "}" + elseif tail =~ '^<.+' + return ">" + else + return "" + endif +endfunction " }}}1 + +nnoremap SurroundRepeat . +nnoremap Dsurround :call dosurround(inputtarget()) +nnoremap Csurround :call changesurround() +nnoremap CSurround :call changesurround(1) +nnoremap Yssurround :call opfunc(v:count1) +nnoremap YSsurround :call opfunc2(v:count1) +" discards the numerical argument but there's not much we can do with it +nnoremap Ysurround :set opfunc=opfuncg@ +nnoremap YSurround :set opfunc=opfunc2g@ +vnoremap VSurround :call opfunc(visualmode(),visualmode() ==# 'V' ? 1 : 0) +vnoremap VgSurround :call opfunc(visualmode(),visualmode() ==# 'V' ? 0 : 1) +inoremap Isurround =insert() +inoremap ISurround =insert(1) + +if !exists("g:surround_no_mappings") || ! g:surround_no_mappings + nmap ds Dsurround + nmap cs Csurround + nmap cS CSurround + nmap ys Ysurround + nmap yS YSurround + nmap yss Yssurround + nmap ySs YSsurround + nmap ySS YSsurround + xmap S VSurround + xmap gS VgSurround + if !exists("g:surround_no_insert_mappings") || ! g:surround_no_insert_mappings + if !hasmapto("Isurround","i") && "" == mapcheck("","i") + imap Isurround + endif + imap s Isurround + imap S ISurround + endif +endif + +" vim:set ft=vim sw=2 sts=2 et: diff --git a/.vim/bundle/wal.vim/LICENSE.md b/.vim/bundle/wal.vim/LICENSE.md new file mode 100755 index 0000000..e17de65 --- /dev/null +++ b/.vim/bundle/wal.vim/LICENSE.md @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright (c) 2016-2017 Dylan Araps + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.vim/bundle/wal.vim/README.md b/.vim/bundle/wal.vim/README.md new file mode 100644 index 0000000..d4c8278 --- /dev/null +++ b/.vim/bundle/wal.vim/README.md @@ -0,0 +1,15 @@ +# wal.vim + +[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) + +A vim colorscheme for use with **[pywal](https://github.com/dylanaraps/pywal)**. + + +## Installation + +```vim +! Using plug +Plug 'dylanaraps/wal.vim' + +colorscheme wal +``` diff --git a/.vim/bundle/wal.vim/autoload/airline/themes/wal.vim b/.vim/bundle/wal.vim/autoload/airline/themes/wal.vim new file mode 100644 index 0000000..c334ee5 --- /dev/null +++ b/.vim/bundle/wal.vim/autoload/airline/themes/wal.vim @@ -0,0 +1,62 @@ +" wal Airline +let g:airline#themes#wal#palette = {} + +" Normal mode +let s:N = [ '', '', 232, 4, 'BOLD' ] +let s:N2 = [ '', '', 4, 0, 'BOLD' ] + +" Insert mode +let s:I = [ '', '', 232, 2, 'BOLD' ] +let s:I2 = [ '', '', 2, 0, 'BOLD' ] + +" Visual mode +let s:V = [ '', '', 232, 1, 'BOLD' ] +let s:V2 = [ '', '', 1, 0, 'BOLD' ] + +" Replace mode +let s:R = [ '', '', 232, 5, 'BOLD' ] +let s:R2 = [ '', '', 5, 0, 'BOLD' ] + +let g:airline#themes#wal#palette.normal = airline#themes#generate_color_map(s:N, s:N2, s:N2) +let g:airline#themes#wal#palette.insert = airline#themes#generate_color_map(s:I, s:I2, s:I2) +let g:airline#themes#wal#palette.visual = airline#themes#generate_color_map(s:V, s:V2, s:V2) +let g:airline#themes#wal#palette.replace = airline#themes#generate_color_map(s:R, s:R2, s:R2) + +let g:airline#themes#wal#palette.accents = { 'red': [ '', '', 0, 2, 'BOLD' ] } + +" Inactive mode +let s:IN1 = [ '', '', 0, 8 ] +let s:IN2 = [ '', '', 0, 0 ] + +let s:IA = [ s:IN1[1], s:IN2[1], s:IN1[3], s:IN2[3], '' ] +let g:airline#themes#wal#palette.inactive = airline#themes#generate_color_map(s:IA, s:IA, s:IA) + +" Warnings +let s:WI = [ '', '', 232, 1, 'BOLD' ] +let g:airline#themes#wal#palette.normal.airline_warning = s:WI +let g:airline#themes#wal#palette.insert.airline_warning = s:WI +let g:airline#themes#wal#palette.visual.airline_warning = s:WI +let g:airline#themes#wal#palette.replace.airline_warning = s:WI + +let g:airline#themes#wal#palette.normal.airline_error = s:WI +let g:airline#themes#wal#palette.insert.airline_error = s:WI +let g:airline#themes#wal#palette.visual.airline_error = s:WI +let g:airline#themes#wal#palette.replace.airline_error = s:WI + +" Tabline +let g:airline#themes#wal#palette.tabline = { + \ 'airline_tab': [ '', '', 4, 0, 'BOLD' ], + \ 'airline_tabsel': [ '', '', 232, 4, 'BOLD' ], + \ 'airline_tabtype': [ '', '', 232, 4, 'BOLD' ], + \ 'airline_tabfill': [ '', '', 4, 0, 'BOLD' ], + \ 'airline_tabmod': [ '', '', 232, 4, 'BOLD' ] +\ } + +if !get(g:, 'loaded_ctrlp', 0) + finish +endif + +let g:airline#themes#wal#palette.ctrlp = airline#extensions#ctrlp#generate_color_map( + \ [ '', '', 0, 0, 'BOLD' ], + \ [ '', '', 0, 0, 'BOLD' ], + \ [ '', '', 0, 0, 'BOLD' ] ) diff --git a/.vim/bundle/wal.vim/colors/wal.vim b/.vim/bundle/wal.vim/colors/wal.vim new file mode 100755 index 0000000..44935a9 --- /dev/null +++ b/.vim/bundle/wal.vim/colors/wal.vim @@ -0,0 +1,193 @@ +" wal.vim -- Vim color scheme. +" Author: Dylan Araps +" Webpage: https://github.com/dylanaraps/wal +" Description: A colorscheme that uses your terminal colors, made to work with 'wal'. + +hi clear +set background=dark + +if exists('syntax_on') + syntax reset +endif + +" Colorscheme name +let g:colors_name = 'wal' + +" highlight groups {{{ + +" set t_Co=16 +hi Normal ctermbg=NONE ctermfg=7 cterm=NONE +hi NonText ctermbg=NONE ctermfg=0 cterm=NONE +hi Comment ctermbg=NONE ctermfg=8 cterm=NONE +hi Constant ctermbg=NONE ctermfg=3 cterm=NONE +hi Error ctermbg=1 ctermfg=7 cterm=NONE +hi Identifier ctermbg=NONE ctermfg=1 cterm=NONE +hi Ignore ctermbg=8 ctermfg=0 cterm=NONE +hi PreProc ctermbg=NONE ctermfg=3 cterm=NONE +hi Special ctermbg=NONE ctermfg=6 cterm=NONE +hi Statement ctermbg=NONE ctermfg=1 cterm=NONE +hi String ctermbg=NONE ctermfg=2 cterm=NONE +hi Number ctermbg=NONE ctermfg=3 cterm=NONE +hi Todo ctermbg=2 ctermfg=0 cterm=NONE +hi Type ctermbg=NONE ctermfg=3 cterm=NONE +hi Underlined ctermbg=NONE ctermfg=1 cterm=underline +hi StatusLine ctermbg=7 ctermfg=0 cterm=NONE +hi StatusLineNC ctermbg=NONE ctermfg=NONE cterm=NONE +hi TabLine ctermbg=NONE ctermfg=8 cterm=NONE +hi TabLineFill ctermbg=NONE ctermfg=8 cterm=NONE +hi TabLineSel ctermbg=4 ctermfg=0 cterm=NONE +hi TermCursorNC ctermbg=3 ctermfg=0 cterm=NONE +hi VertSplit ctermbg=NONE ctermfg=NONE cterm=NONE +hi Title ctermbg=NONE ctermfg=4 cterm=NONE +hi CursorLine ctermbg=8 ctermfg=0 cterm=NONE +hi LineNr ctermbg=NONE ctermfg=8 cterm=NONE +hi CursorLineNr ctermbg=NONE ctermfg=8 cterm=NONE +hi helpLeadBlank ctermbg=NONE ctermfg=7 cterm=NONE +hi helpNormal ctermbg=NONE ctermfg=7 cterm=NONE +hi Visual ctermbg=8 ctermfg=0 cterm=NONE +hi VisualNOS ctermbg=NONE ctermfg=1 cterm=NONE +hi Pmenu ctermbg=8 ctermfg=7 cterm=NONE +hi PmenuSbar ctermbg=6 ctermfg=7 cterm=NONE +hi PmenuSel ctermbg=4 ctermfg=0 cterm=NONE +hi PmenuThumb ctermbg=8 ctermfg=8 cterm=NONE +hi FoldColumn ctermbg=NONE ctermfg=7 cterm=NONE +hi Folded ctermbg=NONE ctermfg=8 cterm=NONE +hi WildMenu ctermbg=2 ctermfg=0 cterm=NONE +hi SpecialKey ctermbg=NONE ctermfg=8 cterm=NONE +hi DiffAdd ctermbg=NONE ctermfg=2 cterm=NONE +hi DiffChange ctermbg=NONE ctermfg=8 cterm=NONE +hi DiffDelete ctermbg=NONE ctermfg=1 cterm=NONE +hi DiffText ctermbg=NONE ctermfg=4 cterm=NONE +hi IncSearch ctermbg=3 ctermfg=0 cterm=NONE +hi Search ctermbg=3 ctermfg=0 cterm=NONE +hi Directory ctermbg=NONE ctermfg=4 cterm=NONE +hi MatchParen ctermbg=8 ctermfg=0 cterm=NONE +hi ColorColumn ctermbg=4 ctermfg=0 cterm=NONE +hi signColumn ctermbg=NONE ctermfg=4 cterm=NONE +hi ErrorMsg ctermbg=NONE ctermfg=8 cterm=NONE +hi ModeMsg ctermbg=NONE ctermfg=2 cterm=NONE +hi MoreMsg ctermbg=NONE ctermfg=2 cterm=NONE +hi Question ctermbg=NONE ctermfg=4 cterm=NONE +hi WarningMsg ctermbg=1 ctermfg=0 cterm=NONE +hi Cursor ctermbg=NONE ctermfg=8 cterm=NONE +hi Structure ctermbg=NONE ctermfg=5 cterm=NONE +hi CursorColumn ctermbg=8 ctermfg=7 cterm=NONE +hi ModeMsg ctermbg=NONE ctermfg=7 cterm=NONE +hi SpellBad ctermbg=1 ctermfg=0 cterm=NONE +hi SpellCap ctermbg=NONE ctermfg=4 cterm=underline +hi SpellLocal ctermbg=NONE ctermfg=5 cterm=underline +hi SpellRare ctermbg=NONE ctermfg=6 cterm=underline +hi Boolean ctermbg=NONE ctermfg=5 cterm=NONE +hi Character ctermbg=NONE ctermfg=1 cterm=NONE +hi Conditional ctermbg=NONE ctermfg=5 cterm=NONE +hi Define ctermbg=NONE ctermfg=5 cterm=NONE +hi Delimiter ctermbg=NONE ctermfg=5 cterm=NONE +hi Float ctermbg=NONE ctermfg=5 cterm=NONE +hi Include ctermbg=NONE ctermfg=4 cterm=NONE +hi Keyword ctermbg=NONE ctermfg=5 cterm=NONE +hi Label ctermbg=NONE ctermfg=3 cterm=NONE +hi Operator ctermbg=NONE ctermfg=7 cterm=NONE +hi Repeat ctermbg=NONE ctermfg=3 cterm=NONE +hi SpecialChar ctermbg=NONE ctermfg=5 cterm=NONE +hi Tag ctermbg=NONE ctermfg=3 cterm=NONE +hi Typedef ctermbg=NONE ctermfg=3 cterm=NONE +hi vimUserCommand ctermbg=NONE ctermfg=1 cterm=BOLD + hi link vimMap vimUserCommand + hi link vimLet vimUserCommand + hi link vimCommand vimUserCommand + hi link vimFTCmd vimUserCommand + hi link vimAutoCmd vimUserCommand + hi link vimNotFunc vimUserCommand +hi vimNotation ctermbg=NONE ctermfg=4 cterm=NONE +hi vimMapModKey ctermbg=NONE ctermfg=4 cterm=NONE +hi vimBracket ctermbg=NONE ctermfg=7 cterm=NONE +hi vimCommentString ctermbg=NONE ctermfg=8 cterm=NONE +hi htmlLink ctermbg=NONE ctermfg=1 cterm=underline +hi htmlBold ctermbg=NONE ctermfg=3 cterm=NONE +hi htmlItalic ctermbg=NONE ctermfg=5 cterm=NONE +hi htmlEndTag ctermbg=NONE ctermfg=7 cterm=NONE +hi htmlTag ctermbg=NONE ctermfg=7 cterm=NONE +hi htmlTagName ctermbg=NONE ctermfg=1 cterm=BOLD +hi htmlH1 ctermbg=NONE ctermfg=7 cterm=NONE + hi link htmlH2 htmlH1 + hi link htmlH3 htmlH1 + hi link htmlH4 htmlH1 + hi link htmlH5 htmlH1 + hi link htmlH6 htmlH1 +hi cssMultiColumnAttr ctermbg=NONE ctermfg=2 cterm=NONE + hi link cssFontAttr cssMultiColumnAttr + hi link cssFlexibleBoxAttr cssMultiColumnAttr +hi cssBraces ctermbg=NONE ctermfg=7 cterm=NONE + hi link cssAttrComma cssBraces +hi cssValueLength ctermbg=NONE ctermfg=7 cterm=NONE +hi cssUnitDecorators ctermbg=NONE ctermfg=7 cterm=NONE +hi cssValueNumber ctermbg=NONE ctermfg=7 cterm=NONE + hi link cssValueLength cssValueNumber +hi cssNoise ctermbg=NONE ctermfg=8 cterm=NONE +hi cssTagName ctermbg=NONE ctermfg=1 cterm=NONE +hi cssFunctionName ctermbg=NONE ctermfg=4 cterm=NONE +hi scssSelectorChar ctermbg=NONE ctermfg=7 cterm=NONE +hi scssAttribute ctermbg=NONE ctermfg=7 cterm=NONE + hi link scssDefinition cssNoise +hi sassidChar ctermbg=NONE ctermfg=1 cterm=NONE +hi sassClassChar ctermbg=NONE ctermfg=5 cterm=NONE +hi sassInclude ctermbg=NONE ctermfg=5 cterm=NONE +hi sassMixing ctermbg=NONE ctermfg=5 cterm=NONE +hi sassMixinName ctermbg=NONE ctermfg=4 cterm=NONE +hi javaScript ctermbg=NONE ctermfg=7 cterm=NONE +hi javaScriptBraces ctermbg=NONE ctermfg=7 cterm=NONE +hi javaScriptNumber ctermbg=NONE ctermfg=5 cterm=NONE +hi markdownH1 ctermbg=NONE ctermfg=7 cterm=NONE + hi link markdownH2 markdownH1 + hi link markdownH3 markdownH1 + hi link markdownH4 markdownH1 + hi link markdownH5 markdownH1 + hi link markdownH6 markdownH1 +hi markdownAutomaticLink ctermbg=NONE ctermfg=1 cterm=underline + hi link markdownUrl markdownAutomaticLink +hi markdownError ctermbg=NONE ctermfg=7 cterm=NONE +hi markdownCode ctermbg=NONE ctermfg=3 cterm=NONE +hi markdownCodeBlock ctermbg=NONE ctermfg=3 cterm=NONE +hi markdownCodeDelimiter ctermbg=NONE ctermfg=5 cterm=NONE +hi xdefaultsValue ctermbg=NONE ctermfg=7 cterm=NONE +hi rubyInclude ctermbg=NONE ctermfg=4 cterm=NONE +hi rubyDefine ctermbg=NONE ctermfg=5 cterm=NONE +hi rubyFunction ctermbg=NONE ctermfg=4 cterm=NONE +hi rubyStringDelimiter ctermbg=NONE ctermfg=2 cterm=NONE +hi rubyInteger ctermbg=NONE ctermfg=3 cterm=NONE +hi rubyAttribute ctermbg=NONE ctermfg=4 cterm=NONE +hi rubyConstant ctermbg=NONE ctermfg=3 cterm=NONE +hi rubyInterpolation ctermbg=NONE ctermfg=2 cterm=NONE +hi rubyInterpolationDelimiter ctermbg=NONE ctermfg=3 cterm=NONE +hi rubyRegexp ctermbg=NONE ctermfg=6 cterm=NONE +hi rubySymbol ctermbg=NONE ctermfg=2 cterm=NONE +hi rubyTodo ctermbg=NONE ctermfg=8 cterm=NONE +hi rubyRegexpAnchor ctermbg=NONE ctermfg=7 cterm=NONE + hi link rubyRegexpQuantifier rubyRegexpAnchor +hi pythonOperator ctermbg=NONE ctermfg=5 cterm=NONE +hi pythonFunction ctermbg=NONE ctermfg=4 cterm=NONE +hi pythonRepeat ctermbg=NONE ctermfg=5 cterm=NONE +hi pythonStatement ctermbg=NONE ctermfg=1 cterm=Bold +hi pythonBuiltIn ctermbg=NONE ctermfg=4 cterm=NONE +hi phpMemberSelector ctermbg=NONE ctermfg=7 cterm=NONE +hi phpComparison ctermbg=NONE ctermfg=7 cterm=NONE +hi phpParent ctermbg=NONE ctermfg=7 cterm=NONE +hi cOperator ctermbg=NONE ctermfg=6 cterm=NONE +hi cPreCondit ctermbg=NONE ctermfg=5 cterm=NONE +hi SignifySignAdd ctermbg=NONE ctermfg=2 cterm=NONE +hi SignifySignChange ctermbg=NONE ctermfg=4 cterm=NONE +hi SignifySignDelete ctermbg=NONE ctermfg=1 cterm=NONE +hi NERDTreeDirSlash ctermbg=NONE ctermfg=4 cterm=NONE +hi NERDTreeExecFile ctermbg=NONE ctermfg=7 cterm=NONE +hi ALEErrorSign ctermbg=NONE ctermfg=1 cterm=NONE +hi ALEWarningSign ctermbg=NONE ctermfg=3 cterm=NONE +hi ALEError ctermbg=NONE ctermfg=1 cterm=NONE +hi ALEWarning ctermbg=NONE ctermfg=3 cterm=NONE + +" }}} + +" Plugin options {{{ + +let g:limelight_conceal_ctermfg = 8 + +" }}} diff --git a/.vim/plugin/dragvisuals.vim b/.vim/plugin/dragvisuals.vim new file mode 100644 index 0000000..12c4f5d --- /dev/null +++ b/.vim/plugin/dragvisuals.vim @@ -0,0 +1,345 @@ +" Vim global plugin for dragging virtual blocks +" Last change: Tue Jul 24 07:19:35 EST 2012 +" Maintainer: Damian Conway +" License: This file is placed in the public domain. + +"######################################################################### +"## ## +"## Add the following (uncommented) to your .vimrc... ## +"## ## +"## runtime plugin/dragvisuals.vim ## +"## ## +"## vmap DVB_Drag('left') ## +"## vmap DVB_Drag('right') ## +"## vmap DVB_Drag('down') ## +"## vmap DVB_Drag('up') ## +"## vmap D DVB_Duplicate() ## +"## ## +"## " Remove any introduced trailing whitespace after moving... ## +"## let g:DVB_TrimWS = 1 ## +"## ## +"## Or, if you use the arrow keys for normal motions, choose ## +"## four other keys for block dragging. For example: ## +"## ## +"## vmap h DVB_Drag('left') ## +"## vmap l DVB_Drag('right') ## +"## vmap j DVB_Drag('down') ## +"## vmap k DVB_Drag('up') ## +"## ## +"## Or: ## +"## ## +"## vmap DVB_Drag('left') ## +"## vmap DVB_Drag('right') ## +"## vmap DVB_Drag('down') ## +"## vmap DVB_Drag('up') ## +"## ## +"## Or even: ## +"## ## +"## vmap DVB_Drag('left') ## +"## vmap DVB_Drag('right') ## +"## vmap DVB_Drag('down') ## +"## vmap DVB_Drag('up') ## +"## ## +"######################################################################### + + +" If already loaded, we're done... +if exists("loaded_dragvirtualblocks") + finish +endif +let loaded_dragvirtualblocks = 1 + +" Preserve external compatibility options, then enable full vim compatibility... +let s:save_cpo = &cpo +set cpo&vim + +"====[ Implementation ]==================================== + +" Toggle this to stop trimming on drags... +if !exists('g:DVB_TrimWS') + let g:DVB_TrimWS = 1 +endif + +function! DVB_Drag (dir) + " No-op in Visual mode... + if mode() ==# 'v' + return "\gv" + + " Do Visual Line drag indirectly via temporary nmap + " (to ensure we have access to block position data)... + elseif mode() ==# 'V' + " Set up a temporary convenience... + exec "nnoremap M \Drag_Lines('".a:dir."')" + + " Return instructions to implement the move and reset selection... + return '"vyM' + + " Otherwise do Visual Block drag indirectly via temporary nmap + " (to ensure we have access to block position data)... + else + " Set up a temporary convenience... + exec "nnoremap M \Drag_Block('".a:dir."')" + + " Return instructions to implement the move and reset selection... + return '"vyM' + endif +endfunction + +" Duplicate selected block and place to the right... +function! DVB_Duplicate () + exec "nnoremap M \DuplicateBlock()" + return '"vyM' +endfunction + +function! s:DuplicateBlock () + nunmap M + " Locate block boundaries... + let [buf_left, line_left, col_left, offset_left ] = getpos("'<") + let [buf_right, line_right, col_right, offset_right] = getpos("'>") + + " Identify special '$' blocks... + let dollar_block = 0 + let start_col = min([col_left+offset_left, col_right+offset_right]) + let end_col = max([col_left+offset_left, col_right+offset_right]) + let visual_width = end_col - start_col + 1 + for visual_line in split(getreg("v"),"\n") + if strlen(visual_line) > visual_width + let dollar_block = 1 + let visual_width = strlen(visual_line) + endif + endfor + let square_up = (dollar_block ? (start_col+visual_width-2).'|' : '') + + set virtualedit=all + return 'gv'.square_up.'yPgv' + \. (visual_width-dollar_block) . 'lo' . (visual_width-dollar_block) . 'l' + \. "y:set virtualedit=block\gv" + \. (dollar_block ? 'o$' : '') +endfunction + + +" Kludge to hide change reporting inside implementation... +let s:NO_REPORT = ":let b:DVB_report=&report\:let &report=1000000000\" +let s:PREV_REPORT = ":let &report = b:DVB_report\" + + +" Drag in specified direction in Visual Line mode... +function! s:Drag_Lines (dir) + " Clean up the temporary convenience... + nunmap M + + " Locate block being shifted... + let [buf_left, line_left, col_left, offset_left ] = getpos("'<") + let [buf_right, line_right, col_right, offset_right] = getpos("'>") + + " Drag entire lines left if possible... + if a:dir == 'left' + " Are all lines indented at least one space??? + let lines = getline(line_left, line_right) + let all_indented = match(lines, '^[^ ]') == -1 + nohlsearch + + " If can't trim one space from start of each line, be a no-op... + if !all_indented + return 'gv' + + " Otherwise drag left by removing one space from start of each line... + else + return s:NO_REPORT + \ . "gv:s/^ //\" + \ . s:PREV_REPORT + \ . "gv" + endif + + " To drag entire lines right, add a space in column 1... + elseif a:dir == 'right' + return s:NO_REPORT + \ . "gv:s/^/ /\:nohlsearch\" + \ . s:PREV_REPORT + \ . "gv" + + " To drag entire lines upwards... + elseif a:dir == 'up' + let EOF = line('$') + + " Can't drag up if at first line... + if line_left == 1 || line_right == 1 + return 'gv' + + " Needs special handling at EOF (because cursor moves up on delete)... + elseif line_left == EOF || line_right == EOF + let height = line_right - line_left + let select_extra = height ? height . 'j' : "" + return s:NO_REPORT + \ . 'gvxP' + \ . s:PREV_REPORT + \ . 'V' . select_extra + + " Otherwise just cut-move-paste-reselect... + else + let height = line_right - line_left + let select_extra = height ? height . 'j' : "" + return s:NO_REPORT + \ . 'gvxkP' + \ . s:PREV_REPORT + \ . 'V' . select_extra + endif + + " To drag entire lines downwards... + elseif a:dir == 'down' + let EOF = line('$') + + " This is how much extra we're going to have to reselect... + let height = line_right - line_left + let select_extra = height ? height . 'j' : "" + + " Needs special handling at EOF (to push selection down into new space)... + if line_left == EOF || line_right == EOF + return "O\gv" + + " Otherwise, just cut-move-paste-reselect... + else + return s:NO_REPORT + \ . 'gvxp' + \ . s:PREV_REPORT + \ . 'V' . select_extra + endif + + endif +endfunction + +" Drag in specified direction in Visual Block mode... +function! s:Drag_Block (dir) + " Clean up the temporary convenience... + nunmap M + + " Locate block being shifted... + let [buf_left, line_left, col_left, offset_left ] = getpos("'<") + let [buf_right, line_right, col_right, offset_right] = getpos("'>") + + " Identify special '$' blocks... + let dollar_block = 0 + let start_col = min([col_left+offset_left, col_right+offset_right]) + let end_col = max([col_left+offset_left, col_right+offset_right]) + let visual_width = end_col - start_col + 1 + for visual_line in split(getreg("v"),"\n") + if strlen(visual_line) > visual_width + let dollar_block = 1 + let visual_width = strlen(visual_line) + endif + endfor + let square_up = (dollar_block ? (start_col+visual_width-2).'|' : '') + + " Drag left... + if a:dir == 'left' + "Can't drag left at left margin... + if col_left == 1 || col_right == 1 + return 'gv' + + " Otherwise reposition one column left (and optionally trim any whitespace)... + elseif g:DVB_TrimWS + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " Are we moving past other text??? + let square_up_final = "" + if dollar_block + let lines = getline(line_left, line_right) + if match(lines, '^.\{'.(start_col-2).'}\S') >= 0 + let dollar_block = 0 + let square_up_final = (start_col+visual_width-3).'|' + endif + endif + + let vcol = start_col - 2 + return 'gv'.square_up.'xhP' + \ . s:NO_REPORT + \ . "gvhoho:s/\\s*$//\gv\" + \ . ':set virtualedit=' . prev_ve . "\" + \ . s:PREV_REPORT + \ . ":nohlsearch\gv" + \ . (dollar_block ? '$' : square_up_final ) + else + return 'gv'.square_up.'xhPgvhoho' + endif + + " Drag right... + elseif a:dir == 'right' + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " Reposition block one column to the right... + if g:DVB_TrimWS + let vcol = start_col + return 'gv'.square_up.'xp' + \ . s:NO_REPORT + \ . "gvlolo" + \ . ":s/\\s*$//\gv\" + \ . ':set virtualedit=' . prev_ve . "\" + \ . s:PREV_REPORT + \ . (dollar_block ? 'gv$' : 'gv') + else + return 'gv'.square_up.'xp:set virtualedit=' . prev_ve . "\gvlolo" + endif + + " Drag upwards... + elseif a:dir == 'up' + " Can't drag upwards at top margin... + if line_left == 1 || line_right == 1 + return 'gv' + endif + + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " If trimming whitespace, jump to just below block to do it... + if g:DVB_TrimWS + let height = line_right - line_left + 1 + return 'gv'.square_up.'xkPgvkoko"vy' + \ . height + \ . 'j:s/\s*$//' + \ . "\:nohlsearch\:set virtualedit=" + \ . prev_ve + \ . "\gv" + \ . (dollar_block ? '$' : '') + + " Otherwise just move and reselect... + else + return 'gv'.square_up.'xkPgvkoko"vy:set virtualedit=' + \ . prev_ve + \ . "\gv" + \ . (dollar_block ? '$' : '') + endif + + " Drag downwards... + elseif a:dir == 'down' + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " If trimming whitespace, move to just above block to do it... + if g:DVB_TrimWS + return 'gv'.square_up.'xjPgvjojo"vyk:s/\s*$//' + \ . "\:nohlsearch\:set virtualedit=" + \ . prev_ve + \ . "\gv" + \ . (dollar_block ? '$' : '') + + " Otherwise just move and reselect... + else + return 'gv'.square_up.'xjPgvjojo"vy' + \ . "\:set virtualedit=" + \ . prev_ve + \ . "\gv" + \ . (dollar_block ? '$' : '') + endif + endif +endfunction + + +" Restore previous external compatibility options +let &cpo = s:save_cpo + diff --git a/.vim/plugin/vmath.vim b/.vim/plugin/vmath.vim new file mode 100644 index 0000000..0e10044 --- /dev/null +++ b/.vim/plugin/vmath.vim @@ -0,0 +1,152 @@ +" Vim global plugin for math on visual regions +" Maintainer: Damian Conway +" License: This file is placed in the public domain. + +"###################################################################### +"## ## +"## To use: ## +"## ## +"## vmap ++ VMATH_YankAndAnalyse() ## +"## nmap ++ vip++ ## +"## ## +"## (or whatever keys you prefer to remap these actions to) ## +"## ## +"###################################################################### + + +" If already loaded, we're done... +if exists("loaded_vmath") + finish +endif +let loaded_vmath = 1 + +" Preserve external compatibility options, then enable full vim compatibility... +let s:save_cpo = &cpo +set cpo&vim + +" Grab visual selection and do simple math on it... +function! VMATH_YankAndAnalyse () + if &showmode + " Don't reselect the visual region if showmode is enabled + " because it will clobber the sum/avg/etc report with the + " "-- VISUAL --" message. + return "y:call VMATH_Analyse()\" + else + return "y:call VMATH_Analyse()\gv" + endif +endfunction + +" What to consider a number... +let s:NUM_PAT = '^[+-]\?\d\+\%([.]\d\+\)\?\([eE][+-]\?\d\+\)\?$' + +" How widely to space the report components... +let s:REPORT_GAP = 3 "spaces between components + +" Do simple math on current yank buffer... +function! VMATH_Analyse () + " Extract data from selection... + let selection = getreg('') + let raw_numbers = filter(split(selection), 'v:val =~ s:NUM_PAT') + let numbers = map(copy(raw_numbers), 'str2float(v:val)') + + " Results include a newline if original selection did... + let newline = selection =~ "\n" ? "\n" : "" + + " Calculate and en-register various interesting metrics... + let summation = len(numbers) ? join( numbers, ' + ') : '0' + call setreg('s', s:tidy( eval( summation ) )) " Sum --> register s + call setreg('a', s:average(raw_numbers) ) " Average --> register a + call setreg('x', s:tidy( s:max(numbers) )) " Max --> register x + call setreg('n', s:tidy( s:min(numbers) )) " Min --> register n + call setreg('r', @n . ' to ' . @x ) " Range --> register r + call setreg('c', len(numbers) ) " Count --> register c + + " Default paste buffer should depend on original contents (TODO) + call setreg('', @s ) + + " Report... + let gap = repeat(" ", s:REPORT_GAP) + highlight NormalUnderlined term=underline cterm=underline gui=underline + echohl NormalUnderlined + echo 's' + echohl NONE + echon 'um: ' . @s . gap + echohl NormalUnderlined + echon 'a' + echohl NONE + echon 'vg: ' . @a . gap + echon 'mi' + echohl NormalUnderlined + echon 'n' + echohl NONE + echon ': ' . @n . gap + echon 'ma' + echohl NormalUnderlined + echon 'x' + echohl NONE + echon ': ' . @x . gap + echohl NormalUnderlined + echon 'c' + echohl NONE + echon 'ount: ' . @c + +endfunction + +" Prettify numbers... +function! s:tidy (number) + let tidied = printf('%g', a:number) + return substitute(tidied, '[.]0\+$', '', '') +endfunction + +" Compute average with meaningful number of decimal places... +function! s:average (numbers) + " Compute average... + let summation = eval( len(a:numbers) ? join( a:numbers, ' + ') : '0' ) + let avg = 1.0 * summation / s:max([len(a:numbers), 1]) + + " Determine significant figures... + let min_decimals = 15 + for num in a:numbers + let decimals = strlen(matchstr(num, '[.]\d\+$')) - 1 + if decimals < min_decimals + let min_decimals = decimals + endif + endfor + + " Adjust answer... + return min_decimals > 0 ? printf('%0.'.min_decimals.'f', avg) + \ : string(avg) +endfunction + +" Reimplement these because the builtins don't handle floats (!!!) +function! s:max (numbers) + if !len(a:numbers) + return 0 + endif + let numbers = copy(a:numbers) + let maxnum = numbers[0] + for nextnum in numbers[1:] + if nextnum > maxnum + let maxnum = nextnum + endif + endfor + return maxnum +endfunction + +function! s:min (numbers) + if !len(a:numbers) + return 0 + endif + let numbers = copy(a:numbers) + let minnum = numbers[0] + for nextnum in numbers[1:] + if nextnum < minnum + let minnum = nextnum + endif + endfor + return minnum +endfunction + + +" Restore previous external compatibility options +let &cpo = s:save_cpo diff --git a/.vim/syntax/i3.vim b/.vim/syntax/i3.vim new file mode 100644 index 0000000..fb93437 --- /dev/null +++ b/.vim/syntax/i3.vim @@ -0,0 +1,110 @@ +" Vim syntax file +" Language: i3-wm config file +" Maintainer: Emanuel Guével +" Latest Revision: 16 October 2012 + +if exists("b:current_syntax") + finish +endif + +" Symbols +syn match i3Operators "+\|→" +syn match i3ChainDelimiter ";" + +syn match i3Var "\$\w\+" + +" Key modifiers +syn keyword i3KeyModifier Shift Control Mod1 Mod2 Mod3 Mod4 Mod5 + +" Strings +syn region i3SimpleString keepend start='[^ \t]' end='$\|;' contained contains=i3ChainDelimiter,i3Var +syn match i3QuotedString '"[^"]\+"' contained +syn cluster i3String contains=i3SimpleString,i3QuotedString + +" Config commands +syn keyword i3ConfigCommand bind bindcode bindsym assign new_window popup_during_fullscreen font floating_modifier floating_minimum_size floating_maximum_size default_orientation workspace_layout for_window focus_folows_mouse bar position colors output tray_output workspace_buttons +syn match i3IpcSocket "ipc-socket" nextgroup=@i3String skipwhite + +" Command keywords +syn keyword i3Command exit reload restart kill fullscreen global layout border focus move open split append_layout mark resize grow shrink restore show +syn keyword i3Param 1pixel default stacked tabbed normal none tiling stacking floating enable disable up down horizontal vertical both up down left right parent child px or ppt leave_fullscreen toggle mode_toggle scratchpad width height top bottom client dock hide primary yes no all window container to +syn keyword i3WsSpecialParam next prev + +" Exec commands +syn region i3ExecCommand keepend start='[^ \t]' end='$\|;' contained contains=i3ChainDelimiter,i3Var +syn match i3QuotedExecCommand '"[^"]\+"' contained +syn keyword i3ExecKeyword exec exec_always nextgroup=i3QuotedExecCommand,i3ExecCommand skipwhite + +" Status command +syn match i3StatusCommand ".*$" contained +syn keyword i3StatusCommandKeyword status_command nextgroup=i3StatusCommand skipwhite + +" Font statement +syn keyword i3FontStatement font nextgroup=@i3String skipwhite + +" Set statement +syn match i3SetVar "\$\w\+" contained nextgroup=@i3String skipwhite +syn keyword i3SetKeyword set nextgroup=i3SetVar skipwhite + +" Workspaces +syn keyword i3WsKeyword workspace nextgroup=i3WsSpecialParam,@i3String skipwhite + +" Mode +syn keyword i3ModeKeyword mode nextgroup=@i3String skipwhite + +" Comments +syn keyword i3Todo contained TODO FIXME XXX NOTE +syn match i3Comment "^\s*#.*$" contains=i3Todo + +" Error (at end of line) +syn match i3Error ".*$" contained + +" Hex color code +syn match i3ColorLast "#[0-9a-fA-F]\{6\}" contained nextgroup=i3Error skipwhite +syn match i3Color2nd "#[0-9a-fA-F]\{6\}" contained nextgroup=i3ColorLast skipwhite +syn match i3Color1st "#[0-9a-fA-F]\{6\}" contained nextgroup=i3Color2nd skipwhite + +syn match i3ColorDef1 "client\.background\|statusline\|background\|separator" nextgroup=i3ColorLast skipwhite +syn match i3ColorDef3 "client\.\(focused_inactive\|focused\|unfocused\|urgent\)\|inactive_workspace\|urgent_workspace\|focused_workspace\|active_workspace" nextgroup=i3Color1st skipwhite + +highlight link i3ChainDelimiter Operator +highlight link i3Operators Operator + +highlight link i3ExecCommand Special +highlight link i3QuotedExecCommand Special +highlight link i3StatusCommand Special + +highlight link i3Param Constant +highlight link i3Color1st Constant +highlight link i3Color2nd Constant +highlight link i3ColorLast Constant +highlight link i3WsSpecialParam Constant + +highlight link i3Var Identifier +highlight link i3SetVar Identifier + +highlight link i3KeyModifier Function + +highlight link i3SimpleString String +highlight link i3QuotedString String +highlight link i3WsName String +highlight link i3QuotedWsName String +highlight link i3SetValue String +highlight link i3Font String + +highlight link i3ExecKeyword Keyword +highlight link i3Command Keyword +highlight link i3WsKeyword Keyword + +highlight link i3ColorDef1 Define +highlight link i3ColorDef3 Define +highlight link i3ConfigCommand Define +highlight link i3IpcSocket Define +highlight link i3SetKeyword Define +highlight link i3ModeKeyword Define +highlight link i3FontStatement Define +highlight link i3StatusCommandKeyword Define + +highlight link i3Todo Todo +highlight link i3Comment Comment +highlight link i3Error Error