mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-24 06:20:05 +08:00
197 lines
6.1 KiB
VimL
197 lines
6.1 KiB
VimL
|
" Vim library for short description
|
||
|
" Maintainer: Barry Arthur <barry.arthur@gmail.com>
|
||
|
" Israel Chauca F. <israelchauca@gmail.com>
|
||
|
" Version: 0.1
|
||
|
" Description: Long description.
|
||
|
" Last Change: 2013-02-03
|
||
|
" License: Vim License (see :help license)
|
||
|
" Location: autoload/vrs.vim
|
||
|
" Website: https://github.com/Raimondi/vrs
|
||
|
"
|
||
|
" See vrs.txt for help. This can be accessed by doing:
|
||
|
"
|
||
|
" :helptags ~/.vim/doc
|
||
|
" :help vrs
|
||
|
|
||
|
" Vimscript Setup: {{{1
|
||
|
" Allow use of line continuation.
|
||
|
let s:save_cpo = &cpo
|
||
|
set cpo&vim
|
||
|
|
||
|
" load guard
|
||
|
" uncomment after plugin development
|
||
|
" Remove the conditions you do not need, they are there just as an example.
|
||
|
"if exists("g:loaded_lib_vrs")
|
||
|
" \ || v:version < 700
|
||
|
" \ || v:version == 703 && !has('patch338')
|
||
|
" \ || &compatible
|
||
|
" let &cpo = s:save_cpo
|
||
|
" finish
|
||
|
"endif
|
||
|
"let g:loaded_lib_vrs = 1
|
||
|
|
||
|
" Private Functions: {{{1
|
||
|
|
||
|
" Library Interface: {{{1
|
||
|
|
||
|
let s:vrs_patterns = {}
|
||
|
let s:erex = ExtendedRegexObject('vrs#get')
|
||
|
let g:vrs_collection = []
|
||
|
let g:vrs_collection_stack = []
|
||
|
|
||
|
function! vrs#set(name, flavour, pattern)
|
||
|
if !has_key(s:vrs_patterns, a:name)
|
||
|
let s:vrs_patterns[a:name] = {}
|
||
|
endif
|
||
|
if has_key(s:vrs_patterns[a:name], a:flavour)
|
||
|
echohl ErrorMsg
|
||
|
echom 'VRS: A pattern of that flavour ('.a:flavour.') already exists under "'.a:name.'".'
|
||
|
echohl None
|
||
|
return 0
|
||
|
endif
|
||
|
" let s:vrs_patterns[a:name][a:flavour] = (a:flavour == 'vim' ? s:erex.parse(a:pattern) : s:erex.parse_multiline_regex(a:pattern))
|
||
|
let s:vrs_patterns[a:name][a:flavour] = (a:flavour == 'vim' ? s:erex.parse(a:pattern) : a:pattern)
|
||
|
return 1
|
||
|
endfunction
|
||
|
|
||
|
function! vrs#get(name, ...)
|
||
|
let flavor = a:0 ? a:1 : 'vim'
|
||
|
" Allow using a list of names as well.
|
||
|
return type(a:name) == type("")
|
||
|
\ ? get(get(s:vrs_patterns, a:name, {}), flavor, '')
|
||
|
\ : map(a:name, 's:vrs_patterns[v:val].' . flavor)
|
||
|
endfunction
|
||
|
|
||
|
function! vrs#match(string, pattern, ...)
|
||
|
let args = extend([a:string, vrs#get(a:pattern)], a:000)
|
||
|
return call('match', args)
|
||
|
endfunction
|
||
|
|
||
|
function! vrs#matchend(string, pattern, ...)
|
||
|
let args = extend([a:string, vrs#get(a:pattern)], a:000)
|
||
|
return call('matchend', args)
|
||
|
endfunction
|
||
|
|
||
|
function! vrs#matches(string, pattern, ...)
|
||
|
return call('vrs#match', extend([a:string, a:pattern], a:000)) != -1
|
||
|
endfunction
|
||
|
|
||
|
function! vrs#exactly(string, pattern, ...)
|
||
|
return (call('vrs#match', extend([a:string, a:pattern], a:000)) == 0) && (call('vrs#matchend', extend([a:string, a:pattern], a:000)) == (len(a:string)))
|
||
|
endfunction
|
||
|
|
||
|
" XXX Should these two return the filtered dict or just a list of keys?
|
||
|
function! vrs#from_partial(partial)
|
||
|
return keys(filter(copy(s:vrs_patterns), 'stridx(v:key, a:partial) > -1'))
|
||
|
endfunction
|
||
|
|
||
|
function! vrs#from_sample(sample)
|
||
|
return keys(filter(copy(s:vrs_patterns), 'a:sample =~# v:val.vim'))
|
||
|
endfunction
|
||
|
|
||
|
" operate on each match within a string
|
||
|
" TODO: allow this to work over a range
|
||
|
" perhaps make the default callback be a new collection
|
||
|
" example: :call vrs#each(getline(1, '$'), 'ip4', 'vrs#collect')
|
||
|
function! vrs#each(source, pattern, callback)
|
||
|
let pattern = vrs#get(a:pattern)
|
||
|
let remaining = match(a:source, pattern)
|
||
|
while remaining != -1
|
||
|
call call(a:callback, [matchlist(a:source, vrs#get(a:pattern), remaining)])
|
||
|
let remaining = match(a:source, pattern, 1 + remaining)
|
||
|
endwhile
|
||
|
endfunction
|
||
|
|
||
|
" callback for adding to the current collection
|
||
|
function! vrs#collect(item)
|
||
|
call add(g:vrs_collection, a:item)
|
||
|
endfunction
|
||
|
|
||
|
" reset the current collection
|
||
|
function! vrs#delete_collection()
|
||
|
let g:vrs_collection = []
|
||
|
endfunction
|
||
|
|
||
|
" extract a common submatch from the collection (defaults to 0 - the whole match)
|
||
|
function! vrs#slice_collection(...)
|
||
|
let submatch = a:0 ? a:1 : 0
|
||
|
return map(copy(g:vrs_collection), 'v:val[' . submatch . ']')
|
||
|
endfunction
|
||
|
|
||
|
" dump the collection submatch (default 0) at cursor point
|
||
|
function! vrs#append_collection(...)
|
||
|
call append('.', call('vrs#slice_collection', a:000))
|
||
|
endfunction
|
||
|
|
||
|
" save this collection on the stack
|
||
|
function! vrs#push_collection()
|
||
|
call add(g:vrs_collection_stack, g:vrs_collection)
|
||
|
endfunction
|
||
|
|
||
|
" save this collection and clear it ready for new collection
|
||
|
function! vrs#new_collection()
|
||
|
call vrs#push_collection()
|
||
|
call vrs#delete_collection()
|
||
|
endfunction
|
||
|
|
||
|
" restore a saved collection
|
||
|
function! vrs#pop_collection()
|
||
|
if len(g:vrs_collection_stack) > 0
|
||
|
let g:vrs_collection = remove(g:vrs_collection_stack, 0)
|
||
|
else
|
||
|
let g:vrs_collection = []
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
" TODO: Add commands for the collection functions to make them simpler to use
|
||
|
|
||
|
" load VRS patterns
|
||
|
|
||
|
let erex = ExtendedRegexObject('vrs#get')
|
||
|
for pfile in split(glob(expand('<sfile>:p:h:h') . '/patterns/*.vrs'), "\n")
|
||
|
" skip syntax test file
|
||
|
if fnamemodify(pfile, ':t') == 'test.vrs'
|
||
|
continue
|
||
|
endif
|
||
|
" echo fnamemodify(pfile, ':t')
|
||
|
let [name, flavour, pattern] = ['', '', '']
|
||
|
for line in readfile(pfile)
|
||
|
" skip blank and comment only lines
|
||
|
if line =~ '^\s*\(#\|$\)'
|
||
|
continue
|
||
|
endif
|
||
|
" name lines must be flush to first column (no leading spaces)
|
||
|
if line =~ '^\S'
|
||
|
" strip trailing comments
|
||
|
let line = substitute(line, '\s*#.*', '', '')
|
||
|
if !empty(name)
|
||
|
" finalise & add prior multiline pattern
|
||
|
" echo 'call vrs#set(' . name . ' ' . flavour . ' ' . erex.parse(pattern) . ')'
|
||
|
call vrs#set(name, flavour, pattern)
|
||
|
let [name, flavour, pattern] = ['', '', '']
|
||
|
endif
|
||
|
if line =~ '\s\+\S\+\s\+\S'
|
||
|
let [all, name, flavour, pattern ;rest] = matchlist(line, '^\(\S\+\)\s\+\(\S\+\)\s\+\(.*\)')
|
||
|
" echo 'call vrs#set(' . name . ' ' . flavour . ' ' . erex.parse(pattern) . ')'
|
||
|
call vrs#set(name, flavour, pattern)
|
||
|
let [name, flavour, pattern] = ['', '', '']
|
||
|
else
|
||
|
let [all, name, flavour ;rest] = matchlist(line, '^\s*\(\S\+\)\s\+\(\S\+\)')
|
||
|
let pattern = ''
|
||
|
endif
|
||
|
else
|
||
|
" collect multiline pattern - each line must be preceded by spaces
|
||
|
let pattern .= line
|
||
|
endif
|
||
|
endfor
|
||
|
if !empty(name)
|
||
|
" echo 'call vrs#set(' . name . ' ' . flavour . ' ' . erex.parse(pattern) . ')'
|
||
|
call vrs#set(name, flavour, pattern)
|
||
|
endif
|
||
|
endfor
|
||
|
" Teardown:{{{1
|
||
|
"reset &cpo back to users setting
|
||
|
let &cpo = s:save_cpo
|
||
|
|
||
|
" vim: set sw=2 sts=2 et fdm=marker:
|