1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-04-14 15:19:12 +08:00

Add vim#regex api (#3791)

This commit is contained in:
Wang Shidong 2020-09-10 00:54:46 +08:00 committed by GitHub
parent bc590ca8f5
commit 8626aba4e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 128 additions and 2 deletions

View File

@ -36,6 +36,7 @@ main () {
_detect autoload/SpaceVim/api.vim
_detect autoload/SpaceVim/api/logger.vim
_detect autoload/SpaceVim/api/vim/buffer.vim
_detect autoload/SpaceVim/api/vim/regex.vim
_detect autoload/SpaceVim/api/vim/compatible.vim
_detect autoload/SpaceVim/api/neovim/floating.vim
_detect autoload/SpaceVim/api/data/list.vim

View File

@ -0,0 +1,109 @@
"=============================================================================
" regex.vim --- regex parser for vim
" Copyright (c) 2016-2019 Wang Shidong & Contributors
" Author: Wang Shidong < wsdjeg@outlook.com >
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================
let s:self = {}
function! s:self.parser(regex, is_perl) abort
let vim_regex = a:regex
" matchadd function needs \ before [%@&]
let vim_regex = substitute(vim_regex, '\([%@&]\)', '\\\1', 'g')
" non-greedy pattern
" replace from what to what?
" let vim_regex = substitute(vim_regex, '(?<!\\)\*\?', '{-}', 'g')
" let vim_regex = substitute(vim_regex, '(?<!\\)\+\?', '{-1,}', 'g')
" let vim_regex = substitute(vim_regex, '(?<!\\)\?\?', '{-0,1}', 'g')
" let vim_regex = substitute(vim_regex, '(?<!\\)\{(.*?)\}\?', '{-\1}', 'g')
if a:is_perl
" *+, ++, ?+, {m,n}+ => *, +, ?, {m,n}
let vim_regex = substitute(vim_regex, '(?<!\\)([*+?}])\+', '\1', 'g')
" remove (?#....)
let vim_regex = substitute(vim_regex, '\(\?#.*?\)', '', 'g')
" (?=atom) => atom\@=
let vim_regex = substitute(vim_regex, '\(\?=(.+?)\)', '(\1)@=', 'g')
" (?!atom) => atom\@!
let vim_regex = substitute(vim_regex, '\(\?!(.+?)\)', '(\1)@!', 'g')
" (?<=atom) => atom\@<=
let vim_regex = substitute(vim_regex, '\(\?<=(.+?)\)', '(\1)@<=', 'g')
" (?<!atom) => atom\@<!
let vim_regex = substitute(vim_regex, '\(\?<!(.+?)\)', '(\1)@<!', 'g')
" (?>atom) => atom\@>
let vim_regex = substitute(vim_regex, '\(\?>(.+?)\)', '(\1)@>', 'g')
endif
" this won't hurt although they are not the same
let vim_regex = substitute(vim_regex, '\\A', '^', 'g')
let vim_regex = substitute(vim_regex, '\\z', '$', 'g')
let vim_regex = substitute(vim_regex, '\\B', '', 'g')
" word boundary
" \bword\b => <word>
let vim_regex = substitute(vim_regex, '\\b\(\w\+\)\\b', '\\<\1\\>', 'g')
" case-insensitive
" (?i)abc => \cabc
" (?-i)abc => \Cabc
let vim_regex = substitute(vim_regex, '(?i)', '\\c', 'g')
let vim_regex = substitute(vim_regex, '(?-i)', '\\C', 'g')
" (?P<name>exp) => (exp)
let vim_regex = substitute(vim_regex, '(?P<\w\+>\([^)]\+\))', '(\1)', 'g')
" (?:exp) => %(exp)
let vim_regex = substitute(vim_regex, '(?:\([^)]\+\))', '%(\1)', 'g')
" \a bell (\x07)
" \f form feed (\x0C)
" \v vertical tab (\x0B)
let vim_regex = substitute(vim_regex, '\\a', '%x07', 'g')
let vim_regex = substitute(vim_regex, '\\f', '%x0C', 'g')
let vim_regex = substitute(vim_regex, '\\v', '%x0B', 'g')
" \123 octal character code (up to three digits) (when enabled)
" \x7F hex character code (exactly two digits)
" let vim_regex = substitute(vim_regex, '\\(x[0-9A-Fa-f][0-9A-Fa-f])', '%\1', 'g')
" \x{10FFFF} any hex character code corresponding to a Unicode code point
" \u007F hex character code (exactly four digits)
" \u{7F} any hex character code corresponding to a Unicode code point
" \U0000007F hex character code (exactly eight digits)
" \U{7F} any hex character code corresponding to a Unicode code point
" let vim_regex = substitute(vim_regex, '\\([uU])', '%\1', 'g')
let vim_regex = substitute(vim_regex, '\[:ascii:\]', '[\\x00-\\x7F]', 'g')
let vim_regex = substitute(vim_regex, '\[:word:\]', '[0-9A-Za-z_]', 'g')
let vim_regex = substitute(vim_regex, '\[:alnum:\]', '[^0-9A-Za-z]', 'g')
let vim_regex = substitute(vim_regex, '\[:alpha:\]', '[^A-Za-z]', 'g')
let vim_regex = substitute(vim_regex, '\[:ascii:\]', '[^\x00-\x7F]', 'g')
let vim_regex = substitute(vim_regex, '\[:blank:\]', '[^\t ]', 'g')
let vim_regex = substitute(vim_regex, '\[:cntrl:\]', '[^\x00-\x1F\x7F]', 'g')
let vim_regex = substitute(vim_regex, '\[:digit:\]', '[^0-9]', 'g')
let vim_regex = substitute(vim_regex, '\[:graph:\]', '[^!-~]', 'g')
let vim_regex = substitute(vim_regex, '\[:lower:\]', '[^a-z]', 'g')
let vim_regex = substitute(vim_regex, '\[:print:\]', '[^ -~]', 'g')
let vim_regex = substitute(vim_regex, '\[:punct:\]', '[^!-/:-@\[-`{-~]', 'g')
let vim_regex = substitute(vim_regex, '\[:space:\]', '[^\t\n\r ]', 'g')
let vim_regex = substitute(vim_regex, '\[:upper:\]', '[^A-Z]', 'g')
let vim_regex = substitute(vim_regex, '\[:word:\]', '[^0-9A-Za-z_]', 'g')
let vim_regex = substitute(vim_regex, '\[:xdigit:\]', '[^0-9A-Fa-f]', 'g')
return '\v' . vim_regex
endfunction
function! SpaceVim#api#vim#regex#get() abort
return deepcopy(s:self)
endfunction
" NOTE:
" This idea of self.parser is from:
" https://github.com/Yggdroot/LeaderF/blob/bc1ed5291191663fa3136f29bb07b8874d1226c3/autoload/leaderf/python/leaderf/rgExpl.py#L300-L380

View File

@ -13,6 +13,7 @@ let s:JOB = SpaceVim#api#import('job')
let s:SYS = SpaceVim#api#import('system')
let s:BUFFER = SpaceVim#api#import('vim#buffer')
let s:LIST = SpaceVim#api#import('data#list')
let s:REGEX = SpaceVim#api#import('vim#regex')
let s:LOGGER =SpaceVim#logger#derive('FlyGrep')
let s:HI = SpaceVim#api#import('vim#highlight')
@ -28,6 +29,7 @@ let s:Window = SpaceVim#api#import('vim#window')
let s:grepid = 0
let s:filename_pattern = '[^:]*:\d\+:\d\+:'
" Init local options: {{{
let s:grep_expr = ''
@ -143,7 +145,10 @@ endfunction
function! s:expr_to_pattern(expr) abort
if s:grep_mode ==# 'expr'
let items = split(a:expr)
return join(items, '\|')
let pattern = join(items, '.*')
let pattern = s:filename_pattern . '.*\zs' . s:REGEX.parser(pattern, 0)
call s:LOGGER.info('matchadd pattern: ' . pattern)
return pattern
else
return a:expr
endif
@ -805,7 +810,7 @@ function! SpaceVim#plugins#flygrep#open(argv) abort
" setlocal nomodifiable
setf SpaceVimFlyGrep
call s:update_statusline()
call s:matchadd('FileName', '[^:]*:\d\+:\d\+:', 3)
call s:matchadd('FileName', s:filename_pattern, 3)
let s:MPT._prompt.begin = get(a:argv, 'input', '')
let fs = get(a:argv, 'files', '')
if fs ==# '@buffers'

11
test/api/vim/regex.vader Normal file
View File

@ -0,0 +1,11 @@
Execute ( SpaceVim api: vim#key ):
let regex = SpaceVim#api#import('vim#regex')
AssertEqual regex.parser('(?i)abc', 0), '\v\cabc'
AssertEqual regex.parser('(?-i)abc', 0), '\v\Cabc'
AssertEqual regex.parser('(?:exp)', 0), '\v%(exp)'
AssertEqual regex.parser('\a\f\v', 0), '\v%x07%x0C%x0B'
AssertEqual regex.parser('[:word:]', 0), '\v[0-9A-Za-z_]'
AssertEqual regex.parser('\bspace\b', 0), '\v\<space\>'
AssertEqual regex.parser('if%@&ab', 0), '\vif\%\@\&ab'
AssertEqual regex.parser('(?P<name>exp)', 0), '\v(exp)'