diff --git a/.vim/.netrwhist b/.vim/.netrwhist new file mode 100644 index 0000000..9e1932d --- /dev/null +++ b/.vim/.netrwhist @@ -0,0 +1,12 @@ +let g:netrw_dirhistmax =10 +let g:netrw_dirhistcnt =0 +let g:netrw_dirhist_0='/usr/local/share/doc/crispy-strife' +let g:netrw_dirhist_9='/usr/local/share/doc/crispy-hexen' +let g:netrw_dirhist_8='/usr/local/share/doc/crispy-heretic' +let g:netrw_dirhist_7='/usr/local/share/doc/crispy-doom' +let g:netrw_dirhist_6='/home/sdk' +let g:netrw_dirhist_5='/home/sdk/.config' +let g:netrw_dirhist_4='/home/sdk/satzung' +let g:netrw_dirhist_3='/usr/xenocara/lib/libva' +let g:netrw_dirhist_2='/home/dpb/usr/ports/mystuff/net/gurk-rs/files' +let g:netrw_dirhist_1='/etc/X11/xenodm' diff --git a/.vim/autoload/pathogen.vim b/.vim/autoload/pathogen.vim new file mode 100644 index 0000000..3582fbf --- /dev/null +++ b/.vim/autoload/pathogen.vim @@ -0,0 +1,264 @@ +" 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() 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. +" If no arguments are given, defaults "bundle/{}", and also "pack/{}/start/{}" +" on versions of Vim without native package support. +function! pathogen#infect(...) abort + if a:0 + let paths = filter(reverse(copy(a:000)), 'type(v:val) == type("")') + else + let paths = ['bundle/{}', 'pack/{}/start/{}'] + endif + if has('packages') + call filter(paths, 'v:val !~# "^pack/[^/]*/start/[^/]*$"') + endif + let static = '^\%([$~\\/]\|\w:[\\/]\)[^{}*]*$' + for path in filter(copy(paths), 'v:val =~# static') + call pathogen#surround(path) + endfor + for path in filter(copy(paths), 'v:val !~# static') + if path =~# '^\%([$~\\/]\|\w:[\\/]\)' + call pathogen#surround(path) + else + 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 + +" 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/vim-easy-align/autoload/easy_align.vim b/.vim/bundle/vim-easy-align/autoload/easy_align.vim new file mode 100644 index 0000000..795ea31 --- /dev/null +++ b/.vim/bundle/vim-easy-align/autoload/easy_align.vim @@ -0,0 +1,1148 @@ +" Copyright (c) 2014 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. + +if exists("g:loaded_easy_align") + finish +endif +let g:loaded_easy_align = 1 + +let s:cpo_save = &cpo +set cpo&vim + +let s:easy_align_delimiters_default = { +\ ' ': { 'pattern': ' ', 'left_margin': 0, 'right_margin': 0, 'stick_to_left': 0 }, +\ '=': { 'pattern': '===\|<=>\|\(&&\|||\|<<\|>>\)=\|=\~[#?]\?\|=>\|[:+/*!%^=><&|.?-]\?=[#?]\?', +\ 'left_margin': 1, 'right_margin': 1, 'stick_to_left': 0 }, +\ ':': { 'pattern': ':', 'left_margin': 0, 'right_margin': 1, 'stick_to_left': 1 }, +\ ',': { 'pattern': ',', 'left_margin': 0, 'right_margin': 1, 'stick_to_left': 1 }, +\ '|': { 'pattern': '|', 'left_margin': 1, 'right_margin': 1, 'stick_to_left': 0 }, +\ '.': { 'pattern': '\.', 'left_margin': 0, 'right_margin': 0, 'stick_to_left': 0 }, +\ '#': { 'pattern': '#\+', 'delimiter_align': 'l', 'ignore_groups': ['!Comment'] }, +\ '"': { 'pattern': '"\+', 'delimiter_align': 'l', 'ignore_groups': ['!Comment'] }, +\ '&': { 'pattern': '\\\@ winlen ? '..' : '' + + echon "\r" + let yet = 0 + for [hl, msg] in a:tokens + if empty(msg) | continue | endif + execute "echohl ". hl + let yet += len(msg) + if yet > winlen - len(ellipsis) + echon msg[ 0 : (winlen - len(ellipsis) - yet - 1) ] . ellipsis + break + else + echon msg + endif + endfor + finally + echohl None + let [&ruler, &showcmd] = xy + endtry +endfunction + +function! s:echon(l, n, r, d, o, warn) + let tokens = [ + \ ['Function', s:live ? ':LiveEasyAlign' : ':EasyAlign'], + \ ['ModeMsg', get(s:mode_labels, a:l, a:l)], + \ ['None', ' ']] + + if a:r == -1 | call add(tokens, ['Comment', '(']) | endif + call add(tokens, [a:n =~ '*' ? 'Repeat' : 'Number', a:n]) + call extend(tokens, a:r == 1 ? + \ [['Delimiter', '/'], ['String', a:d], ['Delimiter', '/']] : + \ [['Identifier', a:d == ' ' ? '\ ' : (a:d == '\' ? '\\' : a:d)]]) + if a:r == -1 | call extend(tokens, [['Normal', '_'], ['Comment', ')']]) | endif + call add(tokens, ['Statement', empty(a:o) ? '' : ' '.string(a:o)]) + if !empty(a:warn) + call add(tokens, ['WarningMsg', ' ('.a:warn.')']) + endif + + call s:echon_(tokens) + return join(map(tokens, 'v:val[1]'), '') +endfunction + +function! s:exit(msg) + call s:echon_([['ErrorMsg', a:msg]]) + throw 'exit' +endfunction + +function! s:ltrim(str) + return substitute(a:str, '^\s\+', '', '') +endfunction + +function! s:rtrim(str) + return substitute(a:str, '\s\+$', '', '') +endfunction + +function! s:trim(str) + return substitute(a:str, '^\s*\(.\{-}\)\s*$', '\1', '') +endfunction + +function! s:fuzzy_lu(key) + if has_key(s:known_options, a:key) + return a:key + endif + let key = tolower(a:key) + + " stl -> ^s.*_t.*_l.* + let regexp1 = '^' .key[0]. '.*' .substitute(key[1 : -1], '\(.\)', '_\1.*', 'g') + let matches = filter(keys(s:known_options), 'v:val =~ regexp1') + if len(matches) == 1 + return matches[0] + endif + + " stl -> ^s.*t.*l.* + let regexp2 = '^' . substitute(substitute(key, '-', '_', 'g'), '\(.\)', '\1.*', 'g') + let matches = filter(keys(s:known_options), 'v:val =~ regexp2') + + if empty(matches) + call s:exit("Unknown option key: ". a:key) + elseif len(matches) == 1 + return matches[0] + else + " Avoid ambiguity introduced by deprecated margin_left and margin_right + if sort(matches) == ['margin_left', 'margin_right', 'mode_sequence'] + return 'mode_sequence' + endif + if sort(matches) == ['ignore_groups', 'ignores'] + return 'ignore_groups' + endif + call s:exit("Ambiguous option key: ". a:key ." (" .join(matches, ', '). ")") + endif +endfunction + +function! s:shift(modes, cycle) + let item = remove(a:modes, 0) + if a:cycle || empty(a:modes) + call add(a:modes, item) + endif + return item +endfunction + +function! s:normalize_options(opts) + let ret = {} + for k in keys(a:opts) + let v = a:opts[k] + let k = s:fuzzy_lu(k) + " Backward-compatibility + if k == 'margin_left' | let k = 'left_margin' | endif + if k == 'margin_right' | let k = 'right_margin' | endif + if k == 'mode_sequence' | let k = 'align' | endif + let ret[k] = v + unlet v + endfor + return s:validate_options(ret) +endfunction + +function! s:compact_options(opts) + let ret = {} + for k in keys(a:opts) + let ret[s:shorthand[k]] = a:opts[k] + endfor + return ret +endfunction + +function! s:validate_options(opts) + for k in keys(a:opts) + let v = a:opts[k] + if index(s:known_options[k], type(v)) == -1 + call s:exit("Invalid type for option: ". k) + endif + unlet v + endfor + return a:opts +endfunction + +function! s:split_line(line, nth, modes, cycle, fc, lc, pattern, stick_to_left, ignore_unmatched, ignore_groups) + let mode = '' + + let string = a:lc ? + \ strpart(getline(a:line), a:fc - 1, a:lc - a:fc + 1) : + \ strpart(getline(a:line), a:fc - 1) + let idx = 0 + let nomagic = match(a:pattern, '\\v') > match(a:pattern, '\C\\[mMV]') + let pattern = '^.\{-}\s*\zs\('.a:pattern.(nomagic ? ')' : '\)') + let tokens = [] + let delims = [] + + " Phase 1: split + let ignorable = 0 + let token = '' + let phantom = 0 + while 1 + let matchidx = match(string, pattern, idx) + " No match + if matchidx < 0 | break | endif + let matchend = matchend(string, pattern, idx) + let spaces = matchstr(string, '\s'.(a:stick_to_left ? '*' : '\{-}'), matchend + (matchidx == matchend)) + + " Match, but empty + if len(spaces) + matchend - idx == 0 + let char = strpart(string, idx, 1) + if empty(char) | break | endif + let [match, part, delim] = [char, char, ''] + " Match + else + let match = strpart(string, idx, matchend - idx + len(spaces)) + let part = strpart(string, idx, matchidx - idx) + let delim = strpart(string, matchidx, matchend - matchidx) + endif + + let ignorable = s:highlighted_as(a:line, idx + len(part) + a:fc, a:ignore_groups) + if ignorable + let token .= match + else + let [pmode, mode] = [mode, s:shift(a:modes, a:cycle)] + call add(tokens, token . match) + call add(delims, delim) + let token = '' + endif + + let idx += len(match) + + " If the string is non-empty and ends with the delimiter, + " append an empty token to the list + if idx == len(string) + let phantom = 1 + break + endif + endwhile + + let leftover = token . strpart(string, idx) + if !empty(leftover) + let ignorable = s:highlighted_as(a:line, len(string) + a:fc - 1, a:ignore_groups) + call add(tokens, leftover) + call add(delims, '') + elseif phantom + call add(tokens, '') + call add(delims, '') + endif + let [pmode, mode] = [mode, s:shift(a:modes, a:cycle)] + + " Preserve indentation - merge first two tokens + if len(tokens) > 1 && empty(s:rtrim(tokens[0])) + let tokens[1] = tokens[0] . tokens[1] + call remove(tokens, 0) + call remove(delims, 0) + let mode = pmode + endif + + " Skip comment line + if ignorable && len(tokens) == 1 && a:ignore_unmatched + let tokens = [] + let delims = [] + " Append an empty item to enable right/center alignment of the last token + " - if the last token is not ignorable or ignorable but not the only token + elseif a:ignore_unmatched != 1 && + \ (mode ==? 'r' || mode ==? 'c') && + \ (!ignorable || len(tokens) > 1) && + \ a:nth >= 0 " includes -0 + call add(tokens, '') + call add(delims, '') + endif + + return [tokens, delims] +endfunction + +function! s:do_align(todo, modes, all_tokens, all_delims, fl, ll, fc, lc, nth, recur, dict) + let mode = a:modes[0] + let lines = {} + let min_indent = -1 + let max = { 'pivot_len2': 0, 'token_len': 0, 'just_len': 0, 'delim_len': 0, + \ 'indent': 0, 'tokens': 0, 'strip_len': 0 } + let d = a:dict + let [f, fx] = s:parse_filter(d.filter) + + " Phase 1 + for line in range(a:fl, a:ll) + let snip = a:lc > 0 ? getline(line)[a:fc-1 : a:lc-1] : getline(line) + if f == 1 && snip !~ fx + continue + elseif f == -1 && snip =~ fx + continue + endif + + if !has_key(a:all_tokens, line) + " Split line into the tokens by the delimiters + let [tokens, delims] = s:split_line( + \ line, a:nth, copy(a:modes), a:recur == 2, + \ a:fc, a:lc, d.pattern, + \ d.stick_to_left, d.ignore_unmatched, d.ignore_groups) + + " Remember tokens for subsequent recursive calls + let a:all_tokens[line] = tokens + let a:all_delims[line] = delims + else + let tokens = a:all_tokens[line] + let delims = a:all_delims[line] + endif + + " Skip empty lines + if empty(tokens) + continue + endif + + " Calculate the maximum number of tokens for a line within the range + let max.tokens = max([max.tokens, len(tokens)]) + + if a:nth > 0 " Positive N-th + if len(tokens) < a:nth + continue + endif + let nth = a:nth - 1 " make it 0-based + else " -0 or Negative N-th + if a:nth == 0 && mode !=? 'l' + let nth = len(tokens) - 1 + else + let nth = len(tokens) + a:nth + endif + if empty(delims[len(delims) - 1]) + let nth -= 1 + endif + + if nth < 0 || nth == len(tokens) + continue + endif + endif + + let prefix = nth > 0 ? join(tokens[0 : nth - 1], '') : '' + let delim = delims[nth] + let token = s:rtrim( tokens[nth] ) + let token = s:rtrim( strpart(token, 0, len(token) - len(s:rtrim(delim))) ) + if empty(delim) && !exists('tokens[nth + 1]') && d.ignore_unmatched + continue + endif + + let indent = s:strwidth(matchstr(tokens[0], '^\s*')) + if min_indent < 0 || indent < min_indent + let min_indent = indent + endif + if mode ==? 'c' + let token .= substitute(matchstr(token, '^\s*'), '\t', repeat(' ', &tabstop), 'g') + endif + let [pw, tw] = [s:strwidth(prefix), s:strwidth(token)] + let max.indent = max([max.indent, indent]) + let max.token_len = max([max.token_len, tw]) + let max.just_len = max([max.just_len, pw + tw]) + let max.delim_len = max([max.delim_len, s:strwidth(delim)]) + + if mode ==? 'c' + let pivot_len2 = pw * 2 + tw + if max.pivot_len2 < pivot_len2 + let max.pivot_len2 = pivot_len2 + endif + let max.strip_len = max([max.strip_len, s:strwidth(s:trim(token))]) + endif + let lines[line] = [nth, prefix, token, delim] + endfor + + " Phase 1-5: indentation handling (only on a:nth == 1) + if a:nth == 1 + let idt = d.indentation + if idt ==? 'd' + let indent = max.indent + elseif idt ==? 's' + let indent = min_indent + elseif idt ==? 'n' + let indent = 0 + elseif idt !=? 'k' + call s:exit('Invalid indentation: ' . idt) + end + + if idt !=? 'k' + let max.just_len = 0 + let max.token_len = 0 + let max.pivot_len2 = 0 + + for [line, elems] in items(lines) + let [nth, prefix, token, delim] = elems + + let tindent = matchstr(token, '^\s*') + while 1 + let len = s:strwidth(tindent) + if len < indent + let tindent .= repeat(' ', indent - len) + break + elseif len > indent + let tindent = tindent[0 : -2] + else + break + endif + endwhile + + let token = tindent . s:ltrim(token) + if mode ==? 'c' + let token = substitute(token, '\s*$', repeat(' ', indent), '') + endif + let [pw, tw] = [s:strwidth(prefix), s:strwidth(token)] + let max.token_len = max([max.token_len, tw]) + let max.just_len = max([max.just_len, pw + tw]) + if mode ==? 'c' + let pivot_len2 = pw * 2 + tw + if max.pivot_len2 < pivot_len2 + let max.pivot_len2 = pivot_len2 + endif + endif + + let lines[line][2] = token + endfor + endif + endif + + " Phase 2 + for [line, elems] in items(lines) + let tokens = a:all_tokens[line] + let delims = a:all_delims[line] + let [nth, prefix, token, delim] = elems + + " Remove the leading whitespaces of the next token + if len(tokens) > nth + 1 + let tokens[nth + 1] = s:ltrim(tokens[nth + 1]) + endif + + " Pad the token with spaces + let [pw, tw] = [s:strwidth(prefix), s:strwidth(token)] + let rpad = '' + if mode ==? 'l' + let pad = repeat(' ', max.just_len - pw - tw) + if d.stick_to_left + let rpad = pad + else + let token = token . pad + endif + elseif mode ==? 'r' + let pad = repeat(' ', max.just_len - pw - tw) + let indent = matchstr(token, '^\s*') + let token = indent . pad . s:ltrim(token) + elseif mode ==? 'c' + let p1 = max.pivot_len2 - (pw * 2 + tw) + let p2 = max.token_len - tw + let pf1 = s:floor2(p1) + if pf1 < p1 | let p2 = s:ceil2(p2) + else | let p2 = s:floor2(p2) + endif + let strip = s:ceil2(max.token_len - max.strip_len) / 2 + let indent = matchstr(token, '^\s*') + let token = indent. repeat(' ', pf1 / 2) .s:ltrim(token). repeat(' ', p2 / 2) + let token = substitute(token, repeat(' ', strip) . '$', '', '') + + if d.stick_to_left + if empty(s:rtrim(token)) + let center = len(token) / 2 + let [token, rpad] = [strpart(token, 0, center), strpart(token, center)] + else + let [token, rpad] = [s:rtrim(token), matchstr(token, '\s*$')] + endif + endif + endif + let tokens[nth] = token + + " Pad the delimiter + let dpadl = max.delim_len - s:strwidth(delim) + let da = d.delimiter_align + if da ==? 'l' + let [dl, dr] = ['', repeat(' ', dpadl)] + elseif da ==? 'c' + let dl = repeat(' ', dpadl / 2) + let dr = repeat(' ', dpadl - dpadl / 2) + elseif da ==? 'r' + let [dl, dr] = [repeat(' ', dpadl), ''] + else + call s:exit('Invalid delimiter_align: ' . da) + endif + + " Before and after the range (for blockwise visual mode) + let cline = getline(line) + let before = strpart(cline, 0, a:fc - 1) + let after = a:lc ? strpart(cline, a:lc) : '' + + " Determine the left and right margin around the delimiter + let rest = join(tokens[nth + 1 : -1], '') + let nomore = empty(rest.after) + let ml = (empty(prefix . token) || empty(delim) && nomore) ? '' : d.ml + let mr = nomore ? '' : d.mr + + " Adjust indentation of the lines starting with a delimiter + let lpad = '' + if nth == 0 + let ipad = repeat(' ', min_indent - s:strwidth(token.ml)) + if mode ==? 'l' + let token = ipad . token + else + let lpad = ipad + endif + endif + + " Align the token + let aligned = join([lpad, token, ml, dl, delim, dr, mr, rpad], '') + let tokens[nth] = aligned + + " Update the line + let a:todo[line] = before.join(tokens, '').after + endfor + + if a:nth < max.tokens && (a:recur || len(a:modes) > 1) + call s:shift(a:modes, a:recur == 2) + return [a:todo, a:modes, a:all_tokens, a:all_delims, + \ a:fl, a:ll, a:fc, a:lc, a:nth + 1, a:recur, a:dict] + endif + return [a:todo] +endfunction + +function! s:input(str, default, vis) + if a:vis + normal! gv + redraw + execute "normal! \" + else + " EasyAlign command can be called without visual selection + redraw + endif + let got = input(a:str, a:default) + return got +endfunction + +function! s:atoi(str) + return (a:str =~ '^[0-9]\+$') ? str2nr(a:str) : a:str +endfunction + +function! s:shift_opts(opts, key, vals) + let val = s:shift(a:vals, 1) + if type(val) == 0 && val == -1 + call remove(a:opts, a:key) + else + let a:opts[a:key] = val + endif +endfunction + +function! s:interactive(range, modes, n, d, opts, rules, vis, bvis) + let mode = s:shift(a:modes, 1) + let n = a:n + let d = a:d + let ch = '' + let opts = s:compact_options(a:opts) + let vals = deepcopy(s:option_values) + let regx = 0 + let warn = '' + let undo = 0 + + while 1 + " Live preview + let rdrw = 0 + if undo + silent! undo + let undo = 0 + let rdrw = 1 + endif + if s:live && !empty(d) + let output = s:process(a:range, mode, n, d, s:normalize_options(opts), regx, a:rules, a:bvis) + let &undolevels = &undolevels " Break undo block + call s:update_lines(output.todo) + let undo = !empty(output.todo) + let rdrw = 1 + endif + if rdrw + if a:vis + normal! gv + endif + redraw + if a:vis | execute "normal! \" | endif + endif + call s:echon(mode, n, -1, regx ? '/'.d.'/' : d, opts, warn) + + let check = 0 + let warn = '' + + try + let c = getchar() + catch /^Vim:Interrupt$/ + let c = 27 + endtry + let ch = nr2char(c) + if c == 3 || c == 27 " CTRL-C / ESC + if undo + silent! undo + endif + throw 'exit' + elseif c == "\" + if !empty(d) + let d = '' + let regx = 0 + elseif len(n) > 0 + let n = strpart(n, 0, len(n) - 1) + endif + elseif c == 13 " Enter key + let mode = s:shift(a:modes, 1) + if has_key(opts, 'a') + let opts.a = mode . strpart(opts.a, 1) + endif + elseif ch == '-' + if empty(n) | let n = '-' + elseif n == '-' | let n = '' + else | let check = 1 + endif + elseif ch == '*' + if empty(n) | let n = '*' + elseif n == '*' | let n = '**' + elseif n == '**' | let n = '' + else | let check = 1 + endif + elseif empty(d) && ((c == 48 && len(n) > 0) || c > 48 && c <= 57) " Numbers + if n[0] == '*' | let check = 1 + else | let n = n . ch + end + elseif ch == "\" + call s:shift_opts(opts, 'da', vals['delimiter_align']) + elseif ch == "\" + call s:shift_opts(opts, 'idt', vals['indentation']) + elseif ch == "\" + let lm = s:input("Left margin: ", get(opts, 'lm', ''), a:vis) + if empty(lm) + let warn = 'Set to default. Input 0 to remove it' + silent! call remove(opts, 'lm') + else + let opts['lm'] = s:atoi(lm) + endif + elseif ch == "\" + let rm = s:input("Right margin: ", get(opts, 'rm', ''), a:vis) + if empty(rm) + let warn = 'Set to default. Input 0 to remove it' + silent! call remove(opts, 'rm') + else + let opts['rm'] = s:atoi(rm) + endif + elseif ch == "\" + call s:shift_opts(opts, 'iu', vals['ignore_unmatched']) + elseif ch == "\" + call s:shift_opts(opts, 'ig', vals['ignore_groups']) + elseif ch == "\" + if s:live + if !empty(d) + let ch = d + break + else + let s:live = 0 + endif + else + let s:live = 1 + endif + elseif c == "\" + let opts['stl'] = 1 + let opts['lm'] = 0 + elseif c == "\" + let opts['stl'] = 0 + let opts['lm'] = 1 + elseif c == "\" + let opts['lm'] = 0 + let opts['rm'] = 0 + elseif c == "\" + silent! call remove(opts, 'stl') + silent! call remove(opts, 'lm') + silent! call remove(opts, 'rm') + elseif ch == "\" || ch == "\" + let modes = tolower(s:input("Alignment ([lrc...][[*]*]): ", get(opts, 'a', mode), a:vis)) + if match(modes, '^[lrc]\+\*\{0,2}$') != -1 + let opts['a'] = modes + let mode = modes[0] + while mode != s:shift(a:modes, 1) + endwhile + else + silent! call remove(opts, 'a') + endif + elseif ch == "\" || ch == "\" + if s:live && regx && !empty(d) + break + endif + + let prompt = 'Regular expression: ' + let ch = s:input(prompt, '', a:vis) + if !empty(ch) && s:valid_regexp(ch) + let regx = 1 + let d = ch + if !s:live | break | endif + else + let warn = 'Invalid regular expression: '.ch + endif + elseif ch == "\" + let f = s:input("Filter (g/../ or v/../): ", get(opts, 'f', ''), a:vis) + let m = matchlist(f, '^[gv]/\(.\{-}\)/\?$') + if empty(f) + silent! call remove(opts, 'f') + elseif !empty(m) && s:valid_regexp(m[1]) + let opts['f'] = f + else + let warn = 'Invalid filter expression' + endif + elseif ch =~ '[[:print:]]' + let check = 1 + else + let warn = 'Invalid character' + endif + + if check + if empty(d) + if has_key(a:rules, ch) + let d = ch + if !s:live + if a:vis + execute "normal! gv\" + endif + break + endif + else + let warn = 'Unknown delimiter key: '.ch + endif + else + if regx + let warn = 'Press to finish' + else + if d == ch + break + else + let warn = 'Press '''.d.''' again to finish' + endif + end + endif + endif + endwhile + if s:live + let copts = call('s:summarize', output.summarize) + let s:live = 0 + let g:easy_align_last_command = s:echon('', n, regx, d, copts, '') + let s:live = 1 + end + return [mode, n, ch, opts, regx] +endfunction + +function! s:valid_regexp(regexp) + try + call matchlist('', a:regexp) + catch + return 0 + endtry + return 1 +endfunction + +function! s:test_regexp(regexp) + let regexp = empty(a:regexp) ? @/ : a:regexp + if !s:valid_regexp(regexp) + call s:exit('Invalid regular expression: '. regexp) + endif + return regexp +endfunction + +let s:shorthand_regex = + \ '\s*\%(' + \ .'\(lm\?[0-9]\+\)\|\(rm\?[0-9]\+\)\|\(iu[01]\)\|\(\%(s\%(tl\)\?[01]\)\|[<>]\)\|' + \ .'\(da\?[clr]\)\|\(\%(ms\?\|a\)[lrc*]\+\)\|\(i\%(dt\)\?[kdsn]\)\|\([gv]/.*/\)\|\(ig\[.*\]\)' + \ .'\)\+\s*$' + +function! s:parse_shorthand_opts(expr) + let opts = {} + let expr = substitute(a:expr, '\s', '', 'g') + let regex = '^'. s:shorthand_regex + + if empty(expr) + return opts + elseif expr !~ regex + call s:exit("Invalid expression: ". a:expr) + else + let match = matchlist(expr, regex) + for m in filter(match[ 1 : -1 ], '!empty(v:val)') + for key in ['lm', 'rm', 'l', 'r', 'stl', 's', '<', '>', 'iu', 'da', 'd', 'ms', 'm', 'ig', 'i', 'g', 'v', 'a'] + if stridx(tolower(m), key) == 0 + let rest = strpart(m, len(key)) + if key == 'i' | let key = 'idt' | endif + if key == 'g' || key == 'v' + let rest = key.rest + let key = 'f' + endif + + if key == 'idt' || index(['d', 'f', 'm', 'a'], key[0]) >= 0 + let opts[key] = rest + elseif key == 'ig' + try + let arr = eval(rest) + if type(arr) == 3 + let opts[key] = arr + else + throw 'Not an array' + endif + catch + call s:exit("Invalid ignore_groups: ". a:expr) + endtry + elseif key =~ '[<>]' + let opts['stl'] = key == '<' + else + let opts[key] = str2nr(rest) + endif + break + endif + endfor + endfor + endif + return s:normalize_options(opts) +endfunction + +function! s:parse_args(args) + if empty(a:args) + return ['', '', {}, 0] + endif + let n = '' + let ch = '' + let args = a:args + let cand = '' + let opts = {} + + " Poor man's option parser + let idx = 0 + while 1 + let midx = match(args, '\s*{.*}\s*$', idx) + if midx == -1 | break | endif + + let cand = strpart(args, midx) + try + let [l, r, c, k, s, d, n] = ['l', 'r', 'c', 'k', 's', 'd', 'n'] + let [L, R, C, K, S, D, N] = ['l', 'r', 'c', 'k', 's', 'd', 'n'] + let o = eval(cand) + if type(o) == 4 + let opts = o + if args[midx - 1 : midx] == '\ ' + let midx += 1 + endif + let args = strpart(args, 0, midx) + break + endif + catch + " Ignore + endtry + let idx = midx + 1 + endwhile + + " Invalid option dictionary + if len(substitute(cand, '\s', '', 'g')) > 2 && empty(opts) + call s:exit("Invalid option: ". cand) + else + let opts = s:normalize_options(opts) + endif + + " Shorthand option notation + let sopts = matchstr(args, s:shorthand_regex) + if !empty(sopts) + let args = strpart(args, 0, len(args) - len(sopts)) + let opts = extend(s:parse_shorthand_opts(sopts), opts) + endif + + " Has /Regexp/? + let matches = matchlist(args, '^\(.\{-}\)\s*/\(.*\)/\s*$') + + " Found regexp + if !empty(matches) + return [matches[1], s:test_regexp(matches[2]), opts, 1] + else + let tokens = matchlist(args, '^\([1-9][0-9]*\|-[0-9]*\|\*\*\?\)\?\s*\(.\{-}\)\?$') + " Try swapping n and ch + let [n, ch] = empty(tokens[2]) ? reverse(tokens[1:2]) : tokens[1:2] + + " Resolving command-line ambiguity + " '\ ' => ' ' + " '\' => ' ' + if ch =~ '^\\\s*$' + let ch = ' ' + " '\\' => '\' + elseif ch =~ '^\\\\\s*$' + let ch = '\' + endif + + return [n, ch, opts, 0] + endif +endfunction + +function! s:parse_filter(f) + let m = matchlist(a:f, '^\([gv]\)/\(.\{-}\)/\?$') + if empty(m) + return [0, ''] + else + return [m[1] == 'g' ? 1 : -1, m[2]] + endif +endfunction + +function! s:interactive_modes(bang) + return get(g:, + \ (a:bang ? 'easy_align_bang_interactive_modes' : 'easy_align_interactive_modes'), + \ (a:bang ? ['r', 'l', 'c'] : ['l', 'r', 'c'])) +endfunction + +function! s:alternating_modes(mode) + return a:mode ==? 'r' ? 'rl' : 'lr' +endfunction + +function! s:update_lines(todo) + for [line, content] in items(a:todo) + call setline(line, s:rtrim(content)) + endfor +endfunction + +function! s:parse_nth(n) + let n = a:n + let recur = 0 + if n == '*' | let [nth, recur] = [1, 1] + elseif n == '**' | let [nth, recur] = [1, 2] + elseif n == '-' | let nth = -1 + elseif empty(n) | let nth = 1 + elseif n == '0' || ( n != '-0' && n != string(str2nr(n)) ) + call s:exit('Invalid N-th parameter: '. n) + else + let nth = n + endif + return [nth, recur] +endfunction + +function! s:build_dict(delimiters, ch, regexp, opts) + if a:regexp + let dict = { 'pattern': a:ch } + else + if !has_key(a:delimiters, a:ch) + call s:exit('Unknown delimiter key: '. a:ch) + endif + let dict = copy(a:delimiters[a:ch]) + endif + call extend(dict, a:opts) + + let ml = get(dict, 'left_margin', ' ') + let mr = get(dict, 'right_margin', ' ') + if type(ml) == 0 | let ml = repeat(' ', ml) | endif + if type(mr) == 0 | let mr = repeat(' ', mr) | endif + call extend(dict, { 'ml': ml, 'mr': mr }) + + let dict.pattern = get(dict, 'pattern', a:ch) + let dict.delimiter_align = + \ get(dict, 'delimiter_align', get(g:, 'easy_align_delimiter_align', 'r'))[0] + let dict.indentation = + \ get(dict, 'indentation', get(g:, 'easy_align_indentation', 'k'))[0] + let dict.stick_to_left = + \ get(dict, 'stick_to_left', 0) + let dict.ignore_unmatched = + \ get(dict, 'ignore_unmatched', get(g:, 'easy_align_ignore_unmatched', 2)) + let dict.ignore_groups = + \ get(dict, 'ignore_groups', get(dict, 'ignores', s:ignored_syntax())) + let dict.filter = + \ get(dict, 'filter', '') + return dict +endfunction + +function! s:build_mode_sequence(expr, recur) + let [expr, recur] = [a:expr, a:recur] + let suffix = matchstr(a:expr, '\*\+$') + if suffix == '*' + let expr = expr[0 : -2] + let recur = 1 + elseif suffix == '**' + let expr = expr[0 : -3] + let recur = 2 + endif + return [tolower(expr), recur] +endfunction + +function! s:process(range, mode, n, ch, opts, regexp, rules, bvis) + let [nth, recur] = s:parse_nth((empty(a:n) && exists('g:easy_align_nth')) ? g:easy_align_nth : a:n) + let dict = s:build_dict(a:rules, a:ch, a:regexp, a:opts) + let [mode_sequence, recur] = s:build_mode_sequence( + \ get(dict, 'align', recur == 2 ? s:alternating_modes(a:mode) : a:mode), + \ recur) + + let ve = &virtualedit + set ve=all + let args = [ + \ {}, split(mode_sequence, '\zs'), + \ {}, {}, a:range[0], a:range[1], + \ a:bvis ? min([virtcol("'<"), virtcol("'>")]) : 1, + \ (!recur && a:bvis) ? max([virtcol("'<"), virtcol("'>")]) : 0, + \ nth, recur, dict ] + let &ve = ve + while len(args) > 1 + let args = call('s:do_align', args) + endwhile + + " todo: lines to update + " summarize: arguments to s:summarize + return { 'todo': args[0], 'summarize': [ a:opts, recur, mode_sequence ] } +endfunction + +function s:summarize(opts, recur, mode_sequence) + let copts = s:compact_options(a:opts) + let nbmode = s:interactive_modes(0)[0] + if !has_key(copts, 'a') && ( + \ (a:recur == 2 && s:alternating_modes(nbmode) != a:mode_sequence) || + \ (a:recur != 2 && (a:mode_sequence[0] != nbmode || len(a:mode_sequence) > 1)) + \ ) + call extend(copts, { 'a': a:mode_sequence }) + endif + return copts +endfunction + +function! s:align(bang, live, visualmode, first_line, last_line, expr) + " Heuristically determine if the user was in visual mode + if a:visualmode == 'command' + let vis = a:first_line == line("'<") && a:last_line == line("'>") + let bvis = vis && visualmode() == "\" + elseif empty(a:visualmode) + let vis = 0 + let bvis = 0 + else + let vis = 1 + let bvis = a:visualmode == "\" + end + let range = [a:first_line, a:last_line] + let modes = s:interactive_modes(a:bang) + let mode = modes[0] + let s:live = a:live + + let rules = s:easy_align_delimiters_default + if exists('g:easy_align_delimiters') + let rules = extend(copy(rules), g:easy_align_delimiters) + endif + + let [n, ch, opts, regexp] = s:parse_args(a:expr) + + let bypass_fold = get(g:, 'easy_align_bypass_fold', 0) + let ofm = &l:foldmethod + try + if bypass_fold | let &l:foldmethod = 'manual' | endif + + if empty(n) && empty(ch) || s:live + let [mode, n, ch, opts, regexp] = s:interactive(range, copy(modes), n, ch, opts, rules, vis, bvis) + endif + + if !s:live + let output = s:process(range, mode, n, ch, s:normalize_options(opts), regexp, rules, bvis) + call s:update_lines(output.todo) + let copts = call('s:summarize', output.summarize) + let g:easy_align_last_command = s:echon('', n, regexp, ch, copts, '') + endif + finally + if bypass_fold | let &l:foldmethod = ofm | endif + endtry +endfunction + +function! easy_align#align(bang, live, visualmode, expr) range + try + call s:align(a:bang, a:live, a:visualmode, a:firstline, a:lastline, a:expr) + catch /^\%(Vim:Interrupt\|exit\)$/ + if empty(a:visualmode) + echon "\r" + echon "\r" + else + normal! gv + endif + endtry +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + diff --git a/.vim/bundle/vim-easy-align/doc/easy_align.txt b/.vim/bundle/vim-easy-align/doc/easy_align.txt new file mode 100644 index 0000000..5a82e5e --- /dev/null +++ b/.vim/bundle/vim-easy-align/doc/easy_align.txt @@ -0,0 +1,891 @@ +easy-align.txt easy-align Last change: December 14 2014 +EASY-ALIGN - TABLE OF CONTENTS *easyalign* *easy-align* *easy-align-toc* +============================================================================== + + vim-easy-align + Demo |easy-align-1| + Features |easy-align-2| + Installation |easy-align-3| + TLDR - One-minute guide |easy-align-4| + Usage |easy-align-5| + Concept of alignment rule |easy-align-5-1| + Execution models |easy-align-5-2| + 1. Using mappings |easy-align-5-2-1| + 2. Using :EasyAlign command |easy-align-5-2-2| + Interactive mode |easy-align-5-3| + Predefined alignment rules |easy-align-5-3-1| + Examples |easy-align-5-3-2| + Using regular expressions |easy-align-5-3-3| + Alignment options in interactive mode |easy-align-5-3-4| + Live interactive mode |easy-align-5-4| + Non-interactive mode |easy-align-5-5| + Partial alignment in blockwise-visual mode |easy-align-5-6| + Alignment options |easy-align-6| + List of options |easy-align-6-1| + Filtering lines |easy-align-6-2| + Examples |easy-align-6-2-1| + Ignoring delimiters in comments or strings |easy-align-6-3| + Ignoring unmatched lines |easy-align-6-4| + Aligning delimiters of different lengths |easy-align-6-5| + Adjusting indentation |easy-align-6-6| + Alignments over multiple occurrences of delimiters |easy-align-6-7| + Extending alignment rules |easy-align-6-8| + Examples |easy-align-6-8-1| + Other options |easy-align-7| + Disabling &foldmethod during alignment |easy-align-7-1| + Left/right/center mode switch in interactive mode |easy-align-7-2| + Advanced examples and use cases |easy-align-8| + Related work |easy-align-9| + Author |easy-align-10| + License |easy-align-11| + + +VIM-EASY-ALIGN *vim-easy-align* +============================================================================== + +A simple, easy-to-use Vim alignment plugin. + + + *easy-align-1* +DEMO *easy-align-demo* +============================================================================== + +Screencast: +https://raw.githubusercontent.com/junegunn/i/master/vim-easy-align.gif + +(Too fast? Slower GIF is {here}{1}) + +{1} https://raw.githubusercontent.com/junegunn/i/master/vim-easy-align-slow.gif + + + *easy-align-2* +FEATURES *easy-align-features* +============================================================================== + + - Easy to use + - Comes with a predefined set of alignment rules + - Provides a fast and intuitive interface + - Extensible + - You can define your own rules + - Supports arbitrary regular expressions + - Optimized for code editing + - Takes advantage of syntax highlighting feature to avoid unwanted + alignments + + + *easy-align-3* +INSTALLATION *easy-align-installation* +============================================================================== + +Use your favorite plugin manager. + +Using {vim-plug}{2}: +> + Plug 'junegunn/vim-easy-align' +< + {2} https://github.com/junegunn/vim-plug + + + *easy-align-4* +TLDR - ONE-MINUTE GUIDE *easy-align-tldr-one-minute-guide* +============================================================================== + +Add the following mappings to your .vimrc. + + *(EasyAlign)* +> + " Start interactive EasyAlign in visual mode (e.g. vip) + vmap (EasyAlign) + + " Start interactive EasyAlign for a motion/text object (e.g. gaip) + nmap ga (EasyAlign) +< +And with the following lines of text, +> + apple =red + grass+=green + sky-= blue +< +try these commands: + + - vip= + - `v`isual-select `i`nner `p`aragraph + - Start EasyAlign command () + - Align around `=` + - `gaip=` + - Start EasyAlign command (`ga`) for `i`nner `p`aragraph + - Align around `=` + +Notice that the commands are repeatable with `.` key if you have installed +{repeat.vim}{3}. Install {visualrepeat}{4} as well if you want to repeat in +visual mode. + + {3} https://github.com/tpope/vim-repeat + {4} https://github.com/vim-scripts/visualrepeat + + + *easy-align-5* +USAGE *easy-align-usage* +============================================================================== + + +< Concept of alignment rule >_________________________________________________~ + *easy-align-concept-of-alignment-rule* + *easy-align-5-1* + +Though easy-align can align lines of text around any delimiter, it provides +shortcuts for the most common use cases with the concept of "alignment rule". + +An alignment rule is a predefined set of options for common alignment tasks, +which is identified by a single character, DELIMITER KEY, such as , +`=`, `:`, `.`, `|`, `&`, `#`, and `,`. + +Think of it as a shortcut. Instead of writing regular expression and setting +several options, you can just type in a single character. + + +< Execution models >__________________________________________________________~ + *easy-align-execution-models* + *easy-align-5-2* + +There are two ways to use easy-align. + + +1. Using mappings~ + *easy-align-1-using-plug-mappings* + *easy-align-5-2-1* + +The recommended method is to use mappings as described earlier. + + *(LiveEasyAlign)* + + ----------------------+--------+----------------------------------------------------- + Mapping | Mode | Description ~ + ----------------------+--------+----------------------------------------------------- + (EasyAlign) | normal | Start interactive mode for a motion/text object + (EasyAlign) | visual | Start interactive mode for the selection + (LiveEasyAlign) | normal | Start live-interactive mode for a motion/text object + (LiveEasyAlign) | visual | Start live-interactive mode for the selection + ----------------------+--------+----------------------------------------------------- + + +2. Using :EasyAlign command~ + *easy-align-2-using-easyalign-command* + *easy-align-5-2-2* + + *:EasyAlign* + +If you prefer command-line or do not want to start interactive mode, you can +use `:EasyAlign` command instead. + + *:LiveEasyAlign* + + -------------------------------------------+----------------------------------------------- + Mode | Command ~ + -------------------------------------------+----------------------------------------------- + Interactive mode | `:EasyAlign[!] [OPTIONS]` + Live interactive mode | `:LiveEasyAlign[!] [...]` + Non-interactive mode (predefined rules) | `:EasyAlign[!] [N-th] DELIMITER_KEY [OPTIONS]` + Non-interactive mode (regular expressions) | `:EasyAlign[!] [N-th] /REGEXP/ [OPTIONS]` + -------------------------------------------+----------------------------------------------- + + +< Interactive mode >__________________________________________________________~ + *easy-align-interactive-mode* + *easy-align-5-3* + +The following sections will assume that you have (EasyAlign) mappings in +your .vimrc as below: +> + " Start interactive EasyAlign in visual mode (e.g. vip) + vmap (EasyAlign) + + " Start interactive EasyAlign for a motion/text object (e.g. gaip) + nmap ga (EasyAlign) +< +With these mappings, you can align text with only a few keystrokes. + + 1. key in visual mode, or `ga` followed by a motion or a text object to + start interactive mode + 2. Optional: Enter keys to select alignment mode (left, right, or center) + 3. Optional: N-th delimiter (default: 1) + - `1` Around the 1st occurrences of delimiters + - `2` Around the 2nd occurrences of delimiters + - ... + - `*` Around all occurrences of delimiters + - `**` Left-right alternating alignment around all delimiters + - `-` Around the last occurrences of delimiters (`-1`) + - `-2` Around the second to last occurrences of delimiters + - ... + 4. Delimiter key (a single keystroke; , `=`, `:`, `.`, `|`, `&`, `#`, `,`) + + +Predefined alignment rules~ + *easy-align-predefined-alignment-rules* + *easy-align-5-3-1* + + --------------+-------------------------------------------------------------------- + Delimiter key | Description/Use cases ~ + --------------+-------------------------------------------------------------------- + | General alignment around whitespaces + `=` | Operators containing equals sign ( `=` , `==,` `!=` , `+=` , `&&=` , ...) + `:` | Suitable for formatting JSON or YAML + `.` | Multi-line method chaining + `,` | Multi-line method arguments + `&` | LaTeX tables (matches `&` and `\\` ) + `#` | Ruby/Python comments + `"` | Vim comments + | Table markdown + --------------+-------------------------------------------------------------------- + + *g:easy_align_delimiters* + +You can override these default rules or define your own rules with +`g:easy_align_delimiters`, which will be described in {the later section}{5}. + + {5} https://github.com/junegunn/vim-easy-align#extending-alignment-rules + + +Examples~ + *easy-align-examples* + *easy-align-5-3-2* + + ------------------+------------------------------------+-------------------- + With visual map | Description | Equivalent command ~ + ------------------+------------------------------------+-------------------- + | Around 1st whitespaces | :'<,'>EasyAlign\ + 2 | Around 2nd whitespaces | :'<,'>EasyAlign2\ + - | Around the last whitespaces | :'<,'>EasyAlign-\ + -2 | Around the 2nd to last whitespaces | :'<,'>EasyAlign-2\ + : | Around 1st colon ( `key: value` ) | :'<,'>EasyAlign: + : | Around 1st colon ( `key : value` ) | :'<,'>EasyAlign:= | Around 1st operators with = | :'<,'>EasyAlign= + 3= | Around 3rd operators with = | :'<,'>EasyAlign3= + *= | Around all operators with = | :'<,'>EasyAlign*= + **= | Left-right alternating around = | :'<,'>EasyAlign**= + = | Right alignment around 1st = | :'<,'>EasyAlign!= + **= | Right-left alternating around = | :'<,'>EasyAlign!**= + ------------------+------------------------------------+-------------------- + + +Using regular expressions~ + *easy-align-using-regular-expressions* + *easy-align-5-3-3* + +Instead of finishing the command with a predefined delimiter key, you can type +in a regular expression after CTRL-/ or CTRL-X key. For example, if you want +to align text around all occurrences of numbers: + + - + - `*` + - CTRL-X + - `[0-9]\+` + + +Alignment options in interactive mode~ + *easy-align-alignment-options-in-interactive-mode* + *easy-align-5-3-4* + +While in interactive mode, you can set alignment options using special +shortcut keys listed below. The meaning of each option will be described in +{the following sections}{6}. + + --------+--------------------+--------------------------------------------------- + Key | Option | Values ~ + --------+--------------------+--------------------------------------------------- + CTRL-F | `filter` | Input string ( `[gv]/.*/?` ) + CTRL-I | `indentation` | shallow, deep, none, keep + CTRL-L | `left_margin` | Input number or string + CTRL-R | `right_margin` | Input number or string + CTRL-D | `delimiter_align` | left, center, right + CTRL-U | `ignore_unmatched` | 0, 1 + CTRL-G | `ignore_groups` | [], ["String'], ["Comment'], ["String', "Comment'] + CTRL-A | `align` | Input string ( `/[lrc]+\*{0,2}/` ) + | `stick_to_left` | `{ 'stick_to_left': 1, 'left_margin': 0 }` + | `stick_to_left` | `{ 'stick_to_left': 0, 'left_margin': 1 }` + | `*_margin` | `{ 'left_margin': 0, 'right_margin': 0 }` + --------+--------------------+--------------------------------------------------- + + {6} https://github.com/junegunn/vim-easy-align#alignment-options + + +< Live interactive mode >_____________________________________________________~ + *easy-align-live-interactive-mode* + *easy-align-5-4* + +If you're performing a complex alignment where multiple options should be +carefully adjusted, try "live interactive mode" where you can preview the +result of the alignment on-the-fly as you type in. + +Live interactive mode can be started with either (LiveEasyAlign) map or +`:LiveEasyAlign` command. Or you can switch to live interactive mode while in +ordinary interactive mode by pressing CTRL-P. (P for Preview) + +In live interactive mode, you have to type in the same delimiter (or CTRL-X on +regular expression) again to finalize the alignment. This allows you to +preview the result of the alignment and freely change the delimiter using +backspace key without leaving the interactive mode. + + +< Non-interactive mode >______________________________________________________~ + *easy-align-non-interactive-mode* + *easy-align-5-5* + +Instead of starting interactive mode, you can use declarative, non-interactive +`:EasyAlign` command. +> + " Using predefined alignment rules + " :EasyAlign[!] [N-th] DELIMITER_KEY [OPTIONS] + :EasyAlign : + :EasyAlign = + :EasyAlign *= + :EasyAlign 3\ + + " Using arbitrary regular expressions + " :EasyAlign[!] [N-th] /REGEXP/ [OPTIONS] + :EasyAlign /[:;]\+/ + :EasyAlign 2/[:;]\+/ + :EasyAlign */[:;]\+/ + :EasyAlign **/[:;]\+/ +< +A command can end with alignment options, {each of which will be discussed in +detail later}{6}, in Vim dictionary format. + + - `:EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': 0 }` + +`stick_to_left` of 1 means that the matched delimiter should be positioned +right next to the preceding token, and `left_margin` of 0 removes the margin +on the left. So we get: +> + apple;: banana:: cake + data;; exchange:; format +< +Option names are fuzzy-matched, so you can write as follows: + + - `:EasyAlign * /[:;]\+/ { 'stl': 1, 'l': 0 }` + +You can even omit spaces between the arguments, so concisely (or cryptically): + + - `:EasyAlign*/[:;]\+/{'s':1,'l':0}` + +Nice. But let's make it even shorter. Option values can be written in +shorthand notation. + + - `:EasyAlign*/[:;]\+/` + `ignore_unmatched` | `iu[01]` + `ignore_groups` | `ig\[.*\]` + `align` | `a[lrc*]*` + `delimiter_align` | `d[lrc]` + `indentation` | `i[ksdn]` + -------------------+----------- + +For your information, the same operation can be done in interactive mode as +follows: + + - + - `*` + - + - CTRL-X + - `[:;]\+` + + {6} https://github.com/junegunn/vim-easy-align#alignment-options + + +< Partial alignment in blockwise-visual mode >________________________________~ + *easy-align-partial-alignment-in-blockwise-visual-mode* + *easy-align-5-6* + +In blockwise-visual mode (CTRL-V), EasyAlign command aligns only the selected +text in the block, instead of the whole lines in the range. + +Consider the following case where you want to align text around `=>` +operators. +> + my_hash = { :a => 1, + :aa => 2, + :aaa => 3 } +< +In non-blockwise visual mode (`v` / `V`), = won't work since the +assignment operator in the first line gets in the way. So we instead enter +blockwise-visual mode (CTRL-V), and select the text around`=>` operators, then +press =. +> + my_hash = { :a => 1, + :aa => 2, + :aaa => 3 } +< +However, in this case, we don't really need blockwise visual mode since the +same can be easily done using the negative N-th parameter: -= + + + *easy-align-6* +ALIGNMENT OPTIONS *easy-align-alignment-options* +============================================================================== + + +< List of options >___________________________________________________________~ + *easy-align-list-of-options* + *easy-align-6-1* + + -------------------+---------+-----------------------+-------------------------------------------------------- + Option | Type | Default | Description ~ + -------------------+---------+-----------------------+-------------------------------------------------------- + `filter` | string | | Line filtering expression: `g/../` or `v/../` + `left_margin` | number | 1 | Number of spaces to attach before delimiter + `left_margin` | string | `' '` | String to attach before delimiter + `right_margin` | number | 1 | Number of spaces to attach after delimiter + `right_margin` | string | `' '` | String to attach after delimiter + `stick_to_left` | boolean | 0 | Whether to position delimiter on the left-side + `ignore_groups` | list | ["String', "Comment'] | Delimiters in these syntax highlight groups are ignored + `ignore_unmatched` | boolean | 1 | Whether to ignore lines without matching delimiter + `indentation` | string | `k` | Indentation method (keep, deep, shallow, none) + `delimiter_align` | string | `r` | Determines how to align delimiters of different lengths + `align` | string | `l` | Alignment modes for multiple occurrences of delimiters + -------------------+---------+-----------------------+-------------------------------------------------------- + +There are 4 ways to set alignment options (from lowest precedence to highest): + + 1. Some option values can be set with corresponding global variables + 2. Option values can be specified in the definition of each alignment rule + 3. Option values can be given as arguments to `:EasyAlign` command + 4. Option values can be set in interactive mode using special shortcut keys + + *g:easy_align_ignore_groups* *g:easy_align_ignore_unmatched* + *g:easy_align_indentation* *g:easy_align_delimiter_align* + + -------------------+-----------------+-------------+-------------------------------- + Option name | Shortcut key | Abbreviated | Global variable ~ + -------------------+-----------------+-------------+-------------------------------- + `filter` | CTRL-F | `[gv]/.*/` | + `left_margin` | CTRL-L | `l[0-9]+` | + `right_margin` | CTRL-R | `r[0-9]+` | + `stick_to_left` | , | `<` or `>` | + `ignore_groups` | CTRL-G | `ig\[.*\]` | `g:easy_align_ignore_groups` + `ignore_unmatched` | CTRL-U | `iu[01]` | `g:easy_align_ignore_unmatched` + `indentation` | CTRL-I | `i[ksdn]` | `g:easy_align_indentation` + `delimiter_align` | CTRL-D | `d[lrc]` | `g:easy_align_delimiter_align` + `align` | CTRL-A | `a[lrc*]*` | + -------------------+-----------------+-------------+-------------------------------- + + +< Filtering lines >___________________________________________________________~ + *easy-align-filtering-lines* + *easy-align-6-2* + +With `filter` option, you can align lines that only match or do not match a +given pattern. There are several ways to set the pattern. + + 1. Press CTRL-F in interactive mode and type in `g/pat/` or `v/pat/` + 2. In command-line, it can be written in dictionary format: `{'filter': + 'g/pat/'}` + 3. Or in shorthand notation: `g/pat/` or `v/pat/` + +(You don't need to escape "/'s in the regular expression) + + +Examples~ + + *easy-align-6-2-1* +> + " Start interactive mode with filter option set to g/hello/ + EasyAlign g/hello/ + + " Start live interactive mode with filter option set to v/goodbye/ + LiveEasyAlign v/goodbye/ + + " Align the lines with 'hi' around the first colons + EasyAlign:g/hi/ +< + +< Ignoring delimiters in comments or strings >________________________________~ + *easy-align-ignoring-delimiters-in-comments-or-strings* + *easy-align-6-3* + +EasyAlign can be configured to ignore delimiters in certain syntax highlight +groups, such as code comments or strings. By default, delimiters that are +highlighted as code comments or strings are ignored. +> + " Default: + " If a delimiter is in a highlight group whose name matches + " any of the followings, it will be ignored. + let g:easy_align_ignore_groups = ['Comment', 'String'] +< +For example, the following paragraph +> + { + # Quantity of apples: 1 + apple: 1, + # Quantity of bananas: 2 + bananas: 2, + # Quantity of grape:fruits: 3 + 'grape:fruits': 3 + } +< +becomes as follows on : (or `:EasyAlign:`) +> + { + # Quantity of apples: 1 + apple: 1, + # Quantity of bananas: 2 + bananas: 2, + # Quantity of grape:fruits: 3 + 'grape:fruits': 3 + } +< +Naturally, this feature only works when syntax highlighting is enabled. + +You can change the default rule by using one of these 4 methods. + + 1. Press CTRL-G in interactive mode to switch groups + 2. Define global `g:easy_align_ignore_groups` list + 3. Define a custom rule in `g:easy_align_delimiters` with `ignore_groups` option + 4. Provide `ignore_groups` option to `:EasyAlign` command. e.g. `:EasyAlign:ig[]` + +For example if you set `ignore_groups` option to be an empty list, you get +> + { + # Quantity of apples: 1 + apple: 1, + # Quantity of bananas: 2 + bananas: 2, + # Quantity of grape: fruits: 3 + 'grape: fruits': 3 + } +< +If a pattern in `ignore_groups` is prepended by a `!`, it will have the +opposite meaning. For instance, if `ignore_groups` is given as `['!Comment']`, +delimiters that are not highlighted as Comment will be ignored during the +alignment. + + +< Ignoring unmatched lines >__________________________________________________~ + *easy-align-ignoring-unmatched-lines* + *easy-align-6-4* + +`ignore_unmatched` option determines how EasyAlign command processes lines +that do not have N-th delimiter. + + 1. In left-alignment mode, they are ignored + 2. In right or center-alignment mode, they are not ignored, and the last tokens + from those lines are aligned as well as if there is an invisible trailing + delimiter at the end of each line + 3. If `ignore_unmatched` is 1, they are ignored regardless of the alignment mode + 4. If `ignore_unmatched` is 0, they are not ignored regardless of the mode + +Let's take an example. When we align the following code block around the (1st) +colons, +> + { + apple: proc { + this_line_does_not_have_a_colon + }, + bananas: 2, + grapefruits: 3 + } +< +this is usually what we want. +> + { + apple: proc { + this_line_does_not_have_a_colon + }, + bananas: 2, + grapefruits: 3 + } +< +However, we can override this default behavior by setting `ignore_unmatched` +option to zero using one of the following methods. + + 1. Press CTRL-U in interactive mode to toggle `ignore_unmatched` option + 2. Set the global `g:easy_align_ignore_unmatched` variable to 0 + 3. Define a custom alignment rule with `ignore_unmatched` option set to 0 + 4. Provide `ignore_unmatched` option to `:EasyAlign` command. e.g. + `:EasyAlign:iu0` + +Then we get, +> + { + apple: proc { + this_line_does_not_have_a_colon + }, + bananas: 2, + grapefruits: 3 + } +< + +< Aligning delimiters of different lengths >__________________________________~ + *easy-align-aligning-delimiters-of-different-lengths* + *easy-align-6-5* + +Global `g:easy_align_delimiter_align` option and rule-wise/command-wise +`delimiter_align` option determines how matched delimiters of different +lengths are aligned. +> + apple = 1 + banana += apple + cake ||= banana +< +By default, delimiters are right-aligned as follows. +> + apple = 1 + banana += apple + cake ||= banana +< +However, with `:EasyAlign=dl`, delimiters are left-aligned. +> + apple = 1 + banana += apple + cake ||= banana +< +And on `:EasyAlign=dc`, center-aligned. +> + apple = 1 + banana += apple + cake ||= banana +< +In interactive mode, you can change the option value with CTRL-D key. + + +< Adjusting indentation >_____________________________________________________~ + *easy-align-adjusting-indentation* + *easy-align-6-6* + +By default :EasyAlign command keeps the original indentation of the lines. But +then again we have `indentation` option. See the following example. +> + # Lines with different indentation + apple = 1 + banana = 2 + cake = 3 + daisy = 4 + eggplant = 5 + + # Default: _k_eep the original indentation + # :EasyAlign= + apple = 1 + banana = 2 + cake = 3 + daisy = 4 + eggplant = 5 + + # Use the _s_hallowest indentation among the lines + # :EasyAlign=is + apple = 1 + banana = 2 + cake = 3 + daisy = 4 + eggplant = 5 + + # Use the _d_eepest indentation among the lines + # :EasyAlign=id + apple = 1 + banana = 2 + cake = 3 + daisy = 4 + eggplant = 5 + + # Indentation: _n_one + # :EasyAlign=in + apple = 1 + banana = 2 + cake = 3 + daisy = 4 + eggplant = 5 +< +In interactive mode, you can change the option value with CTRL-I key. + + +< Alignments over multiple occurrences of delimiters >________________________~ + *easy-align-alignments-over-multiple-occurrences-of-delimiters* + *easy-align-6-7* + +As stated above, "N-th" parameter is used to target specific occurrences of +the delimiter when it appears multiple times in each line. + +To recap: +> + " Left-alignment around the FIRST occurrences of delimiters + :EasyAlign = + + " Left-alignment around the SECOND occurrences of delimiters + :EasyAlign 2= + + " Left-alignment around the LAST occurrences of delimiters + :EasyAlign -= + + " Left-alignment around ALL occurrences of delimiters + :EasyAlign *= + + " Left-right ALTERNATING alignment around all occurrences of delimiters + :EasyAlign **= + + " Right-left ALTERNATING alignment around all occurrences of delimiters + :EasyAlign! **= +< +In addition to these, you can fine-tune alignments over multiple occurrences +of the delimiters with "align' option. (The option can also be set in +interactive mode with the special key CTRL-A) +> + " Left alignment over the first two occurrences of delimiters + :EasyAlign = { 'align': 'll' } + + " Right, left, center alignment over the 1st to 3rd occurrences of delimiters + :EasyAlign = { 'a': 'rlc' } + + " Using shorthand notation + :EasyAlign = arlc + + " Right, left, center alignment over the 2nd to 4th occurrences of delimiters + :EasyAlign 2=arlc + + " (*) Repeating alignments (default: l, r, or c) + " Right, left, center, center, center, center, ... + :EasyAlign *=arlc + + " (**) Alternating alignments (default: lr or rl) + " Right, left, center, right, left, center, ... + :EasyAlign **=arlc + + " Right, left, center, center, center, ... repeating alignment + " over the 3rd to the last occurrences of delimiters + :EasyAlign 3=arlc* + + " Right, left, center, right, left, center, ... alternating alignment + " over the 3rd to the last occurrences of delimiters + :EasyAlign 3=arlc** +< + +< Extending alignment rules >_________________________________________________~ + *easy-align-extending-alignment-rules* + *easy-align-6-8* + +Although the default rules should cover the most of the use cases, you can +extend the rules by setting a dictionary named `g:easy_align_delimiters`. + +You may refer to the definitions of the default alignment rules {here}{7}. + +{7} https://github.com/junegunn/vim-easy-align/blob/2.9.6/autoload/easy_align.vim#L32-L46 + + +Examples~ + + *easy-align-6-8-1* +> + let g:easy_align_delimiters = { + \ '>': { 'pattern': '>>\|=>\|>' }, + \ '/': { + \ 'pattern': '//\+\|/\*\|\*/', + \ 'delimiter_align': 'l', + \ 'ignore_groups': ['!Comment'] }, + \ ']': { + \ 'pattern': '[[\]]', + \ 'left_margin': 0, + \ 'right_margin': 0, + \ 'stick_to_left': 0 + \ }, + \ ')': { + \ 'pattern': '[()]', + \ 'left_margin': 0, + \ 'right_margin': 0, + \ 'stick_to_left': 0 + \ }, + \ 'd': { + \ 'pattern': ' \(\S\+\s*[;=]\)\@=', + \ 'left_margin': 0, + \ 'right_margin': 0 + \ } + \ } +< + + *easy-align-7* +OTHER OPTIONS *easy-align-other-options* +============================================================================== + + +< Disabling &foldmethod during alignment >____________________________________~ + *easy-align-disabling-foldmethod-during-alignment* + *easy-align-7-1* + + *g:easy_align_bypass_fold* + +{It is reported}{8} that 'foldmethod' value of `expr` or `syntax` can +significantly slow down the alignment when editing a large, complex file with +many folds. To alleviate this issue, EasyAlign provides an option to +temporarily set 'foldmethod' to `manual` during the alignment task. In order +to enable this feature, set `g:easy_align_bypass_fold` switch to 1. +> + let g:easy_align_bypass_fold = 1 +< + {8} https://github.com/junegunn/vim-easy-align/issues/14 + + +< Left/right/center mode switch in interactive mode >_________________________~ + *easy-align-left-right-center-mode-switch-in-interactive-mode* + *easy-align-7-2* + +In interactive mode, you can choose the alignment mode you want by pressing +enter keys. The non-bang command, `:EasyAlign` starts in left-alignment mode +and changes to right and center mode as you press enter keys, while the bang +version first starts in right-alignment mode. + + - `:EasyAlign` + - Left, Right, Center + - `:EasyAlign!` + - Right, Left, Center + +If you do not prefer this default mode transition, you can define your own +settings as follows. + + *g:easy_align_interactive_modes* *g:easy_align_bang_interactive_modes* +> + let g:easy_align_interactive_modes = ['l', 'r'] + let g:easy_align_bang_interactive_modes = ['c', 'r'] +< + + *easy-align-8* +ADVANCED EXAMPLES AND USE CASES *easy-align-advanced-examples-and-use-cases* +============================================================================== + +See {EXAMPLES.md}{9} for more examples. + + {9} https://github.com/junegunn/vim-easy-align/blob/master/EXAMPLES.md + + + *easy-align-9* +RELATED WORK *easy-align-related-work* +============================================================================== + + - {DrChip's Alignment Tool for Vim}{10} + - {Tabular}{11} + + {10} http://www.drchip.org/astronaut/vim/align.html + {11} https://github.com/godlygeek/tabular + + + *easy-align-10* +AUTHOR *easy-align-author* +============================================================================== + +{Junegunn Choi}{12} + + {12} https://github.com/junegunn + + + *easy-align-11* +LICENSE *easy-align-license* +============================================================================== + +MIT + +============================================================================== +vim:tw=78:sw=2:ts=2:ft=help:norl:nowrap: diff --git a/.vim/bundle/vim-easy-align/doc/tags b/.vim/bundle/vim-easy-align/doc/tags new file mode 100644 index 0000000..0411c5f --- /dev/null +++ b/.vim/bundle/vim-easy-align/doc/tags @@ -0,0 +1,84 @@ +:EasyAlign easy_align.txt /*:EasyAlign* +:LiveEasyAlign easy_align.txt /*:LiveEasyAlign* +(EasyAlign) easy_align.txt /*(EasyAlign)* +(LiveEasyAlign) easy_align.txt /*(LiveEasyAlign)* +easy-align easy_align.txt /*easy-align* +easy-align-1 easy_align.txt /*easy-align-1* +easy-align-1-using-plug-mappings easy_align.txt /*easy-align-1-using-plug-mappings* +easy-align-10 easy_align.txt /*easy-align-10* +easy-align-11 easy_align.txt /*easy-align-11* +easy-align-2 easy_align.txt /*easy-align-2* +easy-align-2-using-easyalign-command easy_align.txt /*easy-align-2-using-easyalign-command* +easy-align-3 easy_align.txt /*easy-align-3* +easy-align-4 easy_align.txt /*easy-align-4* +easy-align-5 easy_align.txt /*easy-align-5* +easy-align-5-1 easy_align.txt /*easy-align-5-1* +easy-align-5-2 easy_align.txt /*easy-align-5-2* +easy-align-5-2-1 easy_align.txt /*easy-align-5-2-1* +easy-align-5-2-2 easy_align.txt /*easy-align-5-2-2* +easy-align-5-3 easy_align.txt /*easy-align-5-3* +easy-align-5-3-1 easy_align.txt /*easy-align-5-3-1* +easy-align-5-3-2 easy_align.txt /*easy-align-5-3-2* +easy-align-5-3-3 easy_align.txt /*easy-align-5-3-3* +easy-align-5-3-4 easy_align.txt /*easy-align-5-3-4* +easy-align-5-4 easy_align.txt /*easy-align-5-4* +easy-align-5-5 easy_align.txt /*easy-align-5-5* +easy-align-5-6 easy_align.txt /*easy-align-5-6* +easy-align-6 easy_align.txt /*easy-align-6* +easy-align-6-1 easy_align.txt /*easy-align-6-1* +easy-align-6-2 easy_align.txt /*easy-align-6-2* +easy-align-6-2-1 easy_align.txt /*easy-align-6-2-1* +easy-align-6-3 easy_align.txt /*easy-align-6-3* +easy-align-6-4 easy_align.txt /*easy-align-6-4* +easy-align-6-5 easy_align.txt /*easy-align-6-5* +easy-align-6-6 easy_align.txt /*easy-align-6-6* +easy-align-6-7 easy_align.txt /*easy-align-6-7* +easy-align-6-8 easy_align.txt /*easy-align-6-8* +easy-align-6-8-1 easy_align.txt /*easy-align-6-8-1* +easy-align-7 easy_align.txt /*easy-align-7* +easy-align-7-1 easy_align.txt /*easy-align-7-1* +easy-align-7-2 easy_align.txt /*easy-align-7-2* +easy-align-8 easy_align.txt /*easy-align-8* +easy-align-9 easy_align.txt /*easy-align-9* +easy-align-adjusting-indentation easy_align.txt /*easy-align-adjusting-indentation* +easy-align-advanced-examples-and-use-cases easy_align.txt /*easy-align-advanced-examples-and-use-cases* +easy-align-aligning-delimiters-of-different-lengths easy_align.txt /*easy-align-aligning-delimiters-of-different-lengths* +easy-align-alignment-options easy_align.txt /*easy-align-alignment-options* +easy-align-alignment-options-in-interactive-mode easy_align.txt /*easy-align-alignment-options-in-interactive-mode* +easy-align-alignments-over-multiple-occurrences-of-delimiters easy_align.txt /*easy-align-alignments-over-multiple-occurrences-of-delimiters* +easy-align-author easy_align.txt /*easy-align-author* +easy-align-concept-of-alignment-rule easy_align.txt /*easy-align-concept-of-alignment-rule* +easy-align-demo easy_align.txt /*easy-align-demo* +easy-align-disabling-foldmethod-during-alignment easy_align.txt /*easy-align-disabling-foldmethod-during-alignment* +easy-align-examples easy_align.txt /*easy-align-examples* +easy-align-execution-models easy_align.txt /*easy-align-execution-models* +easy-align-extending-alignment-rules easy_align.txt /*easy-align-extending-alignment-rules* +easy-align-features easy_align.txt /*easy-align-features* +easy-align-filtering-lines easy_align.txt /*easy-align-filtering-lines* +easy-align-ignoring-delimiters-in-comments-or-strings easy_align.txt /*easy-align-ignoring-delimiters-in-comments-or-strings* +easy-align-ignoring-unmatched-lines easy_align.txt /*easy-align-ignoring-unmatched-lines* +easy-align-installation easy_align.txt /*easy-align-installation* +easy-align-interactive-mode easy_align.txt /*easy-align-interactive-mode* +easy-align-left-right-center-mode-switch-in-interactive-mode easy_align.txt /*easy-align-left-right-center-mode-switch-in-interactive-mode* +easy-align-license easy_align.txt /*easy-align-license* +easy-align-list-of-options easy_align.txt /*easy-align-list-of-options* +easy-align-live-interactive-mode easy_align.txt /*easy-align-live-interactive-mode* +easy-align-non-interactive-mode easy_align.txt /*easy-align-non-interactive-mode* +easy-align-other-options easy_align.txt /*easy-align-other-options* +easy-align-partial-alignment-in-blockwise-visual-mode easy_align.txt /*easy-align-partial-alignment-in-blockwise-visual-mode* +easy-align-predefined-alignment-rules easy_align.txt /*easy-align-predefined-alignment-rules* +easy-align-related-work easy_align.txt /*easy-align-related-work* +easy-align-tldr-one-minute-guide easy_align.txt /*easy-align-tldr-one-minute-guide* +easy-align-toc easy_align.txt /*easy-align-toc* +easy-align-usage easy_align.txt /*easy-align-usage* +easy-align-using-regular-expressions easy_align.txt /*easy-align-using-regular-expressions* +easyalign easy_align.txt /*easyalign* +g:easy_align_bang_interactive_modes easy_align.txt /*g:easy_align_bang_interactive_modes* +g:easy_align_bypass_fold easy_align.txt /*g:easy_align_bypass_fold* +g:easy_align_delimiter_align easy_align.txt /*g:easy_align_delimiter_align* +g:easy_align_delimiters easy_align.txt /*g:easy_align_delimiters* +g:easy_align_ignore_groups easy_align.txt /*g:easy_align_ignore_groups* +g:easy_align_ignore_unmatched easy_align.txt /*g:easy_align_ignore_unmatched* +g:easy_align_indentation easy_align.txt /*g:easy_align_indentation* +g:easy_align_interactive_modes easy_align.txt /*g:easy_align_interactive_modes* +vim-easy-align easy_align.txt /*vim-easy-align* diff --git a/.vim/bundle/vim-easy-align/plugin/easy_align.vim b/.vim/bundle/vim-easy-align/plugin/easy_align.vim new file mode 100644 index 0000000..c71af4e --- /dev/null +++ b/.vim/bundle/vim-easy-align/plugin/easy_align.vim @@ -0,0 +1,142 @@ +" Copyright (c) 2014 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. + +if exists("g:loaded_easy_align_plugin") + finish +endif +let g:loaded_easy_align_plugin = 1 + +command! -nargs=* -range -bang EasyAlign ,call easy_align#align(0, 0, 'command', ) +command! -nargs=* -range -bang LiveEasyAlign ,call easy_align#align(0, 1, 'command', ) + +let s:last_command = 'EasyAlign' + +function! s:abs(v) + return a:v >= 0 ? a:v : - a:v +endfunction + +function! s:remember_visual(mode) + let s:last_visual = [a:mode, s:abs(line("'>") - line("'<")), s:abs(col("'>") - col("'<"))] +endfunction + +function! s:repeat_visual() + let [mode, ldiff, cdiff] = s:last_visual + let cmd = 'normal! '.mode + if ldiff > 0 + let cmd .= ldiff . 'j' + endif + + let ve_save = &virtualedit + try + if mode == "\" + if cdiff > 0 + let cmd .= cdiff . 'l' + endif + set virtualedit+=block + endif + execute cmd.":\=g:easy_align_last_command\\" + call s:set_repeat() + finally + if ve_save != &virtualedit + let &virtualedit = ve_save + endif + endtry +endfunction + +function! s:repeat_in_visual() + if exists('g:easy_align_last_command') + call s:remember_visual(visualmode()) + call s:repeat_visual() + endif +endfunction + +function! s:set_repeat() + silent! call repeat#set("\(EasyAlignRepeat)") +endfunction + +function! s:generic_easy_align_op(type, vmode, live) + if !&modifiable + if a:vmode + normal! gv + endif + return + endif + let sel_save = &selection + let &selection = "inclusive" + + if a:vmode + let vmode = a:type + let [l1, l2] = ["'<", "'>"] + call s:remember_visual(vmode) + else + let vmode = '' + let [l1, l2] = [line("'["), line("']")] + unlet! s:last_visual + endif + + try + let range = l1.','.l2 + if get(g:, 'easy_align_need_repeat', 0) + execute range . g:easy_align_last_command + else + execute range . "call easy_align#align(0, a:live, vmode, '')" + end + call s:set_repeat() + finally + let &selection = sel_save + endtry +endfunction + +function! s:easy_align_op(type, ...) + call s:generic_easy_align_op(a:type, a:0, 0) +endfunction + +function! s:live_easy_align_op(type, ...) + call s:generic_easy_align_op(a:type, a:0, 1) +endfunction + +function! s:easy_align_repeat() + if exists('s:last_visual') + call s:repeat_visual() + else + try + let g:easy_align_need_repeat = 1 + normal! . + finally + unlet! g:easy_align_need_repeat + endtry + endif +endfunction + +nnoremap (EasyAlign) :set opfunc=easy_align_opg@ +vnoremap (EasyAlign) :call easy_align_op(visualmode(), 1) +nnoremap (LiveEasyAlign) :set opfunc=live_easy_align_opg@ +vnoremap (LiveEasyAlign) :call live_easy_align_op(visualmode(), 1) + +" vim-repeat support +nnoremap (EasyAlignRepeat) :call easy_align_repeat() +vnoremap (EasyAlignRepeat) :call repeat_in_visual() + +" Backward-compatibility (deprecated) +nnoremap (EasyAlignOperator) :set opfunc=easy_align_opg@ + diff --git a/.vim/bundle/vim-gnupg/plugin/gnupg.vim b/.vim/bundle/vim-gnupg/plugin/gnupg.vim new file mode 100644 index 0000000..da5768e --- /dev/null +++ b/.vim/bundle/vim-gnupg/plugin/gnupg.vim @@ -0,0 +1,1459 @@ +" Name: gnupg.vim +" Last Change: 2018 Jun 22 +" Maintainer: James McCoy +" Original Author: Markus Braun +" Summary: Vim plugin for transparent editing of gpg encrypted files. +" License: This program is free software; you can redistribute it and/or +" modify it under the terms of the GNU General Public License +" as published by the Free Software Foundation; either version +" 2 of the License, or (at your option) any later version. +" See http://www.gnu.org/copyleft/gpl-2.0.txt +" +" Section: Documentation {{{1 +" +" Description: {{{2 +" +" This script implements transparent editing of gpg encrypted files. The +" filename must have a ".gpg", ".pgp" or ".asc" suffix. When opening such +" a file the content is decrypted, when opening a new file the script will +" ask for the recipients of the encrypted file. The file content will be +" encrypted to all recipients before it is written. The script turns off +" viminfo, swapfile, and undofile to increase security. +" +" Installation: {{{2 +" +" Copy the gnupg.vim file to the $HOME/.vim/plugin directory. +" Refer to ':help add-plugin', ':help add-global-plugin' and ':help +" runtimepath' for more details about Vim plugins. +" +" From "man 1 gpg-agent": +" +" ... +" You should always add the following lines to your .bashrc or whatever +" initialization file is used for all shell invocations: +" +" GPG_TTY=`tty` +" export GPG_TTY +" +" It is important that this environment variable always reflects the out‐ +" put of the tty command. For W32 systems this option is not required. +" ... +" +" Most distributions provide software to ease handling of gpg and gpg-agent. +" Examples are keychain or seahorse. +" +" If there are specific actions that should take place when editing a +" GnuPG-managed buffer, an autocmd for the User event and GnuPG pattern can +" be defined. For example, the following will set 'textwidth' to 72 for all +" GnuPG-encrypted buffers: +" +" autocmd User GnuPG setl textwidth=72 +" +" This will be triggered before any BufRead or BufNewFile autocmds, and +" therefore will not take precedence over settings specific to any filetype +" that may get set. +" +" Commands: {{{2 +" +" :GPGEditRecipients +" Opens a scratch buffer to change the list of recipients. Recipients that +" are unknown (not in your public key) are highlighted and have +" a prepended "!". Closing the buffer makes the changes permanent. +" +" :GPGViewRecipients +" Prints the list of recipients. +" +" :GPGEditOptions +" Opens a scratch buffer to change the options for encryption (symmetric, +" asymmetric, signing). Closing the buffer makes the changes permanent. +" WARNING: There is no check of the entered options, so you need to know +" what you are doing. +" +" :GPGViewOptions +" Prints the list of options. +" +" Variables: {{{2 +" +" g:GPGExecutable +" If set used as gpg executable. If unset, defaults to +" "gpg --trust-model always" if "gpg" is available, falling back to +" "gpg2 --trust-model always" if not. +" +" g:GPGUseAgent +" If set to 0 a possible available gpg-agent won't be used. Defaults to 1. +" +" g:GPGPreferSymmetric +" If set to 1 symmetric encryption is preferred for new files. Defaults to 0. +" +" g:GPGPreferArmor +" If set to 1 armored data is preferred for new files. Defaults to 0 +" unless a "*.asc" file is being edited. +" +" g:GPGPreferSign +" If set to 1 signed data is preferred for new files. Defaults to 0. +" +" g:GPGDefaultRecipients +" If set, these recipients are used as defaults when no other recipient is +" defined. This variable is a Vim list. Default is unset. +" +" g:GPGPossibleRecipients +" If set, these contents are loaded into the recipients dialog. This +" allows to add commented lines with possible recipients to the list, +" which can be uncommented to select the actual recipients. Default is +" unset. Example: +" +" let g:GPGPossibleRecipients=[ +" \"Example User ", +" \"Other User " +" \] +" +" +" g:GPGUsePipes +" If set to 1, use pipes instead of temporary files when interacting with +" gnupg. When set to 1, this can cause terminal-based gpg agents to not +" display correctly when prompting for passwords. Defaults to 0. +" +" g:GPGHomedir +" If set, specifies the directory that will be used for GPG's homedir. +" This corresponds to gpg's --homedir option. This variable is a Vim +" string. Default is unset. +" +" g:GPGFilePattern +" If set, overrides the default set of file patterns that determine +" whether this plugin will be activated. Defaults to +" '*.\(gpg\|asc\|pgp\)'. +" +" Known Issues: {{{2 +" +" In some cases gvim can't decrypt files + +" This is caused by the fact that a running gvim has no TTY and thus gpg is +" not able to ask for the passphrase by itself. This is a problem for Windows +" and Linux versions of gvim and could not be solved unless a "terminal +" emulation" is implemented for gvim. To circumvent this you have to use any +" combination of gpg-agent and a graphical pinentry program: +" +" - gpg-agent only: +" you need to provide the passphrase for the needed key to gpg-agent +" in a terminal before you open files with gvim which require this key. +" +" - pinentry only: +" you will get a popup window every time you open a file that needs to +" be decrypted. +" +" - gpgagent and pinentry: +" you will get a popup window the first time you open a file that +" needs to be decrypted. +" +" If you're using Vim <7.4.959, after the plugin runs any external command, +" Vim will no longer be able to yank to/paste from the X clipboard or +" primary selections. This is caused by a workaround for a different bug +" where Vim no longer recognizes the key codes for keys such as the arrow +" keys after running GnuPG. See the discussion at +" https://github.com/jamessan/vim-gnupg/issues/36 for more details. +" +" Credits: {{{2 +" +" - Mathieu Clabaut for inspirations through his vimspell.vim script. +" - Richard Bronosky for patch to enable ".pgp" suffix. +" - Erik Remmelzwaal for patch to enable windows support and patient beta +" testing. +" - Lars Becker for patch to make gpg2 working. +" - Thomas Arendsen Hein for patch to convert encoding of gpg output. +" - Karl-Heinz Ruskowski for patch to fix unknown recipients and trust model +" and patient beta testing. +" - Giel van Schijndel for patch to get GPG_TTY dynamically. +" - Sebastian Luettich for patch to fix issue with symmetric encryption an set +" recipients. +" - Tim Swast for patch to generate signed files. +" - James Vega for patches for better '*.asc' handling, better filename +" escaping and better handling of multiple keyrings. +" +" Section: Plugin header {{{1 + +" guard against multiple loads {{{2 +if (exists("g:loaded_gnupg") || &cp || exists("#GnuPG")) + finish +endif +let g:loaded_gnupg = '2.6.1-dev' +let s:GPGInitRun = 0 + +" check for correct vim version {{{2 +if (v:version < 702) + echohl ErrorMsg | echo 'plugin gnupg.vim requires Vim version >= 7.2' | echohl None + finish +endif + +" Section: Autocmd setup {{{1 + +if (!exists("g:GPGFilePattern")) + let g:GPGFilePattern = '*.\(gpg\|asc\|pgp\)' +endif + +augroup GnuPG + autocmd! + + " do the decryption + exe "autocmd BufReadCmd " . g:GPGFilePattern . " call s:GPGInit(1) |" . + \ " call s:GPGDecrypt(1)" + exe "autocmd FileReadCmd " . g:GPGFilePattern . " call s:GPGInit(0) |" . + \ " call s:GPGDecrypt(0)" + + " convert all text to encrypted text before writing + " We check for GPGCorrespondingTo to avoid triggering on writes in GPG Options/Recipient windows + exe "autocmd BufWriteCmd,FileWriteCmd " . g:GPGFilePattern . " if !exists('b:GPGCorrespondingTo') |" . + \ " call s:GPGInit(0) |" . + \ " call s:GPGEncrypt() |" . + \ " endif" +augroup END + +" Section: Constants {{{1 + +let s:GPGMagicString = "\t \t" +let s:keyPattern = '\%(0x\)\=[[:xdigit:]]\{8,16}' + +" Section: Highlight setup {{{1 + +highlight default link GPGWarning WarningMsg +highlight default link GPGError ErrorMsg +highlight default link GPGHighlightUnknownRecipient ErrorMsg + +" Section: Functions {{{1 + +" Function: s:shellescape(s[, dict]) {{{2 +" +" Calls shellescape(), also taking into account 'shellslash' +" when on Windows and using $COMSPEC as the shell. +" +" Recognized keys are: +" special - Passed through as special argument for Vim's shellescape() +" cygpath - When true and s:useCygpath is true, adjust the path to work with +" Gpg4win from cygwin +" +" Returns: shellescaped string +" +function s:shellescape(s, ...) + let opts = a:0 ? a:1 : {} + let special = get(opts, 'special', 0) + let cygpath = get(opts, 'cygpath', 0) + let s = a:s + if cygpath && s:useCygpath + let s = matchstr(system('cygpath -am '.shellescape(s)), '[^\x0a\x0d]*') + endif + if exists('+shellslash') && &shell == $COMSPEC + let ssl = &shellslash + set noshellslash + + let escaped = shellescape(s, special) + + let &shellslash = ssl + else + let escaped = shellescape(s, special) + endif + + return escaped +endfunction + +" Function: s:unencrypted() {{{2 +" +" Determines if the buffer corresponds to an existing, unencrypted file and, +" if so, warns the user that GPG functionality has been disabled. +" +" Returns: true if current buffer corresponds to an existing, unencrypted file +function! s:unencrypted() + if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0) + echohl GPGWarning + echom "File is not encrypted, all GPG functions disabled!" + echohl None + return 1 + endif + + return 0 +endfunction + +" Function: s:GPGInit(bufread) {{{2 +" +" initialize the plugin +" The bufread argument specifies whether this was called due to BufReadCmd +" +function s:GPGInit(bufread) + call s:GPGDebug(3, printf(">>>>>>>> Entering s:GPGInit(%d)", a:bufread)) + + " For FileReadCmd, we're reading the contents into another buffer. If that + " buffer is also destined to be encrypted, then these settings will have + " already been set, otherwise don't set them since it limits the + " functionality of the cleartext buffer. + if a:bufread + " we don't want a swap file, as it writes unencrypted data to disk + setl noswapfile + + " if persistent undo is present, disable it for this buffer + if exists('+undofile') + setl noundofile + endif + + " first make sure nothing is written to ~/.viminfo while editing + " an encrypted file. + set viminfo= + endif + + " the rest only has to be run once + if s:GPGInitRun + return + endif + + " check what gpg command to use + if (!exists("g:GPGExecutable")) + if executable("gpg") + let g:GPGExecutable = "gpg --trust-model always" + else + let g:GPGExecutable = "gpg2 --trust-model always" + endif + endif + + " check if gpg-agent is allowed + if (!exists("g:GPGUseAgent")) + let g:GPGUseAgent = 1 + endif + + " check if symmetric encryption is preferred + if (!exists("g:GPGPreferSymmetric")) + let g:GPGPreferSymmetric = 0 + endif + + " check if signed files are preferred + if (!exists("g:GPGPreferSign")) + let g:GPGPreferSign = 0 + endif + + " start with empty default recipients if none is defined so far + if (!exists("g:GPGDefaultRecipients")) + let g:GPGDefaultRecipients = [] + endif + + if (!exists("g:GPGPossibleRecipients")) + let g:GPGPossibleRecipients = [] + endif + + + " prefer not to use pipes since it can garble gpg agent display + if (!exists("g:GPGUsePipes")) + let g:GPGUsePipes = 0 + endif + + " allow alternate gnupg homedir + if (!exists('g:GPGHomedir')) + let g:GPGHomedir = '' + endif + + " print version + call s:GPGDebug(1, "gnupg.vim ". g:loaded_gnupg) + + let s:GPGCommand = g:GPGExecutable + + " don't use tty in gvim except for windows: we get their a tty for free. + " FIXME find a better way to avoid an error. + " with this solution only --use-agent will work + if (has("gui_running") && !has("gui_win32")) + let s:GPGCommand .= " --no-tty" + endif + + " setup shell environment for unix and windows + let s:shellredirsave = &shellredir + let s:shellsave = &shell + let s:shelltempsave = &shelltemp + " noshelltemp isn't currently supported on Windows, but it doesn't cause any + " errors and this future proofs us against requiring changes if Windows + " gains noshelltemp functionality + let s:shelltemp = !g:GPGUsePipes + if (has("unix")) + " unix specific settings + let s:shellredir = ">%s 2>&1" + let s:shell = '/bin/sh' + let s:stderrredirnull = '2>/dev/null' + else + " windows specific settings + let s:shellredir = '>%s' + let s:shell = &shell + let s:stderrredirnull = '2>nul' + endif + + call s:GPGDebug(3, "shellredirsave: " . s:shellredirsave) + call s:GPGDebug(3, "shellsave: " . s:shellsave) + call s:GPGDebug(3, "shelltempsave: " . s:shelltempsave) + + call s:GPGDebug(3, "shell: " . s:shell) + call s:GPGDebug(3, "shellcmdflag: " . &shellcmdflag) + call s:GPGDebug(3, "shellxquote: " . &shellxquote) + call s:GPGDebug(3, "shellredir: " . s:shellredir) + call s:GPGDebug(3, "stderrredirnull: " . s:stderrredirnull) + + call s:GPGDebug(3, "shell implementation: " . resolve(s:shell)) + + " find the supported algorithms + let output = s:GPGSystem({ 'level': 2, 'args': '--version' }) + + let gpgversion = substitute(output, '^gpg (GnuPG) \([0-9]\+\.\d\+\).*', '\1', '') + let s:GPGPubkey = substitute(output, ".*Pubkey: \\(.\\{-}\\)\n.*", "\\1", "") + let s:GPGCipher = substitute(output, ".*Cipher: \\(.\\{-}\\)\n.*", "\\1", "") + let s:GPGHash = substitute(output, ".*Hash: \\(.\\{-}\\)\n.*", "\\1", "") + let s:GPGCompress = substitute(output, ".*Compress.\\{-}: \\(.\\{-}\\)\n.*", "\\1", "") + let s:GPGHome = matchstr(output, '.*Home: \zs.\{-}\ze\r\=\n') + + let s:useCygpath = 0 + if has('win32unix') && s:GPGHome =~ '\a:[/\\]' + call s:GPGDebug(1, 'Enabling use of cygpath') + let s:useCygpath = 1 + endif + + " determine if gnupg can use the gpg-agent + if (str2float(gpgversion) >= 2.1 || (exists("$GPG_AGENT_INFO") && g:GPGUseAgent == 1)) + if (!exists("$GPG_TTY") && !has("gui_running")) + " Need to determine the associated tty by running a command in the + " shell. We can't use system() here because that doesn't run in a shell + " connected to a tty, so it's rather useless. + " + " Save/restore &modified so the buffer isn't incorrectly marked as + " modified just by detecting the correct tty value. + " Do the &undolevels dance so the :read and :delete don't get added into + " the undo tree, as the user needn't be aware of these. + let [mod, levels] = [&l:modified, &undolevels] + set undolevels=-1 + silent read !tty + let $GPG_TTY = getline('.') + silent delete + let [&l:modified, &undolevels] = [mod, levels] + " redraw is needed since we're using silent to run !tty, c.f. :help :! + redraw! + if (v:shell_error) + let $GPG_TTY = "" + echohl GPGWarning + echom "$GPG_TTY is not set and the `tty` command failed! gpg-agent might not work." + echohl None + endif + endif + let s:GPGCommand .= " --use-agent" + else + let s:GPGCommand .= " --no-use-agent" + endif + + call s:GPGDebug(2, "public key algorithms: " . s:GPGPubkey) + call s:GPGDebug(2, "cipher algorithms: " . s:GPGCipher) + call s:GPGDebug(2, "hashing algorithms: " . s:GPGHash) + call s:GPGDebug(2, "compression algorithms: " . s:GPGCompress) + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGInit()") + let s:GPGInitRun = 1 +endfunction + + +" Function: s:GPGDecrypt(bufread) {{{2 +" +" decrypt the buffer and find all recipients of the encrypted file +" The bufread argument specifies whether this was called due to BufReadCmd +" +function s:GPGDecrypt(bufread) + call s:GPGDebug(3, printf(">>>>>>>> Entering s:GPGDecrypt(%d)", a:bufread)) + + " get the filename of the current buffer + let filename = resolve(expand(":p")) + + " clear GPGRecipients and GPGOptions + if type(g:GPGDefaultRecipients) == type([]) + let b:GPGRecipients = copy(g:GPGDefaultRecipients) + else + let b:GPGRecipients = [] + echohl GPGWarning + echom "g:GPGDefaultRecipients is not a Vim list, please correct this in your vimrc!" + echohl None + endif + let b:GPGOptions = [] + + " file name minus extension + let autocmd_filename = fnamemodify(filename, ':r') + + " File doesn't exist yet, so nothing to decrypt + if !filereadable(filename) + if !a:bufread + redraw! + echohl GPGError + echom "E484: Can't open file" filename + echohl None + return + endif + + " Allow the user to define actions for GnuPG buffers + silent doautocmd User GnuPG + silent execute ':doautocmd BufNewFile ' . fnameescape(autocmd_filename) + call s:GPGDebug(2, 'called BufNewFile autocommand for ' . autocmd_filename) + + set buftype=acwrite + " Remove the buffer name ... + silent 0file + " ... so we can force it to be absolute + exe 'silent file' fnameescape(filename) + + " This is a new file, so force the user to edit the recipient list if + " they open a new file and public keys are preferred + if (g:GPGPreferSymmetric == 0) + call s:GPGEditRecipients() + endif + + return + endif + + " Only let this if the file actually exists, otherwise GPG functionality + " will be disabled when editing a buffer that doesn't yet have a backing + " file + let b:GPGEncrypted = 0 + + " find the recipients of the file + let cmd = { 'level': 3 } + let cmd.args = '--verbose --decrypt --list-only --dry-run --no-use-agent --logger-fd 1 ' . s:shellescape(filename, { 'cygpath': 1 }) + let output = s:GPGSystem(cmd) + + " Suppress the "N more lines" message when editing a file, not when reading + " the contents of a file into a buffer + let silent = a:bufread ? 'silent ' : '' + + let asymmPattern = 'gpg: public key is ' . s:keyPattern + " check if the file is symmetric/asymmetric encrypted + if (match(output, "gpg: encrypted with [[:digit:]]\\+ passphrase") >= 0) + " file is symmetric encrypted + let b:GPGEncrypted = 1 + call s:GPGDebug(1, "this file is symmetric encrypted") + + let b:GPGOptions += ["symmetric"] + + " find the used cipher algorithm + let cipher = substitute(output, ".*gpg: \\([^ ]\\+\\) encrypted data.*", "\\1", "") + if (match(s:GPGCipher, "\\<" . cipher . "\\>") >= 0) + let b:GPGOptions += ["cipher-algo " . cipher] + call s:GPGDebug(1, "cipher-algo is " . cipher) + else + echohl GPGWarning + echom "The cipher " . cipher . " is not known by the local gpg command. Using default!" + echo + echohl None + endif + elseif (match(output, asymmPattern) >= 0) + " file is asymmetric encrypted + let b:GPGEncrypted = 1 + call s:GPGDebug(1, "this file is asymmetric encrypted") + + let b:GPGOptions += ["encrypt"] + + " find the used public keys + let start = match(output, asymmPattern) + while (start >= 0) + let start = start + strlen("gpg: public key is ") + let recipient = matchstr(output, s:keyPattern, start) + call s:GPGDebug(1, "recipient is " . recipient) + " In order to support anonymous communication, GnuPG allows eliding + " information in the encryption metadata specifying what keys the file + " was encrypted to (c.f., --throw-keyids and --hidden-recipient). In + " that case, the recipient(s) will be listed as having used a key of all + " zeroes. + " Since this will obviously never actually be in a keyring, only try to + " convert to an ID or add to the recipients list if it's not a hidden + " recipient. + if recipient !~? '^0x0\+$' + let name = s:GPGNameToID(recipient) + if !empty(name) + let b:GPGRecipients += [name] + call s:GPGDebug(1, "name of recipient is " . name) + else + let b:GPGRecipients += [recipient] + echohl GPGWarning + echom "The recipient \"" . recipient . "\" is not in your public keyring!" + echohl None + end + end + let start = match(output, asymmPattern, start) + endwhile + else + " file is not encrypted + let b:GPGEncrypted = 0 + call s:GPGDebug(1, "this file is not encrypted") + echohl GPGWarning + echom "File is not encrypted, all GPG functions disabled!" + echohl None + endif + + let bufname = b:GPGEncrypted ? autocmd_filename : filename + if a:bufread + silent execute ':doautocmd BufReadPre ' . fnameescape(bufname) + call s:GPGDebug(2, 'called BufReadPre autocommand for ' . bufname) + else + silent execute ':doautocmd FileReadPre ' . fnameescape(bufname) + call s:GPGDebug(2, 'called FileReadPre autocommand for ' . bufname) + endif + + if b:GPGEncrypted + " check if the message is armored + if (match(output, "gpg: armor header") >= 0) + call s:GPGDebug(1, "this file is armored") + let b:GPGOptions += ["armor"] + endif + + " finally decrypt the buffer content + " since even with the --quiet option passphrase typos will be reported, + " we must redirect stderr (using shell temporarily) + call s:GPGDebug(1, "decrypting file") + let cmd = { 'level': 1, 'ex': silent . 'read ++edit !' } + let cmd.args = '--quiet --decrypt ' . s:shellescape(filename, { 'special': 1, 'cygpath': 1 }) + call s:GPGExecute(cmd) + + if (v:shell_error) " message could not be decrypted + echohl GPGError + let blackhole = input("Message could not be decrypted! (Press ENTER)") + echohl None + " Only wipeout the buffer if we were creating one to start with. + " FileReadCmd just reads the content into the existing buffer + if a:bufread + silent bwipeout! + endif + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGDecrypt()") + return + endif + if a:bufread + " Ensure the buffer is only saved by using our BufWriteCmd + set buftype=acwrite + " Always set the buffer name to the absolute path, otherwise Vim won't + " track the correct buffer name when changing directories (due to + " buftype=acwrite). + exe 'file' fnameescape(filename) + endif + else + execute silent 'read' fnameescape(filename) + endif + + if a:bufread + " In order to make :undo a no-op immediately after the buffer is read, + " we need to do this dance with 'undolevels'. Actually discarding the undo + " history requires performing a change after setting 'undolevels' to -1 and, + " luckily, we have one we need to do (delete the extra line from the :r + " command) + let levels = &undolevels + set undolevels=-1 + " :lockmarks doesn't actually prevent '[,'] from being overwritten, so we + " need to manually set them ourselves instead + silent 1delete + 1mark [ + $mark ] + let &undolevels = levels + " The buffer should be readonly if + " - 'readonly' is already set (e.g., when using view/vim -R) + " - permissions don't allow writing + let &readonly = &readonly || (filereadable(filename) && filewritable(filename) == 0) + silent execute ':doautocmd BufReadPost ' . fnameescape(bufname) + call s:GPGDebug(2, 'called BufReadPost autocommand for ' . bufname) + else + silent execute ':doautocmd FileReadPost ' . fnameescape(bufname) + call s:GPGDebug(2, 'called FileReadPost autocommand for ' . bufname) + endif + + if b:GPGEncrypted + " Allow the user to define actions for GnuPG buffers + silent doautocmd User GnuPG + + " refresh screen + redraw! + endif + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGDecrypt()") +endfunction + +" Function: s:GPGEncrypt() {{{2 +" +" encrypts the buffer to all previous recipients +" +function s:GPGEncrypt() + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGEncrypt()") + + " FileWriteCmd is only called when a portion of a buffer is being written to + " disk. Since Vim always sets the '[,'] marks to the part of a buffer that + " is being written, that can be used to determine whether BufWriteCmd or + " FileWriteCmd triggered us. + if [line("'["), line("']")] == [1, line('$')] + let auType = 'BufWrite' + else + let auType = 'FileWrite' + endif + + " file name minus extension + let autocmd_filename = expand(':p:r') + + silent exe ':doautocmd '. auType .'Pre '. fnameescape(autocmd_filename) + call s:GPGDebug(2, 'called '. auType .'Pre autocommand for ' . autocmd_filename) + + " guard for unencrypted files + if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0) + echohl GPGError + let blackhole = input("Message could not be encrypted! (Press ENTER)") + echohl None + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGEncrypt()") + return + endif + + let filename = resolve(expand(':p')) + " initialize GPGOptions if not happened before + if (!exists("b:GPGOptions") || empty(b:GPGOptions)) + let b:GPGOptions = [] + if (exists("g:GPGPreferSymmetric") && g:GPGPreferSymmetric == 1) + let b:GPGOptions += ["symmetric"] + let b:GPGRecipients = [] + else + let b:GPGOptions += ["encrypt"] + endif + " Fallback to preference by filename if the user didn't indicate + " their preference. + let preferArmor = get(g:, 'GPGPreferArmor', -1) + if (preferArmor >= 0 && preferArmor) || filename =~ '\.asc$' + let b:GPGOptions += ["armor"] + endif + if (exists("g:GPGPreferSign") && g:GPGPreferSign == 1) + let b:GPGOptions += ["sign"] + endif + call s:GPGDebug(1, "no options set, so using default options: " . string(b:GPGOptions)) + endif + + " built list of options + let options = "" + for option in b:GPGOptions + let options = options . " --" . option . " " + endfor + + if (!exists('b:GPGRecipients')) + let b:GPGRecipients = [] + endif + + " check here again if all recipients are available in the keyring + let recipients = s:GPGCheckRecipients(b:GPGRecipients) + + " check if there are unknown recipients and warn + if !empty(recipients.unknown) + echohl GPGWarning + echom "Please use GPGEditRecipients to correct!!" + echo + echohl None + + " Let user know whats happend and copy known_recipients back to buffer + let dummy = input("Press ENTER to quit") + endif + + " built list of recipients + let options .= ' ' . join(map(recipients.valid, '"-r ".v:val'), ' ') + + " encrypt the buffer + let destfile = tempname() + let cmd = { 'level': 1, 'ex': "'[,']write !" } + let cmd.args = '--quiet --no-encrypt-to ' . options + let cmd.redirect = '>' . s:shellescape(destfile, { 'special': 1, 'cygpath': 1 }) + silent call s:GPGExecute(cmd) + + if (v:shell_error) " message could not be encrypted + " Command failed, so clean up the tempfile + call delete(destfile) + echohl GPGError + let blackhole = input("Message could not be encrypted! (Press ENTER)") + echohl None + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGEncrypt()") + return + endif + + if rename(destfile, filename) + " Rename failed, so clean up the tempfile + call delete(destfile) + echohl GPGError + echom printf("\"%s\" E212: Can't open file for writing", filename) + echohl None + return + endif + + if auType == 'BufWrite' + if expand('%:p') == filename + setl nomodified + endif + setl buftype=acwrite + let &readonly = filereadable(filename) && filewritable(filename) == 0 + endif + + silent exe ':doautocmd '. auType .'Post '. fnameescape(autocmd_filename) + call s:GPGDebug(2, 'called '. auType .'Post autocommand for ' . autocmd_filename) + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGEncrypt()") +endfunction + +" Function: s:GPGViewRecipients() {{{2 +" +" echo the recipients +" +function s:GPGViewRecipients() + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGViewRecipients()") + + " guard for unencrypted files + if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0) + echohl GPGWarning + echom "File is not encrypted, all GPG functions disabled!" + echohl None + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGViewRecipients()") + return + endif + + let recipients = s:GPGCheckRecipients(b:GPGRecipients) + + echo 'This file has following recipients (Unknown recipients have a prepended "!"):' + if empty(recipients.valid) + echohl GPGError + echo 'There are no known recipients!' + echohl None + else + echo join(map(recipients.valid, 's:GPGIDToName(v:val)'), "\n") + endif + + if !empty(recipients.unknown) + echohl GPGWarning + echo join(map(recipients.unknown, '"!".v:val'), "\n") + echohl None + endif + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGViewRecipients()") +endfunction + +" Function: s:GPGEditRecipients() {{{2 +" +" create a scratch buffer with all recipients to add/remove recipients +" +function s:GPGEditRecipients() + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGEditRecipients()") + + if s:unencrypted() + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGEditRecipients()") + return + endif + + " only do this if it isn't already a GPGRecipients_* buffer + if (!exists('b:GPGCorrespondingTo')) + + " save buffer name + let buffername = bufnr("%") + let editbuffername = "GPGRecipients_" . buffername + + " check if this buffer exists + if (!bufexists(editbuffername)) + " create scratch buffer + execute 'silent! split ' . fnameescape(editbuffername) + + " add a autocommand to regenerate the recipients after a write + autocmd BufHidden,BufUnload,BufWriteCmd call s:GPGFinishRecipientsBuffer() + else + if (bufwinnr(editbuffername) >= 0) + " switch to scratch buffer window + execute 'silent! ' . bufwinnr(editbuffername) . "wincmd w" + else + " split scratch buffer window + execute 'silent! sbuffer ' . fnameescape(editbuffername) + + " add a autocommand to regenerate the recipients after a write + autocmd BufHidden,BufUnload,BufWriteCmd call s:GPGFinishRecipientsBuffer() + endif + + " empty the buffer + silent %delete + endif + + " Mark the buffer as a scratch buffer + setlocal buftype=acwrite + setlocal bufhidden=hide + setlocal noswapfile + setlocal nowrap + setlocal nobuflisted + setlocal nonumber + + " so we know for which other buffer this edit buffer is + let b:GPGCorrespondingTo = buffername + + " put some comments to the scratch buffer + silent put ='GPG: ----------------------------------------------------------------------' + silent put ='GPG: Please edit the list of recipients, one recipient per line.' + silent put ='GPG: Unknown recipients have a prepended \"!\".' + silent put ='GPG: Lines beginning with \"GPG:\" are removed automatically.' + silent put ='GPG: Data after recipients between and including \"(\" and \")\" is ignored.' + silent put ='GPG: Closing this buffer commits changes.' + silent put ='GPG: ----------------------------------------------------------------------' + + " get the recipients + let recipients = s:GPGCheckRecipients(getbufvar(b:GPGCorrespondingTo, "GPGRecipients")) + + " if there are no known or unknown recipients, use the default ones + if (empty(recipients.valid) && empty(recipients.unknown)) + if (type(g:GPGDefaultRecipients) == type([])) + let recipients = s:GPGCheckRecipients(g:GPGDefaultRecipients) + else + echohl GPGWarning + echom "g:GPGDefaultRecipients is not a Vim list, please correct this in your vimrc!" + echohl None + endif + endif + + " put the recipients in the scratch buffer + for name in recipients.valid + let name = s:GPGIDToName(name) + silent put =name + endfor + + " put the unknown recipients in the scratch buffer + let syntaxPattern = '' + if !empty(recipients.unknown) + let flaggedNames = map(recipients.unknown, '"!".v:val') + call append('$', flaggedNames) + let syntaxPattern = '\(' . join(flaggedNames, '\|') . '\)' + endif + + for line in g:GPGPossibleRecipients + silent put ='GPG: '.line + endfor + + " define highlight + if (has("syntax") && exists("g:syntax_on")) + highlight clear GPGUnknownRecipient + if !empty(syntaxPattern) + execute 'syntax match GPGUnknownRecipient "' . syntaxPattern . '"' + highlight link GPGUnknownRecipient GPGHighlightUnknownRecipient + endif + + syntax match GPGComment "^GPG:.*$" + execute 'syntax match GPGComment "' . s:GPGMagicString . '.*$"' + highlight clear GPGComment + highlight link GPGComment Comment + endif + + " delete the empty first line + silent 1delete + + " jump to the first recipient + silent $ + + endif + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGEditRecipients()") +endfunction + +" Function: s:GPGFinishRecipientsBuffer() {{{2 +" +" create a new recipient list from RecipientsBuffer +" +function s:GPGFinishRecipientsBuffer() + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGFinishRecipientsBuffer()") + + if s:unencrypted() + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGFinishRecipientsBuffer()") + return + endif + + " go to buffer before doing work + if (bufnr("%") != expand("")) + " switch to scratch buffer window + execute 'silent! ' . bufwinnr(expand(":p")) . "wincmd w" + endif + + " delete the autocommand + autocmd! * + + " get the recipients from the scratch buffer + let recipients = [] + let lines = getline(1,"$") + for recipient in lines + let matches = matchlist(recipient, '^\(.\{-}\)\%(' . s:GPGMagicString . '(ID:\s\+\(' . s:keyPattern . '\)\s\+.*\)\=$') + + let recipient = matches[2] ? matches[2] : matches[1] + + " delete all spaces at beginning and end of the recipient + " also delete a '!' at the beginning of the recipient + let recipient = substitute(recipient, "^[[:space:]!]*\\(.\\{-}\\)[[:space:]]*$", "\\1", "") + + " delete comment lines + let recipient = substitute(recipient, "^GPG:.*$", "", "") + + " only do this if the line is not empty + if !empty(recipient) + let gpgid = s:GPGNameToID(recipient) + if !empty(gpgid) + if (match(recipients, gpgid) < 0) + let recipients += [gpgid] + endif + else + if (match(recipients, recipient) < 0) + let recipients += [recipient] + echohl GPGWarning + echom "The recipient \"" . recipient . "\" is not in your public keyring!" + echohl None + endif + endif + endif + endfor + + " write back the new recipient list to the corresponding buffer and mark it + " as modified. Buffer is now for sure an encrypted buffer. + call setbufvar(b:GPGCorrespondingTo, "GPGRecipients", recipients) + call setbufvar(b:GPGCorrespondingTo, "&mod", 1) + call setbufvar(b:GPGCorrespondingTo, "GPGEncrypted", 1) + + " check if there is any known recipient + if empty(recipients) + echohl GPGError + echom 'There are no known recipients!' + echohl None + endif + + " reset modified flag + setl nomodified + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGFinishRecipientsBuffer()") +endfunction + +" Function: s:GPGViewOptions() {{{2 +" +" echo the recipients +" +function s:GPGViewOptions() + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGViewOptions()") + + if s:unencrypted() + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGViewOptions()") + return + endif + + if (exists("b:GPGOptions")) + echo 'This file has following options:' + echo join(b:GPGOptions, "\n") + endif + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGViewOptions()") +endfunction + +" Function: s:GPGEditOptions() {{{2 +" +" create a scratch buffer with all recipients to add/remove recipients +" +function s:GPGEditOptions() + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGEditOptions()") + + if s:unencrypted() + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGEditOptions()") + return + endif + + " only do this if it isn't already a GPGOptions_* buffer + if (!exists('b:GPGCorrespondingTo')) + + " save buffer name + let buffername = bufnr("%") + let editbuffername = "GPGOptions_" . buffername + + " check if this buffer exists + if (!bufexists(editbuffername)) + " create scratch buffer + execute 'silent! split ' . fnameescape(editbuffername) + + " add a autocommand to regenerate the options after a write + autocmd BufHidden,BufUnload,BufWriteCmd call s:GPGFinishOptionsBuffer() + else + if (bufwinnr(editbuffername) >= 0) + " switch to scratch buffer window + execute 'silent! ' . bufwinnr(editbuffername) . "wincmd w" + else + " split scratch buffer window + execute 'silent! sbuffer ' . fnameescape(editbuffername) + + " add a autocommand to regenerate the options after a write + autocmd BufHidden,BufUnload,BufWriteCmd call s:GPGFinishOptionsBuffer() + endif + + " empty the buffer + silent %delete + endif + + " Mark the buffer as a scratch buffer + setlocal buftype=nofile + setlocal noswapfile + setlocal nowrap + setlocal nobuflisted + setlocal nonumber + + " so we know for which other buffer this edit buffer is + let b:GPGCorrespondingTo = buffername + + " put some comments to the scratch buffer + silent put ='GPG: ----------------------------------------------------------------------' + silent put ='GPG: THERE IS NO CHECK OF THE ENTERED OPTIONS!' + silent put ='GPG: YOU NEED TO KNOW WHAT YOU ARE DOING!' + silent put ='GPG: IF IN DOUBT, QUICKLY EXIT USING :x OR :bd.' + silent put ='GPG: Please edit the list of options, one option per line.' + silent put ='GPG: Please refer to the gpg documentation for valid options.' + silent put ='GPG: Lines beginning with \"GPG:\" are removed automatically.' + silent put ='GPG: Closing this buffer commits changes.' + silent put ='GPG: ----------------------------------------------------------------------' + + " put the options in the scratch buffer + let options = getbufvar(b:GPGCorrespondingTo, "GPGOptions") + + for option in options + silent put =option + endfor + + " delete the empty first line + silent 1delete + + " jump to the first option + silent $ + + " define highlight + if (has("syntax") && exists("g:syntax_on")) + syntax match GPGComment "^GPG:.*$" + highlight clear GPGComment + highlight link GPGComment Comment + endif + endif + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGEditOptions()") +endfunction + +" Function: s:GPGFinishOptionsBuffer() {{{2 +" +" create a new option list from OptionsBuffer +" +function s:GPGFinishOptionsBuffer() + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGFinishOptionsBuffer()") + + if s:unencrypted() + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGFinishOptionsBuffer()") + return + endif + + " go to buffer before doing work + if (bufnr("%") != expand("")) + " switch to scratch buffer window + execute 'silent! ' . bufwinnr(expand(":p")) . "wincmd w" + endif + + " clear options and unknownOptions + let options = [] + let unknownOptions = [] + + " delete the autocommand + autocmd! * + + " get the options from the scratch buffer + let lines = getline(1, "$") + for option in lines + " delete all spaces at beginning and end of the option + " also delete a '!' at the beginning of the option + let option = substitute(option, "^[[:space:]!]*\\(.\\{-}\\)[[:space:]]*$", "\\1", "") + " delete comment lines + let option = substitute(option, "^GPG:.*$", "", "") + + " only do this if the line is not empty + if (!empty(option) && match(options, option) < 0) + let options += [option] + endif + endfor + + " write back the new option list to the corresponding buffer and mark it + " as modified + call setbufvar(b:GPGCorrespondingTo, "GPGOptions", options) + call setbufvar(b:GPGCorrespondingTo, "&mod", 1) + + " reset modified flag + setl nomodified + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGFinishOptionsBuffer()") +endfunction + +" Function: s:GPGCheckRecipients(tocheck) {{{2 +" +" check if recipients are known +" Returns: dictionary of recipients, {'valid': [], 'unknown': []} +" +function s:GPGCheckRecipients(tocheck) + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGCheckRecipients()") + + let recipients = {'valid': [], 'unknown': []} + + if (type(a:tocheck) == type([])) + for recipient in a:tocheck + let gpgid = s:GPGNameToID(recipient) + if !empty(gpgid) + if (match(recipients.valid, gpgid) < 0) + call add(recipients.valid, gpgid) + endif + else + if (match(recipients.unknown, recipient) < 0) + call add(recipients.unknown, recipient) + echohl GPGWarning + echom "The recipient \"" . recipient . "\" is not in your public keyring!" + echohl None + endif + end + endfor + endif + + call s:GPGDebug(2, "recipients are: " . string(recipients.valid)) + call s:GPGDebug(2, "unknown recipients are: " . string(recipients.unknown)) + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGCheckRecipients()") + return recipients +endfunction + +" Function: s:GPGNameToID(name) {{{2 +" +" find GPG key ID corresponding to a name +" Returns: ID for the given name +" +function s:GPGNameToID(name) + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGNameToID()") + + " ask gpg for the id for a name + let cmd = { 'level': 2 } + let cmd.args = '--quiet --with-colons --fixed-list-mode --list-keys ' . s:shellescape(a:name) + let output = s:GPGSystem(cmd) + + " when called with "--with-colons" gpg encodes its output _ALWAYS_ as UTF-8, + " so convert it, if necessary + if (&encoding != "utf-8") + let output = iconv(output, "utf-8", &encoding) + endif + let lines = split(output, "\n") + + " parse the output of gpg + let pubseen = 0 + let counter = 0 + let gpgids = [] + let seen_keys = {} + let skip_key = 0 + let has_strftime = exists('*strftime') + let choices = "The name \"" . a:name . "\" is ambiguous. Please select the correct key:\n" + for line in lines + + let fields = split(line, ":") + + " search for the next pub + if (fields[0] == "pub") + " check if this key has already been processed + if has_key(seen_keys, fields[4]) + let skip_key = 1 + continue + endif + let skip_key = 0 + let seen_keys[fields[4]] = 1 + + " Ignore keys which are not usable for encryption + if fields[11] !~? 'e' + continue + endif + + let identity = fields[4] + let gpgids += [identity] + if has_strftime + let choices = choices . counter . ": ID: 0x" . identity . " created at " . strftime("%c", fields[5]) . "\n" + else + let choices = choices . counter . ": ID: 0x" . identity . "\n" + endif + let counter = counter+1 + let pubseen = 1 + " search for the next uid + elseif (!skip_key && fields[0] == "uid") + let choices = choices . " " . fields[9] . "\n" + endif + + endfor + + " counter > 1 means we have more than one results + let answer = 0 + if (counter > 1) + let choices = choices . "Enter number: " + let answer = input(choices, "0") + while (answer == "") + let answer = input("Enter number: ", "0") + endwhile + endif + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGNameToID()") + return get(gpgids, answer, "") +endfunction + +" Function: s:GPGIDToName(identity) {{{2 +" +" find name corresponding to a GPG key ID +" Returns: Name for the given ID +" +function s:GPGIDToName(identity) + call s:GPGDebug(3, ">>>>>>>> Entering s:GPGIDToName()") + + " TODO is the encryption subkey really unique? + + " ask gpg for the id for a name + let cmd = { 'level': 2 } + let cmd.args = '--quiet --with-colons --fixed-list-mode --list-keys ' . a:identity + let output = s:GPGSystem(cmd) + + " when called with "--with-colons" gpg encodes its output _ALWAYS_ as UTF-8, + " so convert it, if necessary + if (&encoding != "utf-8") + let output = iconv(output, "utf-8", &encoding) + endif + let lines = split(output, "\n") + + " parse the output of gpg + let pubseen = 0 + let uid = "" + for line in lines + let fields = split(line, ":") + + if !pubseen " search for the next pub + if (fields[0] == "pub") + " Ignore keys which are not usable for encryption + if fields[11] !~? 'e' + continue + endif + + let pubseen = 1 + endif + else " search for the next uid + if (fields[0] == "uid") + let pubseen = 0 + if exists("*strftime") + let uid = fields[9] . s:GPGMagicString . "(ID: 0x" . a:identity . " created at " . strftime("%c", fields[5]) . ")" + else + let uid = fields[9] . s:GPGMagicString . "(ID: 0x" . a:identity . ")" + endif + break + endif + endif + endfor + + call s:GPGDebug(3, "<<<<<<<< Leaving s:GPGIDToName()") + return uid +endfunction + +" Function: s:GPGPreCmd() {{{2 +" +" Setup the environment for running the gpg command +" +function s:GPGPreCmd() + let &shellredir = s:shellredir + let &shell = s:shell + let &shelltemp = s:shelltemp + " Force C locale so GPG output is consistent + let s:messages = v:lang + language messages C +endfunction + + +" Function: s:GPGPostCmd() {{{2 +" +" Restore the user's environment after running the gpg command +" +function s:GPGPostCmd() + let &shellredir = s:shellredirsave + let &shell = s:shellsave + let &shelltemp = s:shelltempsave + execute 'language messages' s:messages + " Workaround a bug in the interaction between console vim and + " pinentry-curses by forcing Vim to re-detect and setup its terminal + " settings + let &term = &term + silent doautocmd TermChanged +endfunction + +" Function: s:GPGSystem(dict) {{{2 +" +" run g:GPGCommand using system(), logging the commandline and output. This +" uses temp files (regardless of how 'shelltemp' is set) to hold the output of +" the command, so it must not be used for sensitive commands. +" Recognized keys are: +" level - Debug level at which the commandline and output will be logged +" args - Arguments to be given to g:GPGCommand +" +" Returns: command output +" +function s:GPGSystem(dict) + let commandline = s:GPGCommand + if (!empty(g:GPGHomedir)) + let commandline .= ' --homedir ' . s:shellescape(g:GPGHomedir, { 'cygpath': 1 }) + endif + let commandline .= ' ' . a:dict.args + let commandline .= ' ' . s:stderrredirnull + call s:GPGDebug(a:dict.level, "command: ". commandline) + + call s:GPGPreCmd() + let output = system(commandline) + call s:GPGPostCmd() + + call s:GPGDebug(a:dict.level, "rc: ". v:shell_error) + call s:GPGDebug(a:dict.level, "output: ". output) + return output +endfunction + +" Function: s:GPGExecute(dict) {{{2 +" +" run g:GPGCommand using :execute, logging the commandline +" Recognized keys are: +" level - Debug level at which the commandline will be logged +" args - Arguments to be given to g:GPGCommand +" ex - Ex command which will be :executed +" redirect - Shell redirect to use, if needed +" +function s:GPGExecute(dict) + let commandline = printf('%s%s', a:dict.ex, s:GPGCommand) + if (!empty(g:GPGHomedir)) + let commandline .= ' --homedir ' . s:shellescape(g:GPGHomedir, { 'special': 1, 'cygpath': 1 }) + endif + let commandline .= ' ' . a:dict.args + if (has_key(a:dict, 'redirect')) + let commandline .= ' ' . a:dict.redirect + endif + let commandline .= ' ' . s:stderrredirnull + call s:GPGDebug(a:dict.level, "command: " . commandline) + + call s:GPGPreCmd() + execute commandline + call s:GPGPostCmd() + + call s:GPGDebug(a:dict.level, "rc: ". v:shell_error) +endfunction + +" Function: s:GPGDebug(level, text) {{{2 +" +" output debug message, if this message has high enough importance +" only define function if GPGDebugLevel set at all +" +function s:GPGDebug(level, text) + if exists("g:GPGDebugLevel") && g:GPGDebugLevel >= a:level + if exists("g:GPGDebugLog") + execute "redir >> " . g:GPGDebugLog + silent echom "GnuPG: " . a:text + redir END + else + echom "GnuPG: " . a:text + endif + endif +endfunction + +" Section: Commands {{{1 + +command! GPGViewRecipients call s:GPGViewRecipients() +command! GPGEditRecipients call s:GPGEditRecipients() +command! GPGViewOptions call s:GPGViewOptions() +command! GPGEditOptions call s:GPGEditOptions() + +" Section: Menu {{{1 + +if (has("menu")) + amenu Plugin.GnuPG.View\ Recipients :GPGViewRecipients + amenu Plugin.GnuPG.Edit\ Recipients :GPGEditRecipients + amenu Plugin.GnuPG.View\ Options :GPGViewOptions + amenu Plugin.GnuPG.Edit\ Options :GPGEditOptions +endif + +" vim600: set foldmethod=marker foldlevel=0 : diff --git a/.vim/bundle/vim-mail/ftplugin/mail.vim b/.vim/bundle/vim-mail/ftplugin/mail.vim new file mode 100644 index 0000000..0f92422 --- /dev/null +++ b/.vim/bundle/vim-mail/ftplugin/mail.vim @@ -0,0 +1,38 @@ +setl wrap " softwrap the text +setl linebreak " don't break in the middle of the word +setl nolist " list disables linebreak +setl textwidth=72 +setl formatprg=par\ -B+.,\\-\\!\\?\\\"\\\'\\*\\<\ -w72qie +setl enc=utf-8 +setl nojs +setl nosmartindent +setl spell + +setl comments=n:> +setl formatoptions= +setl fo+=r " Insert the current comment leader after hitting in Insert mode. +setl fo+=o " Insert the current comment leader after hitting 'o' or 'O' in Normal mode. +setl fo+=q " Allow formatting of comments with "gq". +setl fo+=w " Trailing white space indicates a paragraph continues in the next line. +setl fo+=b " Like 'v', but only auto-wrap if you enter a blank at or before the wrap margin. +setl fo+=j " Where it makes sense, remove a comment leader when joining lines. + +match ErrorMsg '\s\s\+$' + +syn match quote0 "^>" +syn match quote1 "^> *>" +syn match quote2 "^> *> *>" +syn match quote3 "^> *> *> *>" +syn match quote4 "^> *> *> *> *>" +syn match quote5 "^> *> *> *> *> *>" +syn match quote6 "^> *> *> *> *> *> *>" +syn match quote7 "^> *> *> *> *> *> *> *>" + +hi quote0 ctermfg=magenta +hi quote1 ctermfg=cyan +hi quote2 ctermfg=blue +hi quote3 ctermfg=yellow +hi quote4 ctermfg=magenta +hi quote5 ctermfg=cyan +hi quote6 ctermfg=blue +hi quote7 ctermfg=yellow diff --git a/.vim/bundle/vim-snipmate/after/plugin/snipMate.vim b/.vim/bundle/vim-snipmate/after/plugin/snipMate.vim new file mode 100644 index 0000000..03e79ae --- /dev/null +++ b/.vim/bundle/vim-snipmate/after/plugin/snipMate.vim @@ -0,0 +1,35 @@ +" These are the mappings for snipMate.vim. Putting it here ensures that it +" will be mapped after other plugins such as supertab.vim. +if !exists('loaded_snips') || exists('s:did_snips_mappings') + finish +endif +let s:did_snips_mappings = 1 + +ino =TriggerSnippet() +snor i=TriggerSnippet() +ino =BackwardsSnippet() +snor i=BackwardsSnippet() +ino =ShowAvailableSnips() + +" The default mappings for these are annoying & sometimes break snipMate. +" You can change them back if you want, I've put them here for convenience. +snor b +snor a +snor bi +snor ' b' +snor ` b` +snor % b% +snor U bU +snor ^ b^ +snor \ b\ +snor b + +" By default load snippets in snippets_dir +if empty(snippets_dir) + finish +endif + +call GetSnippets(snippets_dir, '_') " Get global snippets + +au FileType * if &ft != 'help' | call GetSnippets(snippets_dir, &ft) | endif +" vim:noet:sw=4:ts=4:ft=vim diff --git a/.vim/bundle/vim-snipmate/autoload/snipMate.vim b/.vim/bundle/vim-snipmate/autoload/snipMate.vim new file mode 100644 index 0000000..dcd28f6 --- /dev/null +++ b/.vim/bundle/vim-snipmate/autoload/snipMate.vim @@ -0,0 +1,433 @@ +fun! Filename(...) + let filename = expand('%:t:r') + if filename == '' | return a:0 == 2 ? a:2 : '' | endif + return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g') +endf + +fun s:RemoveSnippet() + unl! g:snipPos s:curPos s:snipLen s:endCol s:endLine s:prevLen + \ s:lastBuf s:oldWord + if exists('s:update') + unl s:startCol s:origWordLen s:update + if exists('s:oldVars') | unl s:oldVars s:oldEndCol | endif + endif + aug! snipMateAutocmds +endf + +fun snipMate#expandSnip(snip, col) + let lnum = line('.') | let col = a:col + + let snippet = s:ProcessSnippet(a:snip) + " Avoid error if eval evaluates to nothing + if snippet == '' | return '' | endif + + " Expand snippet onto current position with the tab stops removed + let snipLines = split(substitute(snippet, '$\d\+\|${\d\+.\{-}}', '', 'g'), "\n", 1) + + let line = getline(lnum) + let afterCursor = strpart(line, col - 1) + " Keep text after the cursor + if afterCursor != "\t" && afterCursor != ' ' + let line = strpart(line, 0, col - 1) + let snipLines[-1] .= afterCursor + else + let afterCursor = '' + " For some reason the cursor needs to move one right after this + if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore' + let col += 1 + endif + endif + + call setline(lnum, line.snipLines[0]) + + " Autoindent snippet according to previous indentation + let indent = matchend(line, '^.\{-}\ze\(\S\|$\)') + 1 + call append(lnum, map(snipLines[1:], "'".strpart(line, 0, indent - 1)."'.v:val")) + + " Open any folds snippet expands into + if &fen | sil! exe lnum.','.(lnum + len(snipLines) - 1).'foldopen' | endif + + let [g:snipPos, s:snipLen] = s:BuildTabStops(snippet, lnum, col - indent, indent) + + if s:snipLen + aug snipMateAutocmds + au CursorMovedI * call s:UpdateChangedSnip(0) + au InsertEnter * call s:UpdateChangedSnip(1) + aug END + let s:lastBuf = bufnr(0) " Only expand snippet while in current buffer + let s:curPos = 0 + let s:endCol = g:snipPos[s:curPos][1] + let s:endLine = g:snipPos[s:curPos][0] + + call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1]) + let s:prevLen = [line('$'), col('$')] + if g:snipPos[s:curPos][2] != -1 | return s:SelectWord() | endif + else + unl g:snipPos s:snipLen + " Place cursor at end of snippet if no tab stop is given + let newlines = len(snipLines) - 1 + call cursor(lnum + newlines, indent + len(snipLines[-1]) - len(afterCursor) + \ + (newlines ? 0: col - 1)) + endif + return '' +endf + +" Prepare snippet to be processed by s:BuildTabStops +fun s:ProcessSnippet(snip) + let snippet = a:snip + " Evaluate eval (`...`) expressions. + " Using a loop here instead of a regex fixes a bug with nested "\=". + if stridx(snippet, '`') != -1 + while match(snippet, '`.\{-}`') != -1 + let snippet = substitute(snippet, '`.\{-}`', + \ substitute(eval(matchstr(snippet, '`\zs.\{-}\ze`')), + \ "\n\\%$", '', ''), '') + endw + let snippet = substitute(snippet, "\r", "\n", 'g') + endif + + " Place all text after a colon in a tab stop after the tab stop + " (e.g. "${#:foo}" becomes "${:foo}foo"). + " This helps tell the position of the tab stops later. + let snippet = substitute(snippet, '${\d\+:\(.\{-}\)}', '&\1', 'g') + + " Update the a:snip so that all the $# become the text after + " the colon in their associated ${#}. + " (e.g. "${1:foo}" turns all "$1"'s into "foo") + let i = 1 + while stridx(snippet, '${'.i) != -1 + let s = matchstr(snippet, '${'.i.':\zs.\{-}\ze}') + if s != '' + let snippet = substitute(snippet, '$'.i, s.'&', 'g') + endif + let i += 1 + endw + + if &et " Expand tabs to spaces if 'expandtab' is set. + return substitute(snippet, '\t', repeat(' ', &sts ? &sts : &sw), 'g') + endif + return snippet +endf + +" Counts occurences of haystack in needle +fun s:Count(haystack, needle) + let counter = 0 + let index = stridx(a:haystack, a:needle) + while index != -1 + let index = stridx(a:haystack, a:needle, index+1) + let counter += 1 + endw + return counter +endf + +" Builds a list of a list of each tab stop in the snippet containing: +" 1.) The tab stop's line number. +" 2.) The tab stop's column number +" (by getting the length of the string between the last "\n" and the +" tab stop). +" 3.) The length of the text after the colon for the current tab stop +" (e.g. "${1:foo}" would return 3). If there is no text, -1 is returned. +" 4.) If the "${#:}" construct is given, another list containing all +" the matches of "$#", to be replaced with the placeholder. This list is +" composed the same way as the parent; the first item is the line number, +" and the second is the column. +fun s:BuildTabStops(snip, lnum, col, indent) + let snipPos = [] + let i = 1 + let withoutVars = substitute(a:snip, '$\d\+', '', 'g') + while stridx(a:snip, '${'.i) != -1 + let beforeTabStop = matchstr(withoutVars, '^.*\ze${'.i.'\D') + let withoutOthers = substitute(withoutVars, '${\('.i.'\D\)\@!\d\+.\{-}}', '', 'g') + + let j = i - 1 + call add(snipPos, [0, 0, -1]) + let snipPos[j][0] = a:lnum + s:Count(beforeTabStop, "\n") + let snipPos[j][1] = a:indent + len(matchstr(withoutOthers, '.*\(\n\|^\)\zs.*\ze${'.i.'\D')) + if snipPos[j][0] == a:lnum | let snipPos[j][1] += a:col | endif + + " Get all $# matches in another list, if ${#:name} is given + if stridx(withoutVars, '${'.i.':') != -1 + let snipPos[j][2] = len(matchstr(withoutVars, '${'.i.':\zs.\{-}\ze}')) + let dots = repeat('.', snipPos[j][2]) + call add(snipPos[j], []) + let withoutOthers = substitute(a:snip, '${\d\+.\{-}}\|$'.i.'\@!\d\+', '', 'g') + while match(withoutOthers, '$'.i.'\(\D\|$\)') != -1 + let beforeMark = matchstr(withoutOthers, '^.\{-}\ze'.dots.'$'.i.'\(\D\|$\)') + call add(snipPos[j][3], [0, 0]) + let snipPos[j][3][-1][0] = a:lnum + s:Count(beforeMark, "\n") + let snipPos[j][3][-1][1] = a:indent + (snipPos[j][3][-1][0] > a:lnum + \ ? len(matchstr(beforeMark, '.*\n\zs.*')) + \ : a:col + len(beforeMark)) + let withoutOthers = substitute(withoutOthers, '$'.i.'\ze\(\D\|$\)', '', '') + endw + endif + let i += 1 + endw + return [snipPos, i - 1] +endf + +fun snipMate#jumpTabStop(backwards) + let leftPlaceholder = exists('s:origWordLen') + \ && s:origWordLen != g:snipPos[s:curPos][2] + if leftPlaceholder && exists('s:oldEndCol') + let startPlaceholder = s:oldEndCol + 1 + endif + + if exists('s:update') + call s:UpdatePlaceholderTabStops() + else + call s:UpdateTabStops() + endif + + " Don't reselect placeholder if it has been modified + if leftPlaceholder && g:snipPos[s:curPos][2] != -1 + if exists('startPlaceholder') + let g:snipPos[s:curPos][1] = startPlaceholder + else + let g:snipPos[s:curPos][1] = col('.') + let g:snipPos[s:curPos][2] = 0 + endif + endif + + let s:curPos += a:backwards ? -1 : 1 + " Loop over the snippet when going backwards from the beginning + if s:curPos < 0 | let s:curPos = s:snipLen - 1 | endif + + if s:curPos == s:snipLen + let sMode = s:endCol == g:snipPos[s:curPos-1][1]+g:snipPos[s:curPos-1][2] + call s:RemoveSnippet() + return sMode ? "\" : TriggerSnippet() + endif + + call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1]) + + let s:endLine = g:snipPos[s:curPos][0] + let s:endCol = g:snipPos[s:curPos][1] + let s:prevLen = [line('$'), col('$')] + + return g:snipPos[s:curPos][2] == -1 ? '' : s:SelectWord() +endf + +fun s:UpdatePlaceholderTabStops() + let changeLen = s:origWordLen - g:snipPos[s:curPos][2] + unl s:startCol s:origWordLen s:update + if !exists('s:oldVars') | return | endif + " Update tab stops in snippet if text has been added via "$#" + " (e.g., in "${1:foo}bar$1${2}"). + if changeLen != 0 + let curLine = line('.') + + for pos in g:snipPos + if pos == g:snipPos[s:curPos] | continue | endif + let changed = pos[0] == curLine && pos[1] > s:oldEndCol + let changedVars = 0 + let endPlaceholder = pos[2] - 1 + pos[1] + " Subtract changeLen from each tab stop that was after any of + " the current tab stop's placeholders. + for [lnum, col] in s:oldVars + if lnum > pos[0] | break | endif + if pos[0] == lnum + if pos[1] > col || (pos[2] == -1 && pos[1] == col) + let changed += 1 + elseif col < endPlaceholder + let changedVars += 1 + endif + endif + endfor + let pos[1] -= changeLen * changed + let pos[2] -= changeLen * changedVars " Parse variables within placeholders + " e.g., "${1:foo} ${2:$1bar}" + + if pos[2] == -1 | continue | endif + " Do the same to any placeholders in the other tab stops. + for nPos in pos[3] + let changed = nPos[0] == curLine && nPos[1] > s:oldEndCol + for [lnum, col] in s:oldVars + if lnum > nPos[0] | break | endif + if nPos[0] == lnum && nPos[1] > col + let changed += 1 + endif + endfor + let nPos[1] -= changeLen * changed + endfor + endfor + endif + unl s:endCol s:oldVars s:oldEndCol +endf + +fun s:UpdateTabStops() + let changeLine = s:endLine - g:snipPos[s:curPos][0] + let changeCol = s:endCol - g:snipPos[s:curPos][1] + if exists('s:origWordLen') + let changeCol -= s:origWordLen + unl s:origWordLen + endif + let lnum = g:snipPos[s:curPos][0] + let col = g:snipPos[s:curPos][1] + " Update the line number of all proceeding tab stops if has + " been inserted. + if changeLine != 0 + let changeLine -= 1 + for pos in g:snipPos + if pos[0] >= lnum + if pos[0] == lnum | let pos[1] += changeCol | endif + let pos[0] += changeLine + endif + if pos[2] == -1 | continue | endif + for nPos in pos[3] + if nPos[0] >= lnum + if nPos[0] == lnum | let nPos[1] += changeCol | endif + let nPos[0] += changeLine + endif + endfor + endfor + elseif changeCol != 0 + " Update the column of all proceeding tab stops if text has + " been inserted/deleted in the current line. + for pos in g:snipPos + if pos[1] >= col && pos[0] == lnum + let pos[1] += changeCol + endif + if pos[2] == -1 | continue | endif + for nPos in pos[3] + if nPos[0] > lnum | break | endif + if nPos[0] == lnum && nPos[1] >= col + let nPos[1] += changeCol + endif + endfor + endfor + endif +endf + +fun s:SelectWord() + let s:origWordLen = g:snipPos[s:curPos][2] + let s:oldWord = strpart(getline('.'), g:snipPos[s:curPos][1] - 1, + \ s:origWordLen) + let s:prevLen[1] -= s:origWordLen + if !empty(g:snipPos[s:curPos][3]) + let s:update = 1 + let s:endCol = -1 + let s:startCol = g:snipPos[s:curPos][1] - 1 + endif + if !s:origWordLen | return '' | endif + let l = col('.') != 1 ? 'l' : '' + if &sel == 'exclusive' + return "\".l.'v'.s:origWordLen."l\" + endif + return s:origWordLen == 1 ? "\".l.'gh' + \ : "\".l.'v'.(s:origWordLen - 1)."l\" +endf + +" This updates the snippet as you type when text needs to be inserted +" into multiple places (e.g. in "${1:default text}foo$1bar$1", +" "default text" would be highlighted, and if the user types something, +" UpdateChangedSnip() would be called so that the text after "foo" & "bar" +" are updated accordingly) +" +" It also automatically quits the snippet if the cursor is moved out of it +" while in insert mode. +fun s:UpdateChangedSnip(entering) + if exists('g:snipPos') && bufnr(0) != s:lastBuf + call s:RemoveSnippet() + elseif exists('s:update') " If modifying a placeholder + if !exists('s:oldVars') && s:curPos + 1 < s:snipLen + " Save the old snippet & word length before it's updated + " s:startCol must be saved too, in case text is added + " before the snippet (e.g. in "foo$1${2}bar${1:foo}"). + let s:oldEndCol = s:startCol + let s:oldVars = deepcopy(g:snipPos[s:curPos][3]) + endif + let col = col('.') - 1 + + if s:endCol != -1 + let changeLen = col('$') - s:prevLen[1] + let s:endCol += changeLen + else " When being updated the first time, after leaving select mode + if a:entering | return | endif + let s:endCol = col - 1 + endif + + " If the cursor moves outside the snippet, quit it + if line('.') != g:snipPos[s:curPos][0] || col < s:startCol || + \ col - 1 > s:endCol + unl! s:startCol s:origWordLen s:oldVars s:update + return s:RemoveSnippet() + endif + + call s:UpdateVars() + let s:prevLen[1] = col('$') + elseif exists('g:snipPos') + if !a:entering && g:snipPos[s:curPos][2] != -1 + let g:snipPos[s:curPos][2] = -2 + endif + + let col = col('.') + let lnum = line('.') + let changeLine = line('$') - s:prevLen[0] + + if lnum == s:endLine + let s:endCol += col('$') - s:prevLen[1] + let s:prevLen = [line('$'), col('$')] + endif + if changeLine != 0 + let s:endLine += changeLine + let s:endCol = col + endif + + " Delete snippet if cursor moves out of it in insert mode + if (lnum == s:endLine && (col > s:endCol || col < g:snipPos[s:curPos][1])) + \ || lnum > s:endLine || lnum < g:snipPos[s:curPos][0] + call s:RemoveSnippet() + endif + endif +endf + +" This updates the variables in a snippet when a placeholder has been edited. +" (e.g., each "$1" in "${1:foo} $1bar $1bar") +fun s:UpdateVars() + let newWordLen = s:endCol - s:startCol + 1 + let newWord = strpart(getline('.'), s:startCol, newWordLen) + if newWord == s:oldWord || empty(g:snipPos[s:curPos][3]) + return + endif + + let changeLen = g:snipPos[s:curPos][2] - newWordLen + let curLine = line('.') + let startCol = col('.') + let oldStartSnip = s:startCol + let updateTabStops = changeLen != 0 + let i = 0 + + for [lnum, col] in g:snipPos[s:curPos][3] + if updateTabStops + let start = s:startCol + if lnum == curLine && col <= start + let s:startCol -= changeLen + let s:endCol -= changeLen + endif + for nPos in g:snipPos[s:curPos][3][(i):] + " This list is in ascending order, so quit if we've gone too far. + if nPos[0] > lnum | break | endif + if nPos[0] == lnum && nPos[1] > col + let nPos[1] -= changeLen + endif + endfor + if lnum == curLine && col > start + let col -= changeLen + let g:snipPos[s:curPos][3][i][1] = col + endif + let i += 1 + endif + + " "Very nomagic" is used here to allow special characters. + call setline(lnum, substitute(getline(lnum), '\%'.col.'c\V'. + \ escape(s:oldWord, '\'), escape(newWord, '\&'), '')) + endfor + if oldStartSnip != s:startCol + call cursor(0, startCol + s:startCol - oldStartSnip) + endif + + let s:oldWord = newWord + let g:snipPos[s:curPos][2] = newWordLen +endf +" vim:noet:sw=4:ts=4:ft=vim diff --git a/.vim/bundle/vim-snipmate/doc/snipMate.txt b/.vim/bundle/vim-snipmate/doc/snipMate.txt new file mode 100644 index 0000000..704d44a --- /dev/null +++ b/.vim/bundle/vim-snipmate/doc/snipMate.txt @@ -0,0 +1,286 @@ +*snipMate.txt* Plugin for using TextMate-style snippets in Vim. + +snipMate *snippet* *snippets* *snipMate* +Last Change: July 13, 2009 + +|snipMate-description| Description +|snipMate-syntax| Snippet syntax +|snipMate-usage| Usage +|snipMate-settings| Settings +|snipMate-features| Features +|snipMate-disadvantages| Disadvantages to TextMate +|snipMate-contact| Contact + +For Vim version 7.0 or later. +This plugin only works if 'compatible' is not set. +{Vi does not have any of these features.} + +============================================================================== +DESCRIPTION *snipMate-description* + +snipMate.vim implements some of TextMate's snippets features in Vim. A +snippet is a piece of often-typed text that you can insert into your +document using a trigger word followed by a . + +For instance, in a C file using the default installation of snipMate.vim, if +you type "for" in insert mode, it will expand a typical for loop in C: > + + for (i = 0; i < count; i++) { + + } + + +To go to the next item in the loop, simply over to it; if there is +repeated code, such as the "i" variable in this example, you can simply +start typing once it's highlighted and all the matches specified in the +snippet will be updated. To go in reverse, use . + +============================================================================== +SYNTAX *snippet-syntax* + +Snippets can be defined in two ways. They can be in their own file, named +after their trigger in 'snippets//.snippet', or they can be +defined together in a 'snippets/.snippets' file. Note that dotted +'filetype' syntax is supported -- e.g., you can use > + + :set ft=html.eruby + +to activate snippets for both HTML and eRuby for the current file. + +The syntax for snippets in *.snippets files is the following: > + + snippet trigger + expanded text + more expanded text + +Note that the first hard tab after the snippet trigger is required, and not +expanded in the actual snippet. The syntax for *.snippet files is the same, +only without the trigger declaration and starting indentation. + +Also note that snippets must be defined using hard tabs. They can be expanded +to spaces later if desired (see |snipMate-indenting|). + +"#" is used as a line-comment character in *.snippets files; however, they can +only be used outside of a snippet declaration. E.g.: > + + # this is a correct comment + snippet trigger + expanded text + snippet another_trigger + # this isn't a comment! + expanded text +< +This should hopefully be obvious with the included syntax highlighting. + + *snipMate-${#}* +Tab stops ~ + +By default, the cursor is placed at the end of a snippet. To specify where the +cursor is to be placed next, use "${#}", where the # is the number of the tab +stop. E.g., to place the cursor first on the id of a
tag, and then allow +the user to press to go to the middle of it: + > + snippet div +
+ ${2} +
+< + *snipMate-placeholders* *snipMate-${#:}* *snipMate-$#* +Placeholders ~ + +Placeholder text can be supplied using "${#:text}", where # is the number of +the tab stop. This text then can be copied throughout the snippet using "$#", +given # is the same number as used before. So, to make a C for loop: > + + snippet for + for (${2:i}; $2 < ${1:count}; $1++) { + ${4} + } + +This will cause "count" to first be selected and change if the user starts +typing. When is pressed, the "i" in ${2}'s position will be selected; +all $2 variables will default to "i" and automatically be updated if the user +starts typing. +NOTE: "$#" syntax is used only for variables, not for tab stops as in TextMate. + +Variables within variables are also possible. For instance: > + + snippet opt + + +Will, as usual, cause "option" to first be selected and update all the $1 +variables if the user starts typing. Since one of these variables is inside of +${2}, this text will then be used as a placeholder for the next tab stop, +allowing the user to change it if he wishes. + +To copy a value throughout a snippet without supplying default text, simply +use the "${#:}" construct without the text; e.g.: > + + snippet foo + ${1:}bar$1 +< *snipMate-commands* +Interpolated Vim Script ~ + +Snippets can also contain Vim script commands that are executed (via |eval()|) +when the snippet is inserted. Commands are given inside backticks (`...`); for +TextMates's functionality, use the |system()| function. E.g.: > + + snippet date + `system("date +%Y-%m-%d")` + +will insert the current date, assuming you are on a Unix system. Note that you +can also (and should) use |strftime()| for this example. + +Filename([{expr}] [, {defaultText}]) *snipMate-filename* *Filename()* + +Since the current filename is used often in snippets, a default function +has been defined for it in snipMate.vim, appropriately called Filename(). + +With no arguments, the default filename without an extension is returned; +the first argument specifies what to place before or after the filename, +and the second argument supplies the default text to be used if the file +has not been named. "$1" in the first argument is replaced with the filename; +if you only want the filename to be returned, the first argument can be left +blank. Examples: > + + snippet filename + `Filename()` + snippet filename_with_default + `Filename('', 'name')` + snippet filename_foo + `filename('$1_foo')` + +The first example returns the filename if it the file has been named, and an +empty string if it hasn't. The second returns the filename if it's been named, +and "name" if it hasn't. The third returns the filename followed by "_foo" if +it has been named, and an empty string if it hasn't. + + *multi_snip* +To specify that a snippet can have multiple matches in a *.snippets file, use +this syntax: > + + snippet trigger A description of snippet #1 + expand this text + snippet trigger A description of snippet #2 + expand THIS text! + +In this example, when "trigger" is typed, a numbered menu containing all +of the descriptions of the "trigger" will be shown; when the user presses the +corresponding number, that snippet will then be expanded. + +To create a snippet with multiple matches using *.snippet files, +simply place all the snippets in a subdirectory with the trigger name: +'snippets///.snippet'. + +============================================================================== +USAGE *snipMate-usage* + + *'snippets'* *g:snippets_dir* +Snippets are by default looked for any 'snippets' directory in your +'runtimepath'. Typically, it is located at '~/.vim/snippets/' on *nix or +'$HOME\vimfiles\snippets\' on Windows. To change that location or add another +one, change the g:snippets_dir variable in your |.vimrc| to your preferred +directory, or use the |ExtractSnips()|function. This will be used by the +|globpath()| function, and so accepts the same syntax as it (e.g., +comma-separated paths). + +ExtractSnipsFile({directory}, {filetype}) *ExtractSnipsFile()* *.snippets* + +ExtractSnipsFile() extracts the specified *.snippets file for the given +filetype. A .snippets file contains multiple snippet declarations for the +filetype. It is further explained above, in |snippet-syntax|. + +ExtractSnips({directory}, {filetype}) *ExtractSnips()* *.snippet* + +ExtractSnips() extracts *.snippet files from the specified directory and +defines them as snippets for the given filetype. The directory tree should +look like this: 'snippets//.snippet'. If the snippet has +multiple matches, it should look like this: +'snippets///.snippet' (see |multi_snip|). + + *ResetSnippets()* +The ResetSnippets() function removes all snippets from memory. This is useful +to put at the top of a snippet setup file for if you would like to |:source| +it multiple times. + + *list-snippets* *i_CTRL-R_* +If you would like to see what snippets are available, simply type +in the current buffer to show a list via |popupmenu-completion|. + +============================================================================== +SETTINGS *snipMate-settings* *g:snips_author* + +The g:snips_author string (similar to $TM_FULLNAME in TextMate) should be set +to your name; it can then be used in snippets to automatically add it. E.g.: > + + let g:snips_author = 'Hubert Farnsworth' + snippet name + `g:snips_author` +< + *snipMate-expandtab* *snipMate-indenting* +If you would like your snippets to be expanded using spaces instead of tabs, +just enable 'expandtab' and set 'softtabstop' to your preferred amount of +spaces. If 'softtabstop' is not set, 'shiftwidth' is used instead. + + *snipMate-remap* +snipMate does not come with a setting to customize the trigger key, but you +can remap it easily in the two lines it's defined in the 'after' directory +under 'plugin/snipMate.vim'. For instance, to change the trigger key +to CTRL-J, just change this: > + + ino =TriggerSnippet() + snor i=TriggerSnippet() + +to this: > + ino =TriggerSnippet() + snor i=TriggerSnippet() + +============================================================================== +FEATURES *snipMate-features* + +snipMate.vim has the following features among others: + - The syntax of snippets is very similar to TextMate's, allowing + easy conversion. + - The position of the snippet is kept transparently (i.e. it does not use + markers/placeholders written to the buffer), which allows you to escape + out of an incomplete snippet, something particularly useful in Vim. + - Variables in snippets are updated as-you-type. + - Snippets can have multiple matches. + - Snippets can be out of order. For instance, in a do...while loop, the + condition can be added before the code. + - [New] File-based snippets are supported. + - [New] Triggers after non-word delimiters are expanded, e.g. "foo" + in "bar.foo". + - [New] can now be used to jump tab stops in reverse order. + +============================================================================== +DISADVANTAGES *snipMate-disadvantages* + +snipMate.vim currently has the following disadvantages to TextMate's snippets: + - There is no $0; the order of tab stops must be explicitly stated. + - Placeholders within placeholders are not possible. E.g.: > + + '${3}
' +< + In TextMate this would first highlight ' id="some_id"', and if + you hit delete it would automatically skip ${2} and go to ${3} + on the next , but if you didn't delete it it would highlight + "some_id" first. You cannot do this in snipMate.vim. + - Regex cannot be performed on variables, such as "${1/.*/\U&}" + - Placeholders cannot span multiple lines. + - Activating snippets in different scopes of the same file is + not possible. + +Perhaps some of these features will be added in a later release. + +============================================================================== +CONTACT *snipMate-contact* *snipMate-author* + +To contact the author (Michael Sanders), please email: + msanders42+snipmate gmail com + +I greatly appreciate any suggestions or improvements offered for the script. + +============================================================================== + +vim:tw=78:ts=8:ft=help:norl: diff --git a/.vim/bundle/vim-snipmate/doc/tags b/.vim/bundle/vim-snipmate/doc/tags new file mode 100644 index 0000000..b21f751 --- /dev/null +++ b/.vim/bundle/vim-snipmate/doc/tags @@ -0,0 +1,33 @@ +'snippets' snipMate.txt /*'snippets'* +.snippet snipMate.txt /*.snippet* +.snippets snipMate.txt /*.snippets* +ExtractSnips() snipMate.txt /*ExtractSnips()* +ExtractSnipsFile() snipMate.txt /*ExtractSnipsFile()* +Filename() snipMate.txt /*Filename()* +ResetSnippets() snipMate.txt /*ResetSnippets()* +g:snippets_dir snipMate.txt /*g:snippets_dir* +g:snips_author snipMate.txt /*g:snips_author* +i_CTRL-R_ snipMate.txt /*i_CTRL-R_* +list-snippets snipMate.txt /*list-snippets* +multi_snip snipMate.txt /*multi_snip* +snipMate snipMate.txt /*snipMate* +snipMate-$# snipMate.txt /*snipMate-$#* +snipMate-${#:} snipMate.txt /*snipMate-${#:}* +snipMate-${#} snipMate.txt /*snipMate-${#}* +snipMate-author snipMate.txt /*snipMate-author* +snipMate-commands snipMate.txt /*snipMate-commands* +snipMate-contact snipMate.txt /*snipMate-contact* +snipMate-description snipMate.txt /*snipMate-description* +snipMate-disadvantages snipMate.txt /*snipMate-disadvantages* +snipMate-expandtab snipMate.txt /*snipMate-expandtab* +snipMate-features snipMate.txt /*snipMate-features* +snipMate-filename snipMate.txt /*snipMate-filename* +snipMate-indenting snipMate.txt /*snipMate-indenting* +snipMate-placeholders snipMate.txt /*snipMate-placeholders* +snipMate-remap snipMate.txt /*snipMate-remap* +snipMate-settings snipMate.txt /*snipMate-settings* +snipMate-usage snipMate.txt /*snipMate-usage* +snipMate.txt snipMate.txt /*snipMate.txt* +snippet snipMate.txt /*snippet* +snippet-syntax snipMate.txt /*snippet-syntax* +snippets snipMate.txt /*snippets* diff --git a/.vim/bundle/vim-snipmate/ftplugin/html_snip_helper.vim b/.vim/bundle/vim-snipmate/ftplugin/html_snip_helper.vim new file mode 100644 index 0000000..2e54570 --- /dev/null +++ b/.vim/bundle/vim-snipmate/ftplugin/html_snip_helper.vim @@ -0,0 +1,10 @@ +" Helper function for (x)html snippets +if exists('s:did_snip_helper') || &cp || !exists('loaded_snips') + finish +endif +let s:did_snip_helper = 1 + +" Automatically closes tag if in xhtml +fun! Close() + return stridx(&ft, 'xhtml') == -1 ? '' : ' /' +endf diff --git a/.vim/bundle/vim-snipmate/plugin/snipMate.vim b/.vim/bundle/vim-snipmate/plugin/snipMate.vim new file mode 100644 index 0000000..3efee2a --- /dev/null +++ b/.vim/bundle/vim-snipmate/plugin/snipMate.vim @@ -0,0 +1,247 @@ +" File: snipMate.vim +" Author: Michael Sanders +" Last Updated: July 13, 2009 +" Version: 0.83 +" Description: snipMate.vim implements some of TextMate's snippets features in +" Vim. A snippet is a piece of often-typed text that you can +" insert into your document using a trigger word followed by a "". +" +" For more help see snipMate.txt; you can do this by using: +" :helptags ~/.vim/doc +" :h snipMate.txt + +if exists('loaded_snips') || &cp || version < 700 + finish +endif +let loaded_snips = 1 +if !exists('snips_author') | let snips_author = 'Me' | endif + +au BufRead,BufNewFile *.snippets\= set ft=snippet +au FileType snippet setl noet fdm=indent + +let s:snippets = {} | let s:multi_snips = {} + +if !exists('snippets_dir') + let snippets_dir = substitute(globpath(&rtp, 'snippets/'), "\n", ',', 'g') +endif + +fun! MakeSnip(scope, trigger, content, ...) + let multisnip = a:0 && a:1 != '' + let var = multisnip ? 's:multi_snips' : 's:snippets' + if !has_key({var}, a:scope) | let {var}[a:scope] = {} | endif + if !has_key({var}[a:scope], a:trigger) + let {var}[a:scope][a:trigger] = multisnip ? [[a:1, a:content]] : a:content + elseif multisnip | let {var}[a:scope][a:trigger] += [[a:1, a:content]] + else + echom 'Warning in snipMate.vim: Snippet '.a:trigger.' is already defined.' + \ .' See :h multi_snip for help on snippets with multiple matches.' + endif +endf + +fun! ExtractSnips(dir, ft) + for path in split(globpath(a:dir, '*'), "\n") + if isdirectory(path) + let pathname = fnamemodify(path, ':t') + for snipFile in split(globpath(path, '*.snippet'), "\n") + call s:ProcessFile(snipFile, a:ft, pathname) + endfor + elseif fnamemodify(path, ':e') == 'snippet' + call s:ProcessFile(path, a:ft) + endif + endfor +endf + +" Processes a single-snippet file; optionally add the name of the parent +" directory for a snippet with multiple matches. +fun s:ProcessFile(file, ft, ...) + let keyword = fnamemodify(a:file, ':t:r') + if keyword == '' | return | endif + try + let text = join(readfile(a:file), "\n") + catch /E484/ + echom "Error in snipMate.vim: couldn't read file: ".a:file + endtry + return a:0 ? MakeSnip(a:ft, a:1, text, keyword) + \ : MakeSnip(a:ft, keyword, text) +endf + +fun! ExtractSnipsFile(file, ft) + if !filereadable(a:file) | return | endif + let text = readfile(a:file) + let inSnip = 0 + for line in text + ["\n"] + if inSnip && (line[0] == "\t" || line == '') + let content .= strpart(line, 1)."\n" + continue + elseif inSnip + call MakeSnip(a:ft, trigger, content[:-2], name) + let inSnip = 0 + endif + + if line[:6] == 'snippet' + let inSnip = 1 + let trigger = strpart(line, 8) + let name = '' + let space = stridx(trigger, ' ') + 1 + if space " Process multi snip + let name = strpart(trigger, space) + let trigger = strpart(trigger, 0, space - 1) + endif + let content = '' + endif + endfor +endf + +fun! ResetSnippets() + let s:snippets = {} | let s:multi_snips = {} | let g:did_ft = {} +endf + +let g:did_ft = {} +fun! GetSnippets(dir, filetypes) + for ft in split(a:filetypes, '\.') + if has_key(g:did_ft, ft) | continue | endif + call s:DefineSnips(a:dir, ft, ft) + if ft == 'objc' || ft == 'cpp' || ft == 'cs' + call s:DefineSnips(a:dir, 'c', ft) + elseif ft == 'xhtml' + call s:DefineSnips(a:dir, 'html', 'xhtml') + endif + let g:did_ft[ft] = 1 + endfor +endf + +" Define "aliasft" snippets for the filetype "realft". +fun s:DefineSnips(dir, aliasft, realft) + for path in split(globpath(a:dir, a:aliasft.'/')."\n". + \ globpath(a:dir, a:aliasft.'-*/'), "\n") + call ExtractSnips(path, a:realft) + endfor + for path in split(globpath(a:dir, a:aliasft.'.snippets')."\n". + \ globpath(a:dir, a:aliasft.'-*.snippets'), "\n") + call ExtractSnipsFile(path, a:realft) + endfor +endf + +fun! TriggerSnippet() + if exists('g:SuperTabMappingForward') + if g:SuperTabMappingForward == "" + let SuperTabKey = "\" + elseif g:SuperTabMappingBackward == "" + let SuperTabKey = "\" + endif + endif + + if pumvisible() " Update snippet if completion is used, or deal with supertab + if exists('SuperTabKey') + call feedkeys(SuperTabKey) | return '' + endif + call feedkeys("\a", 'n') " Close completion menu + call feedkeys("\") | return '' + endif + + if exists('g:snipPos') | return snipMate#jumpTabStop(0) | endif + + let word = matchstr(getline('.'), '\S\+\%'.col('.').'c') + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + let [trigger, snippet] = s:GetSnippet(word, scope) + " If word is a trigger for a snippet, delete the trigger & expand + " the snippet. + if snippet != '' + let col = col('.') - len(trigger) + sil exe 's/\V'.escape(trigger, '/.').'\%#//' + return snipMate#expandSnip(snippet, col) + endif + endfor + + if exists('SuperTabKey') + call feedkeys(SuperTabKey) + return '' + endif + return "\" +endf + +fun! BackwardsSnippet() + if exists('g:snipPos') | return snipMate#jumpTabStop(1) | endif + + if exists('g:SuperTabMappingForward') + if g:SuperTabMappingBackward == "" + let SuperTabKey = "\" + elseif g:SuperTabMappingForward == "" + let SuperTabKey = "\" + endif + endif + if exists('SuperTabKey') + call feedkeys(SuperTabKey) + return '' + endif + return "\" +endf + +" Check if word under cursor is snippet trigger; if it isn't, try checking if +" the text after non-word characters is (e.g. check for "foo" in "bar.foo") +fun s:GetSnippet(word, scope) + let word = a:word | let snippet = '' + while snippet == '' + if exists('s:snippets["'.a:scope.'"]["'.escape(word, '\"').'"]') + let snippet = s:snippets[a:scope][word] + elseif exists('s:multi_snips["'.a:scope.'"]["'.escape(word, '\"').'"]') + let snippet = s:ChooseSnippet(a:scope, word) + if snippet == '' | break | endif + else + if match(word, '\W') == -1 | break | endif + let word = substitute(word, '.\{-}\W', '', '') + endif + endw + if word == '' && a:word != '.' && stridx(a:word, '.') != -1 + let [word, snippet] = s:GetSnippet('.', a:scope) + endif + return [word, snippet] +endf + +fun s:ChooseSnippet(scope, trigger) + let snippet = [] + let i = 1 + for snip in s:multi_snips[a:scope][a:trigger] + let snippet += [i.'. '.snip[0]] + let i += 1 + endfor + if i == 2 | return s:multi_snips[a:scope][a:trigger][0][1] | endif + let num = inputlist(snippet) - 1 + return num == -1 ? '' : s:multi_snips[a:scope][a:trigger][num][1] +endf + +fun! ShowAvailableSnips() + let line = getline('.') + let col = col('.') + let word = matchstr(getline('.'), '\S\+\%'.col.'c') + let words = [word] + if stridx(word, '.') + let words += split(word, '\.', 1) + endif + let matchlen = 0 + let matches = [] + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + let triggers = has_key(s:snippets, scope) ? keys(s:snippets[scope]) : [] + if has_key(s:multi_snips, scope) + let triggers += keys(s:multi_snips[scope]) + endif + for trigger in triggers + for word in words + if word == '' + let matches += [trigger] " Show all matches if word is empty + elseif trigger =~ '^'.word + let matches += [trigger] + let len = len(word) + if len > matchlen | let matchlen = len | endif + endif + endfor + endfor + endfor + + " This is to avoid a bug with Vim when using complete(col - matchlen, matches) + " (Issue#46 on the Google Code snipMate issue tracker). + call setline(line('.'), substitute(line, repeat('.', matchlen).'\%'.col.'c', '', '')) + call complete(col, matches) + return '' +endf +" vim:noet:sw=4:ts=4:ft=vim diff --git a/.vim/bundle/vim-snipmate/snippets/_.snippets b/.vim/bundle/vim-snipmate/snippets/_.snippets new file mode 100644 index 0000000..4abda48 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/_.snippets @@ -0,0 +1,35 @@ +# Global snippets + +# (c) holds no legal value ;) +snippet c) + `&enc[:2] == "utf" ? "©" : "(c)"` Copyright `strftime("%Y")` ${1:`g:snips_author`}. All Rights Reserved.${2} +snippet date + `strftime("%Y-%m-%d")` +snippet mfg + Mit freundlichen Grüßen, + Stefan Hagen +snippet mailf + Sehr geehrte Frau ${1:Name}, + + ${2:Text} + + Mit freundlichen Grüßen, + Stefan Hagen +snippet mailh + Sehr geehrter Herr ${1:Name}, + + ${2:Text} + + Mit freundlichen Grüßen, + Stefan Hagen +snippet sig + -- + Stefan Hagen + T: +49 (0)176 64292517 + M: sh@codevoid.de +snippet je + `strftime("%A %d.%m.%d %H:%M")`: +snippet tel + 017664292517 +snippet worktel + 015162345601 diff --git a/.vim/bundle/vim-snipmate/snippets/c.snippets b/.vim/bundle/vim-snipmate/snippets/c.snippets new file mode 100644 index 0000000..89b81ba --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/c.snippets @@ -0,0 +1,110 @@ +# main() +snippet main + int main(int argc, const char *argv[]) + { + ${1} + return 0; + } +# #include <...> +snippet inc + #include <${1:stdio}.h>${2} +# #include "..." +snippet Inc + #include "${1:`Filename("$1.h")`}"${2} +# #ifndef ... #define ... #endif +snippet Def + #ifndef $1 + #define ${1:SYMBOL} ${2:value} + #endif${3} +snippet def + #define +snippet ifdef + #ifdef ${1:FOO} + ${2:#define } + #endif +snippet #if + #if ${1:FOO} + ${2} + #endif +# Header Include-Guard +# (the randomizer code is taken directly from TextMate; it could probably be +# cleaner, I don't know how to do it in vim script) +snippet once + #ifndef ${1:`toupper(Filename('', 'UNTITLED').'_'.system("/usr/bin/ruby -e 'print (rand * 2821109907455).round.to_s(36)'"))`} + + #define $1 + + ${2} + + #endif /* end of include guard: $1 */ +# If Condition +snippet if + if (${1:/* condition */}) { + ${2:/* code */} + } +snippet el + else { + ${1} + } +# Tertiary conditional +snippet t + ${1:/* condition */} ? ${2:a} : ${3:b} +# Do While Loop +snippet do + do { + ${2:/* code */} + } while (${1:/* condition */}); +# While Loop +snippet wh + while (${1:/* condition */}) { + ${2:/* code */} + } +# For Loop +snippet for + for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) { + ${4:/* code */} + } +# Custom For Loop +snippet forr + for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) { + ${5:/* code */} + } +# Function +snippet fun + ${1:void} ${2:function_name}(${3}) + { + ${4:/* code */} + } +# Function Declaration +snippet fund + ${1:void} ${2:function_name}(${3});${4} +# Typedef +snippet td + typedef ${1:int} ${2:MyCustomType};${3} +# Struct +snippet st + struct ${1:`Filename('$1_t', 'name')`} { + ${2:/* data */} + }${3: /* optional variable list */};${4} +# Typedef struct +snippet tds + typedef struct ${2:_$1 }{ + ${3:/* data */} + } ${1:`Filename('$1_t', 'name')`}; +# Typdef enum +snippet tde + typedef enum { + ${1:/* data */} + } ${2:foo}; +# printf +# unfortunately version this isn't as nice as TextMates's, given the lack of a +# dynamic `...` +snippet pr + printf("${1:%s}\n"${2});${3} +# fprintf (again, this isn't as nice as TextMate's version, but it works) +snippet fpr + fprintf(${1:stderr}, "${2:%s}\n"${3});${4} +snippet . + [${1}]${2} +snippet un + unsigned diff --git a/.vim/bundle/vim-snipmate/snippets/cpp.snippets b/.vim/bundle/vim-snipmate/snippets/cpp.snippets new file mode 100644 index 0000000..e4850cd --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/cpp.snippets @@ -0,0 +1,30 @@ +# Read File Into Vector +snippet readfile + std::vector v; + if (FILE *${2:fp} = fopen(${1:"filename"}, "r")) { + char buf[1024]; + while (size_t len = fread(buf, 1, sizeof(buf), $2)) + v.insert(v.end(), buf, buf + len); + fclose($2); + }${3} +# std::map +snippet map + std::map<${1:key}, ${2:value}> map${3}; +# std::vector +snippet vector + std::vector<${1:char}> v${2}; +# Namespace +snippet ns + namespace ${1:`Filename('', 'my')`} { + ${2} + } /* $1 */ +# Class +snippet cl + class ${1:`Filename('$1_t', 'name')`} { + public: + $1 (${2:arguments}); + virtual ~$1 (); + + private: + ${3:/* data */} + }; diff --git a/.vim/bundle/vim-snipmate/snippets/html.snippets b/.vim/bundle/vim-snipmate/snippets/html.snippets new file mode 100644 index 0000000..aefb9db --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/html.snippets @@ -0,0 +1,190 @@ +# Some useful Unicode entities +# Non-Breaking Space +snippet nbs +   +# ← +snippet left + ← +# → +snippet right + → +# ↑ +snippet up + ↑ +# ↓ +snippet down + ↓ +# ↩ +snippet return + ↩ +# ⇤ +snippet backtab + ⇤ +# ⇥ +snippet tab + ⇥ +# ⇧ +snippet shift + ⇧ +# ⌃ +snippet control + ⌃ +# ⌅ +snippet enter + ⌅ +# ⌘ +snippet command + ⌘ +# ⌥ +snippet option + ⌥ +# ⌦ +snippet delete + ⌦ +# ⌫ +snippet backspace + ⌫ +# ⎋ +snippet escape + ⎋ +# Generic Doctype +snippet doctype HTML 4.01 Strict + +snippet doctype HTML 4.01 Transitional + +snippet doctype HTML 5 + +snippet doctype XHTML 1.0 Frameset + +snippet doctype XHTML 1.0 Strict + +snippet doctype XHTML 1.0 Transitional + +snippet doctype XHTML 1.1 + +# HTML Doctype 4.01 Strict +snippet docts + +# HTML Doctype 4.01 Transitional +snippet doct + +# HTML Doctype 5 +snippet doct5 + +# XHTML Doctype 1.0 Frameset +snippet docxf + +# XHTML Doctype 1.0 Strict +snippet docxs + +# XHTML Doctype 1.0 Transitional +snippet docxt + +# XHTML Doctype 1.1 +snippet docx + +snippet html + + ${1} + +snippet xhtml + + ${1} + +snippet body + + ${1} + +snippet head + + + + ${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`} + ${2} + +snippet title + ${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}${2} +snippet script + ${2} +snippet scriptsrc + ${2} +snippet style + ${3} +snippet base + +snippet r + +snippet div +
+ ${2} +
+# Embed QT Movie +snippet movie + + + + + + ${6} +snippet fieldset +
+ ${1:name} + + ${3} +
+snippet form +
+ ${3} + + +

+
+snippet h1 +

${2:$1}

+snippet input + ${4} +snippet label + ${7} +snippet link + ${4} +snippet mailto + ${3:email me} +snippet meta + ${3} +snippet opt + ${3} +snippet optt + ${2} +snippet select + ${5} +snippet table + + + +
${2:Header}
${3:Data}
${4} +snippet textarea + ${5} diff --git a/.vim/bundle/vim-snipmate/snippets/java.snippets b/.vim/bundle/vim-snipmate/snippets/java.snippets new file mode 100644 index 0000000..fd705cb --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/java.snippets @@ -0,0 +1,78 @@ +snippet main + public static void main (String [] args) + { + ${1:/* code */} + } +snippet pu + public +snippet po + protected +snippet pr + private +snippet st + static +snippet fi + final +snippet ab + abstract +snippet re + return +snippet br + break; +snippet de + default: + ${1} +snippet ca + catch(${1:Exception} ${2:e}) ${3} +snippet th + throw +snippet sy + synchronized +snippet im + import +snippet j.u + java.util +snippet j.i + java.io. +snippet j.b + java.beans. +snippet j.n + java.net. +snippet j.m + java.math. +snippet if + if (${1}) ${2} +snippet el + else +snippet elif + else if (${1}) ${2} +snippet wh + while (${1}) ${2} +snippet for + for (${1}; ${2}; ${3}) ${4} +snippet fore + for (${1} : ${2}) ${3} +snippet sw + switch (${1}) ${2} +snippet cs + case ${1}: + ${2} + ${3} +snippet tc + public class ${1:`Filename()`} extends ${2:TestCase} +snippet t + public void test${1:Name}() throws Exception ${2} +snippet cl + class ${1:`Filename("", "untitled")`} ${2} +snippet in + interface ${1:`Filename("", "untitled")`} ${2:extends Parent}${3} +snippet m + ${1:void} ${2:method}(${3}) ${4:throws }${5} +snippet v + ${1:String} ${2:var}${3: = null}${4};${5} +snippet co + static public final ${1:String} ${2:var} = ${3};${4} +snippet cos + static public final String ${1:var} = "${2}";${3} +snippet as + assert ${1:test} : "${2:Failure message}";${3} diff --git a/.vim/bundle/vim-snipmate/snippets/javascript.snippets b/.vim/bundle/vim-snipmate/snippets/javascript.snippets new file mode 100644 index 0000000..51f5e05 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/javascript.snippets @@ -0,0 +1,74 @@ +# Prototype +snippet proto + ${1:class_name}.prototype.${2:method_name} = + function(${3:first_argument}) { + ${4:// body...} + }; +# Function +snippet fun + function ${1:function_name} (${2:argument}) { + ${3:// body...} + } +# Anonymous Function +snippet f + function(${1}) {${2}}; +# if +snippet if + if (${1:true}) {${2}}; +# if ... else +snippet ife + if (${1:true}) {${2}} + else{${3}}; +# tertiary conditional +snippet t + ${1:/* condition */} ? ${2:a} : ${3:b} +# switch +snippet switch + switch(${1:expression}) { + case '${3:case}': + ${4:// code} + break; + ${5} + default: + ${2:// code} + } +# case +snippet case + case '${1:case}': + ${2:// code} + break; + ${3} +# for (...) {...} +snippet for + for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) { + ${4:$1[$2]} + }; +# for (...) {...} (Improved Native For-Loop) +snippet forr + for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) { + ${4:$1[$2]} + }; +# while (...) {...} +snippet wh + while (${1:/* condition */}) { + ${2:/* code */} + } +# do...while +snippet do + do { + ${2:/* code */} + } while (${1:/* condition */}); +# Object Method +snippet :f + ${1:method_name}: function(${2:attribute}) { + ${4} + }${3:,} +# setTimeout function +snippet timeout + setTimeout(function() {${3}}${2}, ${1:10}; +# Get Elements +snippet get + getElementsBy${1:TagName}('${2}')${3} +# Get Element +snippet gett + getElementBy${1:Id}('${2}')${3} diff --git a/.vim/bundle/vim-snipmate/snippets/perl.snippets b/.vim/bundle/vim-snipmate/snippets/perl.snippets new file mode 100644 index 0000000..cf8f9fc --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/perl.snippets @@ -0,0 +1,91 @@ +# #!/usr/bin/perl +snippet #! + #!/usr/bin/perl + +# Hash Pointer +snippet . + => +# Function +snippet sub + sub ${1:function_name} { + ${2:#body ...} + } +# Conditional +snippet if + if (${1}) { + ${2:# body...} + } +# Conditional if..else +snippet ife + if (${1}) { + ${2:# body...} + } else { + ${3:# else...} + } +# Conditional if..elsif..else +snippet ifee + if (${1}) { + ${2:# body...} + } elsif (${3}) { + ${4:# elsif...} + } else { + ${5:# else...} + } +# Conditional One-line +snippet xif + ${1:expression} if ${2:condition};${3} +# Unless conditional +snippet unless + unless (${1}) { + ${2:# body...} + } +# Unless conditional One-line +snippet xunless + ${1:expression} unless ${2:condition};${3} +# Try/Except +snippet eval + eval { + ${1:# do something risky...} + }; + if ($@) { + ${2:# handle failure...} + } +# While Loop +snippet wh + while (${1}) { + ${2:# body...} + } +# While Loop One-line +snippet xwh + ${1:expression} while ${2:condition};${3} +# For Loop +snippet for + for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) { + ${4:# body...} + } +# Foreach Loop +snippet fore + foreach my $${1:x} (@${2:array}) { + ${3:# body...} + } +# Foreach Loop One-line +snippet xfore + ${1:expression} foreach @${2:array};${3} +# Package +snippet cl + package ${1:ClassName}; + + use base qw(${2:ParentClass}); + + sub new { + my $class = shift; + $class = ref $class if ref $class; + my $self = bless {}, $class; + $self; + } + + 1;${3} +# Read File +snippet slurp + my $${1:var}; + { local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = ; close FILE }${3} diff --git a/.vim/bundle/vim-snipmate/snippets/php.snippets b/.vim/bundle/vim-snipmate/snippets/php.snippets new file mode 100644 index 0000000..3ce9e26 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/php.snippets @@ -0,0 +1,216 @@ +snippet php + +snippet ec + echo "${1:string}"${2}; +snippet inc + include '${1:file}';${2} +snippet inc1 + include_once '${1:file}';${2} +snippet req + require '${1:file}';${2} +snippet req1 + require_once '${1:file}';${2} +# $GLOBALS['...'] +snippet globals + $GLOBALS['${1:variable}']${2: = }${3:something}${4:;}${5} +snippet $_ COOKIE['...'] + $_COOKIE['${1:variable}']${2} +snippet $_ ENV['...'] + $_ENV['${1:variable}']${2} +snippet $_ FILES['...'] + $_FILES['${1:variable}']${2} +snippet $_ Get['...'] + $_GET['${1:variable}']${2} +snippet $_ POST['...'] + $_POST['${1:variable}']${2} +snippet $_ REQUEST['...'] + $_REQUEST['${1:variable}']${2} +snippet $_ SERVER['...'] + $_SERVER['${1:variable}']${2} +snippet $_ SESSION['...'] + $_SESSION['${1:variable}']${2} +# Start Docblock +snippet /* + /** + * ${1} + **/ +# Class - post doc +snippet doc_cp + /** + * ${1:undocumented class} + * + * @package ${2:default} + * @author ${3:`g:snips_author`} + **/${4} +# Class Variable - post doc +snippet doc_vp + /** + * ${1:undocumented class variable} + * + * @var ${2:string} + **/${3} +# Class Variable +snippet doc_v + /** + * ${3:undocumented class variable} + * + * @var ${4:string} + **/ + ${1:var} $${2};${5} +# Class +snippet doc_c + /** + * ${3:undocumented class} + * + * @packaged ${4:default} + * @author ${5:`g:snips_author`} + **/ + ${1:}class ${2:} + {${6} + } // END $1class $2 +# Constant Definition - post doc +snippet doc_dp + /** + * ${1:undocumented constant} + **/${2} +# Constant Definition +snippet doc_d + /** + * ${3:undocumented constant} + **/ + define(${1}, ${2});${4} +# Function - post doc +snippet doc_fp + /** + * ${1:undocumented function} + * + * @return ${2:void} + * @author ${3:`g:snips_author`} + **/${4} +# Function signature +snippet doc_s + /** + * ${4:undocumented function} + * + * @return ${5:void} + * @author ${6:`g:snips_author`} + **/ + ${1}function ${2}(${3});${7} +# Function +snippet doc_f + /** + * ${4:undocumented function} + * + * @return ${5:void} + * @author ${6:`g:snips_author`} + **/ + ${1}function ${2}(${3}) + {${7} + } +# Header +snippet doc_h + /** + * ${1} + * + * @author ${2:`g:snips_author`} + * @version ${3:$Id$} + * @copyright ${4:$2}, `strftime('%d %B, %Y')` + * @package ${5:default} + **/ + + /** + * Define DocBlock + *// +# Interface +snippet doc_i + /** + * ${2:undocumented class} + * + * @package ${3:default} + * @author ${4:`g:snips_author`} + **/ + interface ${1:} + {${5} + } // END interface $1 +# class ... +snippet class + /** + * ${1} + **/ + class ${2:ClassName} + { + ${3} + function ${4:__construct}(${5:argument}) + { + ${6:// code...} + } + } +# define(...) +snippet def + define('${1}'${2});${3} +# defined(...) +snippet def? + ${1}defined('${2}')${3} +snippet wh + while (${1:/* condition */}) { + ${2:// code...} + } +# do ... while +snippet do + do { + ${2:// code... } + } while (${1:/* condition */}); +snippet if + if (${1:/* condition */}) { + ${2:// code...} + } +snippet ife + if (${1:/* condition */}) { + ${2:// code...} + } else { + ${3:// code...} + } + ${4} +snippet else + else { + ${1:// code...} + } +snippet elseif + elseif (${1:/* condition */}) { + ${2:// code...} + } +# Tertiary conditional +snippet t + $${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};${5} +snippet switch + switch ($${1:variable}) { + case '${2:value}': + ${3:// code...} + break; + ${5} + default: + ${4:// code...} + break; + } +snippet case + case '${1:value}': + ${2:// code...} + break;${3} +snippet for + for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) { + ${4: // code...} + } +snippet foreach + foreach ($${1:variable} as $${2:key}) { + ${3:// code...} + } +snippet fun + ${1:public }function ${2:FunctionName}(${3}) + { + ${4:// code...} + } +# $... = array (...) +snippet array + $${1:arrayName} = array('${2}' => ${3});${4} diff --git a/.vim/bundle/vim-snipmate/snippets/python.snippets b/.vim/bundle/vim-snipmate/snippets/python.snippets new file mode 100644 index 0000000..d511184 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/python.snippets @@ -0,0 +1,86 @@ +snippet #! + #!/usr/bin/python + +snippet imp + import ${1:module} +# Module Docstring +snippet docs + ''' + File: ${1:`Filename('$1.py', 'foo.py')`} + Author: ${2:`g:snips_author`} + Description: ${3} + ''' +snippet wh + while ${1:condition}: + ${2:# code...} +snippet for + for ${1:needle} in ${2:haystack}: + ${3:# code...} +# New Class +snippet cl + class ${1:ClassName}(${2:object}): + """${3:docstring for $1}""" + def __init__(self, ${4:arg}): + ${5:super($1, self).__init__()} + self.$4 = $4 + ${6} +# New Function +snippet def + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + """${3:docstring for $1}""" + ${4:pass} +snippet deff + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + ${3} +# New Method +snippet defs + def ${1:mname}(self, ${2:arg}): + ${3:pass} +# New Property +snippet property + def ${1:foo}(): + doc = "${2:The $1 property.}" + def fget(self): + ${3:return self._$1} + def fset(self, value): + ${4:self._$1 = value} +# Lambda +snippet ld + ${1:var} = lambda ${2:vars} : ${3:action} +snippet . + self. +snippet try Try/Except + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} +snippet try Try/Except/Else + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:pass} +snippet try Try/Except/Finally + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + finally: + ${5:pass} +snippet try Try/Except/Else/Finally + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:pass} + finally: + ${6:pass} +# if __name__ == '__main__': +snippet ifmain + if __name__ == '__main__': + ${1:main()} +# __magic__ +snippet _ + __${1:init}__${2} diff --git a/.vim/bundle/vim-snipmate/snippets/ruby.snippets b/.vim/bundle/vim-snipmate/snippets/ruby.snippets new file mode 100644 index 0000000..bf1d7f1 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/ruby.snippets @@ -0,0 +1,420 @@ +# #!/usr/bin/ruby +snippet #! + #!/usr/bin/ruby + +# New Block +snippet =b + =begin rdoc + ${1} + =end +snippet y + :yields: ${1:arguments} +snippet rb + #!/usr/bin/env ruby -wKU + +snippet req + require "${1}"${2} +snippet # + # => +snippet end + __END__ +snippet case + case ${1:object} + when ${2:condition} + ${3} + end +snippet when + when ${1:condition} + ${2} +snippet def + def ${1:method_name} + ${2} + end +snippet deft + def test_${1:case_name} + ${2} + end +snippet if + if ${1:condition} + ${2} + end +snippet ife + if ${1:condition} + ${2} + else + ${3} + end +snippet elsif + elsif ${1:condition} + ${2} +snippet unless + unless ${1:condition} + ${2} + end +snippet while + while ${1:condition} + ${2} + end +snippet until + until ${1:condition} + ${2} + end +snippet cla class .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} + ${2} + end +snippet cla class .. initialize .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} + def initialize(${2:args}) + ${3} + end + + + end +snippet cla class .. < ParentClass .. initialize .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} < ${2:ParentClass} + def initialize(${3:args}) + ${4} + end + + + end +snippet cla ClassName = Struct .. do .. end + ${1:`substitute(Filename(), '^.', '\u&', '')`} = Struct.new(:${2:attr_names}) do + def ${3:method_name} + ${4} + end + + + end +snippet cla class BlankSlate .. initialize .. end + class ${1:BlankSlate} + instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ } +snippet cla class << self .. end + class << ${1:self} + ${2} + end +# class .. < DelegateClass .. initialize .. end +snippet cla- + class ${1:`substitute(Filename(), '^.', '\u&', '')`} < DelegateClass(${2:ParentClass}) + def initialize(${3:args}) + super(${4:del_obj}) + + ${5} + end + + + end +snippet mod module .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + ${2} + end +snippet mod module .. module_function .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + module_function + + ${2} + end +snippet mod module .. ClassMethods .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + module ClassMethods + ${2} + end + + module InstanceMethods + + end + + def self.included(receiver) + receiver.extend ClassMethods + receiver.send :include, InstanceMethods + end + end +# attr_reader +snippet r + attr_reader :${1:attr_names} +# attr_writer +snippet w + attr_writer :${1:attr_names} +# attr_accessor +snippet rw + attr_accessor :${1:attr_names} +# include Enumerable +snippet Enum + include Enumerable + + def each(&block) + ${1} + end +# include Comparable +snippet Comp + include Comparable + + def <=>(other) + ${1} + end +# extend Forwardable +snippet Forw- + extend Forwardable +# def self +snippet defs + def self.${1:class_method_name} + ${2} + end +# def method_missing +snippet defmm + def method_missing(meth, *args, &blk) + ${1} + end +snippet defd + def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name} +snippet defds + def_delegators :${1:@del_obj}, :${2:del_methods} +snippet am + alias_method :${1:new_name}, :${2:old_name} +snippet app + if __FILE__ == $PROGRAM_NAME + ${1} + end +# usage_if() +snippet usai + if ARGV.${1} + abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3} + end +# usage_unless() +snippet usau + unless ARGV.${1} + abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3} + end +snippet array + Array.new(${1:10}) { |${2:i}| ${3} } +snippet hash + Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} } +snippet file File.foreach() { |line| .. } + File.foreach(${1:"path/to/file"}) { |${2:line}| ${3} } +snippet file File.read() + File.read(${1:"path/to/file"})${2} +snippet Dir Dir.global() { |file| .. } + Dir.glob(${1:"dir/glob/*"}) { |${2:file}| ${3} } +snippet Dir Dir[".."] + Dir[${1:"glob/**/*.rb"}]${2} +snippet dir + Filename.dirname(__FILE__) +snippet deli + delete_if { |${1:e}| ${2} } +snippet fil + fill(${1:range}) { |${2:i}| ${3} } +# flatten_once() +snippet flao + inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3} +snippet zip + zip(${1:enums}) { |${2:row}| ${3} } +# downto(0) { |n| .. } +snippet dow + downto(${1:0}) { |${2:n}| ${3} } +snippet ste + step(${1:2}) { |${2:n}| ${3} } +snippet tim + times { |${1:n}| ${2} } +snippet upt + upto(${1:1.0/0.0}) { |${2:n}| ${3} } +snippet loo + loop { ${1} } +snippet ea + each { |${1:e}| ${2} } +snippet eab + each_byte { |${1:byte}| ${2} } +snippet eac- each_char { |chr| .. } + each_char { |${1:chr}| ${2} } +snippet eac- each_cons(..) { |group| .. } + each_cons(${1:2}) { |${2:group}| ${3} } +snippet eai + each_index { |${1:i}| ${2} } +snippet eak + each_key { |${1:key}| ${2} } +snippet eal + each_line { |${1:line}| ${2} } +snippet eap + each_pair { |${1:name}, ${2:val}| ${3} } +snippet eas- + each_slice(${1:2}) { |${2:group}| ${3} } +snippet eav + each_value { |${1:val}| ${2} } +snippet eawi + each_with_index { |${1:e}, ${2:i}| ${3} } +snippet reve + reverse_each { |${1:e}| ${2} } +snippet inj + inject(${1:init}) { |${2:mem}, ${3:var}| ${4} } +snippet map + map { |${1:e}| ${2} } +snippet mapwi- + enum_with_index.map { |${1:e}, ${2:i}| ${3} } +snippet sor + sort { |a, b| ${1} } +snippet sorb + sort_by { |${1:e}| ${2} } +snippet ran + sort_by { rand } +snippet all + all? { |${1:e}| ${2} } +snippet any + any? { |${1:e}| ${2} } +snippet cl + classify { |${1:e}| ${2} } +snippet col + collect { |${1:e}| ${2} } +snippet det + detect { |${1:e}| ${2} } +snippet fet + fetch(${1:name}) { |${2:key}| ${3} } +snippet fin + find { |${1:e}| ${2} } +snippet fina + find_all { |${1:e}| ${2} } +snippet gre + grep(${1:/pattern/}) { |${2:match}| ${3} } +snippet sub + ${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} } +snippet sca + scan(${1:/pattern/}) { |${2:match}| ${3} } +snippet max + max { |a, b|, ${1} } +snippet min + min { |a, b|, ${1} } +snippet par + partition { |${1:e}|, ${2} } +snippet rej + reject { |${1:e}|, ${2} } +snippet sel + select { |${1:e}|, ${2} } +snippet lam + lambda { |${1:args}| ${2} } +snippet do + do |${1:variable}| + ${2} + end +snippet : + :${1:key} => ${2:"value"}${3} +snippet ope + open(${1:"path/or/url/or/pipe"}, "${2:w}") { |${3:io}| ${4} } +# path_from_here() +snippet patfh + File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2} +# unix_filter {} +snippet unif + ARGF.each_line${1} do |${2:line}| + ${3} + end +# option_parse {} +snippet optp + require "optparse" + + options = {${1:default => "args"}} + + ARGV.options do |opts| + opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} +snippet opt + opts.on( "-${1:o}", "--${2:long-option-name}", ${3:String}, + "${4:Option description.}") do |${5:opt}| + ${6} + end +snippet tc + require "test/unit" + + require "${1:library_file_name}" + + class Test${2:$1} < Test::Unit::TestCase + def test_${3:case_name} + ${4} + end + end +snippet ts + require "test/unit" + + require "tc_${1:test_case_file}" + require "tc_${2:test_case_file}"${3} +snippet as + assert(${1:test}, "${2:Failure message.}")${3} +snippet ase + assert_equal(${1:expected}, ${2:actual})${3} +snippet asne + assert_not_equal(${1:unexpected}, ${2:actual})${3} +snippet asid + assert_in_delta(${1:expected_float}, ${2:actual_float}, ${3:2 ** -20})${4} +snippet asio + assert_instance_of(${1:ExpectedClass}, ${2:actual_instance})${3} +snippet asko + assert_kind_of(${1:ExpectedKind}, ${2:actual_instance})${3} +snippet asn + assert_nil(${1:instance})${2} +snippet asnn + assert_not_nil(${1:instance})${2} +snippet asm + assert_match(/${1:expected_pattern}/, ${2:actual_string})${3} +snippet asnm + assert_no_match(/${1:unexpected_pattern}/, ${2:actual_string})${3} +snippet aso + assert_operator(${1:left}, :${2:operator}, ${3:right})${4} +snippet asr + assert_raise(${1:Exception}) { ${2} } +snippet asnr + assert_nothing_raised(${1:Exception}) { ${2} } +snippet asrt + assert_respond_to(${1:object}, :${2:method})${3} +snippet ass assert_same(..) + assert_same(${1:expected}, ${2:actual})${3} +snippet ass assert_send(..) + assert_send([${1:object}, :${2:message}, ${3:args}])${4} +snippet asns + assert_not_same(${1:unexpected}, ${2:actual})${3} +snippet ast + assert_throws(:${1:expected}) { ${2} } +snippet asnt + assert_nothing_thrown { ${1} } +snippet fl + flunk("${1:Failure message.}")${2} +# Benchmark.bmbm do .. end +snippet bm- + TESTS = ${1:10_000} + Benchmark.bmbm do |results| + ${2} + end +snippet rep + results.report("${1:name}:") { TESTS.times { ${2} }} +# Marshal.dump(.., file) +snippet Md + File.open(${1:"path/to/file.dump"}, "wb") { |${2:file}| Marshal.dump(${3:obj}, $2) }${4} +# Mashal.load(obj) +snippet Ml + File.open(${1:"path/to/file.dump"}, "rb") { |${2:file}| Marshal.load($2) }${3} +# deep_copy(..) +snippet deec + Marshal.load(Marshal.dump(${1:obj_to_copy}))${2} +snippet Pn- + PStore.new(${1:"file_name.pstore"})${2} +snippet tra + transaction(${1:true}) { ${2} } +# xmlread(..) +snippet xml- + REXML::Document.new(File.read(${1:"path/to/file"}))${2} +# xpath(..) { .. } +snippet xpa + elements.each(${1:"//Xpath"}) do |${2:node}| + ${3} + end +# class_from_name() +snippet clafn + split("::").inject(Object) { |par, const| par.const_get(const) } +# singleton_class() +snippet sinc + class << self; self end +snippet nam + namespace :${1:`Filename()`} do + ${2} + end +snippet tas + desc "${1:Task description\}" + task :${2:task_name => [:dependent, :tasks]} do + ${3} + end diff --git a/.vim/bundle/vim-snipmate/snippets/sh.snippets b/.vim/bundle/vim-snipmate/snippets/sh.snippets new file mode 100644 index 0000000..0ef01a2 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/sh.snippets @@ -0,0 +1,39 @@ +# #!/bin/sh +snippet #! + #!/bin/sh + +snippet if + if [[ ${1:condition} ]]; then + ${2:#statements} + fi +snippet elif + elif [[ ${1:condition} ]]; then + ${2:#statements} +snippet for + for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do + ${3:#statements} + done +snippet wh + while [[ ${1:condition} ]]; do + ${2:#statements} + done +snippet until + until [[ ${1:condition} ]]; do + ${2:#statements} + done +snippet case + case ${1:word} in + ${2:pattern}) + ${3};; + esac +snippet getopt + while getopts ao: name + do + case $name in + a) flag=1 ;; + o) oarg=$OPTARG ;; + ?) echo "Usage: ..."; exit 2 ;; + esac + done + shift $(($OPTIND - 1)) + echo "Non-option arguments: " "$@" diff --git a/.vim/bundle/vim-snipmate/snippets/snippet.snippets b/.vim/bundle/vim-snipmate/snippets/snippet.snippets new file mode 100644 index 0000000..854c058 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/snippet.snippets @@ -0,0 +1,7 @@ +# snippets for making snippets :) +snippet snip + snippet ${1:trigger} + ${2} +snippet msnip + snippet ${1:trigger} ${2:description} + ${3} diff --git a/.vim/bundle/vim-snipmate/snippets/tcl.snippets b/.vim/bundle/vim-snipmate/snippets/tcl.snippets new file mode 100644 index 0000000..bee2ef8 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/tcl.snippets @@ -0,0 +1,92 @@ +# #!/usr/bin/tclsh +snippet #! + #!/usr/bin/tclsh + +# Process +snippet pro + proc ${1:function_name} {${2:args}} { + ${3:#body ...} + } +#xif +snippet xif + ${1:expr}? ${2:true} : ${3:false} +# Conditional +snippet if + if {${1}} { + ${2:# body...} + } +# Conditional if..else +snippet ife + if {${1}} { + ${2:# body...} + } else { + ${3:# else...} + } +# Conditional if..elsif..else +snippet ifee + if {${1}} { + ${2:# body...} + } elseif {${3}} { + ${4:# elsif...} + } else { + ${5:# else...} + } +# If catch then +snippet ifc + if { [catch {${1:#do something...}} ${2:err}] } { + ${3:# handle failure...} + } +# Catch +snippet catch + catch {${1}} ${2:err} ${3:options} +# While Loop +snippet wh + while {${1}} { + ${2:# body...} + } +# For Loop +snippet for + for {set ${2:var} 0} {$$2 < ${1:count}} {${3:incr} $2} { + ${4:# body...} + } +# Foreach Loop +snippet fore + foreach ${1:x} {${2:#list}} { + ${3:# body...} + } +# after ms script... +snippet af + after ${1:ms} ${2:#do something} +# after cancel id +snippet afc + after cancel ${1:id or script} +# after idle +snippet afi + after idle ${1:script} +# after info id +snippet afin + after info ${1:id} +# Expr +snippet exp + expr {${1:#expression here}} +# Switch +snippet sw + switch ${1:var} { + ${3:pattern 1} { + ${4:#do something} + } + default { + ${2:#do something} + } + } +# Case +snippet ca + ${1:pattern} { + ${2:#do something} + }${3} +# Namespace eval +snippet ns + namespace eval ${1:path} {${2:#script...}} +# Namespace current +snippet nsc + namespace current diff --git a/.vim/bundle/vim-snipmate/snippets/tex.snippets b/.vim/bundle/vim-snipmate/snippets/tex.snippets new file mode 100644 index 0000000..22f7316 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/tex.snippets @@ -0,0 +1,115 @@ +# \begin{}...\end{} +snippet begin + \begin{${1:env}} + ${2} + \end{$1} +# Tabular +snippet tab + \begin{${1:tabular}}{${2:c}} + ${3} + \end{$1} +# Align(ed) +snippet ali + \begin{align${1:ed}} + ${2} + \end{align$1} +# Gather(ed) +snippet gat + \begin{gather${1:ed}} + ${2} + \end{gather$1} +# Equation +snippet eq + \begin{equation} + ${1} + \end{equation} +# Unnumbered Equation +snippet \ + \\[ + ${1} + \\] +# Enumerate +snippet enum + \begin{enumerate} + \item ${1} + \end{enumerate} +# Itemize +snippet item + \begin{itemize} + \item ${1} + \end{itemize} +# Description +snippet desc + \begin{description} + \item[${1}] ${2} + \end{description} +# Matrix +snippet mat + \begin{${1:p/b/v/V/B/small}matrix} + ${2} + \end{$1matrix} +# Cases +snippet cas + \begin{cases} + ${1:equation}, &\text{ if }${2:case}\\ + ${3} + \end{cases} +# Split +snippet spl + \begin{split} + ${1} + \end{split} +# Part +snippet part + \part{${1:part name}} % (fold) + \label{prt:${2:$1}} + ${3} + % part $2 (end) +# Chapter +snippet cha + \chapter{${1:chapter name}} % (fold) + \label{cha:${2:$1}} + ${3} + % chapter $2 (end) +# Section +snippet sec + \section{${1:section name}} % (fold) + \label{sec:${2:$1}} + ${3} + % section $2 (end) +# Sub Section +snippet sub + \subsection{${1:subsection name}} % (fold) + \label{sub:${2:$1}} + ${3} + % subsection $2 (end) +# Sub Sub Section +snippet subs + \subsubsection{${1:subsubsection name}} % (fold) + \label{ssub:${2:$1}} + ${3} + % subsubsection $2 (end) +# Paragraph +snippet par + \paragraph{${1:paragraph name}} % (fold) + \label{par:${2:$1}} + ${3} + % paragraph $2 (end) +# Sub Paragraph +snippet subp + \subparagraph{${1:subparagraph name}} % (fold) + \label{subp:${2:$1}} + ${3} + % subparagraph $2 (end) +snippet itd + \item[${1:description}] ${2:item} +snippet figure + ${1:Figure}~\ref{${2:fig:}}${3} +snippet table + ${1:Table}~\ref{${2:tab:}}${3} +snippet listing + ${1:Listing}~\ref{${2:list}}${3} +snippet section + ${1:Section}~\ref{${2:sec:}}${3} +snippet page + ${1:page}~\pageref{${2}}${3} diff --git a/.vim/bundle/vim-snipmate/snippets/vim.snippets b/.vim/bundle/vim-snipmate/snippets/vim.snippets new file mode 100644 index 0000000..64e7807 --- /dev/null +++ b/.vim/bundle/vim-snipmate/snippets/vim.snippets @@ -0,0 +1,32 @@ +snippet header + " File: ${1:`expand('%:t')`} + " Author: ${2:`g:snips_author`} + " Description: ${3} + ${4:" Last Modified: `strftime("%B %d, %Y")`} +snippet guard + if exists('${1:did_`Filename()`}') || &cp${2: || version < 700} + finish + endif + let $1 = 1${3} +snippet f + fun ${1:function_name}(${2}) + ${3:" code} + endf +snippet for + for ${1:needle} in ${2:haystack} + ${3:" code} + endfor +snippet wh + while ${1:condition} + ${2:" code} + endw +snippet if + if ${1:condition} + ${2:" code} + endif +snippet ife + if ${1:condition} + ${2} + else + ${3} + endif diff --git a/.vim/bundle/vim-snipmate/syntax/snippet.vim b/.vim/bundle/vim-snipmate/syntax/snippet.vim new file mode 100644 index 0000000..5e919e7 --- /dev/null +++ b/.vim/bundle/vim-snipmate/syntax/snippet.vim @@ -0,0 +1,19 @@ +" Syntax highlighting for snippet files (used for snipMate.vim) +" Hopefully this should make snippets a bit nicer to write! +syn match snipComment '^#.*' +syn match placeHolder '\${\d\+\(:.\{-}\)\=}' contains=snipCommand +syn match tabStop '\$\d\+' +syn match snipCommand '`.\{-}`' +syn match snippet '^snippet.*' transparent contains=multiSnipText,snipKeyword +syn match multiSnipText '\S\+ \zs.*' contained +syn match snipKeyword '^snippet'me=s+8 contained +syn match snipError "^[^#s\t].*$" + +hi link snipComment Comment +hi link multiSnipText String +hi link snipKeyword Keyword +hi link snipComment Comment +hi link placeHolder Special +hi link tabStop Special +hi link snipCommand String +hi link snipError Error diff --git a/.vim/bundle/vim-tagbar/autoload/tagbar.vim b/.vim/bundle/vim-tagbar/autoload/tagbar.vim new file mode 100644 index 0000000..7377016 --- /dev/null +++ b/.vim/bundle/vim-tagbar/autoload/tagbar.vim @@ -0,0 +1,3508 @@ +" ============================================================================ +" File: tagbar.vim +" Description: List the current file's tags in a sidebar, ordered by class etc +" Author: Jan Larres +" Licence: Vim licence +" Website: http://majutsushi.github.com/tagbar/ +" Version: 2.7 +" Note: This plugin was heavily inspired by the 'Taglist' plugin by +" Yegappan Lakshmanan and uses a small amount of code from it. +" +" Original taglist copyright notice: +" Permission is hereby granted to use and distribute this code, +" with or without modifications, provided that this copyright +" notice is copied with it. Like anything else that's free, +" taglist.vim is provided *as is* and comes with no warranty of +" any kind, either expressed or implied. In no event will the +" copyright holder be liable for any damamges resulting from the +" use of this software. +" ============================================================================ + +scriptencoding utf-8 + +" Initialization {{{1 + +" If another plugin calls an autoloaded Tagbar function on startup before the +" plugin/tagbar.vim file got loaded, load it explicitly +if exists(':Tagbar') == 0 + runtime plugin/tagbar.vim +endif + +if exists(':Tagbar') == 0 + echomsg 'Tagbar: Could not load plugin code, check your runtimepath!' + finish +endif + +" Basic init {{{2 + +redir => s:ftype_out +silent filetype +redir END +if s:ftype_out !~# 'detection:ON' + echomsg 'Tagbar: Filetype detection is turned off, skipping plugin' + unlet s:ftype_out + finish +endif +unlet s:ftype_out + +let g:tagbar#icon_closed = g:tagbar_iconchars[0] +let g:tagbar#icon_open = g:tagbar_iconchars[1] + +let s:type_init_done = 0 +let s:autocommands_done = 0 +let s:statusline_in_use = 0 +let s:init_done = 0 + +" 0: not checked yet; 1: checked and found; 2: checked and not found +let s:checked_ctags = 0 +let s:checked_ctags_types = 0 +let s:ctags_is_uctags = 0 + +let s:new_window = 1 +let s:is_maximized = 0 +let s:winrestcmd = '' +let s:short_help = 1 +let s:nearby_disabled = 0 +let s:paused = 0 +let s:pwin_by_tagbar = 0 +let s:buffer_seqno = 0 +let s:vim_quitting = 0 +let s:last_alt_bufnr = -1 + +let s:window_expanded = 0 +let s:expand_bufnr = -1 +let s:window_pos = { + \ 'pre' : { 'x' : 0, 'y' : 0 }, + \ 'post' : { 'x' : 0, 'y' : 0 } +\} + +let s:delayed_update_files = [] + +let g:loaded_tagbar = 1 + +let s:last_highlight_tline = 0 + +let s:warnings = { + \ 'type': [], + \ 'encoding': 0 +\ } + +" s:Init() {{{2 +function! s:Init(silent) abort + if s:checked_ctags == 2 && a:silent + return 0 + elseif s:checked_ctags != 1 + if !s:CheckForExCtags(a:silent) + return 0 + endif + endif + + if !s:type_init_done + call s:InitTypes() + endif + + if !s:autocommands_done + call s:CreateAutocommands() + call s:AutoUpdate(fnamemodify(expand('%'), ':p'), 0) + endif + + let s:init_done = 1 + return 1 +endfunction + +" s:InitTypes() {{{2 +function! s:InitTypes() abort + call tagbar#debug#log('Initializing types') + + let supported_types = s:GetSupportedFiletypes() + + if s:ctags_is_uctags + let s:known_types = tagbar#types#uctags#init(supported_types) + else + let s:known_types = tagbar#types#ctags#init(supported_types) + endif + + " Use dart_ctags if available + let dart_ctags = s:CheckFTCtags('dart_ctags', 'dart') + if dart_ctags !=# '' + let supported_types['dart'] = 1 + call tagbar#debug#log('Detected dart_ctags, overriding typedef') + let type_dart = tagbar#prototypes#typeinfo#new() + let type_dart.ctagstype = 'dart' + let type_dart.kinds = [ + \ {'short' : 'i', 'long' : 'imports', 'fold' : 1, 'stl' : 0}, + \ {'short' : 'C', 'long' : 'consts', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'F', 'long' : 'functions', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'f', 'long' : 'fields', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'm', 'long' : 'methods', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'M', 'long' : 'static methods', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'r', 'long' : 'constructors', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'o', 'long' : 'operators', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'g', 'long' : 'getters', 'fold' : 0, 'stl' : 0}, + \ {'short' : 's', 'long' : 'setters', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'a', 'long' : 'abstract functions', 'fold' : 0, 'stl' : 0}, + \ ] + let type_dart.sro = ':' + let type_dart.kind2scope = { + \ 'c' : 'class' + \ } + let type_dart.scope2kind = { + \ 'class' : 'c' + \ } + let type_dart.ctagsbin = dart_ctags + let type_dart.ctagsargs = '-l' + let type_dart.ftype = 'dart' + call type_dart.createKinddict() + let s:known_types.dart = type_dart + endif + + " Use jsctags/doctorjs if available + let jsctags = s:CheckFTCtags('jsctags', 'javascript') + if jsctags !=# '' + call tagbar#debug#log('Detected jsctags, overriding typedef') + let type_javascript = tagbar#prototypes#typeinfo#new() + let type_javascript.ctagstype = 'javascript' + let type_javascript.kinds = [ + \ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1} + \ ] + let type_javascript.sro = '.' + let type_javascript.kind2scope = { + \ 'v' : 'namespace', + \ 'f' : 'namespace' + \ } + let type_javascript.scope2kind = { + \ 'namespace' : 'f' + \ } + let type_javascript.ctagsbin = jsctags + let type_javascript.ctagsargs = '-f -' + let type_javascript.ftype = 'javascript' + call type_javascript.createKinddict() + let s:known_types.javascript = type_javascript + endif + + " Use gotags if available + let gotags = s:CheckFTCtags('gotags', 'go') + if gotags !=# '' + call tagbar#debug#log('Detected gotags, overriding typedef') + let type_go = tagbar#prototypes#typeinfo#new() + let type_go.ctagstype = 'go' + let type_go.kinds = [ + \ {'short' : 'p', 'long' : 'package', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'i', 'long' : 'imports', 'fold' : 1, 'stl' : 0}, + \ {'short' : 'c', 'long' : 'constants', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}, + \ {'short' : 't', 'long' : 'types', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'n', 'long' : 'intefaces', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'w', 'long' : 'fields', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'e', 'long' : 'embedded', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'm', 'long' : 'methods', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'r', 'long' : 'constructors', 'fold' : 0, 'stl' : 0}, + \ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 0}, + \ ] + let type_go.sro = '.' + let type_go.kind2scope = { + \ 't' : 'ctype', + \ 'n' : 'ntype' + \ } + let type_go.scope2kind = { + \ 'ctype' : 't', + \ 'ntype' : 'n' + \ } + let type_go.ctagsbin = gotags + let type_go.ctagsargs = '-sort -silent' + let type_go.ftype = 'go' + call type_go.createKinddict() + let s:known_types.go = type_go + endif + + call s:LoadUserTypeDefs() + + " Add an 'unknown' kind to the types for pseudotags that we can't + " determine the correct kind for since they don't have any children that + " are not pseudotags and that therefore don't provide scope information + for typeinfo in values(s:known_types) + if has_key(typeinfo, 'kind2scope') + let unknown_kind = + \ {'short' : '?', 'long' : 'unknown', 'fold' : 0, 'stl' : 1} + " Check for existence first since some types exist under more than + " one name + if index(typeinfo.kinds, unknown_kind) == -1 + call add(typeinfo.kinds, unknown_kind) + endif + let typeinfo.kind2scope['?'] = 'unknown' + endif + endfor + + let s:type_init_done = 1 +endfunction + +" s:LoadUserTypeDefs() {{{2 +function! s:LoadUserTypeDefs(...) abort + if a:0 > 0 + let type = a:1 + + let defdict = {} + let defdict[type] = g:tagbar_type_{type} + else + let defdict = tagbar#getusertypes() + endif + + let transformed = {} + for [type, def] in items(defdict) + let transformed[type] = s:TransformUserTypeDef(def) + let transformed[type].ftype = type + endfor + + for [key, value] in items(transformed) + call tagbar#debug#log("Initializing user type '" . key . "'") + if !has_key(s:known_types, key) || get(value, 'replace', 0) + let s:known_types[key] = tagbar#prototypes#typeinfo#new(value) + else + call extend(s:known_types[key], value) + endif + call s:known_types[key].createKinddict() + endfor +endfunction + +" s:TransformUserTypeDef() {{{2 +" Transform the user definitions into the internal format +function! s:TransformUserTypeDef(def) abort + let newdef = copy(a:def) + + if has_key(a:def, 'kinds') + let newdef.kinds = [] + let kinds = a:def.kinds + for kind in kinds + let kindlist = split(kind, ':') + let kinddict = {'short' : kindlist[0], 'long' : kindlist[1]} + let kinddict.fold = get(kindlist, 2, 0) + let kinddict.stl = get(kindlist, 3, 1) + call add(newdef.kinds, kinddict) + endfor + endif + + " If the user only specified one of kind2scope and scope2kind then use it + " to generate the respective other + if has_key(a:def, 'kind2scope') && !has_key(a:def, 'scope2kind') + let newdef.scope2kind = {} + for [key, value] in items(a:def.kind2scope) + let newdef.scope2kind[value] = key + endfor + elseif has_key(a:def, 'scope2kind') && !has_key(a:def, 'kind2scope') + let newdef.kind2scope = {} + for [key, value] in items(a:def.scope2kind) + let newdef.kind2scope[value] = key + endfor + endif + + return newdef +endfunction + +" s:RestoreSession() {{{2 +" Properly restore Tagbar after a session got loaded +function! s:RestoreSession() abort + if s:init_done + call tagbar#debug#log('Tagbar already initialized; not restoring session') + return + endif + + call tagbar#debug#log('Restoring session') + + let curfile = fnamemodify(bufname('%'), ':p') + + let tagbarwinnr = bufwinnr(s:TagbarBufName()) + if tagbarwinnr == -1 + " Tagbar wasn't open in the saved session, nothing to do + return + endif + + let in_tagbar = 1 + if winnr() != tagbarwinnr + call s:goto_win(tagbarwinnr, 1) + let in_tagbar = 0 + endif + + let s:last_autofocus = 0 + + call s:Init(0) + + call s:InitWindow(g:tagbar_autoclose) + + call s:AutoUpdate(curfile, 0) + + if !in_tagbar + call s:goto_win('p') + endif +endfunction + +" s:MapKeys() {{{2 +function! s:MapKeys() abort + call tagbar#debug#log('Mapping keys') + + nnoremap