├── .gitignore ├── autoload ├── file.vim ├── variable.vim ├── loclist.vim ├── quickfix.vim ├── rng.vim ├── scripts.vim ├── complete.vim ├── parse │ └── ini.vim ├── vimple │ ├── comparators.vim │ ├── history.vim │ ├── highlight.vim │ ├── scriptnames.vim │ ├── abbreviations.vim │ ├── marks.vim │ ├── version.vim │ ├── undolist.vim │ ├── map.vim │ ├── options.vim │ └── ls.vim ├── regex.vim ├── completers.vim ├── scope.vim ├── args.vim ├── ml │ ├── bayes.vim │ └── porter.vim ├── overlay.vim ├── list.vim ├── vimple.vim └── string.vim ├── test ├── ini_002_out.ini ├── ini_002.ini ├── Makefile ├── ini_001_out.ini ├── ini_001.ini ├── parse_ini_001.vim ├── parse_ini_002.vim ├── vimple001.vim ├── vimple002.vim ├── _setup.vim ├── README ├── buffer_list.vim └── string001.vim ├── ftplugin ├── vim_scope.vim └── python_scope.vim ├── syntax └── vimple_jumplist.vim ├── demo ├── oldfiles.vim ├── tagkinds.vim ├── iabbrevs.vim ├── global_marks.vim ├── identsearch.vim ├── helptoc.vim ├── spellsuggest.vim ├── tagsearch.vim ├── bufgrep.vim ├── jumplist.vim ├── changelist.vim └── calendar.vim ├── plugin ├── vimple.vim └── vimple-lib.vim ├── README.asciidoc └── doc ├── vimple_ls.txt └── vimple.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw? 2 | *.un? 3 | *.vba 4 | *.zip 5 | *.gz 6 | vimball.txt 7 | *.orig 8 | tags 9 | -------------------------------------------------------------------------------- /autoload/file.vim: -------------------------------------------------------------------------------- 1 | function! file#read(file) 2 | return filereadable(a:file) ? readfile(a:file) : [] 3 | endfunction 4 | -------------------------------------------------------------------------------- /test/ini_002_out.ini: -------------------------------------------------------------------------------- 1 | [s1] 2 | peeps = {'alice': {'age': 20, 'sex': 'female'}, 'bob': {'age': 20, 'sex': 'male'}} 3 | sep = \t 4 | lines = [1, 2, 5, 9, 10] 5 | -------------------------------------------------------------------------------- /test/ini_002.ini: -------------------------------------------------------------------------------- 1 | ; lists 2 | [s1] 3 | lines = [1, 2, 5, 9, 10] 4 | peeps = {'bob': {'age': 20, 'sex': 'male'}, 'alice': {'age': 20, 'sex': 'female'}} 5 | sep = \t 6 | -------------------------------------------------------------------------------- /autoload/variable.vim: -------------------------------------------------------------------------------- 1 | function! variable#type_to_string(var) 2 | return ['Number', 'String', 'Funcref', 'List', 'Dictionary', 'Float'][type(a:var)] 3 | endfunction 4 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | # Run tests 2 | # Barry Arthur, 2014-05-10 12:12 3 | 4 | all: 5 | runVimTests.sh -1 *.vim 6 | 7 | clean: 8 | rm *.tap *.msgout 9 | 10 | # vim:ft=make 11 | # 12 | -------------------------------------------------------------------------------- /test/ini_001_out.ini: -------------------------------------------------------------------------------- 1 | another var = with whitespace 2 | this_var = bare 3 | [section1] 4 | age = 10 5 | name = some 'string' here 6 | [section 2] 7 | age = 20 8 | name = some "other" string 9 | -------------------------------------------------------------------------------- /test/ini_001.ini: -------------------------------------------------------------------------------- 1 | ; ignore this 2 | ; and this 3 | 4 | this_var = bare 5 | another var = with whitespace 6 | 7 | [section1] 8 | name = some 'string' here 9 | age = 10 10 | 11 | [section 2] 12 | name = some "other" string 13 | age = 20 14 | -------------------------------------------------------------------------------- /ftplugin/vim_scope.vim: -------------------------------------------------------------------------------- 1 | function! Scope_vim() 2 | let scope = scope#inspect('^\s*fu\%[nction]!\?\s*\([a-zA-Z0-9_#.]\+\)', '^\s*endf\%[unction]') 3 | return ' ' . join(map(scope.stack, 'v:val.head_line_number . "," . v:val.tail_line_number . " " . v:val.head_string'), ' > ') 4 | endfunction 5 | -------------------------------------------------------------------------------- /test/parse_ini_001.vim: -------------------------------------------------------------------------------- 1 | call vimtest#StartTap() 2 | call vimtap#Plan(1) " <== XXX Keep plan number updated. XXX 3 | 4 | let ini_hash = parse#ini#from_file('ini_001.ini') 5 | call parse#ini#to_file(ini_hash, 'ini_001_out.ini') 6 | 7 | call Is(parse#ini#from_file('ini_001_out.ini'), ini_hash , 'round-trip') 8 | 9 | call vimtest#Quit() 10 | -------------------------------------------------------------------------------- /test/parse_ini_002.vim: -------------------------------------------------------------------------------- 1 | call vimtest#StartTap() 2 | call vimtap#Plan(1) " <== XXX Keep plan number updated. XXX 3 | 4 | let ini_hash = parse#ini#from_file('ini_002.ini') 5 | call parse#ini#to_file(ini_hash, 'ini_002_out.ini') 6 | 7 | call Is(parse#ini#from_file('ini_002_out.ini'), ini_hash , 'round-trip') 8 | 9 | call vimtest#Quit() 10 | -------------------------------------------------------------------------------- /syntax/vimple_jumplist.vim: -------------------------------------------------------------------------------- 1 | syn match VJL_X /^.\s*0\s\+/ conceal contained 2 | syn match VJL_L /^l \d\+\s\+/ conceal contained 3 | syn match VJL_F /^f \d\+\s\+/ conceal contained 4 | 5 | syn match VJL_TextLine /^l.*/ contains=VJL_L 6 | syn match VJL_FileLine /^f.*/ contains=VJL_F 7 | syn match VJL_CurrLine /^.\s*0.*/ contains=VJL_X 8 | 9 | hi link VJL_CurrLine Constant 10 | hi link VJL_TextLine String 11 | hi link VJL_FileLine Comment 12 | -------------------------------------------------------------------------------- /test/vimple001.vim: -------------------------------------------------------------------------------- 1 | call vimtest#StartTap() 2 | call vimtap#Plan(2) " <== XXX Keep plan number updated. XXX 3 | 4 | redir => test 5 | set filetype? 6 | redir END 7 | let result = vimple#redir('set filetype?') 8 | call Is(result, split(test, '\n'), '#redir()') 9 | unlet test 10 | unlet result 11 | 12 | let test = ' 12.35' 13 | let result = vimple#format('%8.2l', {'l': ['f', '12.3456']}, '') 14 | call Is(result, test, '#format()') 15 | unlet test 16 | unlet result 17 | 18 | call vimtest#Quit() 19 | -------------------------------------------------------------------------------- /ftplugin/python_scope.vim: -------------------------------------------------------------------------------- 1 | function! Scope_python() 2 | let class_scope = scope#inspect('^\s*class\s\+\([a-zA-Z0-9_.]\+\)', '\ze\n\(\s*class\|\S\)') 3 | let method_scope = scope#inspect('^\s*def\s\+\([a-zA-Z0-9_.]\+\)', '.\(\n\(\n\|\S\)\)\@=') 4 | return ' ' . join(map(class_scope.stack, 'v:val.head_line_number . "," . v:val.tail_line_number . " " . v:val.head_string'), ' :: ') 5 | \. ' >> ' . join(map(method_scope.stack, 'v:val.head_line_number . "," . v:val.tail_line_number . " " . v:val.head_string'), ' > ') 6 | endfunction 7 | -------------------------------------------------------------------------------- /test/vimple002.vim: -------------------------------------------------------------------------------- 1 | call vimtest#StartTap() 2 | call vimtap#Plan(2) " <== XXX Keep plan number updated. XXX 3 | 4 | hi VimpleTestHi term=bold,reverse cterm=bold ctermbg=239 gui=bold guibg=#4e4e4e 5 | 6 | call vimple#hl.update() 7 | let result = vimple#hl.filter_by_term('VimpleTestHi').to_l() 8 | 9 | call Is(len(result), 1, 'handle commas in highlights') 10 | call Is(result[0]['attrs'] 11 | \, 'term=bold,reverse cterm=bold ctermbg=239 gui=bold guibg=#4e4e4e' 12 | \, 'handle commas in highlights') 13 | 14 | call vimtest#Quit() 15 | 16 | -------------------------------------------------------------------------------- /test/_setup.vim: -------------------------------------------------------------------------------- 1 | let &rtp = expand(':p:h:h') . ',' . &rtp . ',' . expand(':p:h:h') . '/after' 2 | 3 | runtime plugin/vimple.vim 4 | runtime plugin/string.vim 5 | 6 | function! Ok(test, desc) 7 | return vimtap#Ok(a:test, '"' . escape(a:test, '"') . '"', a:desc) 8 | endfunction 9 | 10 | function! Is(got, expected, desc) 11 | return vimtap#Is(a:got, a:expected, '"' . escape(a:got, '"') . '"', a:desc) 12 | endfunction 13 | 14 | function! Isnt(got, unexpected, desc) 15 | return vimtap#Isnt(a:got, a:unexpected, '"' . escape(a:got, '"') . '"', a:desc) 16 | endfunction 17 | -------------------------------------------------------------------------------- /autoload/loclist.vim: -------------------------------------------------------------------------------- 1 | " location-list niceties (copied from autoload/loclist.vim) 2 | " Barry Arthur, Mar 2015 3 | 4 | function! loclist#bufnames() 5 | return uniq(sort(map(getloclist(0), 'bufname(v:val.bufnr)'))) 6 | endfunction 7 | 8 | function! loclist#to_args(global) 9 | let global = !empty(a:global) 10 | let arg_cmd = global ? 'args ' : 'arglocal ' 11 | exe arg_cmd . join(map(loclist#bufnames(), 'escape(v:val, " ")'), ' ') 12 | endfunction 13 | 14 | function! loclist#do(cmd) 15 | " create a new window so as not to interfere with user's arglist 16 | split 17 | call loclist#to_args(0) " 0 == local not global 18 | exe 'argdo ' . a:cmd 19 | close 20 | endfunction 21 | 22 | -------------------------------------------------------------------------------- /demo/oldfiles.vim: -------------------------------------------------------------------------------- 1 | " Better navigation of :oldfiles 2 | 3 | " In the overlay window: 4 | " loads the file under the cursor 5 | " q closes the overlay without action 6 | 7 | function! Oldfiles() 8 | call overlay#show( 9 | \ vimple#redir('oldfiles') 10 | \, { 11 | \ '' : ':call OldfilesAccept()' 12 | \ , 'q' : ':call overlay#close()' 13 | \ } 14 | \, {'filter' : 1, 'use_split' : 1}) 15 | endfunction 16 | 17 | function! OldfilesAccept() 18 | let old_file_number = matchstr(overlay#select_line(), '^\d\+') 19 | exe 'edit #<' . old_file_number 20 | endfunction 21 | 22 | command! -nargs=0 Oldfiles call Oldfiles() 23 | -------------------------------------------------------------------------------- /test/README: -------------------------------------------------------------------------------- 1 | The plugins runVimTests (http://www.vim.org/scripts/script.php?script_id=2565) 2 | and VimTAP (http://www.vim.org/scripts/script.php?script_id=2213) are needed to 3 | run these tests. 4 | 5 | Besides the _setup.vim configuration file present in this repo you need to 6 | create a global one and place it in the same dir where the runVimTests 7 | executable is located. Assuming the executable is at '~/bin/runVimTests' this 8 | global configuration file should be '~/bin/runVimTestsSetup.vim' and should 9 | have something like the following lines inside of it: 10 | 11 | " Prepend tests repos to &rtp 12 | let &runtimepath = '/path/to/runVimTests_dir,' . &rtp 13 | let &runtimepath = '/path/to/vimTAP_dir,' . &rtp 14 | -------------------------------------------------------------------------------- /autoload/quickfix.vim: -------------------------------------------------------------------------------- 1 | " quickfix niceties 2 | " Barry Arthur, Jan 2012 3 | 4 | " original idea from: 5 | " http://stackoverflow.com/questions/1830839/how-to-open-multiple-files-in-vim-after-vimgrep 6 | 7 | function! quickfix#bufnames() 8 | return uniq(sort(map(getqflist(), 'bufname(v:val.bufnr)'))) 9 | endfunction 10 | 11 | function! quickfix#to_args(global) 12 | let global = !empty(a:global) 13 | let arg_cmd = global ? 'args ' : 'arglocal ' 14 | exe arg_cmd . join(map(quickfix#bufnames(), 'escape(v:val, " ")'), ' ') 15 | endfunction 16 | 17 | function! quickfix#do(cmd) 18 | " create a new window so as not to interfere with user's arglist 19 | split 20 | call quickfix#to_args(0) " 0 == local not global 21 | exe 'argdo ' . a:cmd 22 | close 23 | endfunction 24 | -------------------------------------------------------------------------------- /test/buffer_list.vim: -------------------------------------------------------------------------------- 1 | call vimtest#StartTap() 2 | call vimtap#Plan(6) " <== XXX Keep plan number updated. XXX 3 | 4 | " silent! call vimple#redir('set') 5 | call Is(type(vimple#bl.buffers()), type({}), 'buffers() returns a dict') 6 | call vimtap#Diag(vimple#bl.to_s()) 7 | call Ok(vimple#bl.to_s() =~ '^ 1 %a\?\s\+".\{-}" line 1', 'Check to_s() output') 8 | 9 | let blist = vimple#bl.to_l() 10 | call Ok(len(blist) == 1, 'Check to_l() output.:'.string(blist).':') 11 | call Ok(has_key(blist[0], 'number') == 1, 'Check to_l() content.:'.string(blist).':') 12 | call Ok(blist[0]['number'] == 1, 'Check to_l() buffer number.:'.string(blist).':') 13 | 14 | new 15 | call vimple#bl.update() 16 | call Ok(len(vimple#bl.to_l()) == 2, 'update() works') 17 | 18 | call vimtest#Quit() 19 | 20 | -------------------------------------------------------------------------------- /autoload/rng.vim: -------------------------------------------------------------------------------- 1 | " George Marsaglia's Multiply-with-carry Random Number Generator 2 | " Modified to work within Vim's semantics 3 | let s:m_w = 1 + getpid() 4 | let s:m_z = localtime() 5 | 6 | " not sure of the wisdom of generating a full 32-bit RN here 7 | " and then using abs() on the sucker. Feedback welcome. 8 | function! rng#rand(...) 9 | if a:0 == 0 10 | let s:m_z = (36969 * and(s:m_z, 0xffff)) + (s:m_z / 65536) 11 | let s:m_w = (18000 * and(s:m_w, 0xffff)) + (s:m_w / 65536) 12 | return (s:m_z * 65536) + s:m_w " 32-bit result 13 | elseif a:0 == 1 " We return a number in [0, a:1] or [a:1, 0] 14 | return a:1 < 0 ? rng#rand(a:1,0) : rng#rand(0,a:1) 15 | else " if a:0 >= 2 16 | return abs(rng#rand()) % (abs(a:2 - a:1) + 1) + a:1 17 | endif 18 | endfunction 19 | -------------------------------------------------------------------------------- /demo/tagkinds.vim: -------------------------------------------------------------------------------- 1 | " TagKind shows an overlay containing the kind of tag requested 2 | 3 | " In the overlay window: 4 | " jumps to the current-line tag name 5 | " q closes the overlay without action 6 | 7 | function! TagKind(kind) 8 | let tags = sort(map(filter(taglist('.'), 'v:val.kind == "' . a:kind . '"'), 'v:val.name')) 9 | call overlay#show( 10 | \ tags 11 | \, { 12 | \ '' : ':call TagKindAccept()' 13 | \ , 'q' : ':call overlay#close()' 14 | \ } 15 | \, {'filter' : 0, 'use_split' : 1}) 16 | endfunction 17 | 18 | function! TagKindAccept() 19 | let tag = overlay#select_line() 20 | exe 'tjump ' . tag 21 | endfunction 22 | 23 | nnoremap tc :call TagKind('c') 24 | nnoremap tf :call TagKind('f') 25 | -------------------------------------------------------------------------------- /demo/iabbrevs.vim: -------------------------------------------------------------------------------- 1 | " Wanna choose from a list of abbreviations? 2 | 3 | " In the overlay window: 4 | " inserts the currently selected abbreviation expansion 5 | " q closes the overlay without action 6 | 7 | " functions {{{1 8 | 9 | function! Abbreviations() "{{{2 10 | call overlay#show( 11 | \ map(g:vimple#ab.update().to_l(), 'v:val["expansion"]') 12 | \, { 13 | \ '' : ':call AbbreviationsAccept()' 14 | \ , 'q' : ':call overlay#close()' 15 | \ } 16 | \, {'filter' : 0, 'use_split' : 1}) 17 | endfunction 18 | 19 | function! AbbreviationsAccept() "{{{2 20 | let line = overlay#select_line() 21 | exe 'norm! a' . line . " \l" 22 | startinsert 23 | endfunction 24 | 25 | " maps {{{1 26 | 27 | inoremap _ :call Abbreviations() 28 | 29 | " vim: fen fdm=marker 30 | -------------------------------------------------------------------------------- /demo/global_marks.vim: -------------------------------------------------------------------------------- 1 | " Wish you could jump to a global mark that's already open in another tabpage? 2 | 3 | " Ensure that: 4 | " set swb+=useopen,usetab 5 | 6 | " In the overlay window: 7 | " does a sbuffer to the current-line global-mark's filename 8 | " q closes the overlay without action 9 | 10 | function! GlobalMarks() 11 | let data = split(g:vimple#ma.update().global_marks().to_s(), "\n") 12 | call overlay#show( 13 | \ data 14 | \, { 15 | \ '' : ':call GlobalMarksAccept()' 16 | \ , 'q' : ':call overlay#close()' 17 | \ } 18 | \, {'filter' : 0, 'use_split' : 1}) 19 | endfunction 20 | 21 | function! GlobalMarksAccept() 22 | let file = matchstr(overlay#select_line(), '\s\zs\S\+$') 23 | silent! exe 'sbuffer ' . file 24 | endfunction 25 | 26 | nnoremap gg' :call GlobalMarks() 27 | -------------------------------------------------------------------------------- /demo/identsearch.vim: -------------------------------------------------------------------------------- 1 | " Are you bored with vanilla [I ? 2 | " Did the improvement above :help [i excite you only briefly? 3 | " Want a better experience? 4 | " Overlay is here for you. 5 | 6 | " In the overlay window: 7 | " You're prompted with a filter pattern. Use to cancel. 8 | " jumps to the current-line ident-search match 9 | " q closes the overlay without action 10 | 11 | function! IdentSearch() 12 | try 13 | let data = vimple#redir('norm! [I') 14 | catch '^Vim\%((\a\+)\)\=:E389:' 15 | echohl Warning 16 | echom 'Could not find pattern' 17 | echohl None 18 | return 19 | endtry 20 | call overlay#show( 21 | \ data 22 | \, { 23 | \ '' : ':call IdentSearchAccept()' 24 | \ , 'q' : ':call overlay#close()' 25 | \ } 26 | \, {'filter' : 1, 'use_split' : 1}) 27 | endfunction 28 | 29 | function! IdentSearchAccept() 30 | let num = matchstr(overlay#select_line(), '\d\+') 31 | exe 'silent! norm! ' . num . "[\t" 32 | endfunction 33 | 34 | nnoremap [I :call IdentSearch() 35 | -------------------------------------------------------------------------------- /demo/helptoc.vim: -------------------------------------------------------------------------------- 1 | " Jump to a help-tag entry in the current help file 2 | 3 | " In the overlay window: 4 | " You're prompted with a filter pattern. Use to cancel. 5 | " jumps to the tag beneath the cursor 6 | " q closes the overlay without action 7 | 8 | " functions {{{1 9 | 10 | function! HelpTOC() "{{{2 11 | call overlay#show( 12 | \ list#lspread(map(filter(string#scanner(getline(1, '$')).collect('\*\S\+\*'), 'v:val =~ "[a-z]"'), 'strpart(v:val, 1, len(v:val)-2)'), 3) 13 | \, { 14 | \ '' : ':exe "tag " . HelpTOCAccept()' 15 | \ , 'q' : ':call overlay#close()' 16 | \ } 17 | \, {'filter' : 1, 'use_split' : 1, 'setlocal tabstop=50' :-0}) 18 | endfunction 19 | 20 | function! HelpTOCAccept() 21 | let line = getline('.') 22 | let idx = strlen(substitute(line[:col('.')], '[^\t]', '', 'g')) 23 | let word_list = split(line, '\t') 24 | call overlay#close() 25 | return word_list[idx] 26 | endfunction 27 | 28 | " maps {{{1 29 | 30 | nnoremap t :call HelpTOC() 31 | 32 | " vim: fen fdm=marker 33 | -------------------------------------------------------------------------------- /demo/spellsuggest.vim: -------------------------------------------------------------------------------- 1 | " Are you bored with vanilla z= ? 2 | 3 | " In the overlay window: 4 | " replaces current word with word under cursor 5 | " q closes the overlay without action 6 | 7 | " functions {{{1 8 | 9 | function! GetSuggestions(ident) "{{{2 10 | let spell = &spell 11 | if ! spell 12 | set spell 13 | endif 14 | let suggestions = list#lspread(spellsuggest(a:ident), 5) 15 | if ! spell 16 | set nospell 17 | endif 18 | return suggestions 19 | endfunction 20 | 21 | function! SpellSuggest(ident) "{{{2 22 | call overlay#show( 23 | \ GetSuggestions(a:ident) 24 | \, { 25 | \ '' : ':call SpellSuggestAccept()' 26 | \ , 'q' : ':call overlay#close()' 27 | \ } 28 | \, {'filter' : 0, 'use_split' : 1}) 29 | endfunction 30 | 31 | function! SpellSuggestAccept() "{{{2 32 | let line = getline('.') 33 | let idx = strlen(substitute(line[:col('.')], '[^\t]', '', 'g')) 34 | let word_list = split(line, '\t') 35 | call overlay#close() 36 | let [r1, r2] = [@@, @-] 37 | exe 'norm! ciw' . word_list[idx] 38 | let [@@, @-] = [r1, r2] 39 | endfunction 40 | 41 | " maps {{{1 42 | 43 | nnoremap z= :call SpellSuggest(expand('')) 44 | 45 | " vim: fen fdm=marker 46 | -------------------------------------------------------------------------------- /demo/tagsearch.vim: -------------------------------------------------------------------------------- 1 | " Are you bored with vanilla g] ? 2 | " Did the improvement above :help g] excite you only briefly? 3 | " Want a better experience? 4 | " Overlay is here for you. 5 | 6 | " In the overlay window: 7 | " You're prompted with a filter pattern. Use to cancel. 8 | " jumps to the current-line tag-search match 9 | " q closes the overlay without action 10 | 11 | function! TagSearch() 12 | let ident = expand('') 13 | let s:tags = taglist(ident) 14 | if empty(s:tags) 15 | echohl Warning 16 | echom 'Tag not found: ' . ident 17 | echohl None 18 | return 19 | endif 20 | let data = map(copy(s:tags), 'v:key . " " . v:val.name . "\t" . v:val.filename') 21 | call overlay#show( 22 | \ data 23 | \, { 24 | \ '' : ':call TagSearchAccept()' 25 | \ , 'q' : ':call overlay#close()' 26 | \ } 27 | \, {'filter' : 1, 'use_split' : 1}) 28 | endfunction 29 | 30 | function! TagSearchAccept() 31 | let ident = matchstr(overlay#select_line(), '^\d\+') 32 | let fname = s:tags[ident].filename 33 | if bufnr(fname) == -1 34 | exec 'edit ' . fname 35 | else 36 | exec 'buffer ' . fname 37 | endif 38 | silent! exe s:tags[ident].cmd 39 | endfunction 40 | 41 | nnoremap g] :call TagSearch() 42 | -------------------------------------------------------------------------------- /demo/bufgrep.vim: -------------------------------------------------------------------------------- 1 | " Wanna grep your buffer and be able to jump to one of the matches quickly? 2 | " 3 | " Use bg or the :G command 4 | 5 | " In the overlay window: 6 | " You're prompted with a filter pattern. Use to cancel. 7 | " jumps to the current-line match 8 | " q closes the overlay without action 9 | 10 | function! BufGrep(pattern) 11 | let pattern = a:pattern 12 | let fc = pattern[0] 13 | let lc = pattern[-1] 14 | if fc !~ '[[:punct:]]' 15 | let fc = '/' 16 | let lc = '/' 17 | elseif fc != lc 18 | let lc = fc 19 | let pattern = pattern[1:] 20 | else 21 | let pattern = pattern[1:-2] 22 | endif 23 | let pattern = escape(pattern, fc) 24 | 25 | let data = vimple#redir('global ' . fc . pattern . lc . '#') 26 | if data[0] =~ 'Pattern not found:' 27 | call vimple#echoc([['Warning', data[0]]]) 28 | return 29 | endif 30 | call overlay#show( 31 | \ data 32 | \, { 33 | \ '' : ':call BufGrepAccept()' 34 | \ , 'q' : ':call overlay#close()' 35 | \ } 36 | \, {'filter' : 1, 'use_split' : 1}) 37 | endfunction 38 | 39 | function! BufGrepAccept() 40 | let num = matchstr(overlay#select_line(), '\d\+') 41 | exe 'silent! norm! ' . num . "G" 42 | endfunction 43 | 44 | nnoremap bg :call BufGrep(input('', '/')) 45 | command! -nargs=* G call BufGrep() 46 | -------------------------------------------------------------------------------- /autoload/scripts.vim: -------------------------------------------------------------------------------- 1 | let s:script_dir = expand(':p:h:h') 2 | let s:script_db = s:script_dir . '/scripts.db' 3 | let s:init_sql = 'create virtual table plugins using fts4 (plugin, file, type, content);' 4 | let s:content_sql = 'insert into plugins values("%s", "%s", "%s", "%s")' 5 | 6 | function! scripts#query(sql) 7 | let sql = 'sqlite3 ' . s:script_db . " '" . a:sql . "'" 8 | return system(sql) 9 | endfunc 10 | 11 | function! scripts#escape(value) 12 | return substitute(substitute(a:value, '"', '""', 'g'), "'", "'\"'\"'", 'g') 13 | endfunc 14 | 15 | function! scripts#init() 16 | if filereadable(s:script_db) 17 | call delete(s:script_db) 18 | endif 19 | call scripts#query(s:init_sql) 20 | redir => scripts 21 | silent scriptnames 22 | redir END 23 | for s in split(scripts, "\n") 24 | if s == "" 25 | continue 26 | endif 27 | let file = matchstr(s, '^\s*\d\+:\s*\zs\(.*\)') 28 | let content = readfile(file) 29 | let plugin = '' 30 | if file =~ '/\.\?\(ex\|gvim\|vim\)rc$' 31 | let type = 'vimrc' 32 | let plugin = matchstr(file, '/\zs.\+\ze/\.\?\(ex\|gvim\|vim\)rc$') 33 | elseif file =~ '/autoload/' 34 | let type = 'autoload' 35 | elseif file =~ '/after/' 36 | let type = matchstr(file, '/\zsafter/.\+\ze/[^/]\+$') 37 | else 38 | let type = matchstr(file, '.*/\zs.\+\ze/[^/]\+$') 39 | endif 40 | if plugin == '' 41 | let plugin = matchstr(file, '.*/\zs.\+\ze/' . type) 42 | endif 43 | echo scripts#query(printf(s:content_sql, scripts#escape(plugin), scripts#escape(file), scripts#escape(type), scripts#escape(join(content, "\n")))) 44 | endfor 45 | endfunction 46 | 47 | command! ScriptMatch echo scripts#query('select file from plugins where content match "' . scripts#escape() . '"') 48 | -------------------------------------------------------------------------------- /test/string001.vim: -------------------------------------------------------------------------------- 1 | call vimtest#StartTap() 2 | call vimtap#Plan(19) " <== XXX Keep plan number updated. XXX 3 | 4 | let s = 'this is a string' 5 | let S = string#scanner(s) 6 | 7 | call Is(S.skip('\w\+') , 4 , 'skips a word') 8 | call Is(S.skip('\s\+') , 6 , 'skips a space') 9 | call Is(S.skip('\s\+') , -1 , '"fail" if pattern to skip not found') 10 | call Is(S.skip('\w\+') , 8 , 'skips another word') 11 | call Is(S.scan('\w\+') , '' , 'no word to scan here') 12 | call Is(S.index , 8 , 'index unchanged from unsuccessful scan') 13 | call Is(S.skip('\d\+') , -1 , 'no digits to skip') 14 | call Isnt(S.skip('\s\+') , -1 , 'skip over whitespace') 15 | call Is(S.scan('\w\+') , 'a' , 'get next word') 16 | 17 | let s = 'this is a string' 18 | let S = string#scanner(s) 19 | 20 | call Is(S.skip('\_s\+') , -1 , 'no leading whitespace to skip') 21 | call Is(S.scan('\w\+') , 'this' , 'scan "this"') 22 | call Isnt(S.skip('\s\+') , -1 , 'skip whitespace') 23 | call Is(S.scan('\w\+') , 'is' , 'scan "is"') 24 | call Isnt(S.skip('\s\+') , -1 , 'skip whitespace') 25 | 26 | let s = 'this is a string' 27 | let S = string#scanner(s) 28 | 29 | call Is(S.skip_until('string') , 10 , 'skips until a target') 30 | call Is(S.scan('\w\+') , 'string' , 'scan collects the pattern match') 31 | 32 | let s = "one foo\ntwo foo" 33 | let S = string#scanner(s) 34 | 35 | call Is(S.inject("\n").string , "\none foo\ntwo foo" , 'inject at start') 36 | call S.skip('\_s*\w\+') 37 | call Is(S.inject("\n").string , "\none\n foo\ntwo foo" , 'inject inside string') 38 | 39 | 40 | 41 | let s = "one foo\ntwo foo\nthree foo\nfour foo\n" 42 | let S = string#scanner(s) 43 | 44 | call Is(S.collect('\n\zs\w\+') , ['one', 'two', 'three', 'four'] , 'collect by pattern') 45 | 46 | 47 | 48 | call vimtest#Quit() 49 | -------------------------------------------------------------------------------- /autoload/complete.vim: -------------------------------------------------------------------------------- 1 | let s:old_cfu = '' 2 | 3 | function! complete#reset() 4 | let &completefunc = s:old_cfu 5 | let s:old_cfu = '' 6 | augroup CompleteTrigger 7 | au! 8 | augroup END 9 | endfunction 10 | 11 | function! complete#trigger(func) 12 | if s:old_cfu == '' 13 | let s:old_cfu = &completefunc 14 | endif 15 | let &completefunc = a:func 16 | augroup CompleteTrigger 17 | au! 18 | au CursorMovedI * call complete#reset() 19 | augroup END 20 | return "\\" 21 | endfunction 22 | 23 | " Example Completers 24 | "------------------- 25 | " 26 | function! complete#short_files_in_path(findstart, base) 27 | if a:findstart 28 | let line = getline('.') 29 | let start = col('.') - 1 30 | while start > 0 && line[start - 1] =~ '\f' 31 | let start -= 1 32 | endwhile 33 | return start 34 | else 35 | let res = map(globpath(&path, a:base . '*', 0, 1) 36 | \, 'fnamemodify(v:val, ":t")') 37 | return res 38 | endif 39 | endfunction 40 | 41 | function! complete#files_in_path(findstart, base) 42 | if a:findstart 43 | let line = getline('.') 44 | let start = col('.') - 1 45 | while start > 0 && line[start - 1] =~ '\f' 46 | let start -= 1 47 | endwhile 48 | return start 49 | else 50 | let res = map(globpath(&path, a:base . '*', 0, 1) 51 | \, 'substitute(v:val, "^\.\/", "", "")') 52 | return res 53 | endif 54 | endfunction 55 | 56 | function! complete#foist(findstart, base) 57 | if a:findstart 58 | return 0 59 | else 60 | let base = matchstr(a:base, '^\s*\zs.*\ze\s*$') 61 | let all_buf_lines = [] 62 | let curbuf = bufnr('%') 63 | silent bufdo call extend(all_buf_lines, getline(1, '$')) 64 | exe "buffer " . curbuf 65 | return filter(all_buf_lines, 'stridx(v:val, base) > -1') 66 | endif 67 | endfunction 68 | -------------------------------------------------------------------------------- /autoload/parse/ini.vim: -------------------------------------------------------------------------------- 1 | function! parse#ini#from_file(file) 2 | let file = a:file 3 | if ! filereadable(file) 4 | throw "E484: Can't open file " . file 5 | endif 6 | return parse#ini#from_string(join(readfile(file), "\n")) 7 | endfunction 8 | 9 | function! parse#ini#from_string(string) 10 | let scanner = string#scanner(a:string) 11 | let data = {} 12 | let current_section = data 13 | 14 | while ! scanner.eos() 15 | call scanner.skip('\_s\+') 16 | if scanner.scan(';') != "" 17 | call scanner.skip_until('[\r\n]\+') 18 | elseif scanner.scan('\[\([^\]]\+\)\]') != "" 19 | let section_name = scanner.matches[1] 20 | let data[section_name] = {} 21 | let current_section = data[section_name] 22 | elseif scanner.scan('\([^=]\+\)\s*=\s*\(\%([\r\n]\@!.\)*\)') != "" 23 | let current_section[string#trim(scanner.matches[1])] 24 | \ = string#eval((scanner.matches[2])) 25 | endif 26 | endwhile 27 | 28 | return data 29 | endfunction 30 | 31 | function! parse#ini#to_file(hash, file) 32 | call writefile(split(parse#ini#to_string(a:hash), "\n"), a:file) 33 | endfunction 34 | 35 | function! parse#ini#to_string(hash) 36 | let hash = a:hash 37 | let head = '' 38 | let body = '' 39 | if type(hash) != type({}) 40 | throw 'Expected Dictionary but given ' . variable#type_to_string(hash) 41 | endif 42 | for [section, values] in items(hash) 43 | if type(values) == type({}) 44 | let body .= '[' . section . "]\n" 45 | for [name, val] in items(values) 46 | let body .= name . ' = ' . string#to_string(val) . "\n" 47 | unlet val 48 | endfor 49 | elseif type(values) == type([]) 50 | " what now?! 51 | else 52 | let head .= section . ' = ' . string#to_string(values) . "\n" 53 | endif 54 | unlet values 55 | endfor 56 | return head . body 57 | endfunction 58 | 59 | -------------------------------------------------------------------------------- /demo/jumplist.vim: -------------------------------------------------------------------------------- 1 | " Think :jumps could be a bit sexier? 2 | " 3 | " Use or :Jumps to enter the jumplist overlay 4 | 5 | " In the overlay window: 6 | " You're prompted with a filter pattern. Use to cancel. 7 | " jumps to the current entry 8 | " q closes the overlay without action 9 | 10 | function! JumpListData() 11 | let data = reverse(vimple#redir('jumps')[1:]) 12 | let files = {} 13 | let lines = [] 14 | for d in data 15 | if d == '>' 16 | call add(lines, "x 0\t<-- At jumplist head") 17 | continue 18 | endif 19 | let [n, l, c; t] = split(matchstr(d, '^>\?\zs.*'), '\s\+') 20 | let tt = join(t, ' ') 21 | let type = 'l' 22 | if (tt != '') && (filereadable(tt) || (bufnr(tt) != -1)) 23 | let type = 'f' 24 | if has_key(files, tt) 25 | continue 26 | endif 27 | let files[tt] = 1 28 | endif 29 | call add(lines, join([type, n, l], ' ') . "\t" . tt) 30 | endfor 31 | return lines 32 | endfunction 33 | 34 | function! JumpList() 35 | call overlay#show( 36 | \ JumpListData() 37 | \, { 38 | \ '' : ':call JumpListAccept()' 39 | \ , 'q' : ':call overlay#close()' 40 | \ } 41 | \, {'filter' : 0, 'use_split' : 1}) 42 | call search('^.\s*0', 'w') 43 | set syntax=vimple_jumplist 44 | setlocal conceallevel=2 concealcursor=nv tabstop=12 45 | endfunction 46 | 47 | function! JumpListAccept() 48 | let l = line('.') 49 | let cur = search('^.\s*0', 'wn') 50 | if l == cur 51 | call overlay#close() 52 | return 53 | else 54 | let lst = overlay#select_buffer() 55 | let num = matchstr(lst[l-1], '\d\+') 56 | let dir = (l > cur) ? "\" : "\" 57 | exe 'silent! norm! ' . num . dir 58 | endif 59 | endfunction 60 | 61 | nnoremap :call JumpList() 62 | nnoremap :call JumpList() 63 | command! -nargs=0 Jumps call JumpList() 64 | -------------------------------------------------------------------------------- /demo/changelist.vim: -------------------------------------------------------------------------------- 1 | " Think :changes could be a bit sexier? 2 | " 3 | " Use g; or :Changes to enter the changelist overlay 4 | 5 | " In the overlay window: 6 | " You're prompted with a filter pattern. Use to cancel. 7 | " jumps to the current entry 8 | " q closes the overlay without action 9 | 10 | function! ChangeListData() 11 | let data = reverse(vimple#redir('changes')[1:]) 12 | let files = {} 13 | let lines = [] 14 | for d in data 15 | if d == '>' 16 | call add(lines, "x 0\t<-- At changelist head") 17 | continue 18 | endif 19 | let [n, l, c; t] = split(matchstr(d, '^>\?\zs.*'), '\s\+') 20 | let tt = join(t, ' ') 21 | let type = 'l' 22 | if (tt != '') && (filereadable(tt) || (bufnr(tt) != -1)) 23 | let type = 'f' 24 | if has_key(files, tt) 25 | continue 26 | endif 27 | let files[tt] = 1 28 | endif 29 | call add(lines, join([type, n, l], ' ') . "\t" . tt) 30 | endfor 31 | return lines 32 | endfunction 33 | 34 | function! ChangeList() 35 | call overlay#show( 36 | \ ChangeListData() 37 | \, { 38 | \ '' : ':call ChangeListAccept()' 39 | \ , 'q' : ':call overlay#close()' 40 | \ } 41 | \, {'filter' : 0, 'use_split' : 1}) 42 | call search('^.\s*0', 'w') 43 | set syntax=vimple_jumplist 44 | setlocal conceallevel=2 concealcursor=nv tabstop=12 45 | endfunction 46 | 47 | function! ChangeListAccept() 48 | let l = line('.') 49 | let cur = search('^.\s*0', 'wn') 50 | if l == cur 51 | call overlay#close() 52 | return 53 | else 54 | let lst = overlay#select_buffer() 55 | let num = matchstr(lst[l-1], '\d\+') 56 | let dir = (l > cur) ? "g;" : "g," 57 | exe 'silent! norm! ' . num . dir 58 | endif 59 | endfunction 60 | 61 | nnoremap g; :call ChangeList() 62 | nnoremap g, :call ChangeList() 63 | command! -nargs=0 Changes call ChangeList() 64 | -------------------------------------------------------------------------------- /autoload/vimple/comparators.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple Sort Comparators 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple sort comparators 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/comparators.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#comparators.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#comparators 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | function! vimple#comparators#numerically(i1, i2) 34 | let i1 = str2nr(a:i1) 35 | let i2 = str2nr(a:i2) 36 | return i1 == i2 ? 0 : i1 > i2 ? 1 : -1 37 | endfunction 38 | 39 | function! vimple#comparators#abbrly(i1, i2) 40 | let i1 = a:i1['abbr'] 41 | let i2 = a:i2['abbr'] 42 | return i1 == i2 ? 0 : i1 > i2 ? 1 : -1 43 | endfunction 44 | 45 | function! vimple#comparators#termly(i1, i2) 46 | let i1 = a:i1['term'] 47 | let i2 = a:i2['term'] 48 | return i1 == i2 ? 0 : i1 > i2 ? 1 : -1 49 | endfunction 50 | 51 | function! vimple#comparators#rhsly(i1, i2) 52 | let i1 = matchstr(a:i1['rhs'], '\c^.*\zs.*') 53 | let i2 = matchstr(a:i2['rhs'], '\c^.*\zs.*') 54 | return i1 == i2 ? 0 : i1 > i2 ? 1 : -1 55 | endfunction 56 | 57 | function! vimple#comparators#lhsly(i1, i2) 58 | let i1 = a:i1['lhs'] 59 | let i2 = a:i2['lhs'] 60 | return i1 == i2 ? 0 : i1 > i2 ? 1 : -1 61 | endfunction 62 | 63 | " Teardown:{{{1 64 | "reset &cpo back to users setting 65 | let &cpo = s:save_cpo 66 | " vim: set sw=2 sts=2 et fdm=marker: 67 | -------------------------------------------------------------------------------- /autoload/regex.vim: -------------------------------------------------------------------------------- 1 | " Allow use of line continuation. 2 | let s:save_cpo = &cpo 3 | set cpo&vim 4 | 5 | function! regex#ExtendedRegex(...) 6 | let erex = {} 7 | let erex.lookup_function = '' 8 | let erex.lookup_dict = {} 9 | 10 | func erex.default_lookup(name) dict 11 | return eval(a:name) 12 | endfunc 13 | 14 | "TODO: revisit this with eval() solution 15 | func erex.lookup(name) dict 16 | if empty(self.lookup_function) 17 | return call(self.default_lookup, [a:name], self) 18 | else 19 | "TODO: this 'self' dict arg needs to be the object's self... 20 | return call(self.lookup_function, [a:name], self.lookup_dict) 21 | endif 22 | endfunc 23 | 24 | func erex.expand_composition_atom(ext_reg) dict 25 | let ext_reg = a:ext_reg 26 | let composition_atom = '\\%{\s*\([^,} \t]\+\)\%(\s*,\s*\(\d\+\)\%(\s*,\s*\(.\{-}\)\)\?\)\?\s*}' 27 | let remaining = match(ext_reg, composition_atom) 28 | while remaining != -1 29 | let [_, name, cnt, sep ;__] = matchlist(ext_reg, composition_atom) 30 | let cnt = cnt ? cnt : 1 31 | let sep = escape(escape(sep, '.*[]$^'), '\\') 32 | let pattern = escape(self.lookup(name), '\\' ) 33 | let ext_reg = substitute(ext_reg, composition_atom, join(repeat([pattern], cnt), sep), '') 34 | let remaining = match(ext_reg, composition_atom) 35 | endwhile 36 | return ext_reg 37 | endfunc 38 | 39 | func erex.expand(ext_reg) dict 40 | return self.expand_composition_atom(a:ext_reg) 41 | endfunc 42 | 43 | func erex.parse_multiline_regex(ext_reg) dict 44 | return substitute(substitute(substitute(a:ext_reg, '#\s\+\S\+', '', 'g'), '\\\@ 1 64 | call erex.register_lookup_dict(a:2) 65 | endif 66 | endif 67 | 68 | return erex 69 | endfunction 70 | 71 | "reset &cpo back to users setting 72 | let &cpo = s:save_cpo 73 | 74 | " vim: set sw=2 sts=2 et fdm=marker: 75 | -------------------------------------------------------------------------------- /autoload/completers.vim: -------------------------------------------------------------------------------- 1 | let completers#completers = [ 2 | \ {'word': "\\", 'abbr': 'abbreviation'} 3 | \, {'word': "\\", 'abbr': 'datetime'} 4 | \, {'word': "\\", 'abbr': 'dictionary'} 5 | \] 6 | 7 | function! completers#trigger(findstart, base) 8 | if a:findstart 9 | let line = getline('.') 10 | let start = col('.') - 1 11 | while start > 0 && line[start-1] =~ '\w' 12 | let start -= 1 13 | endwhile 14 | let b:completers_start = start 15 | return start 16 | else 17 | augroup AfterCompleters 18 | au! 19 | au CompleteDone * call completers#apply_completion() 20 | augroup END 21 | return map(deepcopy(g:completers#completers), 'extend(v:val, {"word" : a:base . get(v:val, "word")})') 22 | endif 23 | endfunction 24 | 25 | function! completers#apply_completion() 26 | augroup AfterCompleters 27 | au! 28 | augroup END 29 | let reg_un = @@ 30 | exe 'normal! d' . (b:completers_start + 1) . '|' 31 | if col('.') == (col('$')-1) && col('.') != 1 32 | let @@ = ' ' . @@ 33 | endif 34 | call feedkeys(@@) 35 | let @@ = reg_un 36 | endfunction 37 | 38 | function! completers#datetime(findstart, base) 39 | if a:findstart 40 | let line = getline('.') 41 | let start = col('.') - 1 42 | while start > 0 && line[start - 1] =~ '[a-zA-Z0-9-./]' 43 | let start -= 1 44 | endwhile 45 | return start 46 | else 47 | let now = localtime() 48 | let datetimes = [] 49 | for ts in ['%c', '%Y %b %d %X', '%Y%m%d %T', '%Y-%m-%d', '%Y%m%d', '%H:%M'] 50 | call add(datetimes, strftime(ts, now)) 51 | endfor 52 | return filter(datetimes, 'v:val =~ "^" . a:base') 53 | endif 54 | endfunction 55 | 56 | function! completers#abbrevs(findstart, base) 57 | if exists('*CompleteAbbrevs') 58 | return CompleteAbbrevs(a:findstart, a:base) 59 | else 60 | echohl Error 61 | echom 'Requires https://github.com/dahu/Aboriginal' 62 | echohl NONE 63 | endif 64 | endfunction 65 | 66 | function! completers#init() 67 | inoremap vimple_completers_trigger complete#trigger('completers#trigger') 68 | inoremap vimple_completers_abbrev_trigger complete#trigger('completers#abbrevs') 69 | inoremap vimple_completers_datetime_trigger complete#trigger('completers#datetime') 70 | if !hasmapto('vimple_completers_trigger', 'i') 71 | imap jj vimple_completers_trigger 72 | endif 73 | if !hasmapto('vimple_completers_abbrev_trigger', 'i') 74 | imap vimple_completers_abbrev_trigger 75 | endif 76 | if !hasmapto('vimple_completers_datetime_trigger', 'i') 77 | imap vimple_completers_datetime_trigger 78 | endif 79 | endfunction 80 | -------------------------------------------------------------------------------- /autoload/scope.vim: -------------------------------------------------------------------------------- 1 | function! scope#pair(head, tail) 2 | let obj = {} 3 | let obj.head = a:head 4 | let obj.tail = a:tail 5 | let obj.head_line_number = obj.head[0] 6 | let obj.tail_line_number = obj.tail[0] 7 | 8 | if len(obj.head[1]) == 0 9 | let obj.head_string = '' 10 | elseif join(obj.head[1][1:]) == '' 11 | let obj.head_string = obj.head[1][0] 12 | else 13 | let obj.head_string = string#trim(join(obj.head[1][1:], ' ')) 14 | endif 15 | 16 | if len(obj.tail[1]) == 0 17 | let obj.tail_string = '' 18 | elseif join(obj.tail[1][1:]) == '' 19 | let obj.tail_string = obj.tail[1][0] 20 | else 21 | let obj.tail_string = join(obj.tail[1][1:], ' ') 22 | endif 23 | 24 | return obj 25 | endfunction 26 | 27 | function! scope#inspect(head_pattern, tail_pattern) 28 | let obj = {} 29 | let obj.head_search_pattern = substitute(a:head_pattern, '\\(', '\\%(', 'g') 30 | let obj.head_collect_pattern = a:head_pattern 31 | let obj.tail_search_pattern = substitute(a:tail_pattern, '\\(', '\\%(', 'g') 32 | if obj.tail_search_pattern !~ '\\z[es]' && obj.tail_search_pattern !~ '\$$' 33 | let obj.tail_search_pattern = obj.tail_search_pattern . '\zs' 34 | endif 35 | let obj.tail_collect_pattern = a:tail_pattern 36 | 37 | func obj.init() 38 | let self.stack = [] 39 | endfunc 40 | 41 | func obj.push(head, tail) 42 | call add(self.stack, scope#pair([a:head, matchlist(getline(a:head), self.head_collect_pattern)], [a:tail, matchlist(getline(a:tail), self.tail_collect_pattern)])) 43 | endfunc 44 | 45 | func obj.find_outer_tail() 46 | let self.outer_tail = searchpair(self.head_search_pattern, '', self.tail_search_pattern, 'rcnW') 47 | endfunc 48 | 49 | func obj.find_outer_head() 50 | let self.outer_head = searchpair(self.head_search_pattern, '', self.tail_search_pattern, 'rbcnW') 51 | endfunc 52 | 53 | func obj.find_current_head() 54 | let self.current_head = searchpair(self.head_search_pattern, '', self.tail_search_pattern, 'bW') 55 | endfunc 56 | 57 | func obj.find_current_tail() 58 | let self.current_tail = searchpair(self.head_search_pattern, '', self.tail_search_pattern, 'nW') 59 | endfunc 60 | 61 | func obj.scope() 62 | let self.stack = reverse(list#lrotate(self.stack)) 63 | return self 64 | endfunc 65 | 66 | func obj.get_scope() 67 | call self.init() 68 | call self.find_outer_tail() 69 | if self.outer_tail == 0 70 | return self 71 | endif 72 | 73 | let cur_pos = getpos('.') 74 | 75 | call self.find_outer_head() 76 | if self.outer_head == 0 77 | return self 78 | endif 79 | call self.push(self.outer_head, self.outer_tail) 80 | call self.find_current_head() 81 | while self.current_head > self.outer_head 82 | call self.find_current_tail() 83 | call self.push(self.current_head, self.current_tail) 84 | call self.find_current_head() 85 | endwhile 86 | 87 | call setpos('.', cur_pos) 88 | return self.scope() 89 | endfunction 90 | 91 | return obj.get_scope() 92 | endfunction 93 | -------------------------------------------------------------------------------- /autoload/vimple/history.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for :history builtin 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's builtin :history command. 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/history.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#history.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#history 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | " TODO: Use the Numerically sort comparator for print() 34 | 35 | function! vimple#history#new() 36 | let hist = {} 37 | let hist.__commands = {} 38 | let hist.__filter = '' 39 | 40 | func hist.update() dict abort 41 | let self.__commands = vimple#associate(vimple#redir('history'), 42 | \ [['^\s*#.*', '', ''], 43 | \ ['[^0-9]*\(\%(\d\+\)\|#\)\s*\(.*\)$', '\1-=-=\2', '']], 44 | \ ['split(v:val, "-=-=")', '{"number": v:val[0], "command": v:val[1]}']) 45 | return self 46 | endfunc 47 | 48 | func hist.to_s(...) dict 49 | let default = "%3n %s\n" 50 | "let format = default 51 | let format = a:0 && a:1 != '' ? a:1 : default 52 | let commands = a:0 > 1 ? a:2.__commands : self.__commands 53 | let str = '' 54 | for i in range(0, len(commands) - 1) 55 | let str .= vimple#format( 56 | \ format, 57 | \ { 'n': ['d', commands[i]['number']], 58 | \ 's': ['s', commands[i]['command']]}, 59 | \ default 60 | \ ) 61 | endfor 62 | return str 63 | endfunc 64 | 65 | " only able to colour print the default to_s() output at this stage 66 | " Note: This is a LOT of dancing just to get coloured numbers ;) 67 | func hist.print() dict 68 | call self.update() 69 | call map(map(map(split(self.to_s(), '\n'), 'split(v:val, "\\d\\@<= ")'), '[["vimple_SN_Number", v:val[0]] , ["vimple_SN_Term", " : " . v:val[1] . "\n"]]'), 'vimple#echoc(v:val)') 70 | endfunc 71 | 72 | func hist.filter(filter) dict abort 73 | let dict = deepcopy(self) 74 | call filter(dict.__commands, a:filter) 75 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 76 | return dict 77 | endfunc 78 | 79 | func hist.filter_by_name(name) dict abort 80 | return self.filter('v:val["command"] =~ "' . escape(a:name, '"') . '"') 81 | endfunc 82 | 83 | call hist.update() 84 | return hist 85 | endfunction 86 | 87 | " Teardown:{{{1 88 | "reset &cpo back to users setting 89 | let &cpo = s:save_cpo 90 | " vim: set sw=2 sts=2 et fdm=marker: 91 | -------------------------------------------------------------------------------- /autoload/args.vim: -------------------------------------------------------------------------------- 1 | function! args#merge_dict(initial, ...) 2 | let dict = a:initial 3 | for arg in a:000 4 | if type(arg) == type({}) 5 | call extend(dict, arg) 6 | elseif type(arg) == type('') 7 | if exists(arg) 8 | call extend(dict, eval(arg)) 9 | endif 10 | elseif type(arg) == type([]) 11 | if ! empty(arg[0]) 12 | if has_key(arg[0][arg[1]], arg[2]) 13 | call extend(dict, get(arg[0][arg[1]], arg[2])) 14 | endif 15 | endif 16 | else 17 | echohl Warning 18 | echom 'args#merge_dict: Unhandled type: ' . type(arg) 19 | echohl None 20 | endif 21 | unlet arg 22 | endfor 23 | return dict 24 | endfunction 25 | 26 | function! args#merge_string(initial, ...) 27 | let str = a:initial 28 | for arg in a:000 29 | if type(arg) == type('') 30 | if exists(arg) 31 | let str = eval(arg) 32 | endif 33 | elseif type(arg) == type([]) 34 | if ! empty(arg[0]) 35 | if has_key(arg[0][arg[1]], arg[2]) 36 | let str = get(arg[0][arg[1]], arg[2]) 37 | endif 38 | endif 39 | else 40 | echohl Warning 41 | echom 'args#merge_string: Unhandled type: ' . type(arg) 42 | echohl None 43 | endif 44 | unlet arg 45 | endfor 46 | return str 47 | endfunction 48 | 49 | function! args#merge(initial, ...) 50 | let initial = a:initial 51 | let type = type(initial) 52 | if type == type({}) 53 | return call('args#merge_dict', [initial] + a:000) 54 | elseif type == type('') 55 | return call('args#merge_string', [initial] + a:000) 56 | else 57 | echohl Warning 58 | echom 'args#merge: Unhandled type: ' . type 59 | echohl None 60 | end 61 | endfunction 62 | 63 | if expand('%:p') == expand(':p') 64 | " TEST string merge 65 | 66 | func! args#test_merge_2(...) 67 | return args#merge( 68 | \ 'override me' 69 | \, 'g:default' 70 | \, 'g:default_2' 71 | \, [a:000, 0, 'my_default'] 72 | \) 73 | endfunc 74 | 75 | let default = 'default' 76 | silent! unlet default_2 77 | echo 'default' == args#test_merge_2() 78 | 79 | let default_2 = 'default 2' 80 | echo 'default 2' == args#test_merge_2() 81 | 82 | echo 'my default' == args#test_merge_2({'my_default' : 'my default'}) 83 | 84 | " TEST dict merge 85 | 86 | let default_styles = { 87 | \ 'one' : 1 88 | \, 'two' : 2 89 | \, 'three' : 3 90 | \} 91 | 92 | func! args#test_merge_1(...) 93 | return args#merge( 94 | \ {} 95 | \, g:default_styles 96 | \, 'g:default_styles_2' 97 | \, [a:000, 0, 'my_styles'] 98 | \) 99 | endfunc 100 | 101 | silent! unlet g:default_styles_2 102 | echo default_styles == args#test_merge_1() 103 | echo default_styles != args#test_merge_1({'my_styles': {'one' : 4}}) 104 | echo {'one' : 4, 'two' : 2, 'three' : 3} == args#test_merge_1({'my_styles' : {'one' : 4}}) 105 | let g:default_styles_2 = {'one' : 5} 106 | echo {'one' : 5, 'two' : 2, 'three' : 3} == args#test_merge_1() 107 | endif 108 | -------------------------------------------------------------------------------- /autoload/ml/bayes.vim: -------------------------------------------------------------------------------- 1 | function! s:as_category(category) 2 | return toupper(substitute(a:category, '_', ' ', 'g')) 3 | endfunction 4 | 5 | function! s:sort_numerically(a, b) 6 | return (a:a[1] - a:b[1]) > 0 7 | endfunction 8 | 9 | " function! s:beyes_base() 10 | 11 | " return obj 12 | " endfunction 13 | 14 | function! ml#beyes#new(category, ...) 15 | " let obj = s:beyes_base() 16 | 17 | let obj = {} 18 | let obj.categories = {} 19 | let obj.words = 0 20 | let obj.counts = {} 21 | let obj.word_count = {} 22 | 23 | func obj.add_category(category) 24 | let arg_type = type(a:category) 25 | if arg_type == type({}) 26 | call extend(self.categories, a:category) 27 | elseif arg_type == type([]) 28 | for c in a:category 29 | call self.add_category(c) 30 | endfor 31 | elseif arg_type == type('') || type(0) || type(0.0) 32 | let self.categories[s:as_category(a:category)] = {} 33 | else 34 | echoerr 'ml#beyes#add_category Error: Unable to handle argument type ' . type(a:category) . ' for argument ' . string(a:category) 35 | endif 36 | endfunc 37 | 38 | func obj.train(category, text) 39 | let category = s:as_category(a:category) 40 | let self.word_count[category] = get(self.word_count, category, 0) 41 | let self.counts[category] = get(self.counts, category, 0) + 1 42 | for [word, cnt] in items(string#words(a:text)) 43 | let self.categories[category][word] = get(self.categories[category], word, 0) + cnt 44 | let self.word_count[category] += cnt 45 | let self.words += cnt 46 | endfor 47 | return self 48 | endfunc 49 | 50 | " Returns the scores in each category of the provided `text`, eg: 51 | " {"Uninteresting" : -12.6997928013932, "Interesting" : -18.4206807439524} 52 | " The score closest to 0 is the one picked out by classify() 53 | func obj.classifications(text) 54 | let scores = {} 55 | let training_count = 0.0 56 | for cnt in values(self.counts) 57 | let training_count += cnt 58 | endfor 59 | for [category, words] in items(self.categories) 60 | let scores[category] = 0 61 | let total = get(self.word_count, category, 1) * 1.0 62 | for [word, cnt] in items(string#words(a:text)) 63 | let scores[category] += log(get(words, word, 0.1) / total) 64 | endfor 65 | " add in prior probability for the category 66 | let scores[category] += log(get(self.counts, category, 0.1) / training_count) 67 | endfor 68 | return scores 69 | endfunc 70 | 71 | func obj.classify(text) 72 | " return sort(items(self.classifications(a:text)), 's:sort_numerically') 73 | return sort(items(self.classifications(a:text)), 's:sort_numerically')[0][0] 74 | endfunc 75 | 76 | 77 | call obj.add_category(a:category) 78 | if a:0 79 | for c in a:000 80 | call obj.add_category(c) 81 | endfor 82 | endif 83 | 84 | return obj 85 | endfunction 86 | 87 | " let b = ml#beyes#new('yes', 'no') 88 | " call b.train('yes', 'this is something good') 89 | " call b.train('no', 'this is something bad and full of hate') 90 | " echo b.classifications('something to hate you with') 91 | " echo b.classify('something to hate you with') 92 | -------------------------------------------------------------------------------- /demo/calendar.vim: -------------------------------------------------------------------------------- 1 | " Interactive Calendar overlay demo 2 | " NOTE: Depends on system 'cal' tool. 3 | " In the overlay window: 4 | " inserts the date as YYYY-MM-DD from the day under the cursor. 5 | " moves back one month 6 | " moves forward one month 7 | " moves back one year 8 | " moves forward one year 9 | " q closes the overlay without action 10 | 11 | " functions {{{1 12 | 13 | function! GetCalendar(month, year) "{{{2 14 | let calendar = split(substitute(substitute(substitute(system('cal ' . a:month . ' ' . a:year), '\n', '\n ', 'g'), '_ _', '*', ''), '\s\+\_$', '', 'g'), "\n") 15 | return calendar 16 | endfunction 17 | 18 | function! Calendar(month, year) "{{{2 19 | call overlay#show( 20 | \ GetCalendar(a:month, a:year) 21 | \, { 22 | \ '' : ':call CalendarAccept()' 23 | \ , '' : ':call CalendarUpdate("m", 1)' 24 | \ , '' : ':call CalendarUpdate("m", -1)' 25 | \ , '' : ':call CalendarUpdate("y", 1)' 26 | \ , '' : ':call CalendarUpdate("y", -1)' 27 | \ , 'q' : ':call overlay#close()' 28 | \ } 29 | \, {'filter' : 0, 'use_split' : 1, 'month' : a:month, 'year' : a:year}) 30 | syntax match Today '\*\d\+' 31 | highlight def link Today TODO 32 | endfunction 33 | 34 | function! CalendarUpdate(time, amount) "{{{2 35 | if a:time == 'm' 36 | let b:options.month += a:amount 37 | else 38 | let b:options.year += a:amount 39 | endif 40 | call overlay#update(GetCalendar(b:options.month, b:options.year)) 41 | endfunction 42 | 43 | function! CalendarAccept() "{{{2 44 | let day = expand('') 45 | let date = b:options.year . '-' . printf('%02d', b:options.month) . '-' . printf('%02d', day) 46 | call overlay#close() 47 | if exists('g:insertlessly_cleanup_trailing_ws') 48 | let insertlessly_cleanup_trailing_ws = g:insertlessly_cleanup_trailing_ws 49 | let insertlessly_cleanup_all_ws = g:insertlessly_cleanup_all_ws 50 | let g:insertlessly_cleanup_trailing_ws = 0 51 | let g:insertlessly_cleanup_all_ws = 0 52 | endif 53 | if exists('b:cal_mode') 54 | let cal_mode = b:cal_mode 55 | unlet b:cal_mode 56 | else 57 | let cal_mode = 'i' 58 | endif 59 | if cal_mode ==# 'I' 60 | exe 'norm! a' . date . ' ' 61 | startinsert 62 | call feedkeys("\l") 63 | elseif cal_mode ==# 'i' 64 | exe 'norm! i' . date 65 | elseif cal_mode ==# 'a' 66 | exe 'norm! a' . date 67 | elseif cal_mode ==# 'c' 68 | exe 'norm! ciW' . date 69 | endif 70 | if exists('g:insertlessly_cleanup_trailing_ws') 71 | let g:insertlessly_cleanup_trailing_ws = insertlessly_cleanup_trailing_ws 72 | let g:insertlessly_cleanup_all_ws = insertlessly_cleanup_all_ws 73 | endif 74 | let b:date = date 75 | return date 76 | endfunction 77 | 78 | function! CalendarToday() "{{{2 79 | return Calendar(strftime('%m'), strftime('%Y')) 80 | endfunction 81 | 82 | " maps {{{1 83 | 84 | inoremap :let b:cal_mode='I':call CalendarToday() 85 | nnoremap dda :let b:cal_mode='a':call CalendarToday() 86 | nnoremap ddi :let b:cal_mode='i':call CalendarToday() 87 | nnoremap ddc :let b:cal_mode='c':call CalendarToday() 88 | 89 | " vim: fen fdm=marker 90 | -------------------------------------------------------------------------------- /autoload/vimple/highlight.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for :highlight builtin 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's builtin :highlight command. 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/highlight.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#highlight.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#highlight 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | " TODO: Use the Numerically sort comparator for print() 34 | " Highlight object 35 | 36 | function! vimple#highlight#new() 37 | let hl = {} 38 | let hl.__data = {} 39 | let hl.__filter = '' 40 | 41 | func hl.update() dict abort 42 | let self.__data = vimple#associate(vimple#join(vimple#redir('highlight'), '^\s\+'), 43 | \ [['^\(\S\+\)\s*\S\+\s*\(.*\)$', '\1\t\2', '']], 44 | \ ['split(v:val, "\t", 2)', 45 | \ '{"term": v:val[0],' 46 | \. '"attrs": substitute(v:val[1], "\\s\\+", " ", "g")}']) 47 | return self 48 | endfunc 49 | 50 | " takes two optional arguments: 51 | " 1 : format 52 | " 2 : data 53 | func hl.to_s(...) dict 54 | let default = "%t %a\n" 55 | let format = a:0 && a:1 != '' ? a:1 : default 56 | let data = a:0 > 1 ? a:2.__data : self.__data 57 | let str = '' 58 | let data = sort(data, 'vimple#comparators#termly') 59 | for i in range(0, len(data) - 1) 60 | let str .= vimple#format( 61 | \ format, 62 | \ { 't': ['s', data[i]['term']], 63 | \ 'a': ['s', data[i]['attrs']]}, 64 | \ default 65 | \ ) 66 | endfor 67 | return str 68 | endfunc 69 | 70 | func hl.to_l(...) dict 71 | return self.__data 72 | endfunc 73 | 74 | " only able to colour print the default to_s() output at this stage 75 | func hl.print() dict 76 | let str = self.to_s() 77 | let dta = map(split(str, "\n"), '[split(v:val, " ")[0], v:val . "\n"]') 78 | call vimple#echoc(dta) 79 | endfunc 80 | 81 | func hl.filter(filter) dict abort 82 | let dict = deepcopy(self) 83 | call filter(dict.__data, a:filter) 84 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 85 | return dict 86 | endfunc 87 | 88 | func hl.filter_by_term(term) dict abort 89 | return self.filter('v:val["term"] =~ "' . escape(a:term, '"') . '"') 90 | endfunc 91 | 92 | func hl.sort() 93 | return sort(self.__data, vimple#comparators#termly) 94 | endfunc 95 | 96 | call hl.update() 97 | return hl 98 | endfunction 99 | 100 | " Teardown:{{{1 101 | "reset &cpo back to users setting 102 | let &cpo = s:save_cpo 103 | " vim: set sw=2 sts=2 et fdm=marker: 104 | -------------------------------------------------------------------------------- /autoload/vimple/scriptnames.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for :scriptnames builtin 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's builtin :scriptnames command. 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/scriptnames.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#scriptnames.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#scriptnames 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | " TODO: Use the Numerically sort comparator for print() 34 | 35 | function! vimple#scriptnames#new() 36 | let sn = {} 37 | let sn.__scripts = {} 38 | let sn.__filter = '' 39 | 40 | " update {{{2 41 | func sn.update() dict abort 42 | let self.__scripts = vimple#associate(vimple#redir('scriptnames'), 43 | \ [['^\s*\(\d\+\):\s*\(.*\)$', 44 | \ '\1,\2', '']], 45 | \ ['split(v:val, ",")', '{"number": v:val[0], "script": v:val[1]}']) 46 | return self 47 | endfunc 48 | 49 | " to_l {{{2 50 | func sn.to_l(...) dict 51 | return self.__scripts 52 | endfunc 53 | 54 | " to_s {{{2 55 | func sn.to_s(...) dict 56 | let default = "%3n %s\n" 57 | "let format = default 58 | let format = a:0 && a:1 != '' ? a:1 : default 59 | let scripts = a:0 > 1 ? a:2.__scripts : self.__scripts 60 | let str = '' 61 | for i in range(0, len(scripts) - 1) 62 | let str .= vimple#format( 63 | \ format, 64 | \ { 'n': ['d', scripts[i]['number']], 65 | \ 's': ['s', scripts[i]['script']]}, 66 | \ default 67 | \ ) 68 | endfor 69 | return str 70 | endfunc 71 | 72 | " print {{{2 73 | " only able to colour print the default to_s() output at this stage 74 | " Note: This is a LOT of dancing just to get coloured numbers ;) 75 | func sn.print() dict 76 | call self.update() 77 | call map(map(map(split(self.to_s(), '\n'), 'split(v:val, "\\d\\@<= ")'), '[["vimple_SN_Number", v:val[0]] , ["vimple_SN_Term", " : " . v:val[1] . "\n"]]'), 'vimple#echoc(v:val)') 78 | endfunc 79 | 80 | " filter {{{2 81 | func sn.filter(filter) dict abort 82 | let dict = deepcopy(self) 83 | call filter(dict.__scripts, a:filter) 84 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 85 | return dict 86 | endfunc 87 | 88 | " filter_by_name {{{2 89 | func sn.filter_by_name(name) dict abort 90 | return self.filter('v:val["script"] =~ "' . escape(a:name, '"') . '"') 91 | endfunc 92 | 93 | call sn.update() 94 | return sn 95 | endfunction 96 | 97 | " Teardown:{{{1 98 | "reset &cpo back to users setting 99 | let &cpo = s:save_cpo 100 | " vim: set sw=2 sts=2 et fdm=marker: 101 | -------------------------------------------------------------------------------- /autoload/overlay.vim: -------------------------------------------------------------------------------- 1 | function! overlay#controller(...) 2 | if a:0 3 | for [key, act] in items(a:1) 4 | exe 'nnoremap ' . key . ' ' . act 5 | endfor 6 | endif 7 | endfunction 8 | 9 | let s:overlay_count = 1 10 | 11 | function! overlay#popup(list, ...) 12 | let actions = {'q' : ':call overlay#close()'} 13 | let user_options = a:0 ? a:1 : {} 14 | let options = extend({'filter' : 0, 'use_split' : 1, 'vertical' : 0}, user_options) 15 | call overlay#show(a:list, actions, options) 16 | endfunction 17 | 18 | function! overlay#show(list, actions, ...) 19 | let overlay_parent_altbuf = bufnr('#') 20 | let overlay_parent = bufnr('%') 21 | 22 | let options = { 23 | \ 'filter' : 1, 24 | \ 'use_split' : 0, 25 | \ 'vertical' : 0, 26 | \ 'auto_act' : 0, 27 | \ 'name' : '__overlay__' 28 | \ } 29 | if a:0 30 | if type(a:1) == type({}) 31 | call extend(options, a:1) 32 | endif 33 | endif 34 | 35 | if options.name == '__overlay__' 36 | let options.name .= s:overlay_count . '__' 37 | let s:overlay_count += 1 38 | endif 39 | 40 | if options.vertical 41 | let options.use_split = 1 42 | endif 43 | if options.use_split 44 | if options.vertical 45 | hide noautocmd vsplit 46 | else 47 | hide noautocmd split 48 | endif 49 | endif 50 | hide noautocmd enew 51 | let b:options = options 52 | let b:overlay_parent = overlay_parent 53 | let b:overlay_parent_altbuf = overlay_parent_altbuf 54 | setlocal buftype=nofile 55 | setlocal bufhidden=hide 56 | setlocal noswapfile 57 | setlocal nobuflisted 58 | setlocal foldmethod=manual 59 | setlocal foldcolumn=0 60 | setlocal nospell 61 | setlocal modifiable 62 | setlocal noreadonly 63 | for o in keys(filter(copy(options), 'v:key =~ "^set"')) 64 | exe o 65 | endfor 66 | exe 'file ' . b:options.name 67 | 68 | 1 69 | call overlay#update(a:list) 70 | 71 | let old_is = &incsearch 72 | set incsearch 73 | let old_hls = &hlsearch 74 | set hlsearch 75 | call overlay#controller(a:actions) 76 | endfunction 77 | 78 | function! overlay#update(list) 79 | let line = line('.') 80 | % delete 81 | call append(0, a:list) 82 | $ 83 | delete _ 84 | exe line 85 | if b:options.filter 86 | if exists(':Filter') 87 | Filter 88 | else 89 | call feedkeys('/') 90 | endif 91 | endif 92 | if b:options.auto_act 93 | if line('$') == 1 94 | call feedkeys("\") 95 | endif 96 | endif 97 | endfunction 98 | 99 | function! overlay#close() 100 | if b:options.use_split 101 | let scratch_buf = bufnr('') 102 | wincmd q 103 | exe 'bwipe ' . scratch_buf 104 | else 105 | exe 'buffer ' . b:overlay_parent 106 | bwipe # 107 | if exists('b:overlay_parent_altbuf') 108 | \ && buflisted(b:overlay_parent_altbuf) 109 | exe 'buffer ' . b:overlay_parent_altbuf 110 | silent! buffer # 111 | endif 112 | endif 113 | endfunction 114 | 115 | function! overlay#select_line() 116 | let line = getline('.') 117 | call overlay#close() 118 | return line 119 | endfunction 120 | 121 | function! overlay#select_buffer() 122 | let lines = getline(1,'$') 123 | call overlay#close() 124 | return lines 125 | endfunction 126 | 127 | function! overlay#command(cmd, actions, options) 128 | call overlay#show(vimple#redir(a:cmd), a:actions, a:options) 129 | endfunction 130 | -------------------------------------------------------------------------------- /autoload/vimple/abbreviations.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for :abbreviations builtin 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's builtin :abbreviations command. 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/abbreviations.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#abbreviations.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#abbreviations 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | " TODO: Use the Numerically sort comparator for print() 34 | " abbreviations object 35 | 36 | function! vimple#abbreviations#new() 37 | let ab = {} 38 | let ab.__data = {} 39 | let ab.__filter = '' 40 | 41 | func ab.update() dict abort 42 | let self.__data = vimple#associate(vimple#join(vimple#redir('iabbrev'), '^\s\+'), 43 | \ [['^\S\+\s*\(\S\+\)\s*\(.*\)$', '\1\t\2', '']], 44 | \ ['split(v:val, "\t", 2)', 45 | \ '{"abbr": v:val[0],' 46 | \. '"type": "i",' 47 | \. '"expansion": substitute(v:val[1], "\\s\\+", " ", "g")}']) 48 | return self 49 | endfunc 50 | 51 | " takes two optional arguments: 52 | " 1 : format 53 | " 2 : data 54 | func ab.to_s(...) dict 55 | let default = "%t %a %e\n" 56 | let format = a:0 && a:1 != '' ? a:1 : default 57 | let data = a:0 > 1 ? a:2.__data : self.__data 58 | let str = '' 59 | let data = sort(data, 'vimple#comparators#abbrly') 60 | for i in range(0, len(data) - 1) 61 | let str .= vimple#format( 62 | \ format, 63 | \ { 'a': ['s', data[i]['abbr']], 64 | \ 't': ['s', data[i]['type']], 65 | \ 'e': ['s', data[i]['expansion']]}, 66 | \ default 67 | \ ) 68 | endfor 69 | return str 70 | endfunc 71 | 72 | func ab.to_l(...) dict 73 | return self.__data 74 | endfunc 75 | 76 | " only able to colour print the default to_s() output at this stage 77 | func ab.print() dict 78 | let str = self.to_s() 79 | let dta = map(split(str, "\n"), '[split(v:val, " ")[0], v:val . "\n"]') 80 | call vimple#echoc(dta) 81 | endfunc 82 | 83 | func ab.filter(filter) dict abort 84 | let dict = deepcopy(self) 85 | call filter(dict.__data, a:filter) 86 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 87 | return dict 88 | endfunc 89 | 90 | func ab.filter_by_abbr(abbr) dict abort 91 | return self.filter('v:val["abbr"] =~ "' . escape(a:abbr, '"') . '"') 92 | endfunc 93 | 94 | func ab.sort() 95 | return sort(self.__data, vimple#comparators#abbrly) 96 | endfunc 97 | 98 | call ab.update() 99 | return ab 100 | endfunction 101 | 102 | " Teardown:{{{1 103 | "reset &cpo back to users setting 104 | let &cpo = s:save_cpo 105 | " vim: set sw=2 sts=2 et fdm=marker: 106 | -------------------------------------------------------------------------------- /plugin/vimple.vim: -------------------------------------------------------------------------------- 1 | " Vimple maps and commands 2 | " NOTE: These can be disabled by adding this line to your $MYVIMRC: 3 | " let g:init_vimple_maps_and_commands = 0 4 | 5 | if ! exists('g:init_vimple_maps_and_commands') 6 | let g:init_vimple_maps_and_commands = 1 7 | endif 8 | 9 | if ! g:init_vimple_maps_and_commands 10 | finish 11 | endif 12 | 13 | if ! exists('g:vimple_override_file_complete') 14 | let g:vimple_override_file_complete = 0 15 | endif 16 | if ! exists('g:vimple_file_complete_short') 17 | let g:vimple_file_complete_short = 0 18 | endif 19 | if ! exists('g:vimple_override_line_complete') 20 | let g:vimple_override_line_complete = 0 21 | endif 22 | 23 | if g:vimple_override_file_complete 24 | if g:vimple_file_complete_short 25 | inoremap complete#trigger('complete#short_files_in_path') 26 | else 27 | inoremap complete#trigger('complete#files_in_path') 28 | endif 29 | endif 30 | if g:vimple_override_line_complete 31 | inoremap complete#trigger('complete#foist') 32 | endif 33 | 34 | 35 | nnoremap vimple_tag_search :call TagSearch() 36 | 37 | if !hasmapto('vimple_tag_search') 38 | nmap g] vimple_tag_search 39 | endif 40 | 41 | 42 | 43 | nnoremap vimple_ident_search :call IdentSearch(0) 44 | nnoremap vimple_ident_search_forward :call IdentSearch(1) 45 | 46 | if !hasmapto('vimple_ident_search') 47 | nmap [I vimple_ident_search 48 | endif 49 | 50 | if !hasmapto('vimple_ident_search_forward') 51 | nmap ]I vimple_ident_search_forward 52 | endif 53 | 54 | 55 | 56 | nnoremap vimple_spell_suggest :call SpellSuggest(expand('')) 57 | 58 | if !hasmapto('vimple_spell_suggest') 59 | nmap z= vimple_spell_suggest 60 | endif 61 | 62 | 63 | 64 | command! -nargs=* G call BufGrep() 65 | 66 | command! -bar -range=% -nargs=+ StringScanner echo StringScanner(, , ) 67 | 68 | 69 | command! -nargs=0 -bar Mkvimrc echom Mkvimrc() 70 | 71 | 72 | command! -nargs=+ BufTypeDo call BufTypeDo() 73 | command! -nargs=+ BufMatchDo call BufMatchDo() 74 | 75 | command! -bar QFargs call quickfix#to_args(1) 76 | command! -bar QFargslocal call quickfix#to_args(0) 77 | command! -bar LLargs call loclist#to_args(1) 78 | command! -bar LLargslocal call loclist#to_args(0) 79 | 80 | command! -bar QFbufs echo quickfix#bufnames() 81 | command! -bar LLbufs echo loclist#bufnames() 82 | 83 | command! -nargs=+ QFdo call quickfix#do() 84 | command! -nargs=+ LLdo call loclist#do() 85 | 86 | command! -range -nargs=0 Filter call vimple#filter(getline(1,'$'), {}).filter() 87 | nnoremap vimple_filter :Filter 88 | 89 | if !hasmapto('vimple_filter') 90 | nmap cf vimple_filter 91 | endif 92 | 93 | 94 | command! -range -nargs=+ -complete=file ReadIntoBuffer ,call ReadIntoBuffer() 95 | 96 | 97 | command! -bar -nargs=+ -complete=command View call View() 98 | command! -bar -nargs=+ -complete=command ViewFT call ViewFT() 99 | command! -bar -nargs=+ -complete=command ViewExpr call ShowInNewBuf(eval()) 100 | command! -bar -nargs=+ -complete=command ViewSys call ShowInNewBuf(split(system(), "\n")) 101 | 102 | 103 | command! -nargs=+ Collect call Collect() 104 | command! -nargs=+ GCollect let GC = GCollect() 105 | 106 | 107 | command! -nargs=+ Silently exe join(map(split(, '|'), '"silent! ".v:val'), '|') 108 | 109 | -------------------------------------------------------------------------------- /autoload/vimple/marks.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for :marks builtin 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's builtin :marks command. 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/scriptnames.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#marks.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#marks 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | " TODO: Use the Numerically sort comparator for print() 34 | 35 | function! vimple#marks#new() 36 | let m = {} 37 | let m.__data = {} 38 | let m.__filter = '' 39 | 40 | func m.update() dict abort 41 | let self.__data = vimple#associate(vimple#redir('marks')[1:-1], 42 | \ [['^\s*', '', '']], 43 | \ ['split(v:val)', 44 | \ '{"mark" : v:val[0], 45 | \ "line" : v:val[1], 46 | \ "col" : v:val[2], 47 | \ "text" : substitute(join(v:val[3:-1], " "), "\n", "", ""), 48 | \ }']) 49 | 50 | return self 51 | endfunc 52 | 53 | func m.to_s(...) dict 54 | let default = "%2m %5l %4o %t\n" 55 | let format = a:0 && a:1 != '' ? a:1 : default 56 | let marks = a:0 > 1 ? a:2.__data : self.__data 57 | let str = '' 58 | for i in range(0, len(marks) - 1) 59 | let str .= vimple#format( 60 | \ format, 61 | \ { 'm': ['s', marks[i]['mark']], 62 | \ 'l': ['d', marks[i]['line']], 63 | \ 'o': ['d', marks[i]['col']], 64 | \ 't': ['s', marks[i]['text']]}, 65 | \ default 66 | \ ) 67 | endfor 68 | return str 69 | endfunc 70 | 71 | func m.to_l() dict 72 | return self.__data 73 | endfunc 74 | 75 | " " only able to colour print the default to_s() output at this stage 76 | " " Note: This is a LOT of dancing just to get coloured numbers ;) 77 | " func m.print() dict 78 | " call self.update() 79 | " call map(map(map(split(self.to_s(), '\n'), 'split(v:val, "\\d\\@<= ")'), '[["vimple_SN_Number", v:val[0]] , ["vimple_SN_Term", " : " . v:val[1] . "\n"]]'), 'vimple#echoc(v:val)') 80 | " endfunc 81 | 82 | "TODO: This looks like a candidate for moving into the parent class... no? 83 | func m.filter(filter) dict abort 84 | let dict = deepcopy(self) 85 | call filter(dict.__data, a:filter) 86 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 87 | return dict 88 | endfunc 89 | 90 | func m.lhs_is(lhs) dict abort 91 | return self.filter('v:val["lhs"] ==# "' . escape(a:lhs, '\"') . '"') 92 | endfunc 93 | 94 | func m.local_marks() dict abort 95 | return self.filter('v:val["mark"] =~# "[a-z]"') 96 | endfunc 97 | 98 | func m.global_marks() dict abort 99 | return self.filter('v:val["mark"] =~# "[A-Z]"') 100 | endfunc 101 | 102 | call m.update() 103 | return m 104 | endfunction 105 | 106 | " Teardown:{{{1 107 | "reset &cpo back to users setting 108 | let &cpo = s:save_cpo 109 | " vim: set sw=2 sts=2 et fdm=marker: 110 | 111 | -------------------------------------------------------------------------------- /autoload/vimple/version.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for :version builtin 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's builtin :version command. 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/version.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#version.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#version 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | function! vimple#version#new() 34 | let vn = {} 35 | let vn.__info = {} 36 | let vn.__filter = '' 37 | 38 | " update {{{2 39 | func vn.update() dict abort 40 | let i = self.__info 41 | let info = vimple#associate(vimple#redir('version'), [], []) 42 | 43 | if has('nvim') 44 | " Special processing for Neovim (on Arch...) 45 | let [i['version'], i['major'], i['minor'] ; rest] = 46 | \ split( 47 | \ substitute(info[0] 48 | \ , '^NVIM v\(\d\+\)\.\(\d\+\)\.\(\d\+\)' 49 | \ , '\1\n\2\n\3\n', '') 50 | \ , "\n", 1) 51 | else 52 | let [i['version'], i['major'], i['minor'], i['build_name'], i['compiled']] = 53 | \ split( 54 | \ substitute(info[0] 55 | \ , '^N\?VIM.\{-}\(\(\d\+\)\.\(\d\+\)\(\.\(\d\+\)\)\?\)' 56 | \ . '\(.\{-}(\([^,]\+\).*\)\?' 57 | \ , '\1\n\2\n\3\n\5\n\7', '') 58 | \ , "\n", 1) 59 | let i['patches'] = substitute(info[1], '^.*:\s\+\(.*\)', '\1', '') 60 | let i['compiled_by'] = info[2] 61 | let i['build_version'] = substitute(info[3], '^\(.\{-}\)\..*', '\1', '') 62 | let i['features'] = {} 63 | for line in range(4, len(info)) 64 | if (info[line] =~ '^\s*$') || (info[line] =~ '^\s\+.*:\s') 65 | break 66 | endif 67 | call map(split(info[line], '\s\+'), 68 | \ 'extend(i["features"], {strpart(v:val, 1) : (v:val =~ "^+" ? 1 : 0)})') 69 | endfor 70 | endif 71 | return self 72 | endfunc 73 | 74 | " to_l {{{2 75 | func vn.to_l(...) dict 76 | return self.__info 77 | endfunc 78 | 79 | " " to_s {{{2 80 | " func vn.to_s(...) dict 81 | " let default = "%3n %s\n" 82 | " "let format = default 83 | " let format = a:0 && a:1 != '' ? a:1 : default 84 | " let scripts = a:0 > 1 ? a:2.__info : self.__info 85 | " let str = '' 86 | " for i in range(0, len(scripts) - 1) 87 | " let str .= vimple#format( 88 | " \ format, 89 | " \ { 'n': ['d', scripts[i]['number']], 90 | " \ 's': ['s', scripts[i]['script']]}, 91 | " \ default 92 | " \ ) 93 | " endfor 94 | " return str 95 | " endfunc 96 | 97 | " " print {{{2 98 | " " only able to colour print the default to_s() output at this stage 99 | " " Note: This is a LOT of dancing just to get coloured numbers ;) 100 | " func vn.print() dict 101 | " call self.update() 102 | " call map(map(map(split(self.to_s(), '\n'), 'split(v:val, "\\d\\@<= ")'), '[["vimple_SN_Number", v:val[0]] , ["vimple_SN_Term", " : " . v:val[1] . "\n"]]'), 'vimple#echoc(v:val)') 103 | " endfunc 104 | 105 | " filter {{{2 106 | func vn.filter(filter) dict abort 107 | let dict = deepcopy(self) 108 | call filter(dict.__info["features"], a:filter) 109 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 110 | return dict 111 | endfunc 112 | 113 | " filter_by_name {{{2 114 | func vn.filter_by_name(name) dict abort 115 | return self.filter('v:key =~ "' . escape(a:name, '"') . '"') 116 | endfunc 117 | 118 | call vn.update() 119 | return vn 120 | endfunction 121 | 122 | " Teardown:{{{1 123 | "reset &cpo back to users setting 124 | let &cpo = s:save_cpo 125 | " vim: set sw=2 sts=2 et fdm=marker: 126 | -------------------------------------------------------------------------------- /autoload/ml/porter.vim: -------------------------------------------------------------------------------- 1 | " Porter stemmer in VimL. 2 | " 3 | " Taken from: 4 | " http://burakkanber.com/blog/machine-learning-full-text-search-in-javascript-relevance-scoring/ 5 | " Which referenced: 6 | " Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14, 7 | " no. 3, pp 130-137, 8 | " 9 | " see also http://www.tartarus.org/~martin/PorterStemmer 10 | 11 | let s:step2list = { 12 | \ "ational" : "ate" 13 | \, "tional" : "tion" 14 | \, "enci" : "ence" 15 | \, "anci" : "ance" 16 | \, "izer" : "ize" 17 | \, "bli" : "ble" 18 | \, "alli" : "al" 19 | \, "entli" : "ent" 20 | \, "eli" : "e" 21 | \, "ousli" : "ous" 22 | \, "ization" : "ize" 23 | \, "ation" : "ate" 24 | \, "ator" : "ate" 25 | \, "alism" : "al" 26 | \, "iveness" : "ive" 27 | \, "fulness" : "ful" 28 | \, "ousness" : "ous" 29 | \, "aliti" : "al" 30 | \, "iviti" : "ive" 31 | \, "biliti" : "ble" 32 | \, "logi" : "log" 33 | \} 34 | 35 | let s:step3list = { 36 | \ "icate" : "ic" 37 | \, "ative" : "" 38 | \, "alize" : "al" 39 | \, "iciti" : "ic" 40 | \, "ical" : "ic" 41 | \, "ful" : "" 42 | \, "ness" : "" 43 | \} 44 | 45 | let s:c = "[^aeiou]" " consonant 46 | let s:v = "[aeiouy]" " vowel 47 | let s:C = s:c . "[^aeiouy]*" " consonant sequence 48 | let s:V = s:v . "[aeiou]*" " vowel sequence 49 | 50 | let s:mgr0 = '^\(' . s:C . '\)\?' . s:V . s:C " [C]VC... is m>0 51 | let s:meq1 = '^\(' . s:C . '\)\?' . s:V . s:C . '\(' . s:V . '\)\?$' " [C]VC[V] is m=1 52 | let s:mgr1 = '^\(' . s:C . '\)\?' . s:V . s:C . s:V . s:C " [C]VCVC... is m>1 53 | let s:s_v = '^\(' . s:C . '\)\?' . s:v " vowel in stem 54 | 55 | function! s:p(s) 56 | return 57 | echom string(a:s) 58 | endfunction 59 | 60 | function! ml#porter#stemmer(w) 61 | let w = a:w 62 | 63 | if len(w) < 3 64 | return w 65 | endif 66 | 67 | let firstch = w[0] 68 | if firstch == 'y' 69 | let w = 'Y' . w[1:] 70 | endif 71 | 72 | " Step 1a 73 | let re = '^\(.\{-}\)\(ss\|i\)es$' 74 | let re2 = '^\(.\{-}\)\([^s]\)s$' 75 | 76 | if w =~ re 77 | let w = substitute(w, re, '\1\2', '') 78 | elseif w =~ re2 79 | let w = substitute(w, re2, '\1\2', '') 80 | endif 81 | 82 | call s:p(w) 83 | 84 | " Step 1b 85 | let re = '^\(.\{-}\)eed$' 86 | let re2 = '^\(.\{-}\)\(ed\|ing\)$' 87 | 88 | if w =~ re 89 | let fp = matchlist(w, re) 90 | let re = s:mgr0 91 | if fp[1] =~ re 92 | let re = '.$' 93 | let w = substitute(w, re, '', '') 94 | endif 95 | elseif w =~ re2 96 | let fp = matchlist(w, re2) 97 | let stem = fp[1] 98 | let re2 = s:s_v 99 | if stem =~ re2 100 | let w = stem 101 | let re2 = '\(at\|bl\|iz\)$' 102 | let re3 = '\([^aeiouylsz]\)\1$' 103 | let re4 = '^' . s:C . s:v . '[^aeiouwxy]$' 104 | if w =~ re2 105 | let w = w . 'e' 106 | elseif w =~ re3 107 | let re = '.$' 108 | let w = substitute(w, re, '', '') 109 | elseif w =~ re4 110 | let w = w . 'e' 111 | endif 112 | endif 113 | endif 114 | 115 | " Step 1c 116 | let re = '^\(.\{-}\)y$' 117 | if w =~ re 118 | let fp = matchlist(w, re) 119 | let stem = fp[1] 120 | let re = s:s_v 121 | if stem =~ re 122 | let w = stem . 'i' 123 | endif 124 | endif 125 | 126 | " Step 2 127 | let re = '^\(.\{-}\)\(ational\|tional\|enci\|anci\|izer\|bli\|alli\|entli\|eli\|ousli\|ization\|ation\|ator\|alism\|iveness\|fulness\|ousness\|aliti\|iviti\|biliti\|logi\)$' 128 | if w =~ re 129 | let fp = matchlist(w, re) 130 | let stem = fp[1] 131 | let suffix = fp[2] 132 | let re = s:mgr0 133 | if stem =~ re 134 | let w = stem . s:step2list[suffix] 135 | endif 136 | endif 137 | 138 | " Step 3 139 | let re = '^\(.\{-}\)\(icate\|ative\|alize\|iciti\|ical\|ful\|ness\)$' 140 | if w =~ re 141 | let fp = matchlist(w, re) 142 | let stem = fp[1] 143 | let suffix = fp[2] 144 | let re = s:mgr0 145 | if stem =~ re 146 | let w = stem . s:step3list[suffix] 147 | endif 148 | endif 149 | 150 | " Step 4 151 | let re = '^\(.\{-}\)\(al\|ance\|ence\|er\|ic\|able\|ible\|ant\|ement\|ment\|ent\|ou\|ism\|ate\|iti\|ous\|ive\|ize\)$' 152 | let re2 = '^\(.\{-}\)\(s\|t\)\(ion\)$' 153 | if w =~ re 154 | let fp = matchlist(w, re) 155 | let stem = fp[1] 156 | let re = s:mgr1 157 | if stem =~ re 158 | let w = stem 159 | endif 160 | elseif w =~ re2 161 | let fp = matchlist(w, re2) 162 | let stem = fp[1] . fp[2] 163 | let re2 = s:mgr1 164 | if stem =~ re2 165 | let w = stem 166 | endif 167 | endif 168 | 169 | " Step 5 170 | let re = '^\(.\{-}\)e$' 171 | if w =~ re 172 | let fp = matchlist(w, re) 173 | let stem = fp[1] 174 | let re = s:mgr1 175 | let re2 = s:meq1 176 | let re3 = '^' . s:C . s:v . '[^aeiouwxy]$' 177 | if (stem =~ re || stem =~ re2) && stem !~ re3 178 | let w = stem 179 | endif 180 | endif 181 | 182 | let re = 'll$' 183 | let re2 = s:mgr1 184 | if w =~ re && w =~ re2 185 | let re = '.$' 186 | let w = substitute(w, re, '', '') 187 | endif 188 | 189 | " and turn initial Y back to y 190 | 191 | if firstch == 'y' 192 | let w = 'y' . w[1:] 193 | endif 194 | 195 | return w 196 | endfunction 197 | -------------------------------------------------------------------------------- /autoload/vimple/undolist.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for :undolist builtin 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's builtin :undolist command. 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/scriptnames.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#undolist.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#undolist 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | function! vimple#undolist#get_undolist() 34 | let bnum = bufnr('%') 35 | let bname = bufname('%') 36 | let ulist = vimple#undolist#new() 37 | if len(ulist.to_l()) != 0 38 | return [ulist.sort_by_age().to_l()[-1]['age'], bnum, bname] 39 | else 40 | return [99999999999, bnum, bname] 41 | endif 42 | endfunction 43 | 44 | function! vimple#undolist#most_recently_used() 45 | let orig_pos = getpos('.') 46 | let orig_pos[0] = bufnr('%') 47 | 48 | let uls = [] 49 | bufdo call add(uls, vimple#undolist#get_undolist()) 50 | call sort(uls) 51 | 52 | exe 'buffer ' . orig_pos[0] 53 | let orig_pos[0] = 0 54 | call setpos('.', orig_pos) 55 | return reverse(uls) 56 | endfunction 57 | 58 | function! vimple#undolist#print_mru() 59 | let mru = vimple#undolist#most_recently_used() 60 | let str = '' 61 | for buf in mru 62 | let str .= printf("%3d %s\n", buf[1], buf[2]) 63 | endfor 64 | return str 65 | endfunction 66 | 67 | nnoremap VimpleMRU :echo vimple#undolist#print_mru() . "\n":buffer 68 | if !hasmapto('VimpleMRU') 69 | nmap gu VimpleMRU 70 | endif 71 | 72 | function! vimple#undolist#normalise_time(t, now) 73 | let t = a:t 74 | let now = a:now 75 | if t =~? '^\d\+ ' 76 | let now -= matchstr(t, '^\d*') 77 | let time = strftime('%Y/%m/%d %H:%M:%S', now) 78 | elseif t !~ '\/' 79 | let time = strftime('%Y/%m/%d ', now) . t 80 | elseif t !~ '\/.*\/' 81 | let time = strftime('%Y/', now) . t 82 | else 83 | let time = t 84 | endif 85 | return time 86 | endfunction 87 | 88 | function! vimple#undolist#julian_date(t) 89 | let [year, mon, day] = matchlist(a:t, '^\(\d\{4}\)/\(\d\d\)/\(\d\d\)')[1:3] 90 | let y = year + 4800 - (mon <= 2) 91 | let m = mon + (mon <= 2 ? 9 : -3) 92 | let jul = day + (153 * m + 2) / 5 + (1461 * y / 4) - 32083 93 | return jul - (y / 100) + (y / 400) + 38 94 | endfunction 95 | 96 | " in UTC 97 | function! vimple#undolist#time_to_seconds(t, now) 98 | let t = vimple#undolist#normalise_time(a:t, a:now) 99 | let jd = vimple#undolist#julian_date(t) 100 | let jd_linux = vimple#undolist#julian_date('1970/01/01 00:00:00') 101 | let [hour, min, sec] = matchlist(t, ' \(\d\d\):\(\d\d\):\(\d\d\)')[1:3] 102 | return (jd - jd_linux) * 86400 + hour * 3600 + min * 60 + sec 103 | endfunction 104 | . 105 | function! vimple#undolist#new() 106 | let m = {} 107 | let m.__data = {} 108 | let m.__filter = '' 109 | 110 | func m.update() dict abort 111 | let now = localtime() 112 | let self.__data = vimple#associate(vimple#redir('undolist')[1:-1], 113 | \ [ 114 | \ ['^\s*', '', ''], 115 | \ ['\s\s\+', '__', 'g'] 116 | \ ], 117 | \ ['split(v:val, "__")', 118 | \ '{"number" : v:val[0], 119 | \ "changes" : v:val[1], 120 | \ "when" : vimple#undolist#normalise_time(v:val[2], ' .now. '), 121 | \ "age" : vimple#undolist#time_to_seconds(v:val[2], ' .now. '), 122 | \ "saved" : len(v:val) == 4 ? v:val[3] : 0 123 | \ }']) 124 | 125 | return self 126 | endfunc 127 | 128 | func m.to_s(...) dict 129 | let default = "%4n %4h %4s %w\n" 130 | let format = a:0 && a:1 != '' ? a:1 : default 131 | let data = a:0 > 1 ? a:2.__data : self.__data 132 | let str = '' 133 | for i in range(0, len(data) - 1) 134 | let str .= vimple#format( 135 | \ format, 136 | \ { 'n': ['d', data[i]['number']], 137 | \ 'h': ['d', data[i]['changes']], 138 | \ 'w': ['s', data[i]['when']], 139 | \ 'a': ['d', data[i]['age']], 140 | \ 's': ['d', data[i]['saved']]}, 141 | \ default 142 | \ ) 143 | endfor 144 | return str 145 | endfunc 146 | 147 | func m.agely(a, b) dict 148 | return a:a['age'] - a:b['age'] 149 | endfunc 150 | 151 | func m.sort_by_age() dict 152 | let Fn_age = self.agely 153 | call sort(self.__data, Fn_age, self) 154 | return self 155 | endfunc 156 | 157 | func m.to_l() dict 158 | return self.__data 159 | endfunc 160 | 161 | "TODO: This looks like a candidate for moving into the parent class... no? 162 | func m.filter(filter) dict abort 163 | let dict = deepcopy(self) 164 | call filter(dict.__data, a:filter) 165 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 166 | return dict 167 | endfunc 168 | 169 | call m.update() 170 | return m 171 | endfunction 172 | 173 | " Teardown:{{{1 174 | "reset &cpo back to users setting 175 | let &cpo = s:save_cpo 176 | " vim: set sw=2 sts=2 et fdm=marker: 177 | -------------------------------------------------------------------------------- /autoload/vimple/map.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for :map builtin 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's builtin :map command. 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/scriptnames.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#map.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#map 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | " TODO: Use the Numerically sort comparator for print() 34 | 35 | function! vimple#map#new() 36 | let m = {} 37 | let m.__data = {} 38 | let m.__filter = '' 39 | 40 | func m.update() dict abort 41 | let self.__data = vimple#associate(vimple#redir('map') + vimple#redir('map!'), 42 | \ [['', 43 | \ '', '']], 44 | \ ['[matchstr(v:val, ''^.''), 45 | \ matchstr(v:val, ''^.\s\+\zs\S\+''), 46 | \ matchstr(v:val, ''^.\s\+\S\+\s\+\zs[*& ]\ze[@ ]\S''), 47 | \ matchstr(v:val, ''^.\s\+\S\+\s\+[*& ]\zs[@ ]\ze\S''), 48 | \ matchstr(v:val, ''^.\s\+\S\+\s\+[*& ][@ ]\zs\S.*'') 49 | \ ]', 50 | \ '{"normal" : v:val[0] =~ "[n ]", 51 | \ "visual" : v:val[0] =~ "[vx ]", 52 | \ "select" : v:val[0] =~ "[vs ]", 53 | \ "operator" : v:val[0] =~ "[o ]", 54 | \ "insert" : v:val[0] =~ "[i!]", 55 | \ "lang" : v:val[0] =~ "l", 56 | \ "command" : v:val[0] =~ "[c!]", 57 | \ "lhs" : v:val[1], 58 | \ "remappable" : v:val[2] != "*", 59 | \ "script_remappable" : v:val[2] == "&", 60 | \ "buffer" : v:val[3] == "@", 61 | \ "rhs" : v:val[4] 62 | \ }']) 63 | return self 64 | endfunc 65 | 66 | func m.map_type(map) 67 | let tt = ['normal', 'insert', 'select', 'visual', 'operator', 'command', 'lang'] 68 | let type = '' 69 | for i in range(0, (len(tt) - 1)) 70 | if a:map[tt[i]] 71 | if i == 3 72 | if type == 's' 73 | let type = 'v' 74 | else 75 | let type = 'x' 76 | endif 77 | else 78 | let type = tt[i][0] 79 | endif 80 | endif 81 | endfor 82 | return type 83 | endfunc 84 | 85 | func m.map_extra(map) 86 | let et = ['remappable', 'script_remappable', 'buffer'] 87 | let rt = [' ', '&', '@'] 88 | let extra = '*' 89 | for i in range(0, (len(et) - 1)) 90 | if a:map[et[i]] 91 | let extra = rt[i] 92 | endif 93 | endfor 94 | return extra 95 | endfunc 96 | 97 | func m.to_s(...) dict 98 | let default = "%3n %s\n" 99 | let default = "%t %L %e %R\n" 100 | "let format = default 101 | let format = a:0 && a:1 != '' ? a:1 : default 102 | let maps = a:0 > 1 ? a:2.__data : self.__data 103 | let str = '' 104 | " for i in range(0, len(maps) - 1) 105 | let lhs_plugs = self.filter('v:val["lhs"] =~ "\\c"').to_l() 106 | let rhs_plugs = self.filter('v:val["rhs"] =~ "\\c"').to_l() 107 | let non_plugs = self.filter('v:val["lhs"] !~ "\\c" && v:val["rhs"] !~ "\\c"').to_l() 108 | let all_maps = sort(lhs_plugs, 'vimple#comparators#lhsly') 109 | \+ sort(rhs_plugs, 'vimple#comparators#rhsly') 110 | \+ sort(non_plugs, 'vimple#comparators#lhsly') 111 | for map in all_maps 112 | let type = self.map_type(map) 113 | let extra = self.map_extra(map) 114 | let str .= vimple#format( 115 | \ format, 116 | \ { 't': ['s', type], 117 | \ 'L': ['s', map['lhs']], 118 | \ 'e': ['s', extra], 119 | \ 'R': ['s', map['rhs']]}, 120 | \ default 121 | \ ) 122 | endfor 123 | return str 124 | endfunc 125 | 126 | " to_l {{{2 127 | func m.to_l(...) dict 128 | return self.__data 129 | endfunc 130 | 131 | " only able to colour print the default to_s() output at this stage 132 | " Note: This is a LOT of dancing just to get coloured numbers ;) 133 | func m.print() dict 134 | call self.update() 135 | call map(map(map(split(self.to_s(), '\n'), 'split(v:val, "\\d\\@<= ")'), '[["vimple_SN_Number", v:val[0]] , ["vimple_SN_Term", " : " . v:val[1] . "\n"]]'), 'vimple#echoc(v:val)') 136 | endfunc 137 | 138 | func m.filter(filter) dict abort 139 | let dict = deepcopy(self) 140 | call filter(dict.__data, a:filter) 141 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 142 | return dict 143 | endfunc 144 | 145 | func m.lhs_is(lhs) dict abort 146 | return self.filter('v:val["lhs"] ==# "' . escape(a:lhs, '\"') . '"') 147 | endfunc 148 | 149 | call m.update() 150 | return m 151 | endfunction 152 | 153 | function! MyMaps() 154 | let maps = split(g:vimple#mp.update().filter('v:val["lhs"] !~ "\\c"').to_s("%t %e %L %R\n"), "\n") 155 | let max_l = 0 156 | for s in maps 157 | let l = stridx(s, ' ', 5) 158 | let max_l = l > max_l ? l : max_l 159 | endfor 160 | let max_l += 1 161 | let ms = [] 162 | let pat = '^.\s.\s\S\+\zs\s\+\ze' 163 | for s in maps 164 | let ns = match(s, pat) 165 | call add(ms, substitute(s, pat, repeat(' ', max_l - ns), '')) 166 | endfor 167 | return ms 168 | endfunction 169 | 170 | command! -nargs=0 -bar MyMaps call ShowInNewBuf(MyMaps()) 171 | 172 | " Teardown:{{{1 173 | "reset &cpo back to users setting 174 | let &cpo = s:save_cpo 175 | " vim: set sw=2 sts=2 et fdm=marker: 176 | 177 | -------------------------------------------------------------------------------- /autoload/list.vim: -------------------------------------------------------------------------------- 1 | " list#flat([elem, ...]) {{{1 2 | " 3 | " Flatten the arguments into a single list. 4 | " 5 | " given: a = ['a', 'b'] 6 | " b = [1, 2] 7 | " list#flat(a,b) : ['a', 'b', 1, 2] 8 | " 9 | function! list#flat(...) 10 | let fl = [] 11 | let list = a:000 12 | if a:0 == 1 13 | let list = list[0] 14 | endif 15 | for el in list 16 | if type(el) == type([]) 17 | call extend(fl, list#flat(el)) 18 | else 19 | call extend(fl, [el]) 20 | endif 21 | unlet el 22 | endfor 23 | return fl 24 | endfunction 25 | 26 | function! list#split(list, match) 27 | let ret = [] 28 | let r = [] 29 | for e in a:list 30 | if e =~ a:match 31 | call add(ret, r) 32 | let r = [] 33 | else 34 | call add(r, e) 35 | endif 36 | endfor 37 | call add(ret, r) 38 | return ret 39 | endfunction 40 | 41 | " list#zip(list_a, list_b, method) {{{1 42 | " 43 | " Join each element of list_a with the corresponding element of list_b 44 | " Use the third argument, method, to dictate how the elements should be 45 | " combined: 46 | " given: a = [a, b] 47 | " b = [1, 2] 48 | " 0 = flattened list : [a, 1, b, 2] 49 | " 1 = list groups : [[a, 1], [b, 2]] 50 | " x = join separator x : [ax1, bx2] 51 | " 52 | " NOTE: If one list is longer than the other, the tail of that list is added 53 | " to the result. 54 | function! list#zip(a, b, ...) 55 | let method = 1 56 | if a:0 57 | let method = a:1 58 | endif 59 | let i = 0 60 | let r = [] 61 | let l_a = len(a:a) 62 | let l_b = len(a:b) 63 | let n = min([len(a:a), len(a:b)]) 64 | while i < n 65 | if method == "0" 66 | call add(r, a:a[i]) 67 | call add(r, a:b[i]) 68 | elseif method == "1" 69 | call add(r, [a:a[i], a:b[i]]) 70 | else 71 | call add(r, join([a:a[i], a:b[i]], method)) 72 | endif 73 | let i+= 1 74 | endwhile 75 | if l_a == l_b 76 | return r 77 | elseif l_a > l_b 78 | exe "return r + a:a[" . n . ":]" 79 | else 80 | exe "return r + a:b[" . n . ":]" 81 | endif 82 | endfunction "}}}1 83 | 84 | " list#inject(list, init, funcref) 85 | function! list#inject(list, init, funcref) 86 | if ! exists('*' . a:funcref) 87 | throw 'vimple: list#inject(): Funcref ' . a:funcref . ' does not exist!' 88 | return a:init 89 | elseif empty(a:list) 90 | return a:init 91 | else 92 | let i = a:list[0] 93 | let r = a:list[1:-1] 94 | let v = call(a:funcref, [a:init, i]) 95 | return list#inject(r, v, a:funcref) 96 | endif 97 | endf 98 | 99 | " partition list into count-element sublists 100 | function! list#partition(list, count) 101 | let lst = deepcopy(a:list) 102 | let len = len(lst) 103 | let cnt = a:count 104 | let newlists = [] 105 | if cnt <= 0 106 | throw 'vimple: list#partition: count must be positive' 107 | endif 108 | if cnt >= len 109 | return lst 110 | endif 111 | for idx in range(0, len - 1, cnt) 112 | if cnt > len(lst) 113 | let cnt = len(lst) 114 | endif 115 | call add(newlists, remove(lst, 0, (cnt - 1))) 116 | endfor 117 | return newlists 118 | endfunc 119 | 120 | " partition list into cols sublists and join with colsep=\t 121 | " list#lspread(list, cols, colsep="\t") 122 | " returns a list 123 | function! list#lspread(list, cols, ...) 124 | let colsep = "\t" 125 | if a:0 126 | let colsep = a:1 127 | endif 128 | return map(list#partition(a:list, a:cols), 'join(v:val, "' . escape(colsep, '"') . '")') 129 | endfunction 130 | 131 | " partition list into cols sublists and join with col and row seps 132 | " list#spread(list, cols, colsep, rowsep) 133 | " returns a string 134 | function! list#spread(list, cols, ...) 135 | let colsep = "\t" 136 | let rowsep = "\n" 137 | if a:0 138 | if a:0 == 2 139 | let colsep = a:1 140 | let rowsep = a:2 141 | else 142 | let colsep = a:1 143 | endif 144 | endif 145 | return join(list#lspread(a:list, a:cols, colsep), rowsep) 146 | endfunction 147 | 148 | " " map expr over each element of each sublist of list 149 | " function! list#lmap(list, expr) 150 | " return map(a:list, 'map(v:val, ''' . a:expr . ''')') 151 | " endfunction 152 | 153 | function! list#shuffle(a) 154 | let b = type(a:a) == type('') ? split(deepcopy(a:a), "\n") : a:a 155 | let n = 0 156 | let length = len(b) 157 | while n < length 158 | let tmp = b[n] 159 | let dst = rng#rand() % length 160 | let b[n] = b[dst] 161 | let b[dst] = tmp 162 | let n += 1 163 | endwhile 164 | return b 165 | endfunction 166 | 167 | function! Shuffle(...) range abort 168 | let reg = @@ 169 | exe a:firstline . ',' . a:lastline . 'd' 170 | let lines = list#shuffle(@@) 171 | call append(a:firstline - 1, lines) 172 | exe a:lastline 173 | let @@ = reg 174 | endfunction 175 | 176 | command! -nargs=0 -range=% -bar Shuffle , call Shuffle() 177 | 178 | " list#paste(a, b, join, sep) 179 | " Emulate the unix paste command 180 | " Arguments: 181 | " a - each of 'a' and 'b' are lists, or 182 | " b - strings containing 'sep' (default='\n') delimited elements 183 | " join - separator (default=' ') to use when joining each respective line of 184 | " a and b 185 | " sep - separator (default='\n') to use when splitting a and b (if strings) 186 | " e.g. 187 | " ------v yank following into register a - "a3yy 188 | " one 189 | " two 190 | " three 191 | " ------v yank following into register b - "b3yy 192 | " satu 193 | " dua 194 | " tiga 195 | " call append('.', Paste(@a, @b)) 196 | function! list#paste(a, b, ...) 197 | let join = (a:0 >= 1) ? a:1 : ' ' 198 | let sep = (a:0 == 2) ? a:2 : '\n' 199 | if type(a:a) == 1 200 | let a = split(a:a, sep) 201 | let b = split(a:b, sep) 202 | else 203 | let a = a:a 204 | let b = a:b 205 | end 206 | return list#zip(a, b, join) 207 | endfunction 208 | 209 | " list#lrotate(array) 210 | " Perform a Left Rotate on array 211 | function! list#lrotate(a) 212 | return extend(a:a[1:-1], [a:a[0]]) 213 | endfunction 214 | 215 | " list#rrotate(array) 216 | " Perform a Right Rotate on array 217 | function! list#rrotate(a) 218 | return extend([a:a[-1]], a:a[0:-2]) 219 | endfunction 220 | -------------------------------------------------------------------------------- /README.asciidoc: -------------------------------------------------------------------------------- 1 | Vimple 2 | ------ 3 | 4 | __Pacifying Vimmers__ 5 | 6 | http://of-vim-and-vigor.blogspot.com/2012/03/pacifying-vimmers.html[Ad] 7 | 8 | Perhaps most usefully, Vimple provides a few maps and commands to make 9 | the casual vimmer's life a little easier. If you don't want any of these 10 | maps and commands, they can be disabled by adding this line to your 11 | $MYVIMRC: 12 | 13 | let g:init_vimple_maps_and_commands = 0 14 | 15 | Here are a few examples of such maps and commands: 16 | 17 | === `:View ex-command` 18 | 19 | Opens a split with the output of `ex-command`. 20 | 21 | === `z=` 22 | 23 | Shows spelling suggestions in an overlay window. Pressing `` 24 | will replace the word under the cursor in the original window with the 25 | current word under the cursor in the overlay. 26 | 27 | Use `vimple_spell_suggest` if you want to map this behaviour 28 | to a differnt key. 29 | 30 | === `[I` 31 | 32 | Shows identifier search results in an overlay window. Pressing `` 33 | will jump to the associated line of the identifier under the cursor. 34 | 35 | Use `vimple_ident_search` if you want to map this behaviour 36 | to a differnt key. 37 | 38 | === `g]` 39 | 40 | Shows tag search results in an overlay window. Pressing `` 41 | will jump to the associated line of the tag under the cursor. 42 | 43 | Use `vimple_tag_search` if you want to map this behaviour 44 | to a differnt key. 45 | 46 | === `SCall( script , function , arg )` 47 | 48 | A function which calls script-local `function` in `script` 49 | with arguments `arg`. This lets you call `` / `s:` 50 | functions by script name rather than SNR (script-number). 51 | 52 | === `:Silently ex-command` 53 | 54 | Performs the series of bar-separated ex-commands silently. 55 | 56 | === `:QFdo ex-command` 57 | 58 | Performs the series of bar-separated ex-commands over the buffers in the QuickFix list. 59 | 60 | NOTE: The location-list analogue is `:LLdo` 61 | 62 | === `:BufTypeDo type ex-commands` 63 | 64 | Performs the series of bar-separated ex-commands over the buffers of the given +type+. 65 | 66 | === `:BufMatchDo pattern ex-commands` 67 | 68 | Performs the series of bar-separated ex-commands over the buffers with names matching +pattern+. 69 | 70 | === `:Collect register-or-variable ex-command` 71 | 72 | Saves the output of `ex-command` into the specified register 73 | or variable. 74 | 75 | === `Collect('register-or-variable ex-command')` 76 | 77 | Saves the output of `ex-command` into the specified register 78 | or variable and returns the output for further use in 79 | expressions. 80 | 81 | === `GCollect( pattern )` 82 | 83 | Uses `pattern` in a `:global /pattern/` command and returns 84 | the results as a list of lines. 85 | 86 | :echo GCollect('^\s*===\s*') 87 | 88 | === `GCCollect( pattern )` 89 | 90 | Uses `pattern` in a `:global /pattern/` command and returns 91 | the results as a list of lines with the `pattern` stripped. 92 | 93 | :echo GCCollect('^\s*===\s*') 94 | 95 | === `:MyMaps` 96 | 97 | Shows your currently active |:map|s and |:imap|s in a new buffer. :MyMaps 98 | attempts to group related maps to more easily allow you to create a custom map 99 | layout for your various |'filetype'|s. 100 | 101 | === `Scope()` 102 | 103 | The Scope() function attempts to show the current function or 104 | class/method scope. Some people like to display this information in 105 | their `statusline`, like: 106 | 107 | set statusline=%f%m%r%h%w\ [%n:%{&ff}/%Y]\%{Scope()}%=[0x\%04.4B][%03v][%p%%\ line\ %l\ of\ %L] 108 | 109 | Currently only Vim & Python (and Python only for testing purposes, created by a NON Pythonista -- patches welcome) have been implemented, but it is very easy for you to write scope functions for your own filetypes. Take Ruby for example: Create `~/.vim/ftplugin/ruby_scope.vim` like this: 110 | 111 | ---- 112 | function! Scope_ruby() 113 | let class_scope = scope#inspect('^\s*class\s\+\([a-zA-Z0-9_.]\+\)', '^\s*end') 114 | let method_scope = scope#inspect('^\s*def\s\+\([a-zA-Z0-9_.]\+\)', '^\s*end') 115 | return ' ' . join(map(class_scope.stack, 'v:val.head_line_number . "," . v:val.tail_line_number . " " . v:val.head_string'), ' :: ') 116 | \. ' >> ' . join(map(method_scope.stack, 'v:val.head_line_number . "," . v:val.tail_line_number . " " . v:val.head_string'), ' > ') 117 | endfunction 118 | ---- 119 | 120 | NOTE: The above example for Ruby is woefully inadequate. A better effect 121 | might be achievable with more context in the regex patterns. The 122 | patterns in `syntax/ruby.vim` might be useful. Parsing with regex is futile. 123 | 124 | === Composable Completions 125 | 126 | By default, `jj` in insert mode activates a user-extendible 127 | meta-completion list. The default list includes abbreviations (if you 128 | have https://github.com/dahu/Aboriginal), some date-time patterns and 129 | the built-in dictionary completion (``). 130 | 131 | The default `jj` can be overridden like this: 132 | 133 | imap vimple_completers_trigger 134 | 135 | Two other example shortcuts provided by vimple by default: 136 | 137 | * `` to complete abbreviations 138 | * `` to complete datetimes 139 | 140 | These defaults can be disabled by adding these lines to your $MYVIMRC: 141 | 142 | imap vimple_completers_trigger 143 | imap vimple_completers_abbrev_trigger 144 | imap vimple_completers_datetime_trigger 145 | 146 | NOTE: `` is used here to trigger a warning if you're re-using a `` map. 147 | 148 | Vimple also provides VimLOO (Object Oriented VimL) objects 149 | for these read-only ++:ex++ commands: 150 | 151 | * ++:ls++ -- vimple#bl 152 | * ++:scriptnames++ -- vimple#sn 153 | * ++:highlight++ -- vimple#hl 154 | * ++:version++ -- vimple#vn 155 | * ++:marks++ -- vimple#ma 156 | * ++:undolist++ -- vimple#ul 157 | * ++:maps++ -- vimple#mp 158 | 159 | NOTE: The awesome plugin 160 | https://github.com/Raimondi/vim-buffalo[buffalo] uses the 161 | `vimple#bl` object. 162 | 163 | In addition to these existing ++:ex++ wrappers, Vimple allows 164 | developers to craft their own objects too. See autoload/vimple/*.vim 165 | for examples. 166 | -------------------------------------------------------------------------------- /autoload/vimple/options.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for options 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's options 6 | " Last Change: 2012-04-08 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/options.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#options.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#options 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | function! vimple#options#new() 34 | if exists('g:vimple#op') 35 | return deepcopy(g:vimple#op).update() 36 | endif 37 | let op = {} 38 | let op.__options = {} 39 | let op.__filter = '' 40 | let op.__update_with_map = 0 41 | 42 | " update {{{2 43 | func op.update() dict abort 44 | if self.__update_with_map 45 | call map(self.__options, 'extend(v:val, {"value": eval("&".v:key)}, "force")') 46 | " Preserve filter. 47 | if !empty(self.__filter) 48 | call filter(self.__options, self.__filter) 49 | endif 50 | return self 51 | endif 52 | 53 | silent! options 54 | let content = getline(1, '$') 55 | close 56 | bwipe option-window 57 | 58 | let long = '' 59 | for l in content 60 | if l =~ '^\s*\%(".*\)\?$' 61 | continue 62 | elseif l =~ '^\s*\d' 63 | continue 64 | elseif l =~ '^\w' 65 | let [long, desc] = split(l, '\t') 66 | let self.__options[long] = {} 67 | let self.__options[long] = {'long' : long, 'desc' : desc} 68 | elseif l =~ '^\t' 69 | let self.__options[long].desc .= ' ' . matchstr(l, '^\t\zs.*') 70 | else 71 | if l =~ 'set \w\+=' 72 | let l = substitute(l, '^ \tset \(\w\+\)=', ' string \1 ', '') 73 | else 74 | let l = substitute(l, '^ \tset \(\w\+\)\t\(\w\+\)', '\=" bool " . (submatch(1) !~? "^no" ? submatch(1) : submatch(2)) . " " . (submatch(1) !~? "^no")', '') 75 | endif 76 | let [type, short] = matchlist(l, '^ \(\w\+\) \(\w\+\)')[1:2] 77 | call extend(self.__options[long], {'type' : type, 'short' : short, 'value': eval('&'.long)}) 78 | endif 79 | endfor 80 | 81 | for o in items(self.__options) 82 | call extend(o[1], {'scope' : (o[1].desc =~ '(.\{-}local.\{-})' ? matchstr(o[1].desc, '(\zs.\{-}\ze)') : 'global')}) 83 | call extend(self.__options, {o[1].short : o[1]}) 84 | endfor 85 | 86 | " Preserve filter. 87 | if !empty(self.__filter) 88 | call filter(self.__options, self.__filter) 89 | endif 90 | let self.__update_with_map = 1 91 | return self 92 | endfunc 93 | 94 | " to_d {{{2 95 | func op.to_d(...) dict 96 | return self.__options 97 | endfunc 98 | 99 | " to_l {{{2 100 | func op.to_l(...) dict 101 | return map(items(self.__options), '[v:val[0], v:val[1].value]') 102 | endfunc 103 | 104 | " to_s {{{2 105 | func op.to_s(...) dict 106 | let default = "%-15l %-2p %1t %v\n" 107 | let format = a:0 && a:1 != '' ? a:1 : default 108 | let opts = a:0 > 1 ? a:2.__options : self.__options 109 | let str = '' 110 | for o in sort(items(opts)) 111 | let str .= vimple#format( 112 | \ format, 113 | \ { 'l': ['s', o[1]['long']], 114 | \ 's': ['s', o[1]['short']], 115 | \ 'd': ['s', o[1]['desc']], 116 | \ 'p': ['s', join(map(filter(split(o[1]['scope']), 'index(["or", "local", "to"], v:val) == -1'), 'strpart(v:val, 0, 1)'), '')], 117 | \ 't': ['s', strpart(o[1]['type'], 0, 1)], 118 | \ 'v': ['s', o[1]['value']]}, 119 | \ default 120 | \ ) 121 | endfor 122 | return str 123 | endfunc 124 | 125 | " changed {{{2 126 | func op.changed() dict 127 | return self.filter('v:val.value !=# eval("&".v:key)') 128 | endfunc 129 | 130 | " short {{{2 131 | func op.short() dict 132 | return self.filter('v:val.short ==# v:key') 133 | endfunc 134 | 135 | " long {{{2 136 | func op.long() dict 137 | return self.filter('v:val.long ==# v:key') 138 | endfunc 139 | 140 | " print {{{2 141 | " only able to colour print the default to_s() output at this stage 142 | func op.print() dict 143 | "let str = self.to_s() 144 | " following code is from hl.print() and would not work as is here 145 | "let dta = map(split(str, "\n"), '[split(v:val, " ")[0], v:val . "\n"]') 146 | "call vimple#echoc(dta) 147 | let pairs = [] 148 | let changed = self.changed() 149 | let max_name = max(map(values(map(copy(self.__options), 'v:val.long." ".v:val.short.""')), 'len(v:val)')) 150 | for key in sort(keys(self.long().__options)) 151 | let option = self.__options[key] 152 | call add(pairs, ['vimple_BL_Number', option.long]) 153 | call add(pairs, ['Normal', ' (']) 154 | call add(pairs, ['vimple_BL_Hidden', option.short]) 155 | call add(pairs, ['Normal', ')' . repeat(' ', max_name - len(option.short) - len(option.long))]) 156 | let len = len(option.value) 157 | if len < &columns 158 | call add(pairs, ['Normal', option.value . "\"]) 159 | else 160 | let screen_len = &columns - max_name - 6 161 | let i = 0 162 | while i <= len 163 | let j = i + screen_len 164 | call add(pairs, ['Normal', repeat(' ', i == 0 ? 0 : max_name + 3) . option.value[i : j] . "\"]) 165 | let i = j + 1 166 | endwhile 167 | endif 168 | if has_key(changed.__options, key) 169 | let len = len(eval('&'.key)) 170 | if len < &columns 171 | call add(pairs, ['vimple_BL_Alternate', repeat(' ', max_name + 3) . eval('&'.key) . "\"]) 172 | else 173 | let screen_len = &columns - max_name - 6 174 | let i = 0 175 | while i <= len 176 | let j = i + screen_len 177 | call add(pairs, ['vimple_BL_Alternate', repeat(' ', max_name + 3) . eval('&'.key)[i : j] . "\"]) 178 | let i = j + 1 179 | endwhile 180 | endif 181 | endif 182 | endfor 183 | call vimple#echoc(pairs) 184 | " Remove the last . Why? 185 | let pairs[-1][1] = pairs[-1][-1][:-2] 186 | return pairs 187 | endfunc 188 | 189 | " filter {{{2 190 | func op.filter(filter) dict abort 191 | let dict = deepcopy(self) 192 | call filter(dict.__options, a:filter) 193 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 194 | return dict 195 | endfunc 196 | 197 | " filter_by_name {{{2 198 | func op.filter_by_name(name) dict abort 199 | return self.filter('v:val["long"] =~ "' . escape(a:name, '"') . '"') 200 | endfunc 201 | 202 | call op.update() 203 | return op 204 | endfunction 205 | 206 | " Teardown:{{{1 207 | "reset &cpo back to users setting 208 | let &cpo = s:save_cpo 209 | " vim: set sw=2 sts=2 et fdm=marker: 210 | -------------------------------------------------------------------------------- /autoload/vimple.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vim library provides objects for builtin ++:ex++ commands 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Version: 0.9 6 | " Description: Vimple provides VimLOO (Object Oriented VimL) objects for 7 | " Vim's write-only ++:ex++ commands, such as ++:ls++, 8 | " ++:scriptnames++ and ++:highlight++. 9 | " Last Change: 2012-04-08 10 | " License: Vim License (see :help license) 11 | " Location: autoload/vimple.vim 12 | " Website: https://github.com/dahu/vimple 13 | " 14 | " See vimple.txt for help. This can be accessed by doing: 15 | " 16 | " :helptags ~/.vim/doc 17 | " :help vimple 18 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 19 | let g:vimple_version = '0.9' 20 | 21 | " Vimscript Setup: {{{1 22 | " Allow use of line continuation. 23 | let s:save_cpo = &cpo 24 | set cpo&vim 25 | 26 | " load guard 27 | " uncomment after plugin development 28 | "if exists("g:loaded_lib_vimple") 29 | " \ || v:version < 700 30 | " \ || v:version == 703 && !has('patch338') 31 | " \ || &compatible 32 | " let &cpo = s:save_cpo 33 | " finish 34 | "endif 35 | "let g:loaded_lib_vimple = 1 36 | 37 | " Library Interface: {{{1 38 | "let str = vimple#format( 39 | " \ format, 40 | " \ { 'b': ['d', 1], 41 | " \ 'f': ['s', "abc"], 42 | " \ 'n': ['s', "efg"], 43 | " \ 'l': ['s', "hij"]}, 44 | " \ default 45 | " \ ) 46 | 47 | function! vimple#format(format, args_d, default) 48 | let format = a:format == '' ? a:default : a:format 49 | let format = substitute(format, '\(%%\)*\zs%[-0-9#+ .]*c', a:default, 'g') 50 | 51 | let args = '' 52 | let items = map(split(substitute(format, '%%', '', 'g'), '\ze%'), 'matchstr(v:val, ''^%[-+#. 0-9]*.'')') 53 | call map(items, 'substitute(v:val, ''^%[-0-9#+ .]*\(.\)'', ''\1'', "g")') 54 | for item in items 55 | let arg_l = get(a:args_d, item, '') 56 | if type(arg_l) != type([]) 57 | continue 58 | endif 59 | let args .= arg_l[0] == 's' ? string(arg_l[1]) : arg_l[1] 60 | let args .= args[-1] =~ ',' ? '' : ', ' 61 | endfor 62 | let args = substitute(args, '^\s*,\s*\(.\{-}\),\s*$', '\1', '') 63 | 64 | let format = substitute(format, '\%(%%\)*%[-1-9#+ .]*\zs.', '\=get(a:args_d[submatch(0)], 0,submatch(0))', 'g') 65 | let printf_str ='printf("'.escape(format, '\"').'", '.args.')' 66 | 67 | return eval(printf_str) 68 | endfunction 69 | 70 | function! vimple#redir(command, ...) 71 | let split_pat = '\n' 72 | let str = '' 73 | if a:0 != 0 74 | let split_pat = a:1 75 | endif 76 | let lang = v:lang 77 | silent! language messages C 78 | redir => str 79 | silent exe a:command 80 | redir END 81 | silent! exec 'language messages ' . lang 82 | return split(str, split_pat) 83 | endfunction 84 | 85 | function! vimple#associate(lines, subs, maps) 86 | let lst = copy(a:lines) 87 | for i in range(0, len(lst) - 1) 88 | " echo lst[i] 89 | for s in a:subs 90 | " echo " " . string(s) 91 | let lst[i] = substitute(lst[i], s[0], s[1], s[2]) 92 | " echo " -->" . string(lst[i]) 93 | endfor 94 | endfor 95 | call filter(lst, 'v:val != ""') 96 | for m in a:maps 97 | " echo "\n" . m 98 | call map(lst, m) 99 | " echo "-->" . string(lst) 100 | endfor 101 | return lst 102 | endfunction 103 | 104 | function! vimple#join(data, pattern) 105 | let x = -1 106 | let lines = repeat([''], len(a:data)) 107 | for line in a:data 108 | if line =~ a:pattern 109 | let lines[x] .= line 110 | else 111 | let x += 1 112 | let lines[x] = line 113 | endif 114 | endfor 115 | return filter(lines, 'v:val !~ "^$"') 116 | endfunction 117 | 118 | function! vimple#echoc(data) 119 | for sets in a:data 120 | exe "echohl " . sets[0] 121 | exe "echon " . string(sets[1]) 122 | endfor 123 | echohl Normal 124 | endfunction 125 | 126 | function! s:vimple_highlight(name, attrs) 127 | if !hlexists(a:name) 128 | silent exe "hi ".a:name." ".a:attrs 129 | endif 130 | endfunction 131 | 132 | " Solarized inspired default colours... 133 | " Doesn't override existing user-defined colours for these highlight terms. 134 | " Shown with case here, but actually case-insensitive within Vim. 135 | " 136 | " TODO: Only vaguely considered at this stage. Based on the 16 colour 137 | " solarized pallette 138 | " the order of applying these to echoc is important 139 | " 140 | function! vimple#default_colorscheme() 141 | " Buffer List 142 | call s:vimple_highlight('vimple_BL_Number' , 'ctermfg=4 ctermbg=8 guifg=#0087ff guibg=#1c1c1c') 143 | call s:vimple_highlight('vimple_BL_Line' , 'ctermfg=10 ctermbg=8 guifg=#4e4e4e guibg=#1c1c1c') 144 | call s:vimple_highlight('vimple_BL_Name' , 'ctermfg=12 ctermbg=8 guifg=#808080 guibg=#1c1c1c') 145 | call s:vimple_highlight('vimple_BL_Unlisted' , 'ctermfg=10 ctermbg=8 guifg=#4e4e4e guibg=#1c1c1c') 146 | call s:vimple_highlight('vimple_BL_CurrentBuffer' , 'ctermfg=14 ctermbg=0 guifg=#8a8a8a guibg=#262626') 147 | call s:vimple_highlight('vimple_BL_AlternateBuffer' , 'ctermfg=14 ctermbg=0 guifg=#8a8a8a guibg=#262626') 148 | " buffer active 149 | call s:vimple_highlight('vimple_BL_Active' , 'ctermfg=12 ctermbg=0 guifg=#808080 guibg=#262626') 150 | call s:vimple_highlight('vimple_BL_Hidden' , 'ctermfg=10 ctermbg=8 guifg=#4e4e4e guibg=#1c1c1c') 151 | " flags 152 | call s:vimple_highlight('vimple_BL_Current' , 'ctermfg=5 guifg=#af005f') 153 | call s:vimple_highlight('vimple_BL_Alternate' , 'ctermfg=13 guifg=#5f5faf') 154 | call s:vimple_highlight('vimple_BL_Modifiable' , 'ctermfg=2 guifg=#5f8700') 155 | call s:vimple_highlight('vimple_BL_Readonly' , 'ctermfg=6 guifg=#00afaf') 156 | call s:vimple_highlight('vimple_BL_Modified' , 'ctermfg=9 guifg=#d75f00') 157 | call s:vimple_highlight('vimple_BL_ReadError' , 'ctermfg=1 guifg=#af0000') 158 | 159 | " Scriptnames 160 | call s:vimple_highlight('vimple_SN_Number' , 'ctermfg=4 ctermbg=8 guifg=#0087ff guibg=#1c1c1c') 161 | call s:vimple_highlight('vimple_SN_Term' , 'ctermfg=12 ctermbg=8 guifg=#808080 guibg=#1c1c1c') 162 | 163 | " Options 164 | call s:vimple_highlight('vimple_OP_BoolEnabled' , 'ctermfg=12 ctermbg=8 guifg=#808080 guibg=#262626') 165 | call s:vimple_highlight('vimple_OP_BoolDisabled' , 'ctermfg=10 ctermbg=8 guifg=#4e4e4e guibg=#1c1c1c') 166 | endfunction 167 | 168 | function! vimple#tracer() 169 | let d = {} 170 | func d.t() 171 | return expand('') 172 | endfunc 173 | echom d.t() 174 | endfunction 175 | 176 | " Buffer Line Filter {{{1 177 | function! vimple#filter(lines, options) 178 | let obj = {} 179 | let obj.lines = a:lines 180 | let obj.options = a:options 181 | 182 | func obj.initialize() dict 183 | if has_key(self.options, 'new') 184 | enew 185 | endif 186 | if has_key(self.options, 'msg') 187 | let self.msg = self.options.msg 188 | else 189 | let self.msg = 'Filter: ' 190 | endif 191 | return self 192 | endfunc 193 | 194 | func obj.filter() dict 195 | let old_hls = &hlsearch 196 | set hlsearch 197 | call self.incremental() 198 | let &hlsearch = old_hls 199 | return self 200 | endfunc 201 | 202 | func obj.incremental() dict 203 | let c = '' 204 | let self.partial = '' 205 | let &ul = &ul 206 | call self.update(0) 207 | while 1 208 | call self.update(1) 209 | let c = nr2char(getchar()) 210 | if c == "\" 211 | break 212 | elseif c == "\" 213 | if self.partial =~ '\k\+\s*$' 214 | let self.partial = substitute(self.partial, '\k\+\s*$', '', '') 215 | else 216 | let self.partial = substitute(self.partial, '.*\k\+\zs.*$', '', '') 217 | endif 218 | elseif c == "\" 219 | silent undo 220 | break 221 | elseif c == '' 222 | let self.partial = self.partial[:-2] 223 | else 224 | let self.partial .= c 225 | endif 226 | endwhile 227 | endfunc 228 | 229 | func obj.update(undojoin) dict 230 | if a:undojoin 231 | undojoin 232 | endif 233 | %delete 234 | let partial = substitute(substitute(self.partial, ' ', '.*', 'g'), '\.\*$', '', '') 235 | if partial =~ '\.\*\$$' 236 | let partial = substitute(partial, '\.\*\$$', '$', '') 237 | endif 238 | call append(0, filter(copy(self.lines), 'v:val =~ partial')) 239 | $delete 240 | if self.partial == '' 241 | nohlsearch 242 | else 243 | exe "silent! norm! /" . partial . "\" 244 | endif 245 | 1 246 | redraw 247 | echo self.msg . self.partial 248 | endfunc 249 | 250 | return obj.initialize() 251 | endfunction 252 | 253 | " Teardown:{{{1 254 | "reset &cpo back to users setting 255 | let &cpo = s:save_cpo 256 | " vim: set sw=2 sts=2 et fdm=marker: 257 | -------------------------------------------------------------------------------- /autoload/string.vim: -------------------------------------------------------------------------------- 1 | function! string#scanner(str) 2 | let obj = {} 3 | if type(a:str) == type([]) 4 | let obj.string = join(a:str, "\n") 5 | else 6 | let obj.string = a:str 7 | endif 8 | let obj.length = len(obj.string) 9 | let obj.index = 0 10 | 11 | func obj.eos() dict 12 | return self.index >= self.length 13 | endfunc 14 | 15 | func obj.inject(str) 16 | let self.string = strpart(self.string, 0, self.index) 17 | \ . a:str . strpart(self.string, self.index) 18 | let self.length = len(self.string) 19 | return self 20 | endfunc 21 | 22 | func obj.skip(pat) dict 23 | let pos = matchend(self.string, '\_^' . a:pat, self.index) 24 | if pos != -1 25 | let self.index = pos 26 | endif 27 | return pos 28 | endfunc 29 | 30 | func obj.skip_until(pat) dict 31 | let pos = matchend(self.string, '\_.\{-}\ze' . a:pat, self.index) 32 | if pos != -1 33 | let self.index = pos 34 | endif 35 | return pos 36 | endfunc 37 | 38 | func obj.scan(pat) dict 39 | " Use \_^ here to anchor the match at the start of the index. 40 | " Otherwise it finds the first match after index. 41 | let m = matchlist(self.string, '\_^' . a:pat, self.index) 42 | if ! empty(m) 43 | let self.index += len(m[0]) 44 | let self.matches = m 45 | return m[0] 46 | endif 47 | return "" 48 | endfunc 49 | 50 | func obj.collect(pat) dict 51 | let matches = [] 52 | while ! self.eos() 53 | if self.skip_until(a:pat) == -1 54 | break 55 | endif 56 | call add(matches, self.scan(a:pat)) 57 | endwhile 58 | return matches 59 | endfunc 60 | 61 | func obj.split(sep, ...) dict 62 | let keepsep = 0 63 | if a:0 64 | let keepsep = a:1 65 | endif 66 | let pieces = [] 67 | let old_index = 0 68 | while ! self.eos() 69 | if self.skip_until(a:sep) == -1 70 | call add(pieces, strpart(self.string, old_index)) 71 | break 72 | endif 73 | let the_piece = strpart(self.string, old_index, (self.index - old_index)) 74 | call add(pieces, the_piece) 75 | let the_sep = self.scan(a:sep) 76 | if keepsep && (the_sep != '') 77 | call add(pieces, the_sep) 78 | endif 79 | if old_index == self.index 80 | call add(pieces, strpart(self.string, old_index, 1)) 81 | let self.index += 1 82 | endif 83 | let old_index = self.index 84 | endwhile 85 | return pieces 86 | endfunc 87 | 88 | return obj 89 | endfunction 90 | 91 | " A list of tokens with navigation methods & element access 92 | function! string#tokens() 93 | let obj = {} 94 | let obj.tokens = [] 95 | let obj.index = 0 96 | let obj.cur_tok = [] 97 | let obj.next_tok = [] 98 | 99 | "foo 100 | func obj.finalise() 101 | call add(self.tokens, ['_end_', '_end_', self.tokens[-1][-1]]) 102 | let self.num_tokens = len(self.tokens) 103 | let self.next_tok = self.tokens[0] 104 | return self 105 | endfunc 106 | 107 | func obj.next() 108 | let self.cur_tok = self.next_tok 109 | if self.index < self.num_tokens 110 | let self.index += 1 111 | endif 112 | let self.next_tok = self.tokens[self.index] 113 | return self.cur_tok 114 | endfunc 115 | 116 | func obj.add(type, value, line) 117 | call add(self.tokens, [a:type, a:value, a:line]) 118 | endfunc 119 | 120 | return obj 121 | endfunction 122 | 123 | function! string#lexer(string) 124 | let obj = {} 125 | let obj.tokens = string#tokens() 126 | let obj.string = '' 127 | let obj.line_continuation_pattern = '\n\s*\\' 128 | let obj.pattern_order = [ 129 | \ 'whitespace', 'name' 130 | \, 'float_number', 'hex_number', 'oct_number', 'int_number' 131 | \, 'tq_string', 'dq_string', 'sq_string' 132 | \, 'operator', 'comment', 'unknown' 133 | \] 134 | let obj.newline_patterns = [ 135 | \ 'whitespace' 136 | \, 'tq_string', 'dq_string', 'sq_string' 137 | \, 'comment', 'unknown' 138 | \] 139 | let obj.patterns = { 140 | \ 'whitespace' : ['\s\+', '\n\%(\s*\\\s*\)\?'] 141 | \, 'name' : ['[ablgstw]:\w*', '[_a-zA-Z]\+'] 142 | \, 'float_number' : ['\d\+\.\d\+\%([eE][+-]\?\d\+\)\?'] 143 | \, 'hex_number' : ['0x\x\+'] 144 | \, 'oct_number' : ['0\o\+'] 145 | \, 'int_number' : ['\d\+'] 146 | \, 'tq_string' : ['"""\_.\{-}"""'] 147 | \, 'dq_string' : ['"\%(\\\.\|[^\n]\)*"'] 148 | \, 'sq_string' : ['''\%(''''\|\_.\)\{-}'''] 149 | \, 'operator' : ['[\\\[\](){}<>:,./\\?=+!@#$%^&*`~|-]\+'] 150 | \, 'comment' : ['"[^\n]*\n'] 151 | \, 'unknown' : ['\S\+'] 152 | \} 153 | 154 | func obj.new(str) 155 | let self.tokens = string#tokens() 156 | if type(a:str) == type([]) 157 | let self.string = join(a:str, "\n") 158 | else 159 | let self.string = a:str 160 | endif 161 | let self.ss = string#scanner(self.string . "\n") 162 | call self.lex() 163 | let self.tokens = self.tokens.finalise() 164 | return self 165 | endfunc 166 | 167 | func obj.join_line_continuations(string) 168 | return substitute(a:string, self.line_continuation_pattern, '', 'g') 169 | endfunc 170 | 171 | func obj.lex() 172 | let lines = 1 173 | while self.ss.index < self.ss.length 174 | let matched = 0 175 | for type in self.pattern_order 176 | for pat in self.patterns[type] 177 | let value = self.ss.scan(pat) 178 | if value != '' 179 | let matched = 1 180 | let t_value = value 181 | if index(self.newline_patterns, type) != -1 182 | let value = self.join_line_continuations(value) 183 | endif 184 | call self.tokens.add(type, value, lines) 185 | if index(self.newline_patterns, type) != -1 186 | let lines += len(substitute(t_value, '[^\n]', '', 'g')) 187 | endif 188 | break 189 | endif 190 | endfor 191 | if matched 192 | break 193 | endif 194 | endfor 195 | endwhile 196 | endfunc 197 | 198 | return obj.new(a:string) 199 | endfunction 200 | 201 | 202 | let s:stops = map( 203 | \ ["a" , "about" , "above" , "after" , "again" , "against" , "all" , "am" , "an" , "and" , "any" , "are" , "aren't" , "as" , "at" , "be" , "because" , "been" , "before" , "being" , "below" , "between" , "both" , "but" , "by" , "can't" , "cannot" , "could" , "couldn't" , "did" , "didn't" , "do" , "does" , "doesn't" , "doing" , "don't" , "down" , "during" , "each" , "few" , "for" , "from" , "further" , "had" , "hadn't" , "has" , "hasn't" , "have" , "haven't" , "having" , "he" , "he'd" , "he'll" , "he's" , "her" , "here" , "here's" , "hers" , "herself" , "him" , "himself" , "his" , "how" , "how's" , "i" , "i'd" , "i'll" , "i'm" , "i've" , "if" , "in" , "into" , "is" , "isn't" , "it" , "it's" , "its" , "itself" , "let's" , "me" , "more" , "most" , "mustn't" , "my" , "myself" , "no" , "nor" , "not" , "of" , "off" , "on" , "once" , "only" , "or" , "other" , "ought" , "our" , "ours" , "ourselves" , "out" , "over" , "own" , "same" , "shan't" , "she" , "she'd" , "she'll" , "she's" , "should" , "shouldn't" , "so" , "some" , "such" , "than" , "that" , "that's" , "the" , "their" , "theirs" , "them" , "themselves" , "then" , "there" , "there's" , "these" , "they" , "they'd" , "they'll" , "they're" , "they've" , "this" , "those" , "through" , "to" , "too" , "under" , "until" , "up" , "very" , "was" , "wasn't" , "we" , "we'd" , "we'll" , "we're" , "we've" , "were" , "weren't" , "what" , "what's" , "when" , "when's" , "where" , "where's" , "which" , "while" , "who" , "who's" , "whom" , "why" , "why's" , "with" , "won't" , "would" , "wouldn't" , "you" , "you'd" , "you'll" , "you're" , "you've" , "your" , "yours" , "yourself" , "yourselves"] 204 | \, 'ml#porter#stemmer(v:val)') 205 | 206 | function! string#tokenize(text) 207 | let t = (type(a:text) == type([]) ? join(a:text, ' ') : a:text) 208 | let text = map( 209 | \ split( 210 | \ substitute( 211 | \ substitute( 212 | \ substitute(tolower(t) 213 | \ , '\W', ' ', 'g') 214 | \ , '\s\+', ' ', 'g') 215 | \ , '^\s*\(.\{-}\)\s*$', '\1', '') 216 | \ , ' ') 217 | \, 'ml#porter#stemmer(v:val)') 218 | 219 | " Filter out stops 220 | let out = [] 221 | for word in text 222 | if index(s:stops, word) == -1 223 | call add(out, word) 224 | endif 225 | endfor 226 | 227 | return out 228 | endfunction 229 | 230 | 231 | function! string#trim(str) 232 | return matchstr(a:str, '^\_s*\zs.\{-}\ze\_s*$') 233 | endfunction 234 | 235 | function! string#to_string(obj) 236 | let obj = a:obj 237 | if type(obj) < 2 238 | return obj 239 | else 240 | return string(obj) 241 | endif 242 | endfunction 243 | 244 | function! string#eval(line) 245 | let line = string#trim(a:line) 246 | if line[0] =~ '[{[]' 247 | return eval(line) 248 | else 249 | return line 250 | endif 251 | endfunction 252 | 253 | " range(number) - ['A' .. 'A'+number] 254 | " range(65, 90) - ['a' .. 'z'] 255 | " range('a', 'f') - ['a' .. 'f'] 256 | " range('A', 6) - ['A' .. 'F'] 257 | function! string#range(...) 258 | if ! a:0 259 | throw 'vimple string#range: not enough arguments' 260 | endif 261 | if a:0 > 2 262 | throw 'vimple string#range: too many arguments' 263 | endif 264 | if a:0 == 1 265 | return map(range(a:1), 'nr2char(char2nr("A")+v:val)') 266 | else 267 | if type(a:1) == type(0) 268 | let start = a:1 269 | else 270 | let start = char2nr(a:1) 271 | endif 272 | if type(a:2) == type(0) 273 | if type(a:1) == type(0) 274 | let end = a:2 275 | else 276 | let end = (start + a:2) - 1 277 | endif 278 | else 279 | let end = char2nr(a:2) 280 | endif 281 | return map(range(start, end), 'nr2char(v:val)') 282 | endif 283 | endfunction 284 | 285 | " returns a dict of {word : count} 286 | function! string#words(text) 287 | let words = {} 288 | for w in split(a:text) 289 | let words[w] = get(words, w, 0) + 1 290 | endfor 291 | return words 292 | endfunction 293 | -------------------------------------------------------------------------------- /doc/vimple_ls.txt: -------------------------------------------------------------------------------- 1 | *vimple#ls.txt* Plugin for accessing the :ls info programatically 2 | 3 | 4 | VIM REFERENCE MANUAL by Barry Arthur 5 | 6 | 7 | Help on using vimple#ls *vimple#ls* 8 | 9 | 1. The Vimple Architecture |vimple#ls-architecture| 10 | 2. The Buffer List Object |vimple#ls-object| 11 | 3. Public Methods |vimple#ls-public_methods| 12 | 4. Plugins Using Vimple Buffer List |vimple#ls-plugins| 13 | 14 | ============================================================================== 15 | 1. THE VIMPLE ARCHITECTURE *vimple#ls-architecture* 16 | 17 | |Vimple| uses VimLOO (Object Oriented VimL) and so returns Objects which 18 | contain methods to update and manipulate them. See OBJECT ORIENTED PROGRAMMING 19 | in section |41.8| to learn more about VimLOO. 20 | 21 | ============================================================================== 22 | 2. THE BUFFER LIST OBJECT *vimple#ls-object* 23 | 24 | The Vimple Buffer List provides a scriptable interface to Vim's |:buffers| (or 25 | |:ls|) command. 26 | 27 | *vimple#ls-constructor* 28 | Constructor~ 29 | 30 | To instantiate a new vimple#ls object: 31 | > 32 | :let bl = vimple#ls#new() 33 | < 34 | 35 | This will create a globally accessible object called: 36 | > 37 | bl 38 | < 39 | 40 | 3. BUFFER LIST PUBLIC METHODS *vimple#ls-public-methods* 41 | *vimple#ls-update()* 42 | ------------------------------------------------------------------------------ 43 | Args: NONE~ 44 | 45 | Overview:~ 46 | 47 | Refreshes the object's internal buffer list data structure. 48 | 49 | Synopsis:~ 50 | > 51 | :call vimple#bl.update() 52 | < 53 | Description:~ 54 | 55 | Use this method to update the vimple#bl object's knowledge of Vim's 56 | current buffer state. If you open new files or use |:bdelete| or |:bwipeout| 57 | to remove buffers, you will need to manually update your vimple#ls 58 | objects to reflect those changes. The need to call this manually for certain 59 | vimple#ls calls might be removed in future versions. 60 | 61 | Return:~ 62 | 63 | The bl object which allows chaining of vimple#ls methods, like: 64 | > 65 | :echo vimple#bl.update().to_s() 66 | < 67 | 68 | *vimple#ls-to_s()* 69 | ------------------------------------------------------------------------------ 70 | Args: [format]~ 71 | 72 | Overview:~ 73 | 74 | Returns a string representation of the buffer list. 75 | 76 | Synopsis:~ 77 | > 78 | :echo vimple#bl.to_s( ... ) 79 | < 80 | Description:~ 81 | 82 | This method returns a simple textual representation of the buffer list. The 83 | default (without arguments) tries to emulate the layout of the builtin |:ls| 84 | output. This method should be used with Vim's :echo or :let statements, like: 85 | > 86 | :echo vimple#bl.to_s() 87 | :echo vimple#bl.to_s("%n\n") 88 | :let my_buffers = split(vimple#bl.to_s("%n\n"), "\n") 89 | < 90 | 91 | Arguments:~ 92 | 93 | format~ 94 | 95 | Using a printf-like format specifier, you can alter the appearance of the 96 | output. The available format specifiers are: 97 | 98 | - %b buffer number 99 | - %n name 100 | - %f flags 101 | - %l cursor line 102 | 103 | Return:~ 104 | 105 | A string of newline terminated buffer list entries similar to the |:ls| 106 | builtin. 107 | 108 | NOTE: Currently you have to manually call vimple#bl.update() before calling 109 | vimple#bl.to_s() if you want the latest information. This may change in a 110 | future version. 111 | 112 | *vimple#ls-to_l()* 113 | ------------------------------------------------------------------------------ 114 | Args: [buffer_property]~ 115 | 116 | Overview:~ 117 | 118 | Returns a list representation of the buffer list. 119 | 120 | Synopsis:~ 121 | > 122 | :echo vimple#bl.to_l( ... ) 123 | < 124 | Description:~ 125 | 126 | This method returns a list representation of the buffer list. 127 | 128 | Arguments:~ 129 | 130 | The to_l() method is actually just a wrapper for the |vimple#ls-buffers()| 131 | method. See that method for details about the buffer_property argument. 132 | 133 | Return:~ 134 | 135 | The to_l() method returns a list of dictionaries, each with the following 136 | fields (with example values): 137 | > 138 | {'active': 0, 139 | 'number': '1', 140 | 'alternate': 0, 141 | 'name': 'doc/buffer_list.txt', 142 | 'readonly': 0, 143 | 'current': 1, 144 | 'line': '1', 145 | 'modified': 0, 146 | 'modifiable': 1, 147 | 'hidden': 0, 148 | 'read_error': 0, 149 | 'listed': 1 150 | } 151 | < 152 | 153 | NOTE: Currently you have to manually call vimple#bl.update() before calling 154 | vimple#bl.to_l() if you want the latest information. This may change in a 155 | future version. 156 | 157 | *vimple#ls-to_d()* 158 | ------------------------------------------------------------------------------ 159 | Args: [buffer_property]~ 160 | 161 | Overview:~ 162 | 163 | Returns a dictionary representation of the buffer list. 164 | 165 | Synopsis:~ 166 | > 167 | :echo vimple#bl.to_d( ... ) 168 | < 169 | Description:~ 170 | 171 | This method returns a dictionary representation of the buffer list. The key 172 | for each entry in the dictionary is the buffer number as shown by |:ls| 173 | 174 | Arguments:~ 175 | 176 | The to_d() method is actually just a wrapper for the |vimple#ls-buffers()| 177 | method. See that method for details about the buffer_property argument. 178 | 179 | Return:~ 180 | 181 | The to_d() method returns a dictionary of dictionaries with the following 182 | fields (with example values): 183 | > 184 | {'1': 185 | {'active': 0, 186 | 'number': '1', 187 | 'alternate': 0, 188 | 'name': 'doc/buffer_list.txt', 189 | 'readonly': 0, 190 | 'current': 1, 191 | 'line': '1', 192 | 'modified': 0, 193 | 'modifiable': 1, 194 | 'hidden': 0, 195 | 'read_error': 0, 196 | 'listed': 1 197 | } 198 | } 199 | < 200 | 201 | NOTE: Currently you have to manually call vimple#bl.update() before calling 202 | vimple#bl.to_d() if you want the latest information. This may change in a 203 | future version. 204 | 205 | *vimple#ls-print()* 206 | ------------------------------------------------------------------------------ 207 | Args: [show_unlisted]~ 208 | 209 | Overview:~ 210 | 211 | Prints (colourfully) the buffer list. 212 | 213 | Synopsis:~ 214 | > 215 | :call vimple#bl.print( BOOL ) 216 | < 217 | Description:~ 218 | 219 | Use this method to print to the screen a coloured representation of the buffer 220 | list. The layout resembles the builtin |:ls| command but is by default 221 | coloured to show important information more obviously. See the 222 | autoload/vimple/vimple.vim file to see how to customise the colours used by 223 | vimple#ls.print(). 224 | 225 | Arguments:~ 226 | 227 | show_unlisted~ 228 | 229 | If this boolean argument is not false then all buffers (including the unlisted 230 | ones) are printed (as with the |:ls!| command. With no argument or one that 231 | evaluates to false, only the listed buffers are shown (as with the |:ls| 232 | command). 233 | 234 | Return:~ 235 | 236 | The bl object (for chaining), although it's not immediately clear how this 237 | could be useful (for the print() method), but a design decision was made to 238 | return the bl object for all methods that didn't have to explicitly return a 239 | different type (as the to_x() methods do). 240 | 241 | NOTE: Unlike most of the other methods, the print() method -does- update the 242 | buffer list (with an internal call to update()) prior to printing. 243 | 244 | *vimple#ls-filter()* 245 | ------------------------------------------------------------------------------ 246 | Args: [filter]~ 247 | 248 | Overview:~ 249 | 250 | Auxilliary method used to filter out desired buffers only. 251 | 252 | Synopsis:~ 253 | > 254 | :call vimple#bl.filter( ... ) 255 | < 256 | Description:~ 257 | 258 | The filter() method selects buffers from the internal list based on the 259 | criteria provided in the argument. This method is used heavily internally by 260 | other public methods, like the to_l() and to_d() and buffers() methods. This 261 | method returns a new vimple#ls object containing only the selected buffers. 262 | 263 | Arguments:~ 264 | 265 | filter~ 266 | 267 | The vimple#ls#filter() method uses the built-in |filter()| function which 268 | uses the |v:val| variable to aaccess the elements of the internal buffer 269 | properties. Call filter() like this: 270 | > 271 | :call vimple#bl.filter('v:val.modified').print() 272 | :call vimple#bl.filter('v:val.name =~ "\.txt$"').print() 273 | :echo vimple#bl.filter('v:val.name =~ "\.txt$"').to_s() 274 | < 275 | The available v:val properties are: 276 | 277 | - active 278 | - alternate 279 | - current 280 | - hidden 281 | - line 282 | - listed 283 | - modifiable 284 | - modified 285 | - name 286 | - number 287 | - read_error 288 | - readonly 289 | 290 | Return:~ 291 | 292 | The bl object (for chaining). 293 | 294 | *vimple#ls-buffers()* 295 | ------------------------------------------------------------------------------ 296 | Args: [buffer_property]~ 297 | 298 | Overview:~ 299 | 300 | Simplified filter wrapper. 301 | 302 | Synopsis:~ 303 | > 304 | :echo vimple#bl.buffers( ... ) 305 | < 306 | Description:~ 307 | 308 | This utility method provides a simpler way to filter based on the flags 309 | commonly used to select buffers. 310 | 311 | Arguments:~ 312 | 313 | buffer_property~ 314 | 315 | Call buffers() like this: 316 | > 317 | :echo vimple#bl.buffers('modified') 318 | :echo vimple#bl.buffers('hidden') 319 | < 320 | The available buffer properties are: 321 | 322 | - active 323 | - hidden 324 | - listed 325 | - modifiable 326 | - modified 327 | - read_error 328 | - readonly 329 | 330 | Return:~ 331 | 332 | The bl object (for chaining). 333 | 334 | 335 | ============================================================================== 336 | 4. PLUGINS USING VIMPLE BUFFER LIST *vimple#ls-plugins* 337 | 338 | Vimple was designed to be a library for Vim developers and plugin writers. The 339 | currently known plugins using Vimple: 340 | 341 | - the buffalo (https://github.com/Raimondi/vim-buffalo) - A lightning fast 342 | buffer switching tool using fuzzy matching. 343 | 344 | vim:tw=78:ts=8:ft=help:norl: 345 | -------------------------------------------------------------------------------- /plugin/vimple-lib.vim: -------------------------------------------------------------------------------- 1 | function! s:SID() 2 | return "" . matchstr(expand(''), '\zs\d\+_\zeSID$') 3 | endfun 4 | 5 | if !exists('g:vim_home') 6 | let vim_home = fnamemodify($MYVIMRC, ':p:h') 7 | endif 8 | if !exists('g:vim_bundle_home') 9 | let vim_bundle_home = g:vim_home . '/bundle/' 10 | endif 11 | 12 | " example call: 13 | " call PathogenAddPlugin(g:vim_bundle_home . '/unused/csapprox{}') 14 | function! PathogenAddPlugin(plugin) 15 | call pathogen#surround(a:plugin) 16 | silent! runtime! plugin/*.vim 17 | endfunction 18 | 19 | function! CurrentPartialWord() 20 | let p = searchpos('\W\zs\w\+\%#', 'bnW') 21 | let b:partial_word = strpart(getline('.'), p[1]-1, col('.')-p[1]) 22 | endfunction 23 | 24 | augroup Vimple 25 | au! 26 | autocmd CursorMovedI * call CurrentPartialWord() 27 | augroup END 28 | 29 | function! Scope() 30 | let ft = tolower(&ft) 31 | if exists('*Scope_' . ft) 32 | return call('Scope_' . ft, []) 33 | endif 34 | endfunction 35 | 36 | function! ExtendedRegexObject(...) 37 | return call('regex#ExtendedRegex', a:000) 38 | endfunction 39 | 40 | " ERex is a global object with access to Vim's vars: 41 | let ERex = ExtendedRegexObject() 42 | 43 | function! TagSearch() 44 | let ident = expand('') 45 | if exists('s:tags') 46 | unlet s:tags 47 | endif 48 | let s:tags = taglist(ident) 49 | if empty(s:tags) 50 | echohl Warning 51 | echom 'Tag not found: ' . ident 52 | echohl None 53 | return 54 | endif 55 | let data = map(copy(s:tags), 'v:key . " " . v:val.name . "\t" . v:val.filename') 56 | call overlay#show( 57 | \ data 58 | \, { 59 | \ '' : ':call ' . s:SID() . 'tagsearchaccept()' 60 | \ , 'q' : ':call overlay#close()' 61 | \ } 62 | \, {'filter' : 1, 'use_split' : 1}) 63 | endfunction 64 | 65 | function! s:tagsearchaccept() 66 | let ident = matchstr(overlay#select_line(), '^\d\+') 67 | let fname = s:tags[ident].filename 68 | if bufnr(fname) == -1 69 | exec 'edit ' . fname 70 | else 71 | exec 'buffer ' . fname 72 | endif 73 | silent! exe s:tags[ident].cmd 74 | endfunction 75 | 76 | 77 | 78 | function! IdentSearch(type) 79 | let type = a:type ? ']I' : '[I' 80 | try 81 | let data = vimple#redir('norm! ' . type) 82 | catch '^Vim\%((\a\+)\)\=:E389:' 83 | echohl Warning 84 | echom 'Could not find pattern' 85 | echohl None 86 | return 87 | endtry 88 | call overlay#show( 89 | \ data 90 | \, { 91 | \ '' : ':call ' . s:SID() . 'identsearchaccept(' . a:type . ')' 92 | \ , 'q' : ':call overlay#close()' 93 | \ } 94 | \, {'filter' : 1, 'use_split' : 1}) 95 | endfunction 96 | 97 | function! s:identsearchaccept(type) 98 | let type = a:type ? ']' : '[' 99 | let num = matchstr(overlay#select_line(), '\d\+') 100 | exe 'silent! norm! ' . num . type . "\t" 101 | endfunction 102 | 103 | 104 | function! SpellSuggest(ident) 105 | call overlay#show( 106 | \ s:getsuggestions(a:ident) 107 | \, { 108 | \ '' : ':call ' . s:SID() . 'spellsuggestaccept()' 109 | \ , 'q' : ':call overlay#close()' 110 | \ } 111 | \, {'filter' : 0, 'use_split' : 1}) 112 | endfunction 113 | 114 | function! s:getsuggestions(ident) 115 | let spell = &spell 116 | if ! spell 117 | set spell 118 | endif 119 | let suggestions = list#lspread(spellsuggest(a:ident), 5) 120 | if ! spell 121 | set nospell 122 | endif 123 | return suggestions 124 | endfunction 125 | 126 | function! s:spellsuggestaccept() 127 | let line = getline('.') 128 | let idx = strlen(substitute(line[:col('.')], '[^\t]', '', 'g')) 129 | let word_list = split(line, '\t') 130 | call overlay#close() 131 | let [r1, r2] = [@@, @-] 132 | exe 'norm! ciw' . word_list[idx] 133 | let [@@, @-] = [r1, r2] 134 | endfunction 135 | 136 | 137 | 138 | function! BufGrep(pattern) 139 | let pattern = a:pattern 140 | let fc = pattern[0] 141 | let lc = pattern[-1] 142 | if fc !~ '[[:punct:]]' 143 | let fc = '/' 144 | let lc = '/' 145 | elseif fc != lc 146 | let lc = fc 147 | let pattern = pattern[1:] 148 | else 149 | let pattern = pattern[1:-2] 150 | endif 151 | let pattern = escape(pattern, fc) 152 | 153 | let data = vimple#redir('global ' . fc . pattern . lc . '#') 154 | if data[0] =~ 'Pattern not found:' 155 | echohl Warning 156 | echo data[0] 157 | echohl None 158 | return 159 | endif 160 | call overlay#show( 161 | \ data 162 | \, { 163 | \ '' : ':call ' . s:SID() . 'bufgrepaccept()' 164 | \ , 'q' : ':call overlay#close()' 165 | \ } 166 | \, {'filter' : 1, 'use_split' : 1}) 167 | endfunction 168 | 169 | function! s:bufgrepaccept() 170 | let num = matchstr(overlay#select_line(), '\d\+') 171 | exe 'silent! norm! ' . num . "G" 172 | endfunction 173 | 174 | 175 | function! StringScanner(first, last, command, ...) 176 | let args = [] 177 | if a:0 178 | let args = a:000 179 | endif 180 | let ss = string#scanner(getline(a:first, a:last)) 181 | let g:vimple#ss = call(eval('ss.' . a:command), args, ss) 182 | return g:vimple#ss 183 | endfunction 184 | 185 | 186 | function! Mkvimrc() 187 | let rtp = uniq(map(filter(map(getline(1, '$'), 188 | \ 'matchstr(v:val, "^\\s*\\d\\+:\\s\\+\\zs.*")'), 'v:val != ""'), 189 | \ 'fnameescape(substitute(v:val, "/\\(autoload\\|colors\\|compiler\\|doc\\|ftdetect\\|ftplugin\\|indent\\|keymap\\|lang\\|plugin\\|syntax\\).*", "", ""))')) 190 | 191 | if empty(rtp) 192 | echohl Error 193 | echom 'Mkvimrc: Buffer does not contain :scriptnames output' 194 | echohl None 195 | return 196 | endif 197 | let vimrc_lines = [ 198 | \ "set nocompatible" 199 | \ , "let &rtp = join(" . string(map(rtp, 'fnameescape(v:val)')) . ", ',') . ',' . &rtp" 200 | \ , "filetype plugin indent on" 201 | \ , "syntax enable" 202 | \ ] 203 | let datetime = localtime() 204 | let vimrc_file = './vimrc-' . datetime 205 | call writefile(vimrc_lines, vimrc_file) 206 | return vimrc_file 207 | endfunction 208 | 209 | 210 | function! BufDo(cmds) 211 | let old_hidden = &hidden 212 | set hidden 213 | tabnew 214 | echom 'bufdo ' . a:cmds 215 | exe 'bufdo ' . a:cmds 216 | tabclose 217 | let &hidden = old_hidden 218 | endfunction 219 | 220 | function! BufTypeDo(args) 221 | let [type; commands] = split(a:args, ' ') 222 | let cmds = join(commands) 223 | call BufDo('if &ft ==? "' . escape(type, '"') . '" | exe "' . escape(cmds, '"') . '" | endif') 224 | endfunction 225 | 226 | function! BufMatchDo(args) 227 | let [pattern; commands] = split(a:args, ' ') 228 | let cmds = join(commands) 229 | call BufDo('if expand("%") =~? "' . escape(pattern, '"') . '" | exe "' . escape(cmds, '"') . '" | endif') 230 | endfunction 231 | 232 | 233 | function! QFbufs() 234 | return quickfix#bufnames() 235 | endfunction 236 | 237 | 238 | " Takes a range as well as optional start and end lines to extract from the 239 | " file. If both ends of the range are given, the shorter of first:last vs 240 | " start:end will be used to fill the range. 241 | function! ReadIntoBuffer(file, ...) range 242 | let first = a:firstline 243 | let last = a:lastline 244 | let lines = readfile(a:file) 245 | let start = 0 246 | let end = len(lines) 247 | if a:0 248 | let start = a:1 - 1 249 | if a:0 > 1 250 | let end = a:2 - 1 251 | endif 252 | endif 253 | if start > len(lines) 254 | return 255 | endif 256 | let lines = lines[start : end] 257 | if len(lines) > (last-first) 258 | let lines = lines[0:(last-first-1)] 259 | endif 260 | call append(first, lines) 261 | endfunction 262 | 263 | 264 | function! View(cmd) 265 | call ShowInNewBuf(vimple#redir(a:cmd)) 266 | endfunction 267 | 268 | function! ViewFT(cmd) 269 | call overlay#show(vimple#redir(a:cmd), { 270 | \ 'q' : ':call overlay#close()', 271 | \ '' : ':let t:linenum = matchstr(getline("."), "^\\s*\\d\\+") \| wincmd w \| exe "normal! " . t:linenum . "G"' 272 | \ }, { 273 | \ 'set ft=' . &ft : 1, 'use_split' : 1, 'filter' : index(g:vimple_auto_filter, 'view') != -1 274 | \ }) 275 | endfunction 276 | 277 | if ! exists('g:vimple_auto_filter') 278 | let g:vimple_auto_filter = ['view', 'vfm'] 279 | endif 280 | 281 | function! ShowInNewBuf(data) 282 | call overlay#show(a:data, {'q' : ':call overlay#close()'}, {'use_split' : 1, 'filter' : index(g:vimple_auto_filter, 'view') != -1}) 283 | endfunction 284 | 285 | function! Collect(args) 286 | let [regvar; command] = split(a:args) 287 | let cmd = join(command, " ") 288 | let list = &list 289 | set nolist 290 | let buf = join(vimple#redir(cmd), "\n") 291 | if list 292 | set list 293 | endif 294 | if len(regvar) > 1 295 | exe 'let ' . regvar . '="' . escape(buf, '"') . '"' 296 | else 297 | call setreg(regvar, buf) 298 | endif 299 | return split(buf, '\n') 300 | endfunction 301 | 302 | function! GCollect(pattern) 303 | return map(Collect('_ g/' . a:pattern), 'substitute(v:val, "^\\s*\\d\\+\\s*", "", "")') 304 | endfunction 305 | 306 | function! GCCollect(pattern) 307 | return map(map(Collect('_ g/' . a:pattern), 'join(split(v:val, "^\\s*\\d\\+\\s*"))'), 308 | \ 'substitute(v:val, a:pattern, "", "")') 309 | endfunction 310 | 311 | function! VCollect(pattern) 312 | return map(Collect('_ v/' . a:pattern), 'substitute(v:val, "^\\s*\\d\\+\\s*", "", "")') 313 | endfunction 314 | 315 | function! VCCollect(pattern) 316 | return map(map(Collect('_ v/' . a:pattern), 'join(split(v:val, "^\\s*\\d\\+\\s*"))'), 317 | \ 'substitute(v:val, a:pattern, "", "")') 318 | endfunction 319 | 320 | 321 | function! SCall(script, function, args) 322 | let scripts = g:vimple#sn.update().filter_by_name(a:script).to_l() 323 | if len(scripts) == 0 324 | echo "SCall: no script matches " . a:script 325 | return 326 | elseif len(scripts) > 1 327 | echo "SCall: more than one script matches " . a:script 328 | endif 329 | let func = '' . scripts[0]['number'] . '_' . a:function 330 | if exists('*' . func) 331 | return call(func, a:args) 332 | else 333 | echo "SCall: no function " . func . " in script " . a:script 334 | return 335 | endif 336 | endfunction 337 | 338 | 339 | " " Pre-initialise library objects 340 | if get(g:, 'vimple_init_vars', 1) 341 | if get(g:, 'vimple_init_ab', 1) 342 | let vimple#ab = vimple#abbreviations#new() 343 | endif 344 | if get(g:, 'vimple_init_bl', 1) 345 | let vimple#bl = vimple#ls#new() 346 | endif 347 | if get(g:, 'vimple_init_hl', 1) 348 | let vimple#hl = vimple#highlight#new() 349 | endif 350 | if get(g:, 'vimple_init_sn', 1) 351 | let vimple#sn = vimple#scriptnames#new() 352 | endif 353 | if get(g:, 'vimple_init_vn', 1) 354 | let vimple#vn = vimple#version#new() 355 | endif 356 | if get(g:, 'vimple_init_ma', 1) 357 | let vimple#ma = vimple#marks#new() 358 | endif 359 | if get(g:, 'vimple_init_ul', 1) 360 | let vimple#ul = vimple#undolist#new() 361 | endif 362 | if get(g:, 'vimple_init_mp', 1) 363 | let vimple#mp = vimple#map#new() 364 | endif 365 | if get(g:, 'vimple_init_op', 0) 366 | let vimple#op = vimple#options#new() 367 | endif 368 | endif 369 | 370 | call vimple#default_colorscheme() 371 | 372 | call completers#init() 373 | 374 | " disabled by default 375 | " let vimple#au = vimple#autocmd#new() 376 | -------------------------------------------------------------------------------- /doc/vimple.txt: -------------------------------------------------------------------------------- 1 | *vimple.txt* Programmatic access to Vim's read-only command output. 2 | 3 | 4 | VIM REFERENCE MANUAL by Barry Arthur 5 | 6 | 7 | Help on using vimple *vimple* 8 | 9 | 0. Vimple maps and commands |vimple-maps-commands| 10 | 1. Introduction |vimple-intro| 11 | 2. View |vimple-view-command| 12 | 3. Collect |vimple-collect-command| 13 | 4. GCollect |vimple-gcollect-function| 14 | 5. GCCollect |vimple-gccollect-function| 15 | 6. MyMaps |vimple-mymaps-command| 16 | 7. ReadIntoBuffer |vimple-readintobuffer-command| 17 | 8. Filter |vimple-filter-command| 18 | 9. QFdo |vimple-quickfix-commands| 19 | 10. BufDo |vimple-bufdo-commands| 20 | 11. Overlay Tools |vimple-overlay-tools| 21 | 12. Scope |vimple-scope| 22 | 13. Custom Insert-mode Completers |vimple-completers| 23 | 24 | 25 | ============================================================================== 26 | 0. VIMPLE MAPS AND COMMANDS *vimple-maps-commands* 27 | 28 | Vimple creates new (and in some cases overrides default) maps and commands. 29 | If you don't want any of these maps and commands, they can be disabled by 30 | adding this line to your |$MYVIMRC|: 31 | > 32 | let g:init_vimple_maps_and_commands = 0 33 | < 34 | 35 | ============================================================================== 36 | 1. INTRODUCTION *vimple-intro* 37 | 38 | Vimple provides VimLOO (Object-oriented VimL) objects for several 39 | built-in commands, such as: 40 | 41 | * ls / buffers -> vimple#bl 42 | * scriptnames -> vimple#sn 43 | * highlight -> vimple#hl 44 | * version -> vimple#vn 45 | * marks -> vimple#ma 46 | * maps -> vimple#mp 47 | * undolist -> vimple#ul 48 | 49 | These objects all support at least the following three methods: 50 | 51 | * update() -> refresh the object's data 52 | * to_s() -> return a string representation fit for :echo 53 | * to_l() -> return a list representation 54 | 55 | Vimple also provides the following two utility commands to make it 56 | easier to work with Vim's command output: 57 | 58 | ============================================================================== 59 | 2. VIEW *:View* *vimple-view-command* 60 | > 61 | :View 62 | < 63 | View will show the output of the given command in a split window. 64 | Having the output in a buffer makes it easily searchable and 65 | modifiable. This command is great if all you want to do is quickly 66 | check for the existance of somthing within the messy formatted output 67 | of a command, or if you need to elaborately massage the output for 68 | some reason. Being in a Vim buffer, you have all of Vim's editing 69 | tools at your disposal. 70 | 71 | By default, :View will prompt you for a pattern to filter the results by. If 72 | you want to disable this default behaviour, add a line like this to your 73 | |$MYVIMRC|: 74 | > 75 | let vimple_auto_filter = [] 76 | < or > 77 | let vimple_auto_filter = ['vfm'] 78 | < (if you want auto-filter in VFM but not :View) 79 | 80 | ============================================================================== 81 | 3. COLLECT *:Collect* *vimple-collect-command* 82 | > 83 | :Collect 84 | < 85 | Collect is useful for grabbing the command's output into a named 86 | register or variable. This is useful for doing further programmatic 87 | manipulations on the data. If the first argument is a single letter 88 | [a-z] then it is treated as the corresponding register to save the 89 | command output into. If you want to save the command output into a 90 | variable, use a fully scoped variable, like: 91 | > 92 | :Collect g:regs registers 93 | < 94 | ============================================================================== 95 | 4. GCollect() *GCollect()* *vimple-gcollect-function* 96 | > 97 | GCollect( pattern ) 98 | < 99 | Uses "pattern" in a :global /pattern/ command and returns the results as a 100 | list of lines. 101 | > 102 | :echo GCollect('^\s*===\s*') 103 | < 104 | ============================================================================== 105 | 5. GCCollect() *CGCollect()* *vimple-gccollect-function* 106 | > 107 | GCCollect( pattern ) 108 | < 109 | Uses "pattern" in a :global /pattern/ command and returns the results as a 110 | list of lines with the "pattern" stripped. 111 | > 112 | :echo GCCollect('^\s*===\s*') 113 | 114 | ============================================================================== 115 | 6. MYMAPS *:MyMaps* *vimple-mymaps-command* 116 | > 117 | :MyMaps 118 | < 119 | Will show in a new buffer your curently active maps (:map and :map!). The maps 120 | are displayed slightly differently to the builtin commands in that the map 121 | special indicators (*, & and @) are shown immediately after the mode indicator 122 | at the start of the map. maps (where appears in the 123 | lefthand-side) are removed for clarity, and the maps are sorted in an attempt 124 | to group related maps together. 125 | 126 | ============================================================================== 127 | 7. READINTOBUFFER *:ReadIntoBuffer* *vimple-readintobuffer-command* 128 | > 129 | :ReadIntoBuffer 130 | < 131 | For those times when you'd like to read in a subset of lines from a file. 132 | > 133 | :ReadIntoBuffer foo 5 10 134 | < 135 | Will grab six lines (5 through 10, both inclusive) from file 'foo' into the 136 | current file beneath the current line (as |:read| does). 137 | 138 | 139 | It defaults to the current line, but you can specify another: 140 | > 141 | :7 ReadIntoBuffer foo 5 10 142 | < 143 | Will grab six lines (5 through 10, both inclusive) from file 'foo' into the 144 | current file beneath line seven (which means it starts on line 8 - the start 145 | range in this command is exclusive; the end range (shown next) is inclusive.) 146 | 147 | 148 | And you can limit the insertion range too: 149 | > 150 | :7,9 ReadIntoBuffer foo 5 10 151 | < 152 | Will grab two lines (5 and 6) from file 'foo' into the current file beneath 153 | line seven (therefore occupying lines 8 and 9 in the current buffer). 154 | 155 | The usefulness of being able to limit the range at both ends is debatable, but 156 | if I didn't I'd get requests to do so, surely. 157 | 158 | ============================================================================== 159 | 8. FILTER *:Filter* *vimple-filter-command* 160 | > 161 | :Filter 162 | < 163 | The :Filter command behaves like an interactive :g/re/p on the current buffer. 164 | Only matching lines are shown, with non-matching ones being filtered out. 165 | 166 | WARNING: This command alters your buffer contents. Using it from within a 167 | buffer you don't intend to filter is ill advised. 168 | 169 | 170 | NEW!: :Filter is now even fuzzier! That's right! Put _down_ your hair-drier, 171 | because :Filter now automatically inserts `.*` whenever you press ! 172 | Awesomes, right? Searching for /some/long/path/to/file.boring?! 173 | Make it fun with s l p t f \o/ 174 | 175 | The :Filter command is heavily used by the |VimFindsMe| plugin from within its 176 | browse window. 177 | 178 | ============================================================================== 179 | 9. QUICKFIX COMMANDS *vimple-quickfix-commands* 180 | *QFdo* 181 | NOTE: The location-list analogue for the QuickFix commands start with LL 182 | 183 | > 184 | :QFdo 185 | :LLdo 186 | < 187 | The :QFdo command performs the series of bar-separated ex-commands over the 188 | buffers in the QuickFix list. 189 | 190 | Example: 191 | > 192 | :vimgrep /prince/j **/*.txt 193 | :QFdo %s/Vim/frog/g 194 | < 195 | Will change all princes into frogs recursively throughout your txt files. 196 | 197 | NOTE: If you have the (https://github.com/dahu/grope) Grope plugin (which uses 198 | the |location-list|, this is even easier: 199 | > 200 | :Grope /prince/ @@txt 201 | :LLdo %s/Vim/frog/g 202 | < 203 | 204 | > 205 | :QFbufs 206 | :LLbufs 207 | < 208 | Returns the unique list of buffer names within the QuickFix / Location list. 209 | 210 | > 211 | :QFargs 212 | :QFargslocal 213 | :LLargs 214 | :LLargslocal 215 | < 216 | Sets the |:args| or |:arglocal| from the relevant list. 217 | 218 | Example: 219 | > 220 | :vimgrep /prince/j **/*.txt 221 | :tabnew | QFargslocal 222 | < 223 | Will open a new tab-page and set the local argument list to the unique set of 224 | buffers contained within the QuickFix list. 225 | 226 | 227 | ============================================================================== 228 | 10. BUFDO COMMANDS *vimple-bufdo-commands* 229 | *BufDo* *BufTypeDo* *BufMatchDo* 230 | 231 | Example: 232 | > 233 | :BufTypeDo vim %s/func\\>\\ze/&tion/e 234 | < 235 | 236 | Will replace 'func' with 'function' in all VIM files. 237 | 238 | Note the use of the 'e' |s_flags| to ignore errors where the search term 239 | doesn't exist in a file. 240 | 241 | Example: 242 | > 243 | :Nexus 1 1 244 | :BufMatchDo test g/Test/s/\\d\\+/\\=Nexus() 245 | < 246 | 247 | Will re-number the test cases in all files containing 'test' in their filename. 248 | 249 | NOTE: This example depends on https://github.com/dahu/Nexus 250 | 251 | 252 | ============================================================================== 253 | 11. OVERLAY TOOLS *vimple-overlay-tools* 254 | *vimple-z=* *vimple-[I* *vimple-g]* 255 | 256 | |z=| 257 | 258 | Shows |spell| suggestions in an overlay window. Pressing `` 259 | will replace the word under the cursor in the original window with the 260 | current word under the cursor in the overlay. 261 | 262 | Use `vimple_spell_suggest` if you want to map this behaviour 263 | to a differnt key. 264 | 265 | |[I| 266 | 267 | Shows |ident-search| results in an overlay window. Pressing `` 268 | will jump to the associated line of the identifier under the cursor. 269 | 270 | Use `vimple_ident_search` if you want to map this behaviour 271 | to a differnt key. 272 | 273 | |g]| 274 | 275 | Shows |tag| search results in an overlay window. Pressing `` 276 | will jump to the associated line of the tag under the cursor. 277 | 278 | Use `vimple_tag_search` if you want to map this behaviour 279 | to a differnt key. 280 | 281 | 282 | 283 | ============================================================================== 284 | 12. SCOPE *vimple-scope* 285 | 286 | The Scope() function attempts to show the current function or class/method 287 | scope. Some people like to display this information in their `statusline`, 288 | like: 289 | > 290 | set statusline=%f%m%r%h%w\ [%n:%{&ff}/%Y]\%{Scope()}%=[0x\%04.4B][%03v][%p%%\ line\ %l\ of\ %L] 291 | < 292 | 293 | Currently only Vim & Python (and Python only for testing purposes, created by 294 | a NON Pythonista -- patches welcome) have been implemented, but it is very 295 | easy for you to write scope functions for your own filetypes. Take Ruby for 296 | example: Create `~/.vim/ftplugin/ruby_scope.vim` like this: 297 | 298 | ---- 299 | function! Scope_ruby() 300 | let class_scope = scope#inspect('^\s*class\s\+\([a-zA-Z0-9_.]\+\)', '^\s*end') 301 | let method_scope = scope#inspect('^\s*def\s\+\([a-zA-Z0-9_.]\+\)', '^\s*end') 302 | return ' ' . join(map(class_scope.stack, 'v:val.head_line_number . "," . v:val.tail_line_number . " " . v:val.head_string'), ' :: ') 303 | \. ' >> ' . join(map(method_scope.stack, 'v:val.head_line_number . "," . v:val.tail_line_number . " " . v:val.head_string'), ' > ') 304 | endfunction 305 | ---- 306 | 307 | NOTE: The above example for Ruby is woefully inadequate. A better effect might 308 | be achievable with more context in the regex patterns. The patterns in 309 | `syntax/ruby.vim` might be useful. Parsing with regex is futile. 310 | 311 | 312 | ============================================================================== 313 | 13. COMPOSABLE COMPLETIONS *vimple-completers* 314 | *vimple-jj* 315 | 316 | 317 | By default, `jj` in insert mode activates a user-extendible meta-completion 318 | list. The default list includes abbreviations (if you have 319 | https://github.com/dahu/Aboriginal), some date-time patterns and the built-in 320 | dictionary completion (``). 321 | 322 | The default `jj` can be overridden like this: 323 | > 324 | imap vimple_completers_trigger 325 | < 326 | 327 | vim:tw=78:ts=8:ft=help:norl: 328 | -------------------------------------------------------------------------------- /autoload/vimple/ls.vim: -------------------------------------------------------------------------------- 1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | " Vimple wrapper for :ls builtin 3 | " Maintainers: Barry Arthur 4 | " Israel Chauca F. 5 | " Description: Vimple object for Vim's builtin :ls command. 6 | " Last Change: 2018-06-09 7 | " License: Vim License (see :help license) 8 | " Location: autoload/vimple/ls.vim 9 | " Website: https://github.com/dahu/vimple 10 | " 11 | " See vimple#ls.txt for help. This can be accessed by doing: 12 | " 13 | " :helptags ~/.vim/doc 14 | " :help vimple#ls 15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 16 | 17 | " Vimscript Setup: {{{1 18 | " Allow use of line continuation. 19 | let s:save_cpo = &cpo 20 | set cpo&vim 21 | 22 | " load guard 23 | " uncomment after plugin development 24 | "if exists("g:loaded_lib_vimple") 25 | " \ || v:version < 700 26 | " \ || v:version == 703 && !has('patch338') 27 | " \ || &compatible 28 | " let &cpo = s:save_cpo 29 | " finish 30 | "endif 31 | "let g:loaded_lib_vimple = 1 32 | 33 | " TODO: Use the Numerically sort comparator for print() 34 | " TODO: Use one s:dict instead of recreating the whole thing. Easier to debug. 35 | " TODO: Improve alignment of line numbers of print(). 36 | 37 | function! vimple#ls#new() 38 | let bl = {} 39 | let bl.__buffers = {} 40 | let bl.current = 0 41 | let bl.alternate = 0 42 | let bl.__filter = '' 43 | 44 | " public interface {{{1 45 | 46 | func bl._filename(bufnum, fallback) 47 | let bname = bufname(a:bufnum) 48 | if bname =~ '^\s*$' 49 | let bname = a:fallback 50 | endif 51 | echo '####' . bname . '#### 52 | return bname 53 | endfunc 54 | 55 | " update {{{2 56 | func bl.update() dict abort 57 | let bufferlist = vimple#associate(vimple#redir('ls!'), 58 | \ [[ '^\s*\(\d\+\)\(\s*[-u%#ahRF?=+x ]*\)\s\+\"\(.*\)\"\s\+\(\S\+\%(\s\+\S\+\)*\)\s\+\(\d\+\)\%(\s\+.*\)\?$', 59 | \ '\1,\2,\4,\5,\3', 60 | \ '' ]], 61 | \ [ 'split(v:val, ",")', 62 | \ 'add(v:val[0:3], join(v:val[4:-1], ","))', 63 | \ '{"number": v:val[0],' 64 | \.'"line_text": v:val[2],' 65 | \.'"line": v:val[3],' 66 | \.'"name": (v:val[4] =~ ''\[.\{-}\]'' ? (bufname(v:val[0] + 0) ? bufname(v:val[0] + 0) : v:val[4]) : v:val[4]),' 67 | \.'"listed": v:val[1] !~ "u",' 68 | \.'"current": v:val[1] =~ "%",' 69 | \.'"alternate": v:val[1] =~ "#",' 70 | \.'"active": v:val[1] =~ "a",' 71 | \.'"hidden": v:val[1] =~ "h",' 72 | \.'"modifiable": v:val[1] !~ "-",' 73 | \.'"readonly": v:val[1] =~ "=",' 74 | \.'"modified": v:val[1] =~ "+",' 75 | \.'"read_error": v:val[1] =~ "x"}' ]) 76 | 77 | let self.__buffers = {} 78 | for bfr in map(copy(bufferlist), '{v:val["number"]: v:val}') 79 | call extend(self.__buffers, bfr) 80 | endfor 81 | if self.__filter != '' 82 | call filter(self.__buffers, self.__filter) 83 | endif 84 | 85 | let current_l = filter(copy(bufferlist), 'v:val["current"] == 1') 86 | let alternate_l = filter(copy(bufferlist), 'v:val["alternate"] == 1') 87 | let self.current = len(current_l) > 0 ?current_l[0].number : 0 88 | let self.alternate = len(alternate_l) > 0 ? alternate_l[0].number : 0 89 | return self 90 | endfun 91 | 92 | " to_s([format]) {{{2 93 | " format: When absent or empty the default value ("%3b%f\"%n\" line %l\n") 94 | " will be used. 95 | " Use %b, %n, %f and %l to insert the buffer number, name, flags and cursor 96 | " line respectively . The last character will be replaced by d or s as 97 | " required by printf(), so you can include extra flags (e.g.: %3b). 98 | func bl.to_s(...) dict 99 | " An empty format argument uses the default. 100 | let default = "%3b%f\"%n\" %t %l\n" 101 | let format = a:0 && a:1 != '' ? a:1 : default 102 | " Apply filter. 103 | let buffers = self.data() 104 | 105 | let str = '' 106 | for key in sort(keys(buffers), 'vimple#comparators#numerically') 107 | let str .= vimple#format( 108 | \ format, 109 | \ { 'b': ['d', buffers[key]['number']], 110 | \ 'f': ['s', self.buffer_flags(buffers[key])], 111 | \ 't': ['s', buffers[key]['line_text']], 112 | \ 'n': ['s', buffers[key]['name']], 113 | \ 'l': ['s', buffers[key]['line']]}, 114 | \ default 115 | \ ) 116 | endfor 117 | return str 118 | endfunc 119 | 120 | " to_l {{{2 121 | func bl.to_l(...) dict 122 | return values(call(self.buffers, a:000, self).__buffers) 123 | endfunc 124 | 125 | " to_d {{{2 126 | func bl.to_d(...) dict 127 | return call(self.buffers, a:000, self).__buffers 128 | endfunc 129 | 130 | " print {{{2 131 | " only able to colour print the default to_s() output at this stage 132 | func bl.print(...) dict 133 | let bang = a:0 ? a:1 : 0 134 | call self.update() 135 | "let str = self.to_s() 136 | " following code is from hl.print() and would not work as is here 137 | "let dta = map(split(str, "\n"), '[split(v:val, " ")[0], v:val . "\n"]') 138 | "call vimple#echoc(dta) 139 | let pairs = [] 140 | let data = self.data() 141 | let max_length = max(map(deepcopy(values(self.data())), 'len(v:val.name)')) 142 | for buffer in sort(values(data), self.compare, self) 143 | if !bang && !buffer.listed 144 | continue 145 | endif 146 | call add(pairs, ['vimple_BL_Nnumber', printf('%3d',buffer.number)]) 147 | if buffer.listed 148 | call add(pairs, ['Normal', ' ']) 149 | else 150 | call add(pairs, ['vimple_BL_Unlisted', 'u']) 151 | endif 152 | if buffer.current 153 | call add(pairs, ['vimple_BL_Current', '%']) 154 | elseif buffer.alternate 155 | call add(pairs, ['vimple_BL_Alternate', '#']) 156 | else 157 | call add(pairs, ['Normal', ' ']) 158 | endif 159 | if buffer.active 160 | call add(pairs, ['vimple_BL_Active', 'a']) 161 | elseif buffer.hidden 162 | call add(pairs, ['vimple_BL_Hidden', 'h']) 163 | else 164 | call add(pairs, ['Normal', ' ']) 165 | endif 166 | if !buffer.modifiable 167 | call add(pairs, ['vimple_BL_Modifiable', '-']) 168 | elseif buffer.readonly 169 | call add(pairs, ['vimple_BL_Readonly', '=']) 170 | else 171 | call add(pairs, ['Normal', ' ']) 172 | endif 173 | if buffer.read_error 174 | call add(pairs, ['vimple_BL_RearError', 'x']) 175 | elseif buffer.modified 176 | call add(pairs, ['vimple_BL_Modified', '+']) 177 | else 178 | call add(pairs, ['Normal', ' ']) 179 | endif 180 | call add(pairs, ['Normal', ' ']) 181 | call add(pairs, [ 182 | \ buffer.current ? 183 | \ 'vimple_BL_CurrentBuffer' : 184 | \ buffer.alternate ? 185 | \ 'vimple_BL_AlternateBuffer' : 186 | \ 'Normal', 187 | \ '"' . buffer.name . '"']) 188 | let spaces = len(buffer.name) >= 29 ? 1 : 29 - len(buffer.name) 189 | call add(pairs, ['Normal', 190 | \ repeat(' ', spaces)]) 191 | call add(pairs, ['vimple_BL_Line', 192 | \ buffer.line_text . ' ']) 193 | call add(pairs, ['vimple_BL_Line', 194 | \ buffer.line . "\" 195 | \ ]) 196 | endfor 197 | call vimple#echoc(pairs) 198 | " Remove the last . Why? 199 | let pairs[-1][1] = pairs[-1][-1][:-2] 200 | return pairs 201 | endfunc 202 | 203 | " compare {{{3 204 | func bl.compare(k1, k2) dict 205 | let k1 = a:k1.number * 1 206 | let k2 = a:k2.number * 1 207 | return k1 == k2 ? 0 : k1 > k2 ? 1 : -1 208 | endfunc 209 | 210 | " filter {{{2 211 | func bl.filter(filter) dict abort 212 | let dict = deepcopy(self) 213 | call filter(dict.__buffers, a:filter) 214 | let dict.__filter .= (dict.__filter == '' ? '' : ' && ').a:filter 215 | return dict 216 | endfunc 217 | 218 | " get_filter {{{3 219 | func bl.get_filter() dict 220 | return string(self.__filter) 221 | endfunc 222 | 223 | " filter_add_or {{{3 224 | func bl.filter_add_or(filter) dict 225 | let self.__filter .= ' || ' . a:filter 226 | endfunc 227 | 228 | " filter_add_and {{{3 229 | func bl.filter_add_and(filter) dict 230 | let self.__filter .= ' && ' . a:filter 231 | endfunc 232 | 233 | " merge {{{3 234 | func bl.merge(bl) dict 235 | let bl = deepcopy(self) 236 | call extend(bl.__buffers, a:bl.__buffers, 'keep') 237 | call bl.filter_add_or(a:bl.__filter) 238 | return bl 239 | endfunc 240 | 241 | " and {{{3 242 | func bl.and(filter) dict 243 | return call(self.buffers, [a:filter], self) 244 | endfunc 245 | 246 | " hidden {{{3 247 | func bl.hidden(...) dict 248 | let filters = { 249 | \ 1: 'v:val.hidden', 250 | \ 2: '!v:val.active && v:val.listed', 251 | \ 3: '!v:val.listed', 252 | \ 4: '!v:val.active && v:val.listed && !v:val.hidden', 253 | \ 5: '!v:val.active || !v:val.listed' 254 | \ } 255 | let choice = a:0 ? a:1 : 1 256 | return self.filter_with_choice(choice, filters) 257 | endfunc 258 | 259 | " active {{{3 260 | func bl.active() dict 261 | return self.filter('v:val.active') 262 | endfunc 263 | 264 | " modifiable {{{3 265 | func bl.modifiable(...) dict 266 | let filters = { 267 | \ 1: '!v:val.modifiable', 268 | \ 2: '!v:val.modifiable || v:val.readonly' 269 | \ } 270 | let choice = a:0 ? a:1 : 1 271 | return self.filter_with_choice(choice, filters) 272 | endfunc 273 | 274 | " readonly {{{3 275 | func bl.readonly(...) dict 276 | let filters = { 277 | \ 1: '!v:val.readonly', 278 | \ 2: '!v:val.modifiable || v:val.readonly' 279 | \ } 280 | let choice = a:0 ? a:1 : 1 281 | return self.filter_with_choice(choice, filters) 282 | endfunc 283 | 284 | " modified {{{3 285 | func bl.modified() dict 286 | return self.filter('v:val.modified') 287 | endfunc 288 | 289 | " read_error {{{3 290 | func bl.read_error() dict 291 | return self.filter('v:val.read_error') 292 | endfunc 293 | 294 | " unloaded {{{3 295 | func bl.unloaded() dict 296 | return self.filter('!v:val.active && !v:val.hidden && v:val.listed') 297 | endfunc 298 | 299 | " buffers - alias for data {{{2 300 | func bl.buffers(...) dict 301 | if !a:0 302 | " Return listed buffers. 303 | return self.filter('v:val.listed') 304 | endif 305 | if a:1 =~ '^\%(non\?\|un\)' 306 | let arg = matchstr(a:1, '^\%(un\|non\)\zs.*') 307 | let bang = '!' 308 | else 309 | let arg = a:1 310 | let bang = '' 311 | endif 312 | if arg == 'hidden' 313 | let filter = 'v:val.hidden' 314 | elseif arg == 'active' 315 | let filter = 'v:val.active' 316 | elseif arg == 'modifiable' 317 | let filter = 'v:val.modifiable' 318 | elseif arg == 'readonly' 319 | let filter = 'v:val.readonly' 320 | elseif arg == 'modified' 321 | let filter = 'v:val.modified' 322 | elseif arg == 'read_error' 323 | let filter = 'v:val.read_error' 324 | elseif arg == 'unloaded' 325 | let filter = '!v:val.active && !v:val.hidden && v:val.listed' 326 | elseif arg == 'listed' 327 | let filter = 'v:val.listed' 328 | elseif arg == 'all' 329 | let filter = '1' 330 | else 331 | let filter = arg 332 | endif 333 | let bl = self.filter(bang . '(' . filter . ')') 334 | return bl 335 | endfunc 336 | 337 | " data - alias for buffers {{{3 338 | func bl.data() dict 339 | return self.__buffers 340 | endfunc 341 | 342 | " Private functions - don't need 'dict' modifier {{{2 343 | 344 | " filter_with_choice {{{3 345 | func bl.filter_with_choice(choice, filters, ...) 346 | if a:0 347 | return filter(deepcopy(a:1), a:filters[a:choice]) 348 | else 349 | return self.filter(a:filters[a:choice]) 350 | endif 351 | endfunc 352 | 353 | " buffer_status {{{3 354 | func bl.buffer_status(b) 355 | return a:b['active'] == 1 ? 'a' : a:b['hidden'] == 1 ? 'h' : '!' 356 | endfunc 357 | 358 | " buffer_type {{{3 359 | func bl.buffer_type(b) 360 | return a:b['current'] == 1 ? '%' : a:b['alternate'] == 1 ? '#' : ' ' 361 | endfunc 362 | 363 | " buffer_flags {{{3 364 | func bl.buffer_flags(b) 365 | return (a:b['listed'] == 0 ? 'u' : ' ') 366 | \. (a:b['current'] == 1 ? '%' : 367 | \ (a:b['alternate'] == 1 ? '#' : ' ')) 368 | \. (a:b['active'] == 1 ? 'a' : 369 | \ (a:b['hidden'] == 1 ? 'h' : ' ')) 370 | \. (a:b['modifiable'] == 0 ? '-' : 371 | \ (a:b['readonly'] == 1 ? '=' : ' ')) 372 | \. (a:b['modified'] == 1 ? '+' : ' ') 373 | \. (a:b['read_error'] == 1 ? 'x' : ' ') 374 | endfunc 375 | " }}}2 376 | 377 | " constructor 378 | 379 | call bl.update() 380 | return bl 381 | endfunction 382 | 383 | " Teardown:{{{1 384 | "reset &cpo back to users setting 385 | let &cpo = s:save_cpo 386 | " vim: set sw=2 sts=2 et fdm=marker: 387 | --------------------------------------------------------------------------------