1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 06:20:05 +08:00
SpaceVim/bundle/VimRegStyle/autoload/vrs.vim

197 lines
6.1 KiB
VimL
Raw Normal View History

2020-09-06 21:56:12 +08:00
" 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: