adding new stuff

This commit is contained in:
ViktorBarzin 2017-07-09 00:22:01 +03:00
parent f84d7183aa
commit 9ef8a96f9a
1580 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,173 @@
if exists("g:__XPT_VIM__")
finish
endif
let g:__XPT_VIM__ = 1
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let XPT#ver = 2
let XPT#let_sid = 'map <Plug>xsid <SID>|let s:sid=matchstr(maparg("<Plug>xsid"), "\\d\\+_")|unmap <Plug>xsid'
let XPT#nullDict = {}
let XPT#nullList = []
let XPT#escapeHead = '\v(\\*)\V'
let XPT#unescapeHead = '\v(\\*)\1\\?\V'
let XPT#nonEscaped = '\%(' . '\%(\[^\\]\|\^\)' . '\%(\\\\\)\*' . '\)' . '\@<='
let XPT#regEval = '\V\w(\|$\w'
let XPT#nonsafe = '{$( '
let XPT#nonsafeHint = '$('
let XPT#item_var = '\V' . '$\w\+'
let XPT#item_qvar = '\V' . '{$\w\+}'
let XPT#item_func = '\V' . '\w\+(\.\*)'
let XPT#item_qfunc = '\V' . '{\w\+(\.\*)}'
let XPT#ptnIncFull = '\V' . '\^Include:' . '\zs' . '\(\.\{-}\)\$'
let XPT#ptnIncSimp = '\V' . '\^:' . '\zs' . '\(\.\{-}\)' . '\ze' . ':\$'
let XPT#ptnRepetition = '\V'. '\^\w\*...\w\*\$'
let XPT#ptnPreEvalFunc = '\v^%(Inc|Inline|ResetIndent|Pre)\('
let XPT#NONE = 0x000
let XPT#BUILT = 0x001
let XPT#NOTBUILT = 0x002
let XPT#DONE = 0x100
let XPT#UNDONE = 0x200
let XPT#GOON = 0x300
let XPT#AGAIN = 0x400
let XPT#BROKEN = -1
let XPT#importConst = '' . 'let s:escapeHead = XPT#escapeHead | ' . 'let s:unescapeHead = XPT#unescapeHead | ' . 'let s:nonEscaped = XPT#nonEscaped | ' . 'let s:regEval = XPT#regEval | ' . 'let s:nonsafe = XPT#nonsafe | ' . 'let s:nonsafeHint = XPT#nonsafeHint | ' . 'let s:nullDict = XPT#nullDict | ' . 'let s:nullList = XPT#nullList | ' . 'let s:item_var = XPT#item_var | ' . 'let s:item_qvar = XPT#item_qvar | ' . 'let s:item_func = XPT#item_func | ' . 'let s:item_qfunc = XPT#item_qfunc | ' . 'let s:ptnIncFull = XPT#ptnIncFull | ' . 'let s:ptnIncSimp = XPT#ptnIncSimp | ' . 'let s:ptnRepetition = XPT#ptnRepetition | ' . 'let s:ptnPreEvalFunc = XPT#ptnPreEvalFunc | ' . 'let s:NONE = XPT#NONE | ' . 'let s:DONE = XPT#DONE | ' . 'let s:UNDONE = XPT#UNDONE | ' . 'let s:GOON = XPT#GOON | ' . 'let s:AGAIN = XPT#AGAIN | ' . 'let s:BROKEN = XPT#BROKEN | ' . 'let s:BUILT = XPT#BUILT | ' . 'let s:NOTBUILT = XPT#NOTBUILT | ' . 'let s:R_NEXT = 0x008 | ' . 'let s:R_OUT = 0x009 | ' . 'let s:R_ = 0x00A | ' . 'let s:R_FOO = 0x00B | ' . 'let s:G_CRESTED = 0x010 | ' . 'let s:G_INITED = 0x020 | ' . 'let s:G_PROCESSED = 0x030 | ' . 'let s:G_REFOCUSED = 0x040 | '
let XPT#priorities = {'all' : 192, 'spec' : 160, 'like' : 128, 'lang' : 96, 'sub' : 64, 'personal' : 32}
let XPT#skipPattern = 'synIDattr(synID(line("."), col("."), 0), "name") =~? "\\vstring|comment"'
fun! XPT#warn(msg)
echohl WarningMsg
echom a:msg
echohl
endfunction
fun! XPT#info(msg)
echom a:msg
endfunction
fun! XPT#error(msg)
echohl ErrorMsg
echom a:msg
echohl
endfunction
fun! XPT#fallback(fbs)
let fbs = a:fbs
if len(fbs) > 0
let [key,flag] = fbs[0]
call remove(fbs,0)
if flag == 'feed'
call feedkeys( key, 'mt' )
return ''
else
return key
endif
else
return ''
endif
endfunction
fun! XPT#softTabStop()
let ts = &l:tabstop
return &l:softtabstop == 0 ? ts : &l:softtabstop
endfunction
fun! XPT#getIndentNr(ln,col)
let line = matchstr( getline(a:ln), '\V\^\s\*' )
let line = ( a:col == 1 ) ? '' : line[ 0 : a:col - 1 - 1 ]
let tabspaces = repeat( ' ', &l:tabstop )
return len( substitute( line, ' ', tabspaces, 'g' ) )
endfunction
fun! XPT#getPreferedIndentNr(ln)
if &indentexpr != ''
let indentexpr = substitute( &indentexpr, '\Vv:lnum', a:ln, '' )
try
return eval(indentexpr)
catch /.*/
return -1
endtry
elseif &cindent
return cindent(a:ln)
else
return -1
endif
endfunction
fun! XPT#getCmdOutput(cmd)
let l:a = ""
redir => l:a
exe a:cmd
redir END
return l:a
endfunction
fun! XPT#convertSpaceToTab(text)
if ( "\n" . a:text ) !~ '\V\n ' || &expandtab
return a:text
else
let tabspaces = repeat( ' ', &tabstop )
let lines = split( a:text, '\V\n', 1 )
let newlines = []
for line in lines
let newline = join( split( line, '\V\^\%(' . tabspaces . '\)', 1 ), ' ' )
let newlines += [newline]
endfor
return join( newlines, "\n" )
endif
endfunction
fun! XPT#SpaceToTab(lines)
if ! &expandtab && match( a:lines, '\v^ ' ) > -1
let cmd = 'join( split( v:val, ''\v^%('' . repeat( '' '', &tabstop ) . '')'', 1 ), '' '' )'
call map(a:lines,cmd)
endif
return a:lines
endfunction
fun! XPT#SpaceToTabExceptFirstLine(lines)
if ! &expandtab && len( a:lines ) > 1 && match( a:lines, '\v^ ', 1 ) > -1
let line0 = a:lines[0]
let cmd = 'join( split( v:val, ''\v^%('' . repeat( '' '', &tabstop ) . '')'', 1 ), '' '' )'
call map(a:lines,cmd)
let a:lines[0] = line0
endif
return a:lines
endfunction
fun! XPT#TextBetween(posList)
return join(XPT#LinesBetween( a:posList ), "\n")
endfunction
fun! XPT#TextInLine(ln,s,e)
if a:s >= a:e
return ""
endif
return getline(a:ln)[a:s - 1 : a:e - 2]
endfunction
fun! XPT#LinesBetween(posList)
let [s,e] = a:posList
if s[0] > e[0]
return ""
endif
if s[0] == e[0]
if s[1] == e[1]
return ""
else
return getline(s[0])[s[1] - 1 : e[1] - 2]
endif
endif
let r = [getline(s[0])[s[1] - 1:]] + getline(s[0]+1,e[0]-1)
if e[1] > 1
let r += [getline(e[0])[:e[1] - 2]]
else
let r += ['']
endif
return r
endfunction
fun! XPT#default(k,v)
if !exists(a:k)
exe "let" a:k "=" string( a:v )
endif
endfunction
fun! XPT#Strlen(s)
return strlen(substitute(a:s, ".", "x", "g"))
endfunction
fun! XPT#Assert(toBeTrue,msg)
if !a:toBeTrue
call XPT#warn(a:msg)
if g:xpt_test_on_error == 'stop'
throw "XPT_TEST: fail: " . a:msg
endif
endi
endfunction
fun! XPT#AssertEq(a,b,msg)
call XPT#Assert( a:a == a:b, 'expect:' . string( a:a ) . ' but:' . string( a:b ) . ' message:' . a:msg )
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,42 @@
if exists("g:__XPPUM_VIM__")
finish
endif
let g:__XPPUM_VIM__ = 1
let s:oldcpo = &cpo
set cpo-=< cpo+=B
exe XPT#let_sid
fun! XPpum#completeFunc(first,base)
if !exists( 'b:__xppum' . s:sid )
if a:first
return col( "." )
else
return []
endif
endif
if a:first
return b:__xppum{s:sid}.col - 1
else
let &completefunc = b:__xppum{s:sid}.oldcfu
call b:__xppum{s:sid}.onShow()
let list = b:__xppum{s:sid}.list
unlet b:__xppum{s:sid}
return list
endif
endfunction
fun! XPpum#complete(col,list,onShow)
let b:__xppum{s:sid} = { 'col' : a:col, 'list' : a:list, 'oldcfu' : &completefunc, 'onShow' : a:onShow }
set completefunc=XPpum#completeFunc
let keyTriggerUserDefinedPum = "\<C-x>\<C-u>"
let keyCleanupPumSetting = "\<C-r>=<SNR>" . s:sid . "RestoreCommpletefunc()\<CR>"
let keyForceRefresh = "\<C-n>\<C-p>"
return keyTriggerUserDefinedPum
endfunction
fun! s:RestoreCommpletefunc()
if !exists( 'b:__xppum' . s:sid )
return ''
endif
let &completefunc = b:__xppum{s:sid}.oldcfu
unlet b:__xppum{s:sid}
return ''
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,21 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
fun! xpt#buf#New()
if exists( 'b:xptemplateData' )
return b:xptemplateData
endif
let b:xptemplateData = { 'filetypes':{}, 'wrapStartPos':0, 'wrap':'', 'savedReg':'', 'snippetToParse':[], 'abbrPrefix':{}, 'fallbacks':[], 'posStack':[], 'stack':[], 'snipFileScope':{'inheritFT':0}, 'snipFileScopeStack':[], }
let b:xptemplateData.renderContext = xpt#rctx#New(b:xptemplateData)
return b:xptemplateData
endfunction
fun! xpt#buf#Pushrctx()
let x = b:xptemplateData
call add(x.stack,x.renderContext)
let x.renderContext = xpt#rctx#New(x)
endfunction
fun! xpt#buf#Poprctx()
let x = b:xptemplateData
let x.renderContext = remove(x.stack,-1)
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,31 @@
if exists( "g:__AUTOLOAD__XPT__CWC__SNPT_VIM__" )
finish
endif
let g:__AUTOLOAD__XPT__CWC__SNPT_VIM__ = 1
let s:oldcpo = &cpo
set cpo-=< cpo+=B
fun! xpt#cwd#snpt#load()
if exists( 'b:xptemplate_cwd_snpt_loaded' )
return
endif
call XPTemplateInit()
for fn in split(globpath('.', '.xpt.vim'), '\n')
exec 'so ' fn
endfor
for fn in split(globpath('.', '.' . &filetype . '.xpt.vim'), '\n')
exec 'so ' fn
endfor
let b:xptemplate_cwd_snpt_loaded = 1
endfunction
fun! xpt#cwd#snpt#reload()
if exists( 'b:xptemplate_cwd_snpt_loaded' )
unlet b:xptemplate_cwd_snpt_loaded
endif
return xpt#cwd#snpt#load()
endfunction
fun! xpt#cwd#snpt#clearFlag()
if exists( 'b:xptemplate_cwd_snpt_loaded' )
unlet b:xptemplate_cwd_snpt_loaded
endif
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,159 @@
if exists( "g:__XPT_DEBUG_VIM__" ) && g:__XPT_DEBUG_VIM__ >= XPT#ver
finish
endif
let g:__XPT_DEBUG_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=<
set cpo+=B
exe XPT#let_sid
let s:globalLogLevel = 'debug'
let s:logLevels = {
\ 'fatal' : 1,
\ 'error' : 2,
\ 'warn' : 3,
\ 'info' : 4,
\ 'log' : 5,
\ 'debug' : 6,
\ }
fun! xpt#debug#Logger( level ) "{{{
let level = s:logLevels[ a:level ]
let level = min( [ level, s:logLevels[ s:globalLogLevel ] ] )
let logger = copy( s:loggerPrototype )
if level < s:logLevels.fatal | let logger.Fatal = s:loggerPrototype.LogNothing | endif
if level < s:logLevels.error | let logger.Error = s:loggerPrototype.LogNothing | endif
if level < s:logLevels.warn | let logger.Warn = s:loggerPrototype.LogNothing | endif
if level < s:logLevels.info | let logger.Info = s:loggerPrototype.LogNothing | endif
if level < s:logLevels.log | let logger.Log = s:loggerPrototype.LogNothing | endif
if level < s:logLevels.debug | let logger.Debug = s:loggerPrototype.LogNothing | endif
return logger
endfunction "}}}
fun! xpt#debug#Assert( shouldBeTrue, msg ) "{{{
if !a:shouldBeTrue
throw a:msg
end
endfunction "}}}
fun! xpt#debug#List( l ) "{{{
let rst = '[' . "\n"
for e in a:l
let rst .= '--- ' . string( e ) . "\n"
unlet e
endfor
return rst . "\n" . ']'
endfunction "}}}
fun! xpt#debug#EchoList( l ) "{{{
echom '['
for e in a:l
echom '--- ' . string( e ) . "\n"
unlet e
endfor
echom ']'
endfunction "}}}
fun! s:Fatal(...) dict "{{{
return call('Log_core', ['Fatal'] + a:000)
endfunction "}}}
fun! s:Error(...) dict "{{{
return call('Log_core', ['Error'] + a:000)
endfunction "}}}
fun! s:Warn(...) dict "{{{
return call('Log_core', ['Warn'] + a:000)
endfunction "}}}
fun! s:Info(...) dict "{{{
return call('Log_core', ['Info'] + a:000)
endfunction "}}}
fun! s:Log(...) dict "{{{
return call('Log_core', ['Log'] + a:000)
endfunction "}}}
fun! s:Debug(...) dict "{{{
return call('Log_core', ['Debug'] + a:000)
endfunction "}}}
fun! s:LogNothing(...) "{{{
endfunction "}}}
fun! Log_core(level, ...) "{{{
if s:logLocation == ''
return
end
" call stack printing
try
throw ''
catch /.*/
let stack = matchstr( v:throwpoint, 'function\s\+\zs.\{-}\ze\.\.\%(Fatal\|Error\|Warn\|Info\|Log\|Debug\).*' )
let stack = substitute( stack, '<SNR>\d\+_', '', 'g' )
endtry
exe 'redir! >> '.s:logLocation
silent echom a:level . ':::' . stack . ' cursor at=' . string( [ line("."), col(".") ] )
for msg in a:000
let l = split(';' . msg . ';', "\n")
let l[0] = l[0][1:]
let l[ -1 ] = l[ -1 ][ :-2 ]
for v in l
silent! echom v
endfor
endfor
redir END
if a:level =~ 'Fatal\|Error\|Warn'
echoerr string( a:000 )
endif
endfunction "}}}
" define script-private functions first and then make reference to them. Thus
" in traceback function name can be shown.
let s:loggerPrototype = {}
let s:loggerPrototype.Fatal = function( "<SNR>" . s:sid . "Fatal" )
let s:loggerPrototype.Error = function( "<SNR>" . s:sid . "Error" )
let s:loggerPrototype.Warn = function( "<SNR>" . s:sid . "Warn" )
let s:loggerPrototype.Info = function( "<SNR>" . s:sid . "Info" )
let s:loggerPrototype.Log = function( "<SNR>" . s:sid . "Log" )
let s:loggerPrototype.Debug = function( "<SNR>" . s:sid . "Debug" )
let s:loggerPrototype.LogNothing = function( "<SNR>" . s:sid . "LogNothing" )
fun! s:MakeLogPath() "{{{
let path = g:xptemplate_debug_log
if path == ''
let s:logLocation = ''
else
let path = substitute( path, '\V\^~/', $HOME . '/', '' )
let s:logLocation = path
call delete(s:logLocation)
endif
endfunction "}}}
call s:MakeLogPath()
let &cpo = s:oldcpo

View file

@ -0,0 +1,75 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
fun! xpt#diff#Diff(a,b)
let [a,b] = [a:a,a:b]
let [astart,aend,bstart,bend] = [0,len(a),0,len(b)]
let [i,lmin] = [0,min([aend,bend])]
while i < lmin && a[i] == b[i] | let i += 1 | endwhile
let [astart,bstart] = [i,i]
let m = min([aend - astart,bend - bstart])
let i = 1
while i <= m && a[aend-i] == b[bend-i]
let i += 1
endwhile
let [aend,bend] = [aend-i+1,bend-i+1]
if type(a) == type('')
let [a,b] = [strpart(a,astart,aend-astart),strpart(b,bstart,bend-bstart)]
else
let [a,b] = [a[astart :],b[bstart :]]
if len(a) > aend - astart
call remove(a,aend-astart,-1)
endif
if len(b) > bend - bstart
call remove(b,bend-bstart,-1)
endif
endif
let [la,lb] = [len(a),len(b)]
let matrix = []
let i = 0
while i < la + 1
let s = []
let j = 0
while j < lb + 1
let s += [[0,0,0]]
let j += 1
endwhile
let matrix += [s]
let i += 1
endwhile
let [i] = [1]
while i < la + 1
let matrix[i][0] = [i-1,0,0]
let i += 1
endwhile
let [j] = [1]
while j < lb + 1
let matrix[0][j] = [0,j-1,0]
let j += 1
endwhile
let [i,j] = [0,0]
while i < la
let j = 0
while j < lb
let matrix[i+1][j+1] = a[i] == b[j] ? [i,j,matrix[i][j][2] + 1] : (matrix[i][j+1][2] > matrix[i+1][j][2] ? [i,j+1,matrix[i][j+1][2]] : [i+1,j,matrix[i+1][j][2]])
let j += 1
endwhile
let i += 1
endwhile
let lst = []
let [i,j] = [la,lb]
while i > 0 || j > 0
while (i > 0 || j > 0) && matrix[i][j][0] < i && matrix[i][j][1] < j
let [i,j] = matrix[i][j][: 1]
endwhile
let [ii,jj] = [i,j]
while (ii > 0 || jj > 0) && (matrix[ii][jj][0] == ii || matrix[ii][jj][1] == jj)
let [ii,jj] = matrix[ii][jj][: 1]
endwhile
let chg = [[astart+ii,astart+i],[bstart+jj,bstart+j]]
let lst = [chg] + lst
let [i,j] = [ii,jj]
endwhile
return lst
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,145 @@
if exists( "g:__AL_XPT_EVAL_VIM__" ) && g:__AL_XPT_EVAL_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_EVAL_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
let s:log = xpt#debug#Logger( 'debug' )
exe XPT#importConst
let s:_evalCache = { 'strMask' : {}, 'compiledExpr' : {} }
fun! xpt#eval#Eval(str,closures)
if a:str == ''
return ''
endif
let globals = a:closures[0]
let x = b:xptemplateData
let expr = xpt#eval#Compile(a:str)
let globals._ctx = { 'closures':a:closures, 'renderContext':x.renderContext, }
let xfunc = globals
try
let r = eval(expr)
return r
catch /.*/
call XPT#warn(v:throwpoint)
call XPT#warn(v:exception)
call XPT#warn(expr)
return ''
endtry
endfunction
fun! xpt#eval#Compile(s)
if a:s is ''
return ''
endif
let expr = get(s:_evalCache.compiledExpr,a:s,0)
if expr is 0
if a:s !~ s:item_var . '\|' . s:item_func
let expr = string(xpt#util#UnescapeChar(a:s,s:nonsafe))
elseif a:s =~ '\V\^$\w\+\$'
let expr = 'xfunc.GetVar(' . string( a:s ) . ')'
else
let expr = s:DoCompile(a:s)
endif
let s:_evalCache.compiledExpr[a:s] = expr
endif
return expr
endfunction
fun! s:DoCompile(s)
let fptn = '\V' . '\w\+(\[^($]\{-})' . '\|' . s:nonEscaped . '{\w\+(\[^($]\{-})}'
let vptn = '\V' . s:nonEscaped . '$\w\+' . '\|' . s:nonEscaped . '{$\w\+}'
let sptn = '\V' . s:nonEscaped . '(\[^($]\{-})'
let patternVarOrFunc = fptn . '\|' . vptn . '\|' . sptn
if a:s !~ s:regEval
return string(xpt#util#UnescapeChar(a:s,s:nonsafe))
endif
let stringMask = s:CreateStringMask(a:s)
if stringMask !~ patternVarOrFunc
return string(xpt#util#UnescapeChar(a:s,s:nonsafe))
endif
let str = a:s
let evalMask = repeat('-', len(stringMask))
while 1
let matchedIndex = match(stringMask,patternVarOrFunc)
if matchedIndex == -1
break
endif
let matchedLen = len(matchstr(stringMask,patternVarOrFunc))
let matched = str[matchedIndex : matchedIndex + matchedLen - 1]
if matched =~ '^{.*}$'
let matched = matched[1:-2]
endif
if matched[0:0] == '(' && matched[-1:-1] == ')'
let contextedMatchedLen = len(matched)
let spaces = repeat(' ', contextedMatchedLen)
let stringMask = (matchedIndex == 0 ? "" : stringMask[:matchedIndex-1]) . spaces . stringMask[matchedIndex + matchedLen :]
continue
elseif matched[-1:] == ')'
let funcname = matchstr(matched, '^\w\+')
let args = matched[len(funcname) + 1 : -2]
let matched = "xfunc.Call('" . funcname . "',[" . args . '])'
elseif matched[0:0] == '$'
let matched = 'xfunc.GetVar(' . string( matched ) . ')'
endif
let contextedMatchedLen = len(matched)
let spaces = repeat(' ', contextedMatchedLen)
let evalMask = (matchedIndex == 0 ? "" : evalMask[:matchedIndex-1]) . '+' . spaces[1:] . evalMask[matchedIndex + matchedLen :]
let stringMask = (matchedIndex == 0 ? "" : stringMask[:matchedIndex-1]) . spaces . stringMask[matchedIndex + matchedLen :]
let str = (matchedIndex == 0 ? "" : str[:matchedIndex-1]) . matched . str[matchedIndex + matchedLen :]
endwhile
let idx = 0
let expr = ''
while 1
let matches = matchlist( evalMask, '\V\(-\*\)\(+ \*\)\?', idx )
if '' == matches[0]
break
endif
if '' != matches[1]
let part = str[idx : idx + len(matches[1]) - 1]
if matches[2] != ''
let part = xpt#util#UnescapeChar(part . '$', '{$( ')
let part = strpart(part,0,strlen(part) - 1)
else
let part = xpt#util#UnescapeChar(part, '{$( ')
endif
let expr .= ',' . string(part)
endif
if '' != matches[2]
let expr .= ',' . str[ idx + len(matches[1]) : idx + len(matches[0]) - 1 ]
endif
let idx += len(matches[0])
endwhile
let expr = "xfunc.Concat(" . expr[ 1: ] . ')'
return expr
endfunction
fun! s:CreateStringMask(str)
if a:str == ''
return ''
endif
if has_key(s:_evalCache.strMask,a:str)
return s:_evalCache.strMask[a:str]
endif
let dqe = '\V\('. s:nonEscaped . '"\)'
let sqe = '\V\('. s:nonEscaped . "'\\)"
let dptn = dqe.'\_.\{-}\1'
let sptn = sqe.'\%(\_[^'']\)\{-}'''
let mask = substitute(a:str, '[ *]', '+', 'g')
while 1
let d = match(mask,dptn)
let s = match(mask,sptn)
if d == -1 && s == -1
break
endif
if d > -1 && (d < s || s == -1)
let sub = matchstr(mask,dptn)
let sub = repeat(' ', len(sub))
let mask = substitute(mask, dptn, sub, '')
elseif s > -1
let sub = matchstr(mask,sptn)
let sub = repeat(' ', len(sub))
let mask = substitute(mask, sptn, sub, '')
endif
endwhile
let s:_evalCache.strMask[a:str] = mask
return mask
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,88 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
let s:log = xpt#debug#Logger( 'debug' )
let g:EmptyFilter = {}
let s:proto = { 'force':0, }
fun! xpt#flt#New(nIndent,text,...)
let flt = deepcopy(s:proto)
call extend(flt,{ 'nIndent':a:nIndent, 'text':a:text, 'force':a:0 == 1 && a:1, }, 'force' )
return flt
endfunction
fun! xpt#flt#NewSimple(nIndent,text,...)
let flt = { 'nIndent' : a:nIndent, 'text' : a:text, }
if a:0 == 1 && a:1
let flt.force = 1
endif
return flt
endfunction
fun! xpt#flt#Extend(flt)
call extend( a:flt, s:proto, 'keep' )
endfunction
fun! xpt#flt#Simplify(flt)
call filter( a:flt, 'v:val!=get(s:proto,v:key,-987654)' )
endfunction
fun! xpt#flt#Eval(snip,flt,closures)
let snipptn = a:snip.ptn
let r = { 'rc' : 1, 'parseIndent' : 1, 'nav' : 'stay' }
let rst = xpt#eval#Eval(a:flt.text,a:closures)
if type(rst) == type(0)
let r.rc = 0
return r
endif
if type( rst ) == type( '' )
if rst =~ snipptn.lft
let r.action = 'build'
else
let r.action = 'text'
endif
let r.text = rst
return r
endif
if type(rst) == type([])
let r.action = 'pum'
let r.pum = rst
return r
endif
call extend( r, rst, 'force' )
if ! has_key( r, 'action' ) && has_key( r, 'text' )
if r.text =~ snipptn.lft
let r.action = 'build'
else
let r.action = 'text'
endif
endif
let r.action = get( r, 'action', '' )
if r.action ==# 'embed'
let r.action = 'build'
endif
if has_key( r, 'cursor' )
call xpt#flt#ParseCursorSpec(r)
endif
return r
endfunction
fun! xpt#flt#ParseCursorSpec(flt_rst)
let rst = a:flt_rst
if type(rst.cursor) == type([]) && type( rst.cursor[ 0 ] ) == type( '' )
let rst.cursor = { 'rel' : 1, 'where':rst.cursor[ 0 ], 'offset':get( rst.cursor, 1, [ 0, 0 ] ) }
endif
let rst.isCursorRel = type(rst.cursor) == type({})
endfunction
fun! s:AddIndentToPHs(flt)
if a:flt.rst.nIndent == 0
return
endif
let nIndent = a:flt.rst.nIndent
let rst = []
for ph in a:flt.rst.phs
if type( ph ) == type( '' )
call add(rst,xpt#util#AddIndent(ph,nIndent))
else
call add(rst,ph)
endif
unlet ph
endfor
let a:flt.rst.phs = rst
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,49 @@
if exists( "g:__AL_XPT_FTSCP_VIM__" ) && g:__AL_XPT_FTSCP_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_FTSCP_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
fun! xpt#ftscope#New()
let inst = { 'filetype':'', 'allTemplates':{}, 'ftkeyword':{ 'regexp' : '\w', 'list' : [] }, 'funcs':{ '$CURSOR_PH' : 'CURSOR' }, 'inited':0, 'varPriority':{}, 'loadedSnipFiles':{}, 'extensionTable':{}, 'snipPieces':[], }
return inst
endfunction
fun! xpt#ftscope#Init(ftscope)
if a:ftscope.inited
return
endif
let l = a:ftscope.funcs.GetVar( '$CL' )
let m = a:ftscope.funcs.GetVar( '$CM' )
if len(l) <= len(m)
let a:ftscope.funcs[ '$CM_OFFSET' ] = ''
let a:ftscope.funcs[ '$CL_STRIP' ] = l
else
let a:ftscope.funcs[ '$CM_OFFSET' ] = repeat( ' ', len( l ) - len( m ) )
let a:ftscope.funcs[ '$CL_STRIP' ] = l[ : -len( m ) -1 ]
endif
let a:ftscope.inited = 1
endfunction
fun! xpt#ftscope#IsSnippetLoaded(inst,filename)
return has_key(a:inst.loadedSnipFiles,a:filename)
endfunction
fun! xpt#ftscope#SetSnippetLoaded(inst,filename)
let a:inst.loadedSnipFiles[a:filename] = 1
let fn = substitute(a:filename, '\\', '/', 'g')
let shortname = matchstr(fn, '\Vftplugin\/\zs\[^/]\+\/\.\*\ze.xpt.vim')
if shortname != ''
let a:inst.loadedSnipFiles[shortname] = 1
endif
endfunction
fun! xpt#ftscope#CheckAndSetSnippetLoaded(inst,filename)
let loaded = has_key(a:inst.loadedSnipFiles,a:filename)
call xpt#ftscope#SetSnippetLoaded(a:inst,a:filename)
return loaded
endfunction
fun! xpt#ftscope#PushPHPieces(ftscope,phs)
call add(a:ftscope.snipPieces,a:phs)
return len(a:ftscope.snipPieces) - 1
endfunction
fun! xpt#ftscope#GetPHPieces(ftscope,phsID)
return a:ftscope.snipPieces[a:phsID]
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,20 @@
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
exe XPT#importConst
fun! xpt#group#New(name,sessid)
let g = { 'name' : a:name, 'fullname':a:name, 'initValue':a:name, 'phase':'created', 'processed':0, 'placeHolders':[], 'keyPH':s:nullDict, 'behavior':{}, 'sessid':a:sessid, }
return g
endfunction
fun! xpt#group#InsertPH(g,ph,where)
if has_key( a:ph, 'isKey' ) && a:g.keyPH != s:nullDict
unlet a:ph.isKey
endif
if has_key( a:ph, 'isKey' )
let a:g.keyPH = a:ph
let a:g.fullname = a:ph.fullname
else
call insert(a:g.placeHolders,a:ph,a:where)
endif
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,85 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
exe XPT#importConst
let s:indent_convert_cmd = 'substitute(v:val, ''\v(^\s*)@<= '', '' '', "g" )'
fun! xpt#indent#ParseStr(text,first_line_shift)
let text = xpt#indent#IndentToTabStr(a:text)
return xpt#indent#ToActualIndentStr(text,a:first_line_shift)
endfunction
fun! xpt#indent#IndentToTabStr(text)
let lines = split( a:text, '\n', 1 )
call xpt#indent#IndentToTab(lines)
return join(lines, "\n")
endfunction
fun! xpt#indent#ToActualIndentStr(text,first_line_shift)
let lines = split( a:text, '\n', 1 )
call xpt#indent#ToActualIndent(lines,a:first_line_shift)
return join(lines, "\n")
endfunction
fun! xpt#indent#IndentToTab(lines)
call map(a:lines,s:indent_convert_cmd)
endfunction
fun! xpt#indent#ToActualIndent(lines,first_line_shift)
let indent_spaces = repeat(' ', &shiftwidth)
let cmd = 'substitute(v:val, ''\v(^ *)@<= '', ''' . indent_spaces . ''', "g" )'
call map(a:lines,cmd)
if a:first_line_shift != 0
let shift_spaces = repeat(' ', a:first_line_shift)
let i = 1
while i < len(a:lines)
if a:lines[i] != '' || i == len(a:lines)-1
let a:lines[i] = shift_spaces . a:lines[i]
endif
let i += 1
endwhile
endif
if &expandtab
return
endif
let tabspaces = repeat( ' ', &tabstop )
let cmd = 'substitute(v:val, ''\v(^\s*)@<=' . tabspaces . ''', '' '', "g" )'
call map(a:lines,cmd)
endfunction
fun! xpt#indent#IndentBefore(pos)
let [ln,col] = a:pos
let line = matchstr( getline(ln), '\V\^\s\*' )
let line = ( col == 1 ) ? '' : line[ 0 : col - 1 - 1 ]
let tabspaces = repeat( ' ', &tabstop )
return len( substitute( line, ' ', tabspaces, 'g' ) )
endfunction
fun! xpt#indent#RemoveIndentStr(text,nIndent)
let reg = '\V\n \{,' . a:nIndent . '\}'
let text = substitute(a:text, reg, '\n', 'g')
return text
endfunction
fun! xpt#indent#ToSpace(text)
if stridx( a:text, " " ) < 0
return a:text
endif
let tabspaces = repeat( ' ', &tabstop )
let reg = '\v' . tabspaces . '| {0,' . (&tabstop-1) . '} '
let rst = []
let lines = split( a:text, '\n', 1 )
for line in lines
let leading_space = matchstr( line, '\v\s*' )
let left = line[len(leading_space) :]
let l = substitute( leading_space, reg, tabspaces, 'g' )
call add(rst,l . left)
endfor
return join(rst, "\n")
endfunction
fun! xpt#indent#SpaceToTab(text)
let indent_spaces = repeat(' ', &shiftwidth)
let reg = 'substitute(v:val, ''\v(^\s*)@<='.indent_spaces.''', " ", "g" )'
let lines = split( a:text, '\n', 1 )
call map(lines,reg)
return join(lines, "\n")
endfunction
fun! xpt#indent#ActualToSnippetNr(n)
let n_one_indent = &shiftwidth
let n_indent = a:n / n_one_indent
return n_indent * 4 + a:n % n_one_indent
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,118 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
fun! xpt#mark#InitBuf()
if ! exists('b:_xpt_snapshot')
let b:_xpt_snapshot = {'lines': getline(1, "$"), 'marks': []}
endif
return b:_xpt_snapshot
endfunction
fun! xpt#mark#Add(positions,opt)
let snp = xpt#mark#InitBuf()
let snp.marks += a:positions
endfunction
fun! xpt#mark#Update()
let snp = xpt#mark#InitBuf()
let lines_b = getline(1, "$")
let marks = snp.marks
let marks = xpt#mark#UpdateMarks(snp.lines,lines_b,marks)
let snp.lines = lines_b
let snp.marks = marks
return marks
endfunction
fun! xpt#mark#UpdateMarks(lines_a,lines_b,marks)
let n_lines_a = len(a:lines_a)
let marks = a:marks[:]
call filter(marks, 'v:val[0]<n_lines_a')
call map(marks, 'v:val[:]')
let changes = xpt#diff#Diff(a:lines_a,a:lines_b)
let [i,j,li,lj,line_offset] = [0,0,len(marks),len(changes),0]
while i < li && j < lj
let [m,c] = [marks[i],changes[j]]
let [ca,cb] = c
let [linenr,colnr] = m
let [cstart,cend] = ca
if linenr < cstart || (linenr == cstart && colnr == 0)
let m[0] += line_offset
let i += 1
elseif linenr >= cend
let line_offset += (cb[1] - cb[0]) - (cend - cstart)
let j += 1
else
if cb[0] == cb[1]
let ii = i
while ii < li && marks[ii][0] < cend
let marks[ii] = [cstart[0] + line_offset,0]
let ii += 1
endwhile
else
let ii = i
while ii < li && marks[ii][0] < cend
let ii += 1
endwhile
let changed_marks = marks[i : ii - 1]
call map(changed_marks, '[v:val[0]-cstart, v:val[1]]')
let changed_2 = xpt#mark#UpdateLineChange(a:lines_a[cstart : cend-1],a:lines_b[cb[0] : cb[1] - 1],changed_marks)
call map(changed_2, '[v:val[0]+cstart+line_offset, v:val[1]]')
let marks = marks[: i][: -2] + changed_2 + marks[ii :]
let i += len(changed_2)
let li = len(marks)
endif
endif
endwhile
while i < li
let marks[i][0] += line_offset
let i += 1
endwhile
return marks
endfunction
fun! xpt#mark#UpdateLineChange(lines_a,lines_b,marks)
let joined_offset = []
let offset = 0
for l in a:lines_a
let joined_offset += [offset]
let offset += len(l) + 1
endfor
let n_lines_a = len(a:lines_a)
let marks = a:marks[:]
call filter(marks, 'v:val[0]<n_lines_a')
call map(marks, 'joined_offset[v:val[0]] + v:val[1]')
let changes = xpt#diff#Diff(join(a:lines_a, "\n"), join(a:lines_b, "\n"))
let [i,j,li,lj,offset] = [0,0,len(marks),len(changes),0]
while i < li && j < lj
let [m,c] = [marks[i],changes[j]]
let [ca,cb] = c
if m <= ca[0] || m < ca[1]
let marks[i] = min([m,ca[0]]) + offset
let i += 1
else
let offset += (cb[1] - cb[0]) - (ca[1] - ca[0])
let j += 1
endif
endwhile
while i < li
let marks[i] += offset
let i += 1
endwhile
let lb_ranges = []
let offset = 0
for l in a:lines_b
let lb_ranges += [[offset,offset + len(l) + 1]]
let offset = lb_ranges[-1][1]
endfor
let [i,j] = [0,0]
let [li,lj] = [len(marks),len(lb_ranges)]
let splitted = []
while i < li && j < lj
let m = marks[i]
let [_start,_end] = lb_ranges[j]
if m < _end
let splitted += [[j,m - _start]]
let i += 1
else
let j += 1
endif
endwhile
return splitted
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,156 @@
if exists( "g:__AL_XPT_MSVR_VIM__" ) && g:__AL_XPT_MSVR_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_MSVR_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
snoremap <Plug>selectToInsert d<BS>
let g:globalStack = []
fun! s:_GetAlighWidth()
nmap <buffer> 1 2
let line = xpt#util#getCmdOutput("silent nmap <buffer> 1")
nunmap <buffer> 1
let line = split(line, "\n")[0]
return len(matchstr(line, '^n.*\ze2$'))
endfunction
let s:alignWidth = s:_GetAlighWidth()
delfunction s:_GetAlighWidth
fun! xpt#msvr#New(isLocal)
return { 'keys':[], 'saved':[], }
endfunction
fun! xpt#msvr#Add(inst,mode,key)
if a:inst.saved != []
throw "keys are already saved and can not be added"
endif
let a:inst.keys += [[a:mode,a:key]]
endfunction
fun! xpt#msvr#AddList(inst,...)
if a:0 > 0 && type(a:1) == type([])
let list = a:1
else
let list = a:000
endif
for item in list
let [ mode, key ] = split( item, '^\w\zs_' )
call xpt#msvr#Add(a:inst,mode,key)
endfor
endfunction
fun! xpt#msvr#UnmapAll(inst)
if a:inst.saved == []
throw "keys are not saved, can not unmap all"
endif
let localStr = '<buffer> '
for [mode,key] in a:inst.keys
exe 'silent! ' . mode . 'unmap ' . localStr . key
endfor
endfunction
fun! xpt#msvr#Save(inst)
if a:inst.saved != []
return
endif
for [mode,key] in a:inst.keys
call insert(a:inst.saved,xpt#msvr#MapInfo(key,mode))
endfor
let stack = s:GetStack()
call add(stack,a:inst)
endfunction
fun! xpt#msvr#Literalize(inst,...)
if a:inst.saved == []
throw "keys are not saved yet, can not literalize"
endif
let option = a:0 == 1 ? a:1 : {}
let insertAsSelect = get(option, 'insertAsSelect', 0)
let localStr = '<buffer> '
let nowait = v:version >= 704 ? '<nowait>' : ''
for [mode,key] in a:inst.keys
if mode == 's' && insertAsSelect
exe 'silent! ' . mode . 'map ' . nowait . localStr . key . ' <Plug>selectToInsert' . key
else
exe 'silent! ' . mode . 'noremap ' . nowait . localStr . key . ' ' . key
endif
endfor
endfunction
fun! xpt#msvr#Restore(inst)
if a:inst.saved == []
return
endif
let stack = s:GetStack()
if empty(stack) || stack[-1] != a:inst
throw "MapSaver: Incorrect Restore of MapSaver:" . s:String( stack ) . ' but ' . string( a:inst.keys )
endif
for info in a:inst.saved
call s:MappingPop(info)
endfor
let a:inst.saved = []
call remove(stack,-1)
endfunction
fun! s:GetStack()
if !exists( 'b:__map_saver_stack__' )
let b:__map_saver_stack__ = []
endif
return b:__map_saver_stack__
endfunction
if v:version >= 704
fun! xpt#msvr#MapInfo(key,mode)
let arg = maparg(a:key,a:mode,0,1)
if arg == {} || arg.buffer == 0
return { 'mode' : a:mode, 'key':a:key, 'nore':'', 'isexpr':'', 'isscript':'', 'isbuf':' <buffer> ', 'cont':''}
endif
let rhs = substitute( arg.rhs, '\V\C<SID>', '<SNR>' . arg.sid . '_', 'g' )
let line = s:GetMappingLine(a:key,a:mode)
let flag = line[0 : 1]
return { 'mode' : a:mode, 'key':a:key, 'nore':arg.noremap ? 'nore' : '', 'isexpr':arg.expr ? '<expr>' : '', 'isscript':flag[0] == '&' ? ' <script> ' : '', 'isbuf':arg.buffer ? '<buffer>' : '', 'cont':rhs }
endfunction
else
fun! xpt#msvr#MapInfo(key,mode)
let line = s:GetMappingLine(a:key,a:mode)
if line == ''
return { 'mode' : a:mode, 'key':a:key, 'nore':'', 'isexpr':'', 'isscript':'', 'isbuf':' <buffer> ', 'cont':''}
endif
let item = line[0:1] " the first 2 characters
let isexpr = ''
if a:mode == 'i' && line[2:] =~ '\V\w(\.\*)' && line[2:] !~? '\V<c-r>' || a:mode != 'i' && line[2:] =~ '\V\w(\.\*)' || a:mode == 'i' && line[2:] =~ '\V\.\*?\.\*:\.\*'
let isexpr = '<expr> '
endif
let info = {'mode' : a:mode, 'key':a:key, 'nore':item =~ '*' ? 'nore' : '', 'isexpr':isexpr, 'isscript':item[0] == '&' ? ' <script> ' : '', 'isbuf':' <buffer> ', 'cont':line[2:]}
return info
endfunction
endif
fun! xpt#msvr#MapCommand(info)
let i = a:info
if i.cont == ''
let cmd = i.mode . 'unmap <silent> ' . i.isbuf . i.key
else
let cmd = i.mode . i['nore'] . 'map <silent> ' . i.isscript . i.isexpr . i.isbuf . i.key . ' ' . i.cont
endif
return "silent! " . cmd
endfunction
fun! s:GetMappingLine(key,mode)
let mcmd = "silent ".a:mode."map <buffer> ".a:key
let str = xpt#util#getCmdOutput(mcmd)
let lines = split(str, "\n")
let localmark = '@'
let ptn = '\V\c' . a:mode . ' ' . escape(a:key, '\') . '\s\{-}' . '\zs\[*& ]' . localmark . '\%>' . s:alignWidth . 'c\S\.\{-}\$'
for line in lines
if line =~? ptn
return matchstr(line,ptn)
endif
endfor
return ""
endfunction
fun! s:MappingPop(info)
let cmd = xpt#msvr#MapCommand(a:info)
try
exe cmd
catch /.*/
endtry
endfunction
fun! s:String(stack)
let rst = ''
for ms in a:stack
let rst .= " **** " . string( ms.keys )
endfor
return rst
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,18 @@
if exists( "g:__AL_XPT_NG_VIM__" ) && g:__AL_XPT_NG_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_NG_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:priorities = XPT#priorities
fun! xpt#ng#SetFiletypeDetector(funName)
if !exists("b:xptemplateData")
call XPTemplateInit()
endif
let x = b:xptemplateData
let prio = get( x.snipFileScope, 'priority', s:priorities.lang )
if prio <= x.ftdetector.priority
let x.ftdetector = { 'priority' : prio, 'func':function( a:funName ) }
endif
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,46 @@
let xpt#once#init = 'if xpt#once#SetAndGetLoaded(expand("<sfile>")) | finish | endif'
fun! xpt#once#SetAndGetLoaded(fn)
if ! exists('g:xptemplate_loaded')
let g:xptemplate_loaded = {}
endif
let fn = resolve(fnamemodify( a:fn, ':p' ))
let fn = s:Norm(fn)
let _rtps = split(&runtimepath, ',')
let rtps = []
for p in _rtps
let p = resolve(fnamemodify( p, ':p' ))
let p = s:Norm(p) . '/'
let rtps += [p]
endfor
call sort(rtps)
call reverse(rtps)
for p in rtps
let pref = fn[0 : len(p) - 1]
if pref == p
let relpath = fn[len(pref) :]
if has_key(g:xptemplate_loaded,relpath)
return 1
else
let g:xptemplate_loaded[relpath] = 1
return 0
endif
endif
endfor
echoerr a:fn . ' not found in any one of &runtimepath'
return 0
endfunction
fun! s:Norm(path)
let path = a:path
let path = substitute(path, '\V\\', '/', 'g')
let path = substitute( path, '\V/\*\$', '', 'g' )
let path = substitute( path, '\V//\*', '/', 'g' )
while 1
let p0 = path
let path = substitute( path, '\V/\[^/]\+/..', '', 'g' )
if p0 == path
break
endif
endwhile
return path
endfunction
exec xpt#once#init

View file

@ -0,0 +1,13 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
call XPT#default('g:xptemplate_cwd_snippet', 0)
augroup XPT_CWD_SNIPPET
au!
if g:xptemplate_cwd_snippet == 1
au BufEnter * call xpt#cwd#snpt#load()
au FileType * call xpt#cwd#snpt#reload()
au BufUnload * call xpt#cwd#snpt#clearFlag()
endif
augroup END
let &cpo = s:oldcpo

View file

@ -0,0 +1,22 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
call XPT#default('g:xptemplate_lib_filter', '\v.')
fun! xpt#option#lib_filter#Match(fn)
if a:fn =~ '\V\<_\w\+\[/\\]\[^/\\]\+' || a:fn =~ '\V~~/xpt/pseudo/ftplugin/'
return 1
end
let regs = []
if type(g:xptemplate_lib_filter) == type('')
let regs = [g:xptemplate_lib_filter]
else
let regs = g:xptemplate_lib_filter
endif
for r in regs
if a:fn =~# r
return 1
endif
endfor
return 0
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,582 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'debug' )
exe XPT#importConst
let s:KEYTYPE_MAP = { '.':'onfocus', '.def':'onfocus', '.ontype':'live', '.onchange':'live', }
let s:KEYTYPE_TO_DICT = { 'pre':'preValues', 'live':'liveFilters', 'onfocus':'onfocusFilters', }
runtime plugin/xptemplate.vim
fun s:CompileSnippetFile(fn)
if a:fn =~ '\V.xpt.vimc\$' || !filereadable( a:fn )
return
endif
let lines = readfile(a:fn)
let lines = xpt#parser#Compact(lines)
let lines = xpt#parser#CompileCompacted(lines)
call writefile( lines, a:fn . 'c' )
endfunction
fun! xpt#parser#Compile(fn)
let compiledFn = a:fn . 'c'
let ctime = getftime(a:fn)
if !filereadable(compiledFn) || getftime(compiledFn) < ctime || g:xptemplate_always_compile
call s:CompileSnippetFile(a:fn)
else
endif
endfunction
fun! xpt#parser#Compact(lines)
let compacted = []
let iSnipPart = match( a:lines, '\V\^XPT\s' )
if iSnipPart < 0
let iSnipPart = len(a:lines)
endif
let [i,len] = [0 - 1,iSnipPart - 1]
while i < len | let i += 1
let l = a:lines[i]
if l != '' && l !~ '\v^"[^"]*$'
call add(compacted,l)
endif
endwhile
let [s,e,lastNonblank] = [-1,-1,100000]
let [i,len] = [iSnipPart - 1,len(a:lines) - 1]
while i < len | let i += 1
let l = a:lines[i]
if l == '' || l =~ '\v^"[^"]*$'
let lastNonblank = min([lastNonblank,i - 1])
continue
endif
if l =~# '\V\^..XPT\>'
if s == -1
let [s,e,lastNonblank] = [-1,-1,100000]
continue
else
let compacted += a:lines[s : i - 1]
let [s,e,lastNonblank] = [-1,-1,100000]
endif
elseif l =~# '\V\^XPT\>'
if s == -1
let [s,lastNonblank] = [i,i]
else
let e = min([i - 1,lastNonblank])
let compacted += a:lines[s : e]
let [s,e,lastNonblank] = [i,-1,100000]
endif
else
let lastNonblank = i
endif
endwhile
if s != -1
let compacted += a:lines[s : min([lastNonblank,i])]
endif
return compacted
endfunction
fun! xpt#parser#CompileCompacted(lines)
let rst = []
let lines = a:lines
let iSnipPart = match( lines, '\V\^XPT\s' )
if iSnipPart < 0
return lines
endif
if iSnipPart > 0
let rst += lines[: iSnipPart - 1]
let lines = lines[iSnipPart :]
endif
let [i,len] = [0,len(lines)]
call xpt#indent#IndentToTab(lines)
let s = i
while i < len-1 | let i += 1
let v = lines[i]
if v =~# '\V\^XPT\>'
let ll = xpt#parser#CompileSnippet(lines[s : i - 1])
let rst += [ll]
let s = i
elseif v =~# '\V\^\\XPT'
let lines[i] = v[1 :]
endif
endwhile
if i >= s
let ll = xpt#parser#CompileSnippet(lines[s : i])
let rst += [ll]
endif
return rst
endfunction
fun! xpt#parser#CompileSnippet(lines)
let lines = a:lines
let snippetLines = []
let setting = xpt#st#New()
let l0 = lines[0]
let pos = match( l0, '\VXPT\s\+\S\+\.\{-}\zs\s' . s:nonEscaped . '"' )
if pos >= 0
let [setting.rawHint, lines[0]] = [ matchstr( l0[ pos + 1 + 1 : ], '\v\S.*' ), l0[ : pos ] ]
endif
let [ x, snippetName; snippetParameters ] = split(lines[0], '\V'.s:nonEscaped.'\s\+')
for pair in snippetParameters
let name = matchstr(pair, '\V\^\[^=]\*')
let value = pair[len(name) :]
let value = value[0:0] == '=' ? xpt#util#UnescapeChar(value[1:], ' ') : 1
let setting[name] = value
endfor
let start = 1
let len = len(lines)
while start < len
let command = matchstr( lines[ start ], '\V\^XSETm\?\ze\s' )
if command != ''
let [key,val,start] = s:GetXSETkeyAndValue(lines,start)
if key == ''
let start += 1
continue
endif
let [keyname,keytype] = xpt#parser#GetKeyType(key)
call s:HandleXSETcommand(setting,command,[keyname,keytype,val])
elseif lines[start] =~# '^\\XSET' " escaped XSET or XSETm
let snippetLines += [lines[start][1:]]
else
call add(snippetLines,lines[start])
endif
let start += 1
endwhile
call xpt#st#Simplify(setting)
if has_key( setting, 'alias' )
return printf( 'call XPTemplateAlias(%s,%s,%s)', string(snippetName),string(setting.alias),string(setting))
else
return printf( 'call XPTdefineSnippet(%s,%s,%s)', string(snippetName),string(setting),string(snippetLines))
endif
endfunction
fun! xpt#parser#Include(...)
call xpt#parser#Load(a:000,1)
endfunction
fun! xpt#parser#Embed(...)
call xpt#parser#Load(a:000,0)
endfunction
fun! xpt#parser#Load(fns,inherit)
let scope = b:xptemplateData.snipFileScope
let ftscope = b:xptemplateData.filetypes[scope.filetype]
let saved_inherit = scope.inheritFT
let scope.inheritFT = a:inherit
let fns = xpt#util#Flatten(a:fns)
for f in fns
if a:inherit && xpt#ftscope#IsSnippetLoaded(ftscope,f)
continue
endif
call xpt#snipfile#Push()
exe 'runtime! ftplugin/' . f . '.xpt.vim'
call xpt#snipfile#Pop()
endfor
let scope.inheritFT = saved_inherit
endfunction
fun! xpt#parser#SetVar(nameSpaceValue)
let x = b:xptemplateData
let ftScope = x.filetypes[x.snipFileScope.filetype]
let name = matchstr(a:nameSpaceValue, '^\S\+\ze')
if name == ''
return
endif
let val = matchstr(a:nameSpaceValue, '\s\+\zs.*')
if val =~ '^''.*''$'
let val = val[1:-2]
else
let val = substitute( val, '\\ ', " ", 'g' )
endif
let val = substitute( val, '\\n', "\n", 'g' )
let priority = x.snipFileScope.priority
if !has_key(ftScope.varPriority,name) || priority <= ftScope.varPriority[name]
let [ftScope.funcs[name],ftScope.varPriority[name]] = [val,priority]
endif
endfunction
fun! xpt#parser#SnipSet(dictNameValue)
let x = b:xptemplateData
let snipScope = x.snipFileScope
let [ dict, nameValue ] = split( a:dictNameValue, '\V.', 1 )
let name = matchstr( nameValue, '^.\{-}\ze=' )
let value = nameValue[len(name) + 1 :]
let snipScope[dict][name] = value
endfunction
fun! xpt#parser#loadSpecialFiletype(ft)
let x = b:xptemplateData
let ft = a:ft
if has_key(x.filetypes,ft)
return
endif
if ft == 'unknown'
call xpt#parser#loadSnippetFile( 'unknown/unknown' )
else
call xpt#parser#InitSnippetFile( '~~/xpt/pseudo/ftplugin/' . ft . '/' . ft . '.xpt.vim' )
call XPTinclude( '_common/common' )
call XPTfiletypeInit()
endif
call XPTparseSnippets()
endfunction
fun! xpt#parser#loadSnippetFile(rel_snip)
exe 'runtime! ftplugin/' . a:rel_snip . '.xpt.vim'
call XPTfiletypeInit()
endfunction
fun! s:AssignSnipFT(filename)
let x = b:xptemplateData
let filename = substitute( a:filename, '\\', '/', 'g' )
if filename =~ 'unknown.xpt.vim$'
return 'unknown'
endif
let ftFolder = matchstr( filename, '\V/ftplugin/\zs\[^\\]\+\ze/' )
if empty(x.snipFileScopeStack)
if filename =~ '\V\<pseudo\>/'
return ftFolder
endif
if &filetype =~ '\<' . ftFolder . '\>' " sub type like 'xpt.vim'
let ft = &filetype
else
let ft = 'not allowed'
endif
else
if x.snipFileScopeStack[-1].inheritFT || ftFolder =~ '\V\^_'
if !has_key( x.snipFileScopeStack[ -1 ], 'filetype' )
throw 'parent may has no XPTemplate command called :' . a:filename
endif
let ft = x.snipFileScopeStack[-1].filetype
else
let ft = ftFolder
endif
endif
return ft
endfunction
fun! xpt#parser#InitSnippetFile(filename,...)
if ! xpt#option#lib_filter#Match(a:filename)
return 'finish'
endif
if !exists("b:xptemplateData")
call XPTemplateInit()
endif
let x = b:xptemplateData
let filetypes = x.filetypes
let snipScope = xpt#snipfile#New(a:filename)
let snipScope.filetype = s:AssignSnipFT(a:filename)
let x.snipFileScope = snipScope
let ft = snipScope.filetype
if ft == 'not allowed'
call s:log.Info( "not allowed:" . a:filename )
return 'finish'
endif
if ! has_key(filetypes,ft)
let filetypes[ft] = xpt#ftscope#New()
endif
let ftScope = filetypes[ft]
if xpt#ftscope#CheckAndSetSnippetLoaded(ftScope,a:filename)
return 'finish'
endif
for pair in a:000
let kv = split( pair, '=', 1 )
let key = kv[0]
let val = join( kv[ 1 : ], '=' )
if key =~ 'prio\%[rity]'
call XPTemplatePriority(val)
elseif key =~ 'mark'
call XPTemplateMark(val[0 : 0],val[1 : 1])
elseif key =~ 'key\%[word]'
call XPTemplateKeyword(val)
endif
endfor
return 'doit'
endfunction
fun! xpt#parser#SnippetFileInit_for_compiled(filename,...)
if !filereadable(a:filename)
return call( function( 'xpt#parser#InitSnippetFile' ), [ a:filename ] + a:000 )
endif
if a:filename =~ '\V.xpt.vim\$'
call xpt#parser#Compile(a:filename)
exe 'so' a:filename . 'c'
return 'finish'
else
return call( function( 'xpt#parser#InitSnippetFile' ), [ a:filename ] + a:000 )
endif
endfunction
fun! xpt#parser#LoadSnippets()
let fts = split( &filetype, '\V.', 1 )
call filter( fts, 'v:val!=""' )
for ft in fts
call xpt#parser#LoadFTSnippets(ft)
endfor
endfunction
fun! s:RTP()
let rtps = split( &runtimepath, ',' )
call filter( rtps, 'v:val!=""' )
let rtps += [ g:XPT_PATH . '/xptsnippets', g:XPT_PATH . '/personal' ]
let rtpath = join( rtps, ',' )
return rtpath
endfunction
fun! xpt#parser#LoadFtDetectors(ft)
let namePattern = a:ft =~ '/' ? a:ft : a:ft . '/*'
let rtpath = s:RTP()
let ftdetectfiles = split( globpath( rtpath, 'ftplugin/' . namePattern . '.ftdetect.vim' ), "\n" )
for fn in ftdetectfiles
exe 'so' fn
endfor
endfunction
fun! xpt#parser#LoadFTSnippets(ft)
let namePattern = a:ft =~ '/' ? a:ft : a:ft . '/*'
let rtpath = s:RTP()
let ftdetectfiles = split( globpath( rtpath, 'ftplugin/' . namePattern . '.ftdetect.vim' ), "\n" )
for fn in ftdetectfiles
exe 'so' fn
endfor
let snipfiles = split( globpath( rtpath, 'ftplugin/' . namePattern . '.xpt.vim' ), "\n" )
for fn in snipfiles
let compiled = fn . 'c'
if !filereadable(compiled) || getftime(compiled) < getftime(fn) || g:xptemplate_always_compile
call xpt#parser#Compile(fn)
exe 'so' compiled
endif
endfor
endfunction
fun! xpt#parser#GetKeyType(rawKey)
let keytype = matchstr(a:rawKey, '\V'.s:nonEscaped.'|\zs\.\{-}\$')
if keytype == ""
let keytype = matchstr(a:rawKey, '\V'.s:nonEscaped.'.\zs\.\{-}\$')
endif
let keyname = keytype == "" ? a:rawKey : a:rawKey[ 0 : - len(keytype) - 2 ]
let keyname = substitute(keyname, '\V\\\(\[.|\\]\)', '\1', 'g')
return [keyname,keytype]
endfunction
let s:KEY_NAME = 0
let s:KEY_TYPE = 1
let s:VALUE = 2
let s:stHandler = {}
fun! s:stHandler.ComeFirst(setting,cmdArgs)
let a:setting.comeFirst = xpt#util#SplitWith( a:cmdArgs[ s:VALUE ], ' ' )
endfunction
fun! s:stHandler.ComeLast(setting,cmdArgs)
let a:setting.comeLast = xpt#util#SplitWith( a:cmdArgs[ s:VALUE ], ' ' )
endfunction
fun! s:stHandler.postQuoter(setting,cmdArgs)
let pq = split( a:cmdArgs[ s:VALUE ], ',' )
let a:setting.postQuoter = { 'start' : pq[0], 'end' : pq[1] }
endfunction
let s:stHandler.PostQuoter = s:stHandler.postQuoter
let s:keytypeHandler = {}
fun! s:keytypeHandler.repl(setting,cmdArgs)
let a:setting.replacements[a:cmdArgs[s:KEY_NAME]] = a:cmdArgs[s:VALUE]
endfunction
fun! s:keytypeHandler.map(setting,cmdArgs)
let [kn,kt,val] = a:cmdArgs
let mp = a:setting.mappings
if !has_key(mp,kn)
let mp[ kn ] = { 'saver' : xpt#msvr#New( 1 ), 'keys' : {} }
endif
let key = matchstr( val, '\V\^\S\+\ze\s' )
let mapping = matchstr( val, '\V\s\+\zs\.\*' )
call xpt#msvr#Add( mp[ kn ].saver, 'i', key )
let mp[kn].keys[key] = xpt#flt#NewSimple(0,mapping)
endfunction
fun! s:keytypeHandler.post(setting,cmdArgs)
let [kn,kt,val] = a:cmdArgs
let val = xpt#ph#AlterFilterByPHName(kn,val)
let a:setting.postFilters[kn] = xpt#flt#NewSimple(0,val)
endfunction
fun! s:HandleXSETcommand(setting,command,cmdArgs)
let [kn,kt,val] = a:cmdArgs
let kt = get( s:KEYTYPE_MAP, '.' . kt, kt )
let fcon = {}
if has_key(s:stHandler,kn)
let fcon.f = s:stHandler[kn]
call fcon.f(a:setting,[kn,kt,val])
elseif has_key(s:KEYTYPE_TO_DICT,kt)
let dicName = s:KEYTYPE_TO_DICT[kt]
let a:setting[dicName][kn] = xpt#flt#NewSimple(0,val)
elseif kn =~ '\V\^$'
let a:setting.variables[kn] = val
elseif has_key(s:keytypeHandler,kt)
let fcon.f = s:keytypeHandler[kt]
call fcon.f(a:setting,[kn,kt,val])
else
throw "unknown key name or type:" . kn . ' ' . kt
endif
endfunction
fun! xpt#parser#LoadSnippetToParseList(fn)
let lines = readfile(a:fn)
let i = match( lines, '\V\^XPTemplateDef' )
if i == -1
let i = match( lines, '\V\^XPT\s' ) - 1
endif
if i < 0
return
endif
let lines = lines[i :]
let x = b:xptemplateData
let x.snippetToParse += [ { 'snipFileScope' : x.snipFileScope, 'lines' : lines } ]
endfunction
fun! xpt#parser#ParseSnippet(p)
call xpt#snipfile#Push()
let x = b:xptemplateData
let x.snipFileScope = a:p.snipFileScope
let lines = a:p.lines
let [i,len] = [0,len(lines)]
let [s,e,blk] = [-1,-1,10000]
while i < len-1 | let i += 1
let v = lines[i]
if v =~ '^\s*$' || v =~ '^"[^"]*$'
let blk = min([blk,i - 1])
continue
endif
if v =~# '^\.\.XPT'
let e = i - 1
call s:XPTemplateParseSnippet(lines[s : e])
let [s,e,blk] = [-1,-1,10000]
elseif v =~# '^XPT\>'
if s != -1
let e = min([i - 1,blk])
call s:XPTemplateParseSnippet(lines[s : e])
let [s,e,blk] = [i,-1,10000]
else
let s = i
let blk = i
endif
elseif v =~# '^\\XPT'
let lines[i] = v[1 :]
else
let blk = i
endif
endwhile
if s != -1
call s:XPTemplateParseSnippet(lines[s : min([blk,i])])
endif
call xpt#snipfile#Pop()
endfunction
fun! s:XPTemplateParseSnippet(lines)
let lines = a:lines
let snipScope = XPTsnipScope()
let snipScope.loadedSnip = get( snipScope, 'loadedSnip', {} )
let snippetLines = []
let setting = deepcopy(g:XPTemplateSettingPrototype)
let [hint,lines[0]] = s:GetSnipCommentHint(lines[0])
if hint != ''
let setting.rawHint = hint
endif
let snippetParameters = split(lines[0], '\V'.s:nonEscaped.'\s\+')
let snippetName = snippetParameters[1]
let snippetParameters = snippetParameters[2:]
for pair in snippetParameters
let name = matchstr(pair, '\V\^\[^=]\*')
let value = pair[len(name) :]
let value = value[0:0] == '=' ? xpt#util#UnescapeChar(value[1:], ' ') : 1
let setting[name] = value
endfor
let start = 1
let len = len(lines)
while start < len
let command = matchstr( lines[ start ], '\V\^XSETm\?\ze\s' )
if command != ''
let [key,val,start] = s:GetXSETkeyAndValue(lines,start)
if key == ''
let start += 1
continue
endif
let [keyname,keytype] = xpt#parser#GetKeyType(key)
call s:HandleXSETcommandOld(setting,command,keyname,keytype,val)
elseif lines[start] =~# '^\\XSET' " escaped XSET or XSETm
let snippetLines += [lines[start][1:]]
else
let snippetLines += [lines[start]]
endif
let start += 1
endwhile
let setting.fromXPT = 1
if has_key( setting, 'alias' )
call XPTemplateAlias(snippetName,setting.alias,setting)
else
call XPTdefineSnippet(snippetName,setting,snippetLines)
endif
if has_key(snipScope.loadedSnip,snippetName)
call XPT#info( "XPT: warn : duplicate snippet:" . snippetName . ' in file:' . snipScope.filename )
endif
let snipScope.loadedSnip[snippetName] = 1
if has_key( setting, 'synonym' )
let synonyms = split( setting.synonym, '|' )
for synonym in synonyms
call XPTemplateAlias(synonym,snippetName,{})
if has_key(snipScope.loadedSnip,synonym)
call XPT#warn( "XPT: warn : duplicate synonym:" . synonym . ' in file:' . snipScope.filename )
endif
let snipScope.loadedSnip[synonym] = 1
endfor
endif
endfunction
fun! s:GetSnipCommentHint(str)
let pos = match(a:str, '\V' . s:nonEscaped . '\shint=')
if pos != -1
return [a:str[pos + 6 :],a:str[: pos - 1]]
endif
let pos = match( a:str, '\VXPT\s\+\S\+\.\{-}\zs\s' . s:nonEscaped . '"' )
if pos == -1
return [ '', a:str ]
else
return [ matchstr( a:str[ pos + 1 + 1 : ], '\S.*' ), a:str[ : pos ] ]
endif
endfunction
fun! s:GetXSETkeyAndValue(lines,start)
let start = a:start
let XSETparam = matchstr(a:lines[start], '\V\^XSET\%[m]\s\+\zs\.\*')
let isMultiLine = a:lines[ start ] =~# '\V\^XSETm'
if isMultiLine
let key = XSETparam
let [start,val] = s:ParseMultiLineValues(a:lines,start)
else
let key = matchstr(XSETparam, '\V\[^=]\*\ze=')
if key == ''
return [ '', '', start + 1 ]
endif
let val = matchstr(XSETparam, '\V=\s\*\zs\.\*')
let val = substitute(val, '\\n', "\n", 'g')
endif
return [key,val,start]
endfunction
fun! s:ParseMultiLineValues(lines,start)
let lines = a:lines
let start = a:start
let endPattern = '\V\^XSETm\s\+END\$'
let start += 1
let multiLineValues = []
while start < len(lines)
let line = lines[start]
if line =~# endPattern
break
endif
if line =~# '^\V\\\+XSET\%[m]'
let slashes = matchstr( line, '^\\\+' )
let nrSlashes = len(slashes + 1) / 2
let line = line[nrSlashes :]
endif
let multiLineValues += [line]
let start += 1
endwhile
let val = join(multiLineValues, "\n")
return [start,val]
endfunction
fun! s:HandleXSETcommandOld(setting,command,keyname,keytype,value)
if a:keyname ==# 'ComeFirst'
let a:setting.comeFirst = xpt#util#SplitWith( a:value, ' ' )
elseif a:keyname ==# 'ComeLast'
let a:setting.comeLast = xpt#util#SplitWith( a:value, ' ' )
elseif a:keyname ==# 'postQuoter'
let a:setting.postQuoter = a:value
elseif a:keyname =~ '\V\^$'
let a:setting.variables[a:keyname] = a:value
elseif a:keytype == "" || a:keytype ==# 'def'
let a:setting.defaultValues[a:keyname] = xpt#flt#New(0,a:value)
elseif a:keytype ==# 'map'
let a:setting.mappings[a:keyname] = get( a:setting.mappings, a:keyname, { 'saver' : xpt#msvr#New(1), 'keys' : {} } )
let key = matchstr( a:value, '\V\^\S\+\ze\s' )
let mapping = matchstr( a:value, '\V\s\+\zs\.\*' )
call xpt#msvr#Add( a:setting.mappings[ a:keyname ].saver, 'i', key )
let a:setting.mappings[a:keyname].keys[key] = xpt#flt#New(0,mapping)
elseif a:keytype ==# 'pre'
let a:setting.preValues[a:keyname] = xpt#flt#New(0,a:value)
elseif a:keytype ==# 'ontype'
let a:setting.ontypeFilters[a:keyname] = xpt#flt#New(0,a:value)
elseif a:keytype ==# 'post'
if a:keyname =~ '\V...'
let a:setting.postFilters[a:keyname] = xpt#flt#New( 0, 'BuildIfNoChange(' . string(a:value) . ')' )
else
let a:setting.postFilters[a:keyname] = xpt#flt#New(0,a:value)
endif
else
throw "unknown key name or type:" . a:keyname . ' ' . a:keytype
endif
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,122 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
exe XPT#importConst
fun! xpt#ph#CreateFromScreen(snipObject,nameInfo,valueInfo)
let xp = a:snipObject.ptn
let toescape = xp.l . xp.r
let leftEdge = xpt#util#TextBetween(a:nameInfo[0 : 1])
let name = xpt#util#TextBetween(a:nameInfo[1 : 2])
let rightEdge = xpt#util#TextBetween(a:nameInfo[2 : 3])
let [leftEdge,name,rightEdge] = [leftEdge[1 :],name[1 :],rightEdge[1 :]]
let leftEdge = xpt#util#UnescapeChar(leftEdge,toescape)
let name = xpt#util#UnescapeChar(name,toescape)
let rightEdge = xpt#util#UnescapeChar(rightEdge,toescape)
if a:valueInfo[1] != a:valueInfo[0]
let posList = [a:valueInfo[0],a:valueInfo[2]]
let val = xpt#util#TextBetween(posList)
let val = val[1:]
let nIndent = indent(a:valueInfo[0][0])
let phFilter = { 'text' : val, 'indent' : nIndent, }
else
let phFilter = 0
endif
return xpt#ph#New(a:snipObject, { 'leftEdge' : leftEdge, 'name':name, 'rightEdge':rightEdge, 'isKey':a:nameInfo[0] != a:nameInfo[1], }, phFilter )
endfunction
fun! xpt#ph#New(snipObject,pieces)
let phptns = a:snipObject.ptn
let textPieces = deepcopy(a:pieces)
call map( textPieces, 'v:val.text' )
let iFilter = match( textPieces, '\V\^' . a:snipObject.ptn.r )
if iFilter > 1
let ph ={ 'leftEdge':a:pieces[ 0 ], 'name':a:pieces[ 1 ].text, 'displayText':a:pieces[ 1 ], 'rightEdge':iFilter > 2 ? a:pieces[2] : { 'nIndent' : a:pieces[ 1 ].nIndent, 'text' : '' }, 'isKey':1 }
let ph.fullname = ph.leftEdge.text . ph.name . ph.rightEdge.text
for key in [ 'leftEdge', 'displayText', 'rightEdge' ]
call xpt#ph#CreateEvaluatablePHElt(a:snipObject,ph,key)
endfor
else
let ph ={ 'name':a:pieces[ 0 ].text, 'displayText':a:pieces[ 0 ], 'fullname':a:pieces[ 0 ].text }
call xpt#ph#CreateEvaluatablePHElt( a:snipObject, ph, 'displayText' )
endif
let spec = xpt#ph#CreateSpecial(a:snipObject,ph)
if spec isnot 0
return spec
endif
if len(a:pieces) - iFilter == 1
return ph
endif
let ftype = len( a:pieces ) - iFilter > 2 ? 'postFilter' : 'liveFilter'
let fltPart = copy(a:pieces[iFilter])
let fltPart.text = fltPart.text[1:]
let fltPart.text = xpt#ph#AlterFilterByPHName(ph.name,fltPart.text)
let flt = xpt#ph#CreatePHEltFilter(a:snipObject,fltPart)
if has_key( ph, 'isKey' ) && ph.name != ''
let a:snipObject.setting[ ftype . 's' ][ ph.name ] = flt
else
let ph[ftype] = flt
endif
return ph
endfunction
fun! xpt#ph#CreateEvaluatablePHElt(snipObject,ph,key)
let phptns = a:snipObject.ptn
if a:ph[ a:key ].text =~ '\V' . phptns.item_var . '\|' . phptns.item_func . '\|\n'
let a:ph[a:key] = xpt#ph#CreatePHEltFilter(a:snipObject,a:ph[a:key])
elseif a:ph[ a:key ].text =~ '\V' . s:ptnIncFull . '\|' . s:ptnIncSimp
let a:ph[a:key] = xpt#ph#CreatePHEltFilter(a:snipObject,a:ph[a:key])
else
let a:ph[a:key] = xpt#util#UnescapeChar(a:ph[a:key].text,a:snipObject.ptn.lr)
endif
endfunction
fun! xpt#ph#CreateSpecial(snipObject,ph)
let phptns = a:snipObject.ptn
if type(a:ph.displayText) == type({})
if a:ph.displayText[ 'text' ] =~ s:ptnIncFull
let params = matchstr( a:ph.displayText[ 'text' ], s:ptnIncFull )
let [name,args] = xpt#snip#ParseInclusionStatement(a:snipObject,params)
let a:ph.displayText[ 'text' ] = 'Inc(' . string( name ) . ', 1, ' . string( args ) .')'
return a:ph
elseif a:ph.displayText[ 'text' ] =~ s:ptnIncSimp
let params = matchstr( a:ph.displayText[ 'text' ], s:ptnIncSimp )
let [name,args] = xpt#snip#ParseInclusionStatement(a:snipObject,params)
let a:ph.displayText[ 'text' ] = 'Inc(' . string( name ) . ', 0, ' . string( args ) .')'
return a:ph
endif
let a:ph.value = 1
return a:ph
endif
return 0
endfunction
fun! xpt#ph#FilterEltKeys(ph)
let phKeys = [ 'leftEdge', 'displayText', 'rightEdge' ]
call filter( phKeys, 'type( get( a:ph, v:val, 0 ) ) is ' . string( type( {} ) ) )
return phKeys
endfunction
fun! xpt#ph#GetPresetFilter(ph,setting)
let phLive = get( a:ph, 'liveFilter', g:EmptyFilter )
if a:ph.name != ''
let pre = get(a:setting.preValues,a:ph.name,g:EmptyFilter)
if get( pre, 'force' )
return pre
endif
let live = get(a:setting.liveFilters,a:ph.name,g:EmptyFilter)
if get( live, 'force' )
return live
endif
let phLive = phLive is g:EmptyFilter || get( pre, 'force' ) ? pre : phLive
let phLive = phLive is g:EmptyFilter || get( live, 'force' ) ? live : phLive
endif
return phLive
endfunction
fun! xpt#ph#CreatePHEltFilter(snipObject,elt)
let val = xpt#util#UnescapeChar(a:elt.text,a:snipObject.ptn.lr)
return xpt#flt#New(-a:elt.nIndent,val)
endfunction
fun! xpt#ph#AlterFilterByPHName(phname,fltText)
if a:phname =~ '\V...\$'
let a:fltText = xpt#util#UnescapeChar( a:fltText, '$({' )
return 'BuildIfNoChange(' . string( a:fltText ) . ')'
endif
return a:fltText
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,223 @@
if exists( "g:__AL_XPT_PHFILTER_VIM__" ) && g:__AL_XPT_PHFILTER_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_PHFILTER_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
let s:log = xpt#debug#Logger( 'debug' )
exe XPT#importConst
fun! xpt#phfilter#Filter(so,PHFilterName,extContext)
let fctx = { 'snipObject':a:so, 'snipSetting':a:so.setting, 'phptns':a:so.ptn, 'phEvalContext':{ 'variables':a:so.setting.variables, 'pos':[ 0, 0 ], 'nIndAdd':0 }, 'srcPHs':a:so.parsedSnip, 'rstPHs':[], 'skip':'\v[^]', 'forceNotSkip':'\v.', }
call extend( fctx, a:extContext, 'force' )
call extend( fctx.phEvalContext, { 'pos' : [ 0, 0 ], 'nIndAdd' : 0 }, 'force' )
let fctx.srcPHs = deepcopy(fctx.srcPHs)
if len(fctx.srcPHs) == 0
return []
endif
call add(b:xptemplateData.phFilterContexts,fctx)
call add( fctx.rstPHs, "\n" )
try
while !empty(fctx.srcPHs)
let fctx.ph = remove(fctx.srcPHs,0)
let r = {a:PHFilterName}(fctx)
endwhile
finally
call remove(b:xptemplateData.phFilterContexts,-1)
endtry
let rst = fctx.rstPHs
if !empty(rst)
let rst[0] = rst[0][1 :]
endif
call filter( rst, 'len(v:val) > 0' )
return rst
endfunction
fun! xpt#phfilter#EvalInstantFilters(fctx)
if type(a:fctx.ph) == type({})
for a:fctx.key in [ 'leftEdge', 'displayText', 'rightEdge' ]
if s:EvalPHElt(a:fctx) isnot s:GOON
return
endif
endfor
endif
call xpt#phfilter#FeedPH(a:fctx)
endfunction
fun! xpt#phfilter#EvalPresetFilters(fctx)
if type(a:fctx.ph) == type({})
if type( a:fctx.ph[ 'displayText' ] ) == type( '' )
let flt = xpt#ph#GetPresetFilter(a:fctx.ph,a:fctx.snipSetting)
if flt isnot g:EmptyFilter
let a:fctx.ph[ 'displayText' ] = flt
endif
endif
for a:fctx.key in [ 'leftEdge', 'displayText', 'rightEdge' ]
if s:EvalPHElt(a:fctx) isnot s:GOON
return
endif
endfor
endif
call xpt#phfilter#FeedPH(a:fctx)
endfunction
fun! s:EvalPHElt(fctx,...)
let a:fctx.key = a:0 > 0 ? a:1 : a:fctx.key
let [ph,key] = [a:fctx.ph,a:fctx.key]
if has_key(ph,key) && type(ph[key]) == type({})
let flt = ph[key]
if flt.text =~# a:fctx.forceNotSkip || flt.text !~# a:fctx.skip
call xpt#flt#Eval(flt, a:fctx.snipObject.ftScope.funcs, a:fctx.phEvalContext)
return xpt#phfilter#HandleEltFilterRst(a:fctx,flt)
endif
endif
return s:GOON
endfunction
fun! xpt#phfilter#HandleEltFilterRst(fctx,flt)
let frst = a:flt.rst
if frst.rc > 0
if has_key( frst, 'action' )
let rc = s:HandleAction(a:fctx,a:flt)
if rc is s:DONE
return rc
endif
endif
if has_key( frst, 'text' )
let a:fctx.ph[a:fctx.key] = frst.text
return s:GOON
else
call XPT#info( 'Failed to pre-eval filter: ' . string( frst ) . ' filter=' . string( a:flt.text ) )
return s:UNDONE
endif
endif
return s:GOON
endfunction
fun! s:HandleAction(fctx,flt)
let frst = a:flt.rst
if frst.action == 'embed'
call extend(a:fctx.srcPHs,frst.phs,0)
else
return s:UNDONE
endif
return s:DONE
endfunction
fun! xpt#phfilter#ReplacePH(fctx)
let ph = a:fctx.ph
let phptns = a:fctx.phptns
let params = a:fctx.replParams
let rst = a:fctx.rstPHs
if type( ph ) == type( '' ) || !has_key(params,ph.name)
call xpt#phfilter#FeedPH(a:fctx)
else
let rep = params[ph.name]
if rep =~ phptns.lft
if rep !~ phptns.rt . '\$'
let rep = phptns.l . rep . phptns.r
endif
let slaveSnip = xpt#snip#NewSlave(a:fctx.snipObject,rep)
call xpt#snip#CompileAndParse(slaveSnip)
for a:fctx.ph in slaveSnip.parsedSnip
call xpt#phfilter#FeedPH(a:fctx)
endfor
let a:fctx.ph = ph
else
let ph.name = rep
let ph.displayText = rep
if ph.displayText =~ '\V' . phptns.item_var . '\|' . phptns.item_func . '\|\n'
let filterText = xpt#util#UnescapeChar(ph.displayText,phptns.lr)
let ph.displayText = xpt#flt#New(-a:fctx.phEvalContext.nIndAdd,filterText)
endif
call xpt#phfilter#FeedPH(a:fctx)
endif
endif
endfunction
fun! xpt#phfilter#PostQuote(fctx)
let ph = a:fctx.ph
let quoter = a:fctx.snipObject.setting.postQuoter
if type( ph ) == type( '' )
call xpt#phfilter#AppendRst(a:fctx,a:fctx.pqStack[-1],ph)
else
call extend( a:fctx.pqStack[ -1 ], [ ph, '' ] )
if ph.name[-len(quoter.start) :] ==# quoter.start
let ph.name = ph.name[0 : -1 - len(quoter.start)]
let ph.displayText = ph.name
call add(a:fctx.pqStack[-1],a:fctx.phEvalContext.nIndAdd)
call add( a:fctx.pqStack, [''] )
elseif ph.name == quoter.end
let stack = remove(a:fctx.pqStack,-1)
call remove(stack,-1)
call remove(stack,-1)
call filter( stack, 'len(v:val) > 0' )
let nIndent = remove(a:fctx.pqStack[-1],-1)
let startPH = a:fctx.pqStack[-1][-2]
let id = xpt#ftsc#PushPHPieces(a:fctx.snipObject.ftScope,stack)
if startPH.name[ -1 : -1 ] == '!'
let funcCall = 'Echo(IsChanged()?EmbedPHs(' . string( id ) . '):0)'
let startPH.name = startPH.name[0 : -len(quoter.start)]
let startPH.displayText = startPH.name
else
let funcCall = 'Echo(!IsChanged()?EmbedPHs(' . string( id ) . '):0)'
endif
let a:fctx.snipObject.setting.postFilters[startPH.name] = xpt#flt#New(-nIndent,funcCall)
endif
endif
endfunction
fun! xpt#phfilter#Repetition(fctx)
let ph = a:fctx.ph
if type( ph ) == type( '' )
call xpt#phfilter#AppendRst(a:fctx,a:fctx.repStack[-1],ph)
else
call extend( a:fctx.repStack[ -1 ], [ ph, '' ] )
if ph.name =~ s:ptnRepetition && !has_key(a:fctx.snipObject.setting.postFilters,ph.name)
if !has_key(a:fctx.repHeads,ph.name)
let a:fctx.repHeads[ph.name] = 1
call add(a:fctx.repStack[-1],a:fctx.phEvalContext.nIndAdd)
call add( a:fctx.repStack, [''] )
else
call remove(a:fctx.repHeads,ph.name)
let stack = remove(a:fctx.repStack,-1)
call filter( stack, 'len(v:val) > 0' )
let nIndent = remove(a:fctx.repStack[-1],-1)
let startPH = a:fctx.repStack[-1][-2]
let id = xpt#ftsc#PushPHPieces(a:fctx.snipObject.ftScope,stack)
let funcCall = 'Echo(!IsChanged()?EmbedPHs(' . string( id ) . '):0)'
let a:fctx.snipObject.setting.postFilters[startPH.name] = xpt#flt#New(-nIndent,funcCall)
endif
endif
endif
endfunction
fun! xpt#phfilter#UpdateIndent(fctx,last)
let evalctx = a:fctx.phEvalContext
if a:last =~ '\V\n'
let evalctx.nIndAdd = xpt#util#LastIndent(a:last)
endif
endfunction
fun! xpt#phfilter#AppendRst(fctx,lst,ph)
let evalctx = a:fctx.phEvalContext
if a:ph =~ '\V\n'
let lines = split( a:ph, '\V\n', 1 )
let evalctx.pos[0] += len(lines) - 1
let evalctx.pos[1] = len(lines[-1])
else
let evalctx.pos[1] += len(a:ph)
endif
let a:lst[-1] .= a:ph
call xpt#phfilter#UpdateIndent(a:fctx,a:lst[-1])
endfunction
fun! xpt#phfilter#FeedPH(fctx)
if type( a:fctx.ph ) == type( {} ) && has_key( a:fctx.ph, 'value' )
let ph = s:MergeEltsIfAllString(a:fctx.ph)
else
let ph = a:fctx.ph
endif
if type( ph ) == type( '' )
call xpt#phfilter#AppendRst(a:fctx,a:fctx.rstPHs,ph)
else
call extend( a:fctx.rstPHs, [ ph, '' ] )
endif
endfunction
fun! s:MergeEltsIfAllString(ph)
if has_key( a:ph, 'value' ) && type( a:ph[ 'displayText' ] ) == type( '' ) && type( get( a:ph, 'leftEdge', '' ) ) == type( '' ) && type( get( a:ph, 'rightEdge', '' ) ) == type( '' )
return get( a:ph, 'leftEdge', '' ) . get( a:ph, 'displayText', '' ) . get( a:ph, 'rightEdge', '' )
else
return a:ph
endif
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,22 @@
if exists( "g:__AL_XPT_PRIORITY_f78d9s873942__" ) && g:__AL_XPT_PRIORITY_f78d9s873942__ >= XPT#ver
finish
endif
let g:__AL_XPT_PRIORITY_f78d9s873942__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:priorities = { 'lowest': 9999999, 'all':64, 'spec' : 48, 'like' : 32, 'lang' : 16, 'sub':8, 'personal' : 0, 'highest':-1, }
let s:priorities.default = s:priorities.lang
fun! xpt#priority#Get(pstr)
return s:priorities[a:pstr]
endfunction
fun! xpt#priority#Parse(pstr)
let pstr = a:pstr
if pstr =~ '\V\[+-]\$'
let pstr .= '1'
endif
let reg = '\V\(\w\+\|\[+-]\)\zs'
let prioParts = split(pstr,reg)
let prioParts[0] = get(s:priorities,prioParts[0],prioParts[0] - 0)
return eval( join( prioParts, '' ) )
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,118 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
let s:phase = { 'uninit':'uninit' , 'popup':'popup' , 'inited':'inited' , 'rendering':'rendering', 'rendered':'rendered' , 'iteminit':'iteminit' , 'fillin':'fillin' , 'post':'post' , 'finished':'finished' , }
let xpt#rctx#phase = s:phase
let p = s:phase
let s:phaseGraph = { p.uninit : [p.popup,p.inited], p.popup : [p.inited], p.inited : [p.rendering], p.rendering : [p.rendered], p.rendered : [p.iteminit], p.iteminit : [p.iteminit,p.fillin,p.post], p.fillin : [p.post,p.finished], p.post : [p.finished,p.iteminit], p.finished : [p.uninit], }
unlet p
fun! xpt#rctx#New(x)
let pre = "X" . len( a:x.stack ) . '_'
let inst = { 'ftScope':{}, 'level':len( a:x.stack ), 'snipObject':{}, 'snipSetting':{}, 'phase':s:phase.uninit, 'nextStep':-1, 'action':'', 'userPostAction':'', 'wrap':{}, 'userWrapped':{}, 'markNamePre':pre, 'item':{}, 'leadingPlaceHolder':{}, 'activeLeaderMarks':'innerMarks', 'history':[], 'namedStep':{}, 'processing':0, 'marks':{ 'tmpl':{ 'start':pre . '`tmpl`s', 'end':pre . '`tmpl`e' } }, 'itemDict':{}, 'itemList':[], 'groupList':[], 'lastContent':'', 'tmpmappings':{}, 'oriIndentkeys':{}, 'leadingCharToReindent':{}, }
let lst = split( &indentkeys, ',' )
let indentkeysList = []
for k in lst
if k == ""
let indentkeysList[ -1 ] .= ','
else
if k[ 0 ] == '0'
call add(indentkeysList,k)
endif
endif
endfor
for k in indentkeysList
if k[ 1 ] == '=' && len( k ) > 2
let inst.oriIndentkeys[k[2:]] = 1
else
let k = k[1:]
if k == ''
let k = ','
endif
let inst.leadingCharToReindent[k] = 1
endif
endfor
return inst
endfunction
fun! xpt#rctx#SwitchPhase(inst,nextPhase)
if -1 == match( s:phaseGraph[ a:inst.phase ], '\V\<' . a:nextPhase . '\>' )
throw 'XPT:RenderContext:switching from [' . a:inst.phase . '] to [' . a:nextPhase . '] is not allowed'
endif
let a:inst.phase = a:nextPhase
endfunction
fun! xpt#rctx#InitOrderedGroupList(rctx)
let a:rctx.firstList = copy(a:rctx.snipSetting.comeFirst)
let a:rctx.lastList = copy(a:rctx.snipSetting.comeLast)
endfunction
fun! xpt#rctx#AddDefaultPHFilters(rctx,ph)
if a:ph.name == ''
return
endif
let pfs = a:rctx.snipSetting.postFilters
if !has_key(pfs,a:ph.name)
if a:ph.name =~ '\V\w\+?\$'
let pfs[ a:ph.name ] = xpt#flt#New( 0, "EchoIfNoChange('')" )
endif
endif
endfunction
fun! xpt#rctx#DefaultMarks(rctx)
if a:rctx.phase == s:phase.post
return 'mark'
else
return 'innerMarks'
endif
endfunction
fun! xpt#rctx#UserOut(rctx,text)
let a:rctx.nextStep = s:R_NEXT
let a:rctx.userPostAction = a:text
endfunction
fun! xpt#rctx#UserOutAppend(rctx,text)
call xpt#rctx#UserOut(a:rctx,a:rctx.userPostAction . a:text)
endfunction
fun! xpt#rctx#AddPHToGroup(rctx,ph)
throw "do not use me any more"
let g = xpt#rctx#GetGroup(a:rctx,a:ph.name)
call xpt#group#InsertPH(g,a:ph,len(g.placeHolders))
return g
endfunction
fun! xpt#rctx#GetGroup(rctx,name)
if has_key(a:rctx.itemDict,a:name)
let g = a:rctx.itemDict[a:name]
else
let g = xpt#group#New(a:name,a:rctx.buildingSessionID)
endif
call xpt#rctx#AddGroup(a:rctx,g)
return g
endfunction
fun! xpt#rctx#AddGroup(rctx,g)
let [rctx,g] = [a:rctx,a:g]
let exist = has_key(rctx.itemDict,g.name)
if g.name != ''
let rctx.itemDict[g.name] = g
endif
if rctx.phase != s:phase.rendering
call add(rctx.firstList,g)
call filter( ctx.groupList, 'v:val isnot g' )
return
endif
if exist
return
endif
if g.name == ''
call add(rctx.groupList,g)
elseif s:AddToOrderList(rctx.firstList,g) || s:AddToOrderList(rctx.lastList,g)
return
else
call add(rctx.groupList,g)
endif
endfunction
fun! s:AddToOrderList(list,g)
let i = index(a:list,a:g.name)
if i != -1
let a:list[i] = a:g
return 1
else
return 0
endif
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,140 @@
if exists( "g:__AL_XPT_RENDER_VIM__" ) && g:__AL_XPT_RENDER_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_RENDER_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
let s:log = xpt#debug#Logger( 'debug' )
exe XPT#importConst
fun! xpt#render#New(rctx,posStart,...)
let p = copy(a:posStart)
let nSp = a:0 == 0 ? 0 : a:1
let render = { 'rctx':a:rctx, 'outerIndent':xpt#util#getIndentNr( p ) + nSp, 'relIndent':0, 'nSpaceToAdd':nSp, 'start':copy( p ), 'pos':copy( p ), 'rst':[ '' ], 'marks':[], }
let p[1] -= 1
let render.offset = p[1] == 0 ? 0 : virtcol(p) - render.outerIndent
return render
endfunction
let s:buildingSeqNr = 0
let s:anonymouseIndex = 0
fun! xpt#render#GenScreenData(render)
let rctx = a:render.rctx
call add(a:render.marks,[rctx.marks.tmpl.start, copy( a:render.pos ), 'l', '\Ve\$' ] )
let rctx.groupList = []
call xpt#render#GenScreenDataOfPHs(a:render,rctx.snipObject.parsedSnip)
call add(a:render.marks,[rctx.marks.tmpl.end, copy( a:render.pos ), 'r', '\Ve\$' ] )
return [a:render.rst,a:render.marks]
endfunction
fun! xpt#render#GenScreenDataOfPHs(render,phs)
let rctx = a:render.rctx
call xpt#rctx#InitOrderedGroupList(rctx)
call xpt#render#BuildPHs(a:render,a:phs)
call filter( rctx.firstList, 'type(v:val) != ' . string( type( '' ) ) )
call filter( rctx.lastList, 'type(v:val) != ' . string( type( '' ) ) )
let rctx.groupList = rctx.firstList + rctx.groupList + rctx.lastList
return [a:render.rst,a:render.marks]
endfunction
let s:buildingSessionID = 0
let s:renderStack = []
fun! xpt#render#BuildPHs(render,phs)
if empty(s:renderStack)
let s:buildingSessionID += 1
let a:render.rctx.itemDict = {}
endif
call add(s:renderStack,a:render)
let a:render.rctx.buildingSessionID = s:buildingSessionID
if a:render.nSpaceToAdd != 0
let phs = [ repeat( ' ', a:render.nSpaceToAdd ) ] + a:phs
else
let phs = a:phs
endif
let phs = xpt#snip#EvalPresetFilters(a:render.rctx,phs,{ 'outerIndent':a:render.outerIndent, 'offset':a:render.offset, 'variables':{ '$_xN_OUTER_INDENT':a:render.outerIndent, '$_xOUTER_INDENT':repeat( ' ', a:render.outerIndent ), '$_xN_OFFSET':a:render.offset, '$_xOFFSET':repeat( ' ', a:render.offset ), } })
for ph in phs
if type(ph) == type({})
call xpt#rctx#AddDefaultPHFilters(a:render.rctx,ph)
endif
unlet ph
endfor
let s:buildingSeqNr += 1
for ph in phs
if type( ph ) == type( '' )
call xpt#render#AppendText(a:render,ph)
else
call s:BuildPH(a:render,ph)
endif
unlet ph
endfor
call remove(s:renderStack,-1)
endfunction
fun! xpt#render#AppendFilter(render,flt)
call xpt#flt#Eval(a:flt,a:render.rctx.ftScope.funcs, { 'nIndAdd' : a:render.relIndent } )
let text = get( a:flt.rst, 'text', '' )
call xpt#render#AppendText(a:render,text)
endfunction
fun! xpt#render#AppendText(render,text)
if a:text =~ '\V\n'
call xpt#render#AppendMultiLine(a:render,a:text,a:render.outerIndent)
else
let a:render.rst[-1] .= a:text
let a:render.pos[1] += len(a:text)
endif
endfunction
fun! xpt#render#AppendMultiLine(render,text,nIndent)
if a:nIndent != 0
let text = xpt#util#AddIndent(a:text,a:nIndent)
else
let text = a:text
endif
let textLines = split( text, "\n", 1 )
let a:render.rst[-1] .= textLines[0]
call extend(a:render.rst,textLines[1 :])
call xpt#render#UpdatePosInfo(a:render)
endfunction
fun! xpt#render#UpdatePosInfo(render)
let a:render.pos = [a:render.start[0] + len(a:render.rst) - 1, len(a:render.rst[-1]) + 1]
let iNonspace = match( a:render.rst[ -1 ], '\v[^ ]' )
let a:render.relIndent = iNonspace == -1 ? XPT#Strlen(a:render.rst[-1]) : iNonspace
endfunction
fun! s:BuildPH(render,ph)
let [rctx,ph] = [a:render.rctx,a:ph]
let g = xpt#rctx#GetGroup(rctx,ph.name)
if g.sessid == rctx.buildingSessionID
call xpt#group#InsertPH(g,a:ph,len(g.placeHolders))
else
call xpt#group#InsertPH(g,a:ph,0)
endif
call s:CreatePHMarkNames(rctx,g,ph)
call add(a:render.marks,[ph.mark.start, copy( a:render.pos ), 'l' ] )
if has_key( ph, 'isKey' )
call s:Append( a:render, ph, 'leftEdge' )
call add(a:render.marks,[ph.editMark.start, copy( a:render.pos ), 'l' ] )
call xpt#render#AppendText( a:render, ph[ 'displayText' ] )
call add(a:render.marks,[ph.editMark.end, copy( a:render.pos ), 'r' ] )
call s:Append( a:render, ph, 'rightEdge' )
else
call xpt#render#AppendText( a:render, ph[ 'displayText' ] )
endif
call add(a:render.marks,[ph.mark.end, copy( a:render.pos ), 'r' ] )
endfunction
fun! s:CreatePHMarkNames(rctx,g,ph)
if a:ph.name == ''
let markName = '``' . s:anonymouseIndex
let s:anonymouseIndex += 1
else
let markName = a:ph.name . s:buildingSeqNr . '`' . ( has_key( a:ph, 'isKey' ) ? 'k' : ( len( a:g.placeHolders ) - 1 ) )
endif
let markPre = a:rctx.markNamePre . markName . '`'
call extend(a:ph, { 'mark' : { 'start' : markPre . 'os', 'end':markPre . 'oe', }, }, 'force' )
if has_key( a:ph, 'isKey' )
call extend(a:ph, { 'editMark' : { 'start' : markPre . 'is', 'end':markPre . 'ie', }, }, 'force' )
let a:ph.innerMarks = a:ph.editMark
else
let a:ph.innerMarks = a:ph.mark
endif
endfunction
fun! s:Append(render,ph,key)
if has_key(a:ph,a:key)
call xpt#render#AppendText(a:render,a:ph[a:key])
endif
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,47 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
fun! xpt#settingswitch#New()
return { 'settings':[], 'saved':[], }
endfunction
fun! xpt#settingswitch#Add(inst,key,value)
if a:inst.saved != []
throw "settings are already saved and can not be added again"
endif
let a:inst.settings += [[a:key,a:value]]
endfunction
fun! xpt#settingswitch#AddList(inst,...)
if a:inst.saved != []
throw "settings are already saved and can not be added again"
endif
for item in a:000
let a:inst.settings += [[item[0],item[1]]]
endfor
endfunction
fun! xpt#settingswitch#Switch(inst)
if a:inst.saved != []
return
endif
for [key,value] in a:inst.settings
call insert(a:inst.saved,[key,eval(key)])
if type( value ) == type( '' )
exe 'let ' key '=' string( value )
elseif type(value) == type({})
if has_key( value, 'exe' )
exe value.exe
endif
endif
unlet value
endfor
endfunction
fun! xpt#settingswitch#Restore(inst)
if a:inst.saved == []
return
endif
for setting in a:inst.saved
exe 'let '. setting[0] . '=' . string( setting[1] )
endfor
let a:inst.saved = []
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,236 @@
if exists( "g:__AL_XPT_SNIP_VIM__" ) && g:__AL_XPT_SNIP_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_SNIP_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
let s:log = xpt#debug#Logger( 'debug' )
exe XPT#importConst
fun! xpt#snip#DefExt(name,setting,lines)
call xpt#st#Extend(a:setting)
call XPTdefineSnippet(a:name,a:setting,a:lines)
endfunction
fun! xpt#snip#New(name,ftScope,snipText,prio,setting,patterns)
return { 'name':a:name, 'compiled':0, 'parsed':0, 'ftScope':a:ftScope, 'rawSnipText':a:snipText, 'snipText':a:snipText, 'priority':a:prio, 'setting':a:setting, 'ptn':a:patterns, }
endfunction
fun! xpt#snip#NewSlave(master,snipText)
return xpt#snip#New( '', a:master.ftScope, a:snipText, 0, a:master.setting,a:master.ptn)
endfunction
fun! xpt#snip#CompileAndParse(so)
if !a:so.parsed
if !a:so.compiled
call xpt#snip#Compile(a:so)
endif
call xpt#snip#Parse(a:so)
endif
endfunction
fun! xpt#snip#Compile(so)
call xpt#ftsc#Init(a:so.ftScope)
if a:so.snipText == ''
let a:so.compiledSnip = [ '' ]
return
endif
let rawLines = s:SplitLines(a:so)
let nIndent = len( matchstr( rawLines[0][0], '\V\^\s\*' ) )
let [l,r] = [a:so.ptn.l,a:so.ptn.r]
let [i,j,nlines,nitems] = [0,0,len(rawLines),len(rawLines[0])]
let [ st, linesCompiled ] = [ 'LeftEdge', [] ]
let buf = [ { 'nIndent' : 0, 'text' : '' } ]
while 1
let elt = rawLines[i][j]
let firstChar = matchstr( elt, '\v.' )
if firstChar == l
if st == 'LeftEdge'
let st = 'Name'
let texts = deepcopy(buf)
call map( texts, 'v:val.text' )
call extend(linesCompiled,texts)
let buf = [ { 'nIndent' : nIndent, 'text' : elt[ 1 : ] } ]
elseif st == 'Name'
call add( buf, { 'nIndent' : nIndent, 'text' : elt[ 1 : ] } )
elseif st == 'Filter'
let st = 'LeftEdge'
let followingText = buf[-1].text[1 :]
let buf[-1].text = buf[-1].text[0 : 0]
call add(linesCompiled,xpt#ph#New(a:so,buf))
let buf = [ { 'nIndent' : nIndent, 'text' : followingText } ]
continue
endif
elseif firstChar == r
if st == 'Name'
let st = 'Filter'
continue
elseif st == 'Filter'
call add( buf, { 'nIndent' : nIndent, 'text' : elt } )
endif
else
let buf[-1].text .= rawLines[i][j]
endif
let j += 1
if j >= nitems
let [i,j] = [i + 1,0]
if i >= nlines
break
endif
let buf[ -1 ].text .= "\n"
let [nIndent,nitems] = [ len( matchstr( rawLines[ i ][ 0 ], '\V\^\s\*' ) ), len( rawLines[ i ] ) ]
endif
endwhile
call filter( linesCompiled, 'len(v:val) > 0' )
let rst = []
for e in linesCompiled
call add(rst, type(e) == type({}) ? e : xpt#util#UnescapeChar(e,a:so.ptn.lr))
unlet e
endfor
let a:so.compiledSnip = rst
let a:so.compiled = 1
endfunction
fun! xpt#snip#TextToPlaceholders(text,ptn)
let [l,r] = [a:ptn.l,a:ptn.r]
let lr = l . r
let toks = xpt#snip#Tokenize(a:text, a:ptn) + ["", "", ""]
let elts = []
let buf = []
let i = -1
while i < len(toks) - 1
let i += 1
let tok = toks[i]
let chr = tok[0]
if chr != l && chr != r
if tok != ""
call add(elts, {'text': xpt#util#UnescapeChar(tok, lr)})
endif
continue
endif
if chr == l
call add(buf, {'text': xpt#util#UnescapeChar(tok[1:], lr)})
continue
endif
let ph = s:EltsToPh(buf)
call add(elts,ph)
let buf = []
if toks[i+1][0] == l
continue
endif
if toks[i + 1] == r
let [flt, iFilterEnd] = [{'text': ''}, i + 1]
else
if toks[i + 2] == r
let [flt, iFilterEnd] = [{'text': xpt#util#UnescapeChar(toks[i + 1], lr)}, i + 2]
else
continue
endif
end
if toks[iFilterEnd + 1] == r
let ph.postFilter = flt
let i = iFilterEnd + 1
else
let ph.liveFilter = flt
let i = iFilterEnd
endif
endwhile
return elts
endfunction
fun! s:EltsToPh(buf)
let buf = a:buf
if len(buf) == 0
throw 'xpt#snip#Unexpected: ' . r
elseif len(buf) == 1
let ph = { 'name': buf[0] }
elseif len(buf) == 2
let ph = { 'leftEdge': buf[0], 'name': buf[1] }
elseif len(buf) == 3
let ph = { 'leftEdge': buf[0], 'name': buf[1], 'rightEdge': buf[2] }
else
throw 'xpt#snip#TooMany: ' . string(buf)
endif
return ph
endfunction
fun! xpt#snip#Parse(so)
let a:so.parsedSnip = a:so.compiledSnip
let a:so.parsedSnip = xpt#snip#ReplacePH(a:so,a:so.setting.replacements)
let a:so.parsedSnip = xpt#snip#EvalInstantFilters(a:so)
let a:so.parsedSnip = xpt#snip#PostQuote(a:so)
let a:so.parsedSnip = xpt#snip#Repetition(a:so)
let a:so.parsed = 1
endfunction
fun! xpt#snip#ReplacePH(so,repls)
let phs = xpt#phfilter#Filter(a:so, 'xpt#phfilter#ReplacePH', { 'replParams' : a:repls } )
return phs
endfunction
fun! xpt#snip#EvalInstantFilters(so)
let phs = xpt#phfilter#Filter(a:so, 'xpt#phfilter#EvalInstantFilters', {'skip' : a:so.ptn.item_func . '\|$_x\w', 'forceNotSkip' : s:ptnPreEvalFunc } )
return phs
endfunction
fun! xpt#snip#PostQuote(so)
let pqContext = { 'pqStack' : [ [] ] }
let pqContext.rstPHs = pqContext.pqStack[0]
let phs = xpt#phfilter#Filter(a:so, 'xpt#phfilter#PostQuote', pqContext )
return phs
endfunction
fun! xpt#snip#Repetition(so)
let repContext = { 'repStack' : [ [] ], 'repHeads' : {} }
let repContext.rstPHs = repContext.repStack[0]
let phs = xpt#phfilter#Filter(a:so, 'xpt#phfilter#Repetition', repContext )
return phs
endfunction
fun! xpt#snip#EvalPresetFilters(rctx,phs,ctx)
let ctx = { 'rctx':a:rctx, 'srcPHs':a:phs, 'snipSetting':a:rctx.snipSetting, 'phEvalContext':a:ctx, }
let phs = xpt#phfilter#Filter(a:rctx.snipObject, 'xpt#phfilter#EvalPresetFilters', ctx )
return phs
endfunction
fun! xpt#snip#DumbCursorInPlace(so,phs)
for ph in a:phs
if type(ph) == type({}) && ph.name is 'cursor'
let ph.name = ''
let ph.displayText = ph.name
endif
unlet ph
endfor
endfunction
fun! xpt#snip#ParseInclusionStatement(so,statement)
let phptns = a:so.ptn
let ptn = '\V\^\[^(]\{-}('
let statement = a:statement
if statement =~ ptn && statement[ -1 : -1 ] == ')'
let name = matchstr(statement,ptn)[: -2]
let paramStr = statement[len(name) + 1 : -2]
let paramStr = xpt#util#UnescapeChar(paramStr,phptns.lr)
let params = {}
try
let params = eval(paramStr)
catch /.*/
XPT#info( 'XPT: Invalid parameter: ' . string( paramStr ) . ' Error=' . v:exception )
endtry
return [name,params]
else
return [statement,{}]
endif
endfunction
fun! s:SplitLines(so)
let delimiter = '\V\ze' . a:so.ptn.lft . '\|\ze' . a:so.ptn.rt
let lines = split( a:so.snipText, "\n", 1 )
call map( lines, 'split(v:val, delimiter, 1)' )
let lines[-1] += [a:so.ptn.l]
return lines
endfunction
fun! xpt#snip#Tokenize(text,ptn)
let delimiter = '\V\ze' . a:ptn.lft . '\|\ze' . a:ptn.rt
let toks = split(a:text,delimiter,0)
if len(toks) == 0
return ['']
end
let rst = []
for tok in toks
if tok == a:ptn.r
call add(rst,tok)
elseif tok[0] == a:ptn.r
call extend(rst,[a:ptn.r,tok[1:]])
else
call add(rst,tok)
end
endfor
return rst
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,26 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
exec XPT#importConst
fun! xpt#snipfile#New(filename)
let r = { 'filename':a:filename, 'ptn':xpt#snipfile#GenPattern( {'l':'`', 'r':'^'} ), 'priority':xpt#priority#Get('default'), 'filetype':'', 'inheritFT':0, }
return r
endfunction
fun! xpt#snipfile#Push()
let x = b:xptemplateData
let x.snipFileScopeStack += [x.snipFileScope]
unlet x.snipFileScope
endfunction
fun! xpt#snipfile#Pop()
let x = b:xptemplateData
if len(x.snipFileScopeStack) > 0
let x.snipFileScope = remove(x.snipFileScopeStack,-1)
else
throw "snipFileScopeStack is empty"
endif
endfunction
fun! xpt#snipfile#GenPattern(marks)
return { 'l':a:marks.l, 'r':a:marks.r, 'lr':a:marks.l . a:marks.r, 'lft':'\V' . s:nonEscaped . a:marks.l, 'rt':'\V' . s:nonEscaped . a:marks.r, 'item_var':'\V' . '$\w\+', 'item_qvar':'\V' . '{$\w\+}', 'item_func':'\V' . '\w\+(\.\*)', 'item_qfunc':'\V' . '{\w\+(\.\*)}', 'itemContent':'\V' . '\_.\{-}', 'item':'\V' . s:nonEscaped . a:marks.l . '\%(' . '\_.\{-}' . '\)' . s:nonEscaped . a:marks.r, }
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,465 @@
if exists( "g:__AL_XPT_SNIPFUNC_VIM__" ) && g:__AL_XPT_SNIPFUNC_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_SNIPFUNC_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
let s:log = xpt#debug#Logger( 'debug' )
fun! xpt#snipfunc#Extend(container)
call extend( a:container, s:f, 'keep' )
endfunction
let s:f = {}
fun! s:f.Pre(a)
return a:a
endfunction
fun! s:f.SnipObject()
return self.phFilterContext isnot 0 ? self.phFilterContext.snipObject : self.renderContext.snipObject
endfunction
fun! s:f.PHs(snipText)
let so = self.SnipObject()
let slave = xpt#snip#NewSlave(so,a:snipText)
call xpt#snip#CompileAndParse(slave)
return slave.parsedSnip
endfunction
fun! s:f.Inline(snipText)
return { 'action' : 'embed', 'phs' : self.PHs( a:snipText ) }
endfunction
fun! s:f.Inc(targetName,keepCursor,params)
let so = self.SnipObject()
let snipDict = so.ftScope.allTemplates
if has_key(snipDict,a:targetName)
let tsnip = snipDict[a:targetName]
call xpt#snip#CompileAndParse(tsnip)
let phs = xpt#phfilter#Filter( tsnip, 'xpt#phfilter#ReplacePH', { 'replParams' : a:params } )
if !a:keepCursor
call xpt#snip#DumbCursorInPlace(tsnip,phs)
endif
call xpt#st#Merge(so.setting,tsnip.setting)
return { 'action' : 'embed', 'nIndent' : 0, 'phs' : phs }
else
return 0
endif
endfunction
fun! s:f.GetDict(...)
return
endfunction
fun! s:f.GetVar(name)
if a:name =~# '\V\^$_x'
let n = a:name[1 :]
if has_key(self,n)
return self[n]()
endif
endif
let varScopes = []
if has_key( self, 'evalContext' )
call add(varScopes,self.evalContext.variables)
endif
if has_key( self, 'renderContext' )
call add( varScopes, get( self.renderContext.snipSetting, 'variables', {} ) )
endif
call add(varScopes,self)
for sc in varScopes
let val = get(sc,a:name)
if val isnot 0
return val
endif
endfor
return a:name
endfunction
fun! s:f._xSnipName()
return self.renderContext.snipObject.name
endfunction
fun! s:f.EmbedWrappedText()
let wrapData = self.renderContext.userWrapped
if !has_key( wrapData, 'text' )
return 0
endif
let ph = self.phFilterContext.ph
if has_key( ph, 'isKey' )
let n = len(wrapData.lines)
let nIndent = self.phFilterContext.phEvalContext.pos[1] - self.phFilterContext.phEvalContext.nIndAdd
if self.phFilterContext.phEvalContext.pos[0] == 0
let nIndent += self.phFilterContext.phEvalContext.offset
endif
let sep = "\n"
let ph = extend(deepcopy(ph),{ 'name':'', 'value':1, }, 'force' )
unlet ph.isKey
let newPHs = []
let i = 0
while i < n
let newph = extend(deepcopy(ph),{ 'displayText':wrapData.lines[ i ], }, 'force' )
call extend(newPHs,[newph,sep])
let i += 1
endwhile
call remove(newPHs,-1)
return { 'action' : 'embed', 'nIndent' : nIndent, 'phs' : newPHs }
else
return { 'nIndent' : wrapData.indent, 'text':wrapData.text }
endif
endfunction
fun! s:f.WrapAlignAfter(min)
let userWrapped = self.renderContext.userWrapped
let n = max([a:min,userWrapped.max]) - len(userWrapped.curline)
return repeat( ' ', n )
endfunction
fun! s:f.WrapAlignBefore(min)
let userWrapped = self.renderContext.userWrapped
let n = max([a:min,userWrapped.max]) - len(userWrapped.lines[0])
return repeat( ' ', n )
endfunction
fun! s:f.Item()
return get( self.renderContext, 'item', {} )
endfunction
fun! s:f.ItemName()
return get( self.Item(), 'name', '' )
endfunction
fun! s:f.ItemFullname()
return get( self.Item(), 'fullname', '')
endfunction
fun! s:f.ItemValue() dict
return get( self.evalContext, 'userInput', '' )
endfunction
fun! s:f.PrevItem(n)
let hist = get( self.renderContext, 'history', [] )
return get(hist,a:n,{})
endfunction
fun! s:f.ItemInitValue()
return get( self.Item(), 'initValue', '' )
endfunction
fun! s:f.ItemInitValueWithEdge()
let [l,r] = self.ItemEdges()
return l . self.ItemInitValue() . r
endfunction
fun! s:f.ItemValueStripped(...)
let ptn = a:0 == 0 || a:1 =~ 'lr' ? '\V\^\s\*\|\s\*\$' : ( a:1 == 'l' ? '\V\^\s\*' : '\V\s\*\$' )
return substitute( self.ItemValue(), ptn, '', 'g' )
endfunction
fun! s:f.ItemPos()
return XPMposStartEnd(self.renderContext.leadingPlaceHolder.mark)
endfunction
fun! s:f.Vmatch(...)
let v = self.V()
for reg in a:000
if match(v,reg) != -1
return 1
endif
endfor
return 0
endfunction
fun! s:f.VMS(reg)
return matchstr(self.V(),a:reg)
endfunction
fun! s:f.ItemStrippedValue()
let v = self.V()
let [edgeLeft,edgeRight] = self.ItemEdges()
let v = substitute( v, '\V\^' . edgeLeft, '', '' )
let v = substitute( v, '\V' . edgeRight . '\$', '', '' )
return v
endfunction
fun! s:f.Phase() dict
return get( self.renderContext, 'phase', '' )
endfunction
fun! s:f.E(s)
return expand(a:s)
endfunction
fun! s:f.Context()
return self.renderContext
endfunction
fun! s:f.S(str,ptn,rep,...)
let flg = a:0 >= 1 ? a:1 : 'g'
return substitute(a:str,a:ptn,a:rep,flg)
endfunction
fun! s:f.SubstituteWithValue(ptn,rep,...)
let flg = a:0 >= 1 ? a:1 : 'g'
return substitute(self.V(),a:ptn,a:rep,flg)
endfunction
fun! s:f.HasStep(name)
let namedStep = get( self.renderContext, 'namedStep', {} )
return has_key(namedStep,a:name)
endfunction
fun! s:f.Reference(name)
let namedStep = get( self.renderContext, 'namedStep', {} )
return get( namedStep, a:name, '' )
endfunction
fun! s:f.Snippet(name)
return get( self.renderContext.ftScope.allTemplates, a:name, { 'tmpl' : '' } )[ 'tmpl' ]
endfunction
fun! s:f.Void(...)
return ""
endfunction
fun! s:f.Echo(...)
if a:0 > 0
return a:1
else
return ''
endif
endfunction
fun! s:f.EchoIf(isTrue,...)
if a:isTrue
return join( a:000, '' )
else
return self.V()
endif
endfunction
fun! s:f.EchoIfEq(expected,...)
if self.V() ==# a:expected
return join( a:000, '' )
else
return self.V()
endif
endfunction
fun! s:f.EchoIfNoChange(...)
if self.V0() ==# self.ItemName()
return join( a:000, '' )
else
return self.V()
endif
endfunction
fun! s:f.Commentize(text)
if has_key( self, '$CL' )
return self[ '$CL' ] . ' ' . a:text . ' ' . self[ '$CR' ]
elseif has_key( self, '$CS' )
return self[ '$CS' ] . ' ' . a:text
endif
return a:text
endfunction
fun! s:f.VoidLine()
return self.Commentize( 'void' )
endfunction
fun! s:f.Empty()
return self.ItemValue() == ''
endfunction
fun! s:f.IsChanged()
let initFull = self.ItemInitValueWithEdge()
let v = self.ItemValue()
return initFull !=# v
endfunction
fun! s:f.EmbedPHs(phsID)
let snipObject = self.renderContext.snipObject
return { 'action' : 'embed', 'phs':xpt#ftsc#GetPHPieces( snipObject.ftScope, a:phsID ) }
endfunction
fun! s:f.Build(...)
return { 'action' : 'build', 'text' : join( a:000, '' ) }
endfunction
fun! s:f.BuildIfChanged(...)
let v = substitute( self.V(), "\\V\n\\|\\s", '', 'g')
let fn = substitute( self.ItemInitValueWithEdge(), "\\V\n\\|\\s", '', 'g')
if v ==# fn || v == ''
return ''
else
return { 'action' : 'build', 'text' : join( a:000, '' ) }
endif
endfunction
fun! s:f.BuildIfNoChange(...)
let v = substitute( self.V(), "\\V\n\\|\\s", '', 'g')
let fn = substitute( self.ItemInitValueWithEdge(), "\\V\n\\|\\s", '', 'g')
if v ==# fn
return { 'action' : 'build', 'text' : join( a:000, '' ) }
else
return 0
endif
endfunction
fun! s:f.Trigger(name)
return {'action' : 'expandTmpl', 'tmplName' : a:name}
endfunction
fun! s:f.Finish(...)
return self.FinishPH( a:0 > 0 ? { 'text' : a:1 } : {} )
endfunction
fun! s:f.FinishOuter(...)
return self.FinishPH(a:0 > 0 ? { 'text' : a:1, 'marks' : 'mark' } : { 'marks' : 'mark' } )
endfunction
fun! s:f.FinishPH(opt)
let opt = a:opt
if empty(self.renderContext.groupList)
let o = { 'action' : g:XPTact.finishPH }
call extend( o, opt, 'keep' )
return o
else
return get( opt, 'text', 0 )
endif
endfunction
fun! s:f.Embed(snippetText)
return { 'action' : g:XPTact.embed, 'text' : a:snippetText }
endfunction
fun! s:f.Next(...)
let rst = { 'action' : 'next' }
if a:0 > 0
let phs = deepcopy(a:000)
call filter( phs, 'type(v:val)==' . type( '' ) )
if len(phs) < len(a:000)
let rst.phs = a:000
else
let text = join( a:000, '' )
let so = self.SnipObject()
if match(text,so.ptn.lft) >= 0
let rst.phs = self.PHs(text)
else
let rst.text = text
endif
endif
endif
return rst
endfunction
fun! s:f.Remove()
return { 'action' : 'remove' }
endfunction
fun! s:f.Choose(lst,...)
let val = { 'action' : 'pum', 'pum' : a:lst }
if a:0 == 1
let val.acceptEmpty = a:1 != 0
endif
return val
endfunction
fun! s:f.ChooseStr(...)
return copy(a:000)
endfunction
fun! s:f.Complete(key,...)
let val = { 'action' : 'complete', 'pum' : a:key }
if a:0 == 1
let val.acceptEmpty = a:1 != 0
endif
return val
endfunction
fun! s:f.xptFinishTemplateWith(postType) dict
endfunction
fun! s:f.xptFinishItemWith(postType) dict
endfunction
fun! s:f.UnescapeMarks(string) dict
let patterns = self.renderContext.snipObject.ptn
let charToEscape = '\(\[' . patterns.l . patterns.r . ']\)'
let r = substitute( a:string, '\v(\\*)\1\\?\V' . charToEscape, '\1\2', 'g')
return r
endfunction
fun! s:f.headerSymbol(...)
let h = expand('%:t')
let h = substitute(h, '\.', '_', 'g') " replace . with _
let h = substitute(h, '.', '\U\0', 'g') " make all characters upper case
return '__'.h.'__'
endfunction
fun! s:f.date(...)
return strftime( self.GetVar( '$DATE_FMT' ) )
endfunction
fun! s:f.datetime(...)
return strftime( self.GetVar( '$DATETIME_FMT' ) )
endfunction
fun! s:f.time(...)
return strftime( self.GetVar( '$TIME_FMT' ) )
endfunction
fun! s:f.file(...)
return expand("%:t")
endfunction
fun! s:f.fileRoot(...)
return expand("%:t:r")
endfunction
fun! s:f.fileExt(...)
return expand("%:t:e")
endfunction
fun! s:f.path(...)
return expand("%:p")
endfunction
fun! s:f.UpperCase(v)
return substitute(a:v, '.', '\u&', 'g')
endfunction
fun! s:f.LowerCase(v)
return substitute(a:v, '.', '\l&', 'g')
endfunction
fun! s:f.ItemEdges()
let leader = get( self.renderContext, 'leadingPlaceHolder', {} )
if has_key( leader, 'leftEdge' )
return [leader.leftEdge,leader.rightEdge]
else
return [ '', '' ]
endif
endfunction
fun! s:f.ItemCreate(name,edges,filters)
let [ml,mr] = XPTmark()
let item = ml . a:name
if has_key( a:edges, 'left' )
let item = ml . a:edges.left . item
endif
if has_key( a:edges, 'right' )
let item .= ml . a:edges.right
endif
let item .= mr
if has_key( a:filters, 'post' )
let item .= a:filters.post . mr . mr
endif
return item
endfunction
fun! s:f.ExpandIfNotEmpty(sep,item,...)
let v = self.V()
let [ml,mr] = XPTmark()
if a:0 != 0
let r = a:1
else
let r = ''
endif
let t = ( v == '' || v =~ '\V' . a:item ) ? '' : self.Build(v . ml . a:sep . ml . a:item . ml . r . mr . 'ExpandIfNotEmpty(' . string( a:sep ) . ', ' . string( a:item ) . ')' . mr . mr )
return t
endfunction
fun! s:f.ExpandInsideEdge(newLeftEdge,newRightEdge)
let v = self.V()
let fullname = self.ItemFullname()
let [el,er] = self.ItemEdges()
if v ==# fullname || v == ''
return ''
endif
return substitute( v, '\V' . er . '\$' , '' , '' ) . self.ItemCreate( self.ItemName(), { 'left' : a:newLeftEdge, 'right' : a:newRightEdge }, {} ) . er
endfunction
fun! s:f.NIndent()
return &shiftwidth
endfunction
fun! s:f.ResetIndent(nIndent,text)
return { 'action' : 'resetIndent', 'resetIndent':1, 'nIndent' : a:nIndent, 'text' : a:text }
endfunction
fun! s:f.CmplQuoter_pre() dict
if !g:xptemplate_brace_complete
return ''
endif
let v = substitute( self.ItemStrippedValue(), '\V\^\s\*', '', '' )
let first = matchstr( v, '\V\^\[''"]' )
if first == ''
return ''
endif
let v = substitute( v, '\V\[^' . first . ']', '', 'g' )
if v == first
return first
else
return ''
endif
endfunction
fun! s:f.AutoCmpl(keepInPost,list,...)
if !a:keepInPost && self.Phase() == 'post'
return ''
endif
if type(a:list) == type([])
let list = a:list
else
let list = [a:list] + a:000
endif
let v = self.V0()
if v == ''
return ''
endif
for word in list
if word =~ '\V\^' . v
return word[len(v) :]
endif
endfor
return ''
endfunction
let s:f.Edges = s:f.ItemEdges
let s:f.UE = s:f.UnescapeMarks
let s:f.VOID = s:f.Void
let s:f.R = s:f.Reference
let s:f.SV = s:f.SubstituteWithValue
let s:f.C = s:f.Context
let s:f.V0 = s:f.ItemStrippedValue
let s:f.IVE = s:f.ItemInitValueWithEdge
let s:f.VS = s:f.ItemValueStripped
let s:f.IV = s:f.ItemInitValue
let s:f.V = s:f.ItemValue
let s:f.NN = s:f.ItemFullname
let s:f.N = s:f.ItemName
let &cpo = s:oldcpo

View file

@ -0,0 +1,29 @@
exec xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:f = xpt#snipfunction#funcs
let s:num_keys = { "nIndent" : 1, "parseIndent" : 1, }
let s:action_names = { "build" : 1, "pum" : 1, "text" : 1, "next" : 1, "remove" : 1, "finishTemplate" : 1, }
fun! s:f.Action(...)
let rst = {}
for kvs in a:000
if type(kvs) == type({})
call extend(rst, kvs, 'force')
continue
endif
for kv in split(kvs, ' ', 0)
if has_key(s:action_names,kv)
let rst.action = kv
else
let [k, v] = split(kv, '=', 1)
if has_key(s:num_keys,k)
let rst[k] = v + 0
else
let rst[k] = v
endif
endif
endfor
endfor
return rst
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,69 @@
if exists( "g:__AL_XPT_EVALSUPPORT_f67523jhrk" ) && g:__AL_XPT_EVALSUPPORT_f67523jhrk >= 1
finish
endif
let g:__AL_XPT_EVALSUPPORT_f67523jhrk = 1
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:f = xpt#snipfunction#funcs
fun! s:f.GetVar(name)
if a:name =~# '\V\^$_x'
let n = a:name[1 :]
return self.Call(n,[])
endif
let closures = self._ctx.closures
let i = len(closures)
while i > 0
let i = i - 1
let c = closures[i]
let v = get(c,a:name,0)
if v isnot 0
return v
endif
endwhile
return ''
endfunction
fun! s:f.Call(name,args)
let F = get(self,a:name,0)
if type(F) == type(function('tr'))
return call(F,a:args,self)
else
return call(function(a:name),a:args)
endif
endfunction
fun! s:f.Concat(...)
let lst = a:000
if len(lst) == 0
return ''
endif
let rst = {}
for e in lst
if type(e) == type(0)
if e == 0
return 0
else
let elt = string(e)
endif
else
let elt = e
endif
if type(elt) == type('')
let rst.text = get(rst, 'text', '') . elt
elseif type(elt) == type([])
let rst.action = get(rst, 'action', 'pum')
let rst.pum = get(rst, 'pum', elt)
else
if has_key(rst, 'text') && has_key(elt, 'text')
let rst.text .= elt.text
endif
call extend(rst, elt, 'keep')
endif
unlet e
unlet elt
endfor
let ks = keys(rst)
if len(ks) == 1 && ks[0] == 'text'
return rst.text
end
return rst
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,10 @@
if exists( "g:__AL_XPT_EVAL_y732hj43k__" ) && g:__AL_XPT_EVAL_y732hj43k__ >= XPT#ver
finish
endif
let g:__AL_XPT_EVAL_y732hj43k__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:f = {}
let xpt#snipfunction#funcs = s:f
runtime! autoload/xpt/snipfuncs/*
let &cpo = s:oldcpo

View file

@ -0,0 +1,16 @@
if exists( "g:__AL_XPT_SNIPLINE_VIM__" ) && g:__AL_XPT_SNIPLINE_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_SNIPLINE_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
fun! xpt#snipline#New(elts)
if len(a:elts) == 0 || type(a:elts[0]) == type({})
let nIndent = 0
else
let nIndent = len( matchstr( a:elts[ 0 ], '\V\^ \*' ) )
endif
return { 'nIndent' : nIndent, 'elts' : a:elts }
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,113 @@
if exists( "g:__AL_XPT_ST_VIM__" ) && g:__AL_XPT_ST_VIM__ >= XPT#ver
finish
endif
let g:__AL_XPT_ST_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
exe XPT#importConst
let s:proto = { 'hidden':0, 'variables':{}, 'preValues':{}, 'onfocusFilters':{}, 'mappings':{}, 'liveFilters':{}, 'postFilters':{}, 'replacements':{}, 'postQuoter':{}, 'comeFirst':[], 'comeLast':[], }
let s:protoDefault = { 'preValues':{ 'cursor' : xpt#flt#New( 0, '$CURSOR_PH' ) }, 'onfocusFilters':{ 'cursor' : xpt#flt#New( 0, 'FinishPH({"text":""})' ) }, 'postQuoter':{ 'start' : '{{', 'end' : '}}' }, }
fun! xpt#st#New()
return deepcopy(s:proto)
endfunction
fun! xpt#st#Extend(setting)
for k in [ 'preValues', 'onfocusFilters', 'liveFilters', 'postFilters' ]
if has_key(a:setting,k)
for val in values(a:setting[k])
call xpt#flt#Extend(val)
endfor
endif
endfor
if has_key( a:setting, 'mappings' )
for phMapping in values(a:setting.mappings)
for mapFilter in values(phMapping.keys)
call xpt#flt#Extend(mapFilter)
endfor
endfor
endif
call extend( a:setting, deepcopy( s:proto ), 'keep' )
for [k,v] in items(s:protoDefault)
call extend( a:setting[ k ], deepcopy( v ), 'keep' )
endfor
endfunction
fun! xpt#st#RenderPhaseCopy(setting)
let setting = copy(a:setting)
for k in [ 'variables', 'preValues', 'onfocusFilters' , 'liveFilters', 'postFilters', 'comeFirst', 'comeLast' ]
let setting[k] = copy(setting[k])
endfor
let x = b:xptemplateData
if x.currentExt != {}
let setting.variables[ '$EXT' ] = x.currentExt.ext
let x.currentExt = {}
endif
return setting
endfunction
fun! xpt#st#What()
endfunction
fun! xpt#st#Simplify(setting)
call filter( a:setting, '!has_key(s:proto,v:key) || v:val!=s:proto[v:key]' )
endfunction
fun! xpt#st#Merge(setting,fromSettings)
let a:setting.comeFirst += a:fromSettings.comeFirst
let a:setting.comeLast = a:fromSettings.comeLast + a:setting.comeLast
call xpt#st#InitItemOrderList(a:setting)
call extend( a:setting.preValues, a:fromSettings.preValues, 'keep' )
call extend( a:setting.onfocusFilters, a:fromSettings.onfocusFilters, 'keep' )
call extend( a:setting.postFilters, a:fromSettings.postFilters, 'keep' )
call extend( a:setting.variables, a:fromSettings.variables, 'keep' )
for key in keys(a:fromSettings.mappings)
if !has_key(a:setting.mappings,key)
let a:setting.mappings[key] = { 'saver' : xpt#msvr#New( 1 ), 'keys' : {} }
endif
for keystroke in keys(a:fromSettings.mappings[key].keys)
let a:setting.mappings[key].keys[keystroke] = a:fromSettings.mappings[key].keys[keystroke]
call xpt#msvr#Add( a:setting.mappings[ key ].saver, 'i', keystroke )
endfor
endfor
endfunction
fun! xpt#st#Parse(setting,snipObject)
let st = a:setting
if get( st, 'wraponly' ) isnot 0
call extend( st, { 'iswrap' : 1, 'iswraponly' : 1, 'wrapPH' : st.wraponly }, 'force' )
elseif get( st, 'wrap' ) isnot 0
call extend( st, { 'iswrap' : 1, 'iswraponly' : 0, 'wrapPH' : st.wrap }, 'force' )
else
call extend( st, { 'iswrap' : 0, 'iswraponly' : 0 }, 'force' )
endif
if st.iswrap && st.wrapPH is 1
let st.wrapPH = 'cursor'
endif
if has_key(st, 'rawHint')
if st.rawHint =~ s:regEval
let x = b:xptemplateData
let x.renderContext.snipObject = a:snipObject
let st.hint = xpt#eval#Eval(st.rawHint, x.filetypes[x.snipFileScope.filetype].funcs, { 'variables' : st.variables } )
else
let st.hint = xpt#util#UnescapeChar(st.rawHint,s:nonsafe)
endif
endif
call xpt#st#ParsePostQuoter(st)
if has_key( st, 'extension' )
let ext = st.extension
let a:snipObject.ftScope.extensionTable[ext] = get(a:snipObject.ftScope.extensionTable,ext,[])
let a:snipObject.ftScope.extensionTable[ext] += [a:snipObject.name]
endif
endfunction
fun! xpt#st#ParsePostQuoter(setting)
if !has_key( a:setting, 'postQuoter' ) || type(a:setting.postQuoter) == type({})
return
endif
let quoters = split( a:setting.postQuoter, ',' )
if len(quoters) < 2
throw 'postQuoter must be separated with ","! :' . a:setting.postQuoter
endif
let a:setting.postQuoter = { 'start' : quoters[0], 'end' : quoters[1] }
endfunction
fun! xpt#st#InitItemOrderList(setting)
call filter( a:setting.comeLast, 'v:val!="cursor"' )
call add( a:setting.comeLast, 'cursor' )
let a:setting.comeFirst = xpt#util#RemoveDuplicate(a:setting.comeFirst)
let a:setting.comeLast = xpt#util#RemoveDuplicate(a:setting.comeLast)
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,244 @@
exe xpt#once#init
let s:oldcpo = &cpo
set cpo-=< cpo+=B
let s:log = xpt#debug#Logger( 'warn' )
exe XPT#importConst
let s:charsPatternTable = {}
fun! xpt#util#Flatten(arr)
let r = []
for e in a:arr
if type(e) == 3
call extend(r,xpt#util#Flatten(e))
else
let r += [e]
endif
unlet e
endfor
return r
endfunction
fun! xpt#util#SplitWith(str,char)
let s = split( a:str, '\V' . s:nonEscaped . a:char, 1 )
return s
endfunction
fun! xpt#util#UnescapeChar(str,chars)
if a:chars == ""
return a:str
endif
if has_key(s:charsPatternTable,a:chars)
return substitute( a:str, s:charsPatternTable[ a:chars ], '\1', 'g' )
else
return substitute( a:str, s:GetUnescapeCharPattern( a:chars ), '\1', 'g' )
endif
endfunction
fun! xpt#util#DeepExtend(to,from)
for key in keys(a:from)
if type(a:from[key]) == 4
if has_key(a:to,key)
call xpt#util#DeepExtend(a:to[key],a:from[key])
else
let a:to[key] = a:from[key]
endif
elseif type(a:from[key]) == 3
if has_key(a:to,key)
call extend(a:to[key],a:from[key])
else
let a:to[key] = a:from[key]
endif
else
let a:to[key] = a:from[key]
endif
endfor
endfunction
fun! xpt#util#RemoveDuplicate(list)
let dict = {}
let newList = []
for e in a:list
if !has_key(dict,e)
call add(newList,e)
endif
let dict[e] = 1
endfor
return newList
endfunction
fun! xpt#util#ExpandTab(text,n)
if stridx( a:text, " " ) < 0
return a:text
endif
let str = "\n" . a:text
let tabspaces = repeat( ' ', a:n )
let last = ''
while str != last
let last = str
let str = substitute( str, '\n *\zs ', tabspaces, 'g' )
endwhile
return str[1 :]
endfunction
fun! xpt#util#convertSpaceToTab(text)
if ( "\n" . a:text ) !~ '\V\n ' || &expandtab
return a:text
else
let tabspaces = repeat( ' ', &tabstop )
let lines = split( a:text, '\V\n', 1 )
let newlines = []
for line in lines
let newline = join( split( line, '\V\^\%(' . tabspaces . '\)', 1 ), ' ' )
let newlines += [newline]
endfor
return join( newlines, "\n" )
endif
endfunction
fun! xpt#util#SpaceToTab(lines)
if ! &expandtab && match( a:lines, '\v^ ' ) > -1
let cmd = 'join( split( v:val, ''\v^%('' . repeat( '' '', &tabstop ) . '')'', 1 ), '' '' )'
call map(a:lines,cmd)
endif
return a:lines
endfunction
fun! xpt#util#SpaceToTabExceptFirstLine(lines)
if ! &expandtab && len( a:lines ) > 1 && match( a:lines, '\v^ ', 1 ) > -1
let line0 = a:lines[0]
let cmd = 'join( split( v:val, ''\v^%('' . repeat( '' '', &tabstop ) . '')'', 1 ), '' '' )'
call map(a:lines,cmd)
let a:lines[0] = line0
endif
return a:lines
endfunction
fun! xpt#util#AddIndent(text,nIndent)
let baseIndent = repeat( " ", a:nIndent )
return substitute(a:text, '\n', '&' . baseIndent, 'g')
endfunction
fun! xpt#util#AddIndent2(text,nIndent)
let baseIndent = repeat( " ", a:nIndent )
if type( a:text ) == type( '' )
return substitute(a:text, '\n', '&' . baseIndent, 'g')
else
call map( a:text, string( baseIndent ) . '.v:val' )
let a:text[0] = a:text[0][a:nIndent :]
return a:text
endif
endfunction
fun! xpt#util#getIndentNr(pos)
let [ln,col] = a:pos
let line = matchstr( getline( ln ), '\V\^\s\*' )
if 1
if col == 1
return 0
else
let line = line[0 : col - 1 - 1]
return virtcol([ln,len(line)])
endif
else
let line = ( col == 1 ) ? '' : line[ 0 : col - 1 - 1 ]
let tabspaces = repeat( ' ', &tabstop )
return len( substitute( line, ' ', tabspaces, 'g' ) )
endif
endfunction
fun! xpt#util#LastIndent(text)
if a:text is ''
return 0
endif
let text = split( a:text, '\V\n', 1 )[ -1 ]
return len( matchstr( text, '\V\^\s\+' ) )
endfunction
fun! xpt#util#GetPreferedIndentNr(ln)
if &indentexpr == ''
return -1
else
let indentexpr = substitute( &indentexpr, '\Vv:lnum', a:ln, '' )
try
return eval(indentexpr)
catch /.*/
return -1
endtry
endif
endfunction
fun! xpt#util#TextBetween(posList)
return join(xpt#util#LinesBetween( a:posList ), "\n")
endfunction
fun! xpt#util#TextInLine(ln,s,e)
if a:s >= a:e
return ""
endif
return getline(a:ln)[a:s - 1 : a:e - 2]
endfunction
fun! xpt#util#LinesBetween(posList)
let [s,e] = a:posList
if s[0] > e[0] || e[0] == 0
return [""]
endif
let r = getline(s[0],e[0])
let r[-1] = strpart(r[-1],0,e[1] - 1)
let r[0] = strpart(r[0],s[1] - 1)
return r
endfunction
fun! xpt#util#SynNameStack(l,c)
if exists( '*synstack' )
let ids = synstack(a:l,a:c)
if empty(ids)
return []
endif
let names = []
for id in ids
let names = names + [synIDattr(id, "name")]
endfor
return names
else
return [synIDattr( synID( a:l, a:c, 0 ), "name" )]
endif
endfunction
fun! xpt#util#NearestSynName()
let pos = [ line( "." ), col( "." ) ]
let synName = synIDattr(synID(pos[0], pos[1], 1), "name")
if synName == ''
let prevPos = searchpos( '\S', 'bWn' )
if prevPos == [0,0]
return synName
endif
let synName = synIDattr(synID(prevPos[0], prevPos[1], 1), "name")
if synName == ''
return &filetype
endif
endif
return synName
endfunction
fun! xpt#util#CharsPattern(chars,...)
let is_magic = 0
if a:0 > 0 && a:1 is 1
let is_magic = 1
endif
let esc = '\['
if is_magic
let esc = '['
endif
let pattern = esc . escape( a:chars, '\]-^' ) . ']'
return pattern
endfunction
fun! s:GetUnescapeCharPattern(chars)
let chars = substitute( a:chars, '\\', '', 'g' )
let pattern = s:unescapeHead . '\ze\[' . escape( chars, '\]-^' ) . ']'
let s:charsPatternTable[a:chars] = pattern
return pattern
endfunction
fun! xpt#util#getCmdOutput(cmd)
let l:a = ""
redir => l:a
exe a:cmd
redir END
return l:a
endfunction
fun! xpt#util#Fallback(fbs)
let fbs = a:fbs
if len(fbs) > 0
let [key,flag] = fbs[0]
call remove(fbs,0)
if flag == 'feed'
call feedkeys( key, 'mt' )
return ''
else
return key
endif
else
return ''
endif
endfunction
let &cpo = s:oldcpo