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,133 @@
if exists( "g:__DEBUG_VIM__" ) && g:__DEBUG_VIM__ >= XPT#ver
finish
endif
let g:__DEBUG_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=<
set cpo+=B
let s:globalLogLevel = 'warn'
" let s:globalLogLevel = 'debug'
com! DebugGetSID let s:sid = matchstr("<SID>", '\zs\d\+_\ze')
DebugGetSID
delc DebugGetSID
fun! CreateLogger( 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! Assert( shouldBeTrue, msg ) "{{{
if !a:shouldBeTrue
throw a:msg
end
endfunction "}}}
com! -nargs=+ Assert call Assert( <args>, <q-args> )
let s:logLevels = {
\ 'fatal' : 1,
\ 'error' : 2,
\ 'warn' : 3,
\ 'info' : 4,
\ 'log' : 5,
\ 'debug' : 6,
\ }
let s:loggerPrototype = {}
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 "}}}
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" )
if len( finddir( $HOME . '/tmp' ) ) > 0
let s:logLocation = finddir( $HOME . '/tmp' )
else
let s:logLocation = $HOME
endif
let s:logLocation .= '/vim.log'
call delete(s:logLocation)
fun! Log_core(level, ...) "{{{
" 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 "}}}
let &cpo = s:oldcpo

View file

@ -0,0 +1,695 @@
if exists( "g:__XPMARK_VIM__" ) && g:__XPMARK_VIM__ >= XPT#ver
finish
endif
let g:__XPMARK_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
com! XPMgetSID let s:sid = matchstr("<SID>", '\zs\d\+_\ze')
XPMgetSID
delc XPMgetSID
runtime plugin/xptemplate.conf.vim
runtime plugin/debug.vim
let s:log = xpt#debug#Logger( 'warn' )
let g:xpm_mark = 'p'
let g:xpm_mark_nextline = 'l'
let g:xpm_changenr_level = 1000
let s:insertPattern = '[i]'
let g:XPM_RET = { 'likely_matched':{'likely_matched' : 1}, 'no_updated_made':{'no_updated_made' : 1}, 'undo_redo':{'undo_redo' : 1}, 'updated':{'updated' : 1}, }
let s:emptyHistoryElt = {'list':[], 'dict' :{}, 'likely' : { 'start' : '', 'end' : '' }}
let g:XPMpreferLeft = 'l'
let g:XPMpreferRight = 'r'
augroup XPM
au!
au BufEnter * call <SID>InitBuf()
augroup END
fun! XPMcheckStatusline()
if stridx( &l:statusline, 'XPMautoUpdate' ) >= 0
return
else
call s:SetupStatusline()
endif
endfunction
fun! s:SetupStatusline()
if &statusline == ""
if &l:statusline == ''
setlocal statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
else
endif
else
if &l:statusline == ''
setlocal statusline<
else
endif
endif
if stridx( &l:statusline, 'XPMautoUpdate' ) < 0
if &l:statusline =~ '\V\^%!'
let &l:statusline .= '.XPMautoUpdate("statusline")'
else
let &l:statusline .= '%{XPMautoUpdate("statusline")}'
endif
endif
endfunction
fun! XPMadd(name,pos,prefer,...)
call XPMcheckStatusline()
let d = s:BufData()
let prefer = a:prefer == 'l' ? 0 : 1
if has_key(d.marks,a:name)
call d.removeMark(a:name)
endif
let d.marks[a:name] = a:pos + [len(getline(a:pos[0])),prefer]
call d.addMarkOrder(a:name,get(a:000,0,0))
endfunction
fun! XPMhere(name,prefer)
call XPMadd( a:name, [ line( "." ), col( "." ) ], a:prefer )
endfunction
fun! XPMremove(name)
let d = s:BufData()
call d.removeMark(a:name)
endfunction
fun! XPMremoveStartEnd(dict)
let d = s:BufData()
call d.removeMark(a:dict.start)
call d.removeMark(a:dict.end)
endfunction
fun! XPMremoveMarkStartWith(prefix)
let d = s:BufData()
for key in keys(d.marks)
if key =~# '^\V' . a:prefix
call d.removeMark(key)
endif
endfor
endfunction
fun! XPMflush()
let d = s:BufData()
let d.marks = {}
let d.orderedMarks = []
let d.changeLikelyBetween = { 'start' : '', 'end' : '' }
let d.markHistory[ changenr() ] = { 'dict' : d.marks, 'list': d.orderedMarks, 'likely' : d.changeLikelyBetween }
endfunction
fun! XPMflushWithHistory()
call XPMflush()
let d = s:BufData()
let d.markHistory = {}
endfunction
fun! XPMgoto(name)
let d = s:BufData()
if has_key(d.marks,a:name)
let pos = d.marks[a:name][: 1]
call cursor(pos)
endif
endfunction
fun! XPMpos(name)
let d = s:BufData()
if has_key(d.marks,a:name)
return d.marks[a:name][: 1]
endif
return [0,0]
endfunction
fun! XPMhas(...)
let d = s:BufData()
for name in a:000
if !has_key(d.marks,name)
return 0
endif
endfor
return 1
endfunction
fun! XPMposStartEnd(dict)
let d = s:BufData()
return [has_key(d.marks,a:dict.start) ? d.marks[a:dict.start][0:1] : [0,0], has_key(d.marks,a:dict.end) ? d.marks[a:dict.end][0:1] : [0,0],]
endfunction
fun! XPMposList(...)
let d = b:_xpmark
let list = []
for name in a:000
call add(list,get(d.marks,name,[0,0])[0:1])
endfor
return list
endfunction
fun! XPMmarkAfter(pos)
let d = b:_xpmark
for name in d.orderedMarks
if d.marks[name][0] >= a:pos[0] && d.marks[name][1] >= a:pos[1]
return { 'name' : name, 'pos' : copy( d.marks[ name ] ) }
endif
endfor
return 0
endfunction
fun! XPMsetLikelyBetween(start,end)
let d = s:BufData()
let d.changeLikelyBetween = { 'start' : a:start, 'end' : a:end }
endfunction
fun! XPMsetUpdateStrategy(mode)
let d = s:BufData()
if a:mode == 'manual'
let d.updateStrategy = a:mode
elseif a:mode == 'normalMode'
let d.updateStrategy = a:mode
elseif a:mode == 'insertMode'
let d.updateStrategy = a:mode
else
let d.updateStrategy = 'auto'
endif
endfunction
fun! XPMupdateSpecificChangedRange(start,end)
let d = s:BufData()
let nr = changenr()
if nr != d.lastChangenr
call d.snapshot()
endif
call d.initCurrentStat()
let rc = d.updateWithNewChangeRange(a:start,a:end)
call d.saveCurrentStat()
return rc
endfunction
fun! XPMautoUpdate(msg)
if !exists( 'b:_xpmark' )
return ''
endif
let d = s:BufData()
let isInsertMode = (d.lastMode == 'i' && mode() == 'i')
if d.updateStrategy == 'manual' || d.updateStrategy == 'normalMode' && isInsertMode || d.updateStrategy == 'insertMode' && !isInsertMode
return ''
endif
call XPMupdate('auto')
return ''
endfunction
fun! XPMupdate(...)
if !exists( 'b:_xpmark' )
return ''
endif
let d = s:BufData()
let mode = a:0 > 0 ? a:000[0] : 'auto'
if mode == 'force'
let needUpdate = 1
else
let needUpdate = d.isUpdateNeeded()
endif
if !needUpdate
call d.snapshot()
call d.saveCurrentStat()
return g:XPM_RET.no_updated_made
endif
call d.initCurrentStat()
if d.lastMode =~ s:insertPattern && d.stat.mode =~ s:insertPattern
let rc = d.insertModeUpdate()
else
let rc = d.normalModeUpdate()
endif
call d.saveCurrentStat()
return rc
endfunction
fun! XPMupdateStat()
let d = s:BufData()
call d.saveCurrentStat()
endfunction
fun! XPMupdateCursorStat(...)
let d = s:BufData()
call d.saveCurrentCursorStat()
endfunction
fun! XPMsetBufSortFunction(funcRef)
if !exists('b:_xpm_compare')
let b:_xpm_compare = a:funcRef
endif
endfunction
fun! XPMallMark()
let d = s:BufData()
let msg = ''
let i = 0
for name in d.orderedMarks
let msg .= printf( '%3d', i ) . ' ' . name . repeat( '-', 30-len( name ) ) . substitute( string( d.marks[ name ] ), '\<\d\>', ' &', 'g' ) . "\n"
let i += 1
endfor
return msg
endfunction
fun! s:isUpdateNeeded() dict
if empty(self.marks) && changenr() == self.lastChangenr
return 0
endif
return 1
endfunction
fun! s:initCurrentStat() dict
let self.stat = { 'currentPosition':[ line( '.' ), col( '.' ) ], 'totalLine':line( "$" ), 'currentLineLength':len( getline( "." ) ), 'mode':mode(), 'positionOfMarkP':[ line( "'" . g:xpm_mark ), col( "'" . g:xpm_mark ) ] }
endfunction
fun! s:snapshot() dict
let nr = changenr()
if nr == self.lastChangenr
return
endif
let n = self.lastChangenr + 1
if !has_key(self.markHistory,n-1)
if has_key(self.markHistory,n-2)
let self.markHistory[n-1] = self.markHistory[n-2]
else
let self.markHistory[n-1] = deepcopy(s:emptyHistoryElt)
endif
endif
while n < nr
let self.markHistory[n] = self.markHistory[n - 1]
if has_key(self.markHistory,n - g:xpm_changenr_level)
unlet self.markHistory[n - g:xpm_changenr_level]
endif
let n += 1
endwhile
let self.marks = copy(self.marks)
let self.orderedMarks = copy(self.orderedMarks)
let self.changeLikelyBetween = deepcopy(self.changeLikelyBetween)
let self.markHistory[ nr ] = { 'dict' : self.marks, 'list': self.orderedMarks, 'likely' : self.changeLikelyBetween }
endfunction
fun! s:handleUndoRedo() dict
let nr = changenr()
if nr < self.lastChangenr
call self.ToChangeNr(nr)
return 1
elseif nr > self.lastChangenr && nr <= self.changenrRange[1]
call self.ToChangeNr(nr)
return 1
else
return 0
endif
endfunction
fun! s:ToChangeNr(nr) dict
if has_key(self.markHistory,a:nr)
let self.marks = self.markHistory[a:nr].dict
let self.orderedMarks = self.markHistory[a:nr].list
let self.changeLikelyBetween = self.markHistory[a:nr].likely
else
call s:log.Info( "No " . a:nr . ' in markHistory, create new mark set' )
let self.marks = {}
let self.orderedMarks = []
let self.changeLikelyBetween = { 'start' : '', 'end' : '' }
endif
endfunction
fun! s:insertModeUpdate() dict
if self.handleUndoRedo()
return g:XPM_RET.undo_redo
endif
let stat = self.stat
if changenr() != self.lastChangenr
call self.snapshot()
endif
if stat.totalLine == self.lastTotalLine
if stat.currentPosition[0] == self.lastPositionAndLength[0] && stat.currentLineLength == self.lastPositionAndLength[2]
return g:XPM_RET.no_updated_made
endif
if self.lastPositionAndLength[2] == len(getline(self.lastPositionAndLength[0]))
return g:XPM_RET.no_updated_made
endif
endif
let lastPos = self.lastPositionAndLength[: 1]
let bLastPos = [self.lastPositionAndLength[0] + stat.totalLine - self.lastTotalLine,0]
let bLastPos[1] = self.lastPositionAndLength[1] - self.lastPositionAndLength[2] + len(getline(bLastPos[0]))
if bLastPos[0] * 10000 + bLastPos[1] >= lastPos[0] * 10000 + lastPos[1]
return self.updateWithNewChangeRange(self.lastPositionAndLength[:1],stat.currentPosition)
else
return self.updateWithNewChangeRange(stat.currentPosition,stat.currentPosition)
endif
endfunction
fun! s:normalModeUpdate() dict
let stat = self.stat
let nr = changenr()
if nr == self.lastChangenr
return g:XPM_RET.no_updated_made
endif
if self.handleUndoRedo()
return g:XPM_RET.undo_redo
endif
let cs = [ line( "'[" ), col( "'[" ) ]
let ce = [ line( "']" ), col( "']" ) ]
call self.snapshot()
let diffOfLine = stat.totalLine - self.lastTotalLine
if stat.mode =~ s:insertPattern
if diffOfLine > 0
if self.lastPositionAndLength[0] < stat.positionOfMarkP[0]
call self.updateMarksAfterLine(self.lastPositionAndLength[0] - 1)
else
call self.updateMarksAfterLine(stat.currentPosition[0] - 1)
endif
elseif self.lastMode =~ 's' || self.lastMode == "\<C-s>"
return self.updateWithNewChangeRange([ line( "'<" ), col( "'<" ) ], stat.currentPosition)
else
return self.updateWithNewChangeRange(stat.currentPosition,stat.currentPosition)
endif
elseif self.lastMode =~ s:insertPattern
return g:XPM_RET.no_updated_made
else
let linewiseDeletion = stat.positionOfMarkP[0] == 0
let lineNrOfChangeEndInLastStat = ce[0] - diffOfLine
if linewiseDeletion
if cs == ce
call self.updateForLinewiseDeletion(cs[0],lineNrOfChangeEndInLastStat)
return g:XPM_RET.updated
else
endif
elseif stat.positionOfMarkP[0] == line( "'" . g:xpm_mark_nextline ) && stat.totalLine < self.lastTotalLine
let endPos = [self.lastPositionAndLength[0],self.lastPositionAndLength[2]]
return self.updateWithNewChangeRange(endPos,endPos)
elseif self.lastMode =~ '[vVsS]'
elseif diffOfLine == -1
let cs = [self.lastPositionAndLength[0],self.lastPositionAndLength[2] + 1]
let ce = [self.lastPositionAndLength[0],self.lastPositionAndLength[2] + 2]
return self.updateWithNewChangeRange(cs,ce)
elseif cs == [1,1] && ce == [stat.totalLine,1] || diffOfLine < -1
call XPMflush()
return g:XPM_RET.updated
endif
return self.updateWithNewChangeRange(cs,ce)
endif
return g:XPM_RET.updated
endfunction
fun! s:updateMarksAfterLine(line) dict
let diffOfLine = self.stat.totalLine - self.lastTotalLine
for [n,v] in items(self.marks)
if v[0] > a:line
let self.marks[n] = [v[0] + diffOfLine,v[1],v[2],v[3]]
endif
endfor
endfunction
fun! s:updateForLinewiseDeletion(fromLine,toLine) dict
for [n,mark] in items(self.marks)
if mark[0] >= a:toLine
let self.marks[n] = [mark[0] + self.stat.totalLine - self.lastTotalLine,mark[1],mark[2],mark[3]]
elseif mark[0] >= a:fromLine && mark[0] < a:toLine
call self.removeMark(n)
endif
endfor
endfunction
fun! s:updateWithNewChangeRange(changeStart,changeEnd) dict
let bChangeEnd = [a:changeEnd[0] - self.stat.totalLine, a:changeEnd[1] - len(getline(a:changeEnd[0]))]
let likelyIndexes = self.findLikelyRange(a:changeStart,bChangeEnd)
if likelyIndexes == [-1,-1]
let indexes = [0,len(self.orderedMarks)]
call self.updateMarks(indexes,a:changeStart,a:changeEnd)
return g:XPM_RET.updated
else
let len = len(self.orderedMarks)
let i = likelyIndexes[0]
let j = likelyIndexes[1]
call self.updateMarksBefore([0,i + 1],a:changeStart,a:changeEnd)
call self.updateMarks([i+1,j],a:changeStart,a:changeEnd)
let len2 = len(self.orderedMarks)
let j += len2 - len
call self.updateMarksAfter([j,len2],a:changeStart,a:changeEnd)
return [self.orderedMarks[i],self.orderedMarks[j]]
endif
endfunction
fun! s:updateMarksBefore(indexRange,changeStart,changeEnd) dict
let lineLengthCS = len(getline(a:changeStart[0]))
let [iStart,iEnd] = [a:indexRange[0] - 1,a:indexRange[1] - 1]
while iStart < iEnd
let iStart += 1
let name = self.orderedMarks[iStart]
let mark = self.marks[name]
let bMark = [mark[0] - self.lastTotalLine,mark[1] - mark[2]]
if mark[0] < a:changeStart[0]
continue
elseif mark[0] == a:changeStart[0] && mark[1] - 1 < a:changeStart[1]
let self.marks[name] = [mark[0],mark[1],lineLengthCS,mark[3]]
else
call s:log.Error( 'mark should be before, but it is after start of change:' . string( [ mark, a:changeStart ] ) )
endif
endwhile
endfunction
fun! s:updateMarksAfter(indexRange,changeStart,changeEnd) dict
let bChangeEnd = [a:changeEnd[0] - self.stat.totalLine, a:changeEnd[1] - len(getline(a:changeEnd[0]))]
let diffOfLine = self.stat.totalLine - self.lastTotalLine
let lineLengthCS = len(getline(a:changeStart[0]))
let lineLengthCE = len(getline(a:changeEnd[0]))
let lineNrOfChangeEndInLastStat = a:changeEnd[0] - diffOfLine
let [iStart,iEnd] = [a:indexRange[0] - 1,a:indexRange[1] - 1]
while iStart < iEnd
let iStart += 1
let name = self.orderedMarks[iStart]
let mark = self.marks[name]
let bMark = [mark[0] - self.lastTotalLine,mark[1] - mark[2]]
if mark[0] > lineNrOfChangeEndInLastStat
if diffOfLine == 0
break
endif
let self.marks[name] = [mark[0] + diffOfLine,mark[1],mark[2],mark[3]]
elseif bMark[0] == bChangeEnd[0] && bMark[1] >= bChangeEnd[1]
let self.marks[name] = [a:changeEnd[0],bMark[1] + lineLengthCE,lineLengthCE,mark[3]]
else
call s:log.Error( 'mark should be after changes, but it is before them:' . string( [ bMark, bChangeEnd ] ))
endif
endwhile
endfunction
fun! s:updateMarks(indexRange,changeStart,changeEnd) dict
let bChangeEnd = [a:changeEnd[0] - self.stat.totalLine, a:changeEnd[1] - len(getline(a:changeEnd[0]))]
let diffOfLine = self.stat.totalLine - self.lastTotalLine
let lineLengthCS = len(getline(a:changeStart[0]))
let lineLengthCE = len(getline(a:changeEnd[0]))
let lineNrOfChangeEndInLastStat = a:changeEnd[0] - diffOfLine
let [iStart,iEnd] = [a:indexRange[0] - 1,a:indexRange[1] - 1]
while iStart < iEnd
let iStart += 1
let name = self.orderedMarks[iStart]
let mark = self.marks[name]
let bMark = [mark[0] - self.lastTotalLine,mark[1] - mark[2]]
if mark[0] < a:changeStart[0]
continue
elseif mark[0] > lineNrOfChangeEndInLastStat
let self.marks[name] = [mark[0] + diffOfLine,mark[1],mark[2],mark[3]]
elseif mark[0 : 1] == a:changeStart && bMark == bChangeEnd
if mark[3] == 0
let self.marks[name] = [mark[0],mark[1],lineLengthCS,0]
else
let self.marks[name] = [a:changeEnd[0],bMark[1] + lineLengthCE,lineLengthCE,1]
endif
elseif mark[0] == a:changeStart[0] && mark[1] - 1 < a:changeStart[1]
let self.marks[name] = [mark[0],mark[1],lineLengthCS,mark[3]]
elseif bMark[0] == bChangeEnd[0] && bMark[1] >= bChangeEnd[1]
let self.marks[name] = [a:changeEnd[0],bMark[1] + lineLengthCE,lineLengthCE,mark[3]]
else
call self.removeMark(name)
let iStart -= 1
let iEnd -= 1
endif
endwhile
endfunction
fun! XPMupdateWithMarkRangeChanging(startMark,endMark,changeStart,changeEnd)
let d = s:BufData()
call d.initCurrentStat()
if changenr() != d.lastChangenr
call d.snapshot()
endif
let startIndex = index(d.orderedMarks,a:startMark)
let endIndex = index(d.orderedMarks,a:endMark,startIndex + 1)
call d.updateMarksAfter([endIndex,len(d.orderedMarks)],a:changeStart,a:changeEnd)
let [i,len] = [startIndex + 1 ,endIndex]
while i < len
let len -= 1
let mark = d.orderedMarks[i]
endwhile
let lineLength = len(getline(a:changeStart[0]))
let [i] = [startIndex + 1]
while i > 0
let i -= 1
let mark = d.orderedMarks[i]
if d.marks[mark][0] < a:changeStart[0]
break
else
let d.marks[mark][2] = len(getline(d.marks[mark][0]))
endif
endwhile
call d.saveCurrentStat()
endfunction
fun! s:findLikelyRange2(changeStart,bChangeEnd) dict
if self.changeLikelyBetween.start == '' || self.changeLikelyBetween.end == ''
return [-1,-1]
elseif !has_key(self.marks,self.changeLikelyBetween.start) || !has_key(self.marks,self.changeLikelyBetween.end)
return [-1,-1]
endif
let [likelyStart,likelyEnd] = [self.marks[self.changeLikelyBetween.start], self.marks[self.changeLikelyBetween.end]]
let bLikelyEnd = [likelyEnd[0] - self.lastTotalLine, likelyEnd[1] - likelyEnd[2]]
let nChangeStart = a:changeStart[0] * 10000 + a:changeStart[1]
let nLikelyStart = likelyStart[0] * 10000 + likelyStart[1]
let nbChangeEnd = a:bChangeEnd[0] * 10000 + a:bChangeEnd[1]
let nbLikelyEnd = bLikelyEnd[0] * 10000 + bLikelyEnd[1]
if nChangeStart >= nLikelyStart && nbChangeEnd <= nbLikelyEnd
let re = []
let [i,len] = [0,len(self.orderedMarks)]
while i < len
if self.orderedMarks[i] == self.changeLikelyBetween.start
call add(re,i)
elseif self.orderedMarks[i] == self.changeLikelyBetween.end
call add(re,i)
return re
endif
let i += 1
endwhile
call s:log.Error( string( self.changeLikelyBetween ) . ' : end mark is not found!' )
else
return [-1,-1]
endif
endfunction
fun! s:findLikelyRange(changeStart,bChangeEnd) dict
if self.changeLikelyBetween.start == '' || self.changeLikelyBetween.end == ''
return [-1,-1]
elseif !has_key(self.marks,self.changeLikelyBetween.start) || !has_key(self.marks,self.changeLikelyBetween.end)
return [-1,-1]
endif
let nChangeStart = a:changeStart[0] * 10000 + a:changeStart[1]
let nbChangeEnd = a:bChangeEnd[0] * 10000 + a:bChangeEnd[1]
let iLikelyStart = -1
let iLikelyEnd = -1
let [i,len] = [0,len(self.orderedMarks)]
while i < len
if self.orderedMarks[i] == self.changeLikelyBetween.start
let iLikelyStart = i
elseif self.orderedMarks[i] == self.changeLikelyBetween.end
let iLikelyEnd = i
break
endif
let i += 1
endwhile
if iLikelyStart == -1 || iLikelyEnd == -1
return [-1,-1]
endif
while iLikelyStart >= 0
let likelyStart = self.marks[self.orderedMarks[iLikelyStart]]
let nLikelyStart = likelyStart[0] * 10000 + likelyStart[1]
if nChangeStart >= nLikelyStart
break
endif
let iLikelyStart -= 1
endwhile
if iLikelyStart == -1
return [-1,-1]
endif
while iLikelyEnd < len(self.orderedMarks)
let likelyEnd = self.marks[self.orderedMarks[iLikelyEnd]]
let bLikelyEnd = [likelyEnd[0] - self.lastTotalLine, likelyEnd[1] - likelyEnd[2]]
let nbLikelyEnd = bLikelyEnd[0] * 10000 + bLikelyEnd[1]
if nbChangeEnd <= nbLikelyEnd
break
endif
let iLikelyEnd += 1
endwhile
if iLikelyEnd == len(self.orderedMarks)
return [-1,-1]
endif
return [iLikelyStart,iLikelyEnd]
endfunction
fun! s:saveCurrentCursorStat() dict
if self.marks == {}
return
endif
let p = [ line( '.' ), col( '.' ) ]
exe 'k'.g:xpm_mark
if p[0] < line( '$' )
exe '+1k' . g:xpm_mark_nextline
else
exe 'delmarks ' . g:xpm_mark_nextline
endif
let self.lastPositionAndLength = p + [ len( getline( "." ) ) ]
let self.lastMode = mode()
endfunction
fun! s:saveCurrentStat() dict
call self.saveCurrentCursorStat()
let self.lastChangenr = changenr()
let self.changenrRange[0] = min([self.lastChangenr,self.changenrRange[0]])
let self.changenrRange[1] = max([self.lastChangenr,self.changenrRange[1]])
let self.lastTotalLine = line( "$" )
endfunction
fun! s:removeMark(name) dict
if !has_key(self.marks,a:name)
return
endif
if self.changeLikelyBetween.start == a:name || self.changeLikelyBetween.end == a:name
let self.changeLikelyBetween = { 'start' : '', 'end' : '' }
endif
call filter( self.orderedMarks, 'v:val != ' . string( a:name ) )
call remove(self.marks,a:name)
endfunction
fun! s:addMarkOrder(name,beforeWhich) dict
let markToAdd = self.marks[a:name]
let nPos = markToAdd[0] * 10000 + markToAdd[1]
let i = -1
for n in self.orderedMarks
let i += 1
let mark = self.marks[n]
let nMark = mark[0] * 10000 + mark[1]
if nMark == nPos
if a:beforeWhich isnot 0 && n =~ a:beforeWhich
call insert(self.orderedMarks,a:name,i)
return
else
let cmp = self.compare(a:name,n)
if cmp == 0
throw 'XPM : overlapped mark:' . a:name . '=' . string(markToAdd) . ' and ' . n . '=' . string( mark )
elseif cmp > 0
continue
else
call insert(self.orderedMarks,a:name,i)
return
endif
endif
elseif nPos < nMark
call insert(self.orderedMarks,a:name,i)
return
endif
endfor
call add (self.orderedMarks,a:name)
endfunction
fun! s:compare(a,b) dict
if exists( 'b:_xpm_compare' )
return b:_xpm_compare(self,a:a,a:b)
else
return s:defaultCompare(self,a:a,a:b)
endif
endfunction
fun! s:ClassPrototype(...)
let p = {}
for name in a:000
let p[ name ] = function( '<SNR>' . s:sid . name )
endfor
return p
endfunction
let s:prototype = s:ClassPrototype( 'ToChangeNr', 'addMarkOrder', 'compare', 'findLikelyRange', 'handleUndoRedo', 'initCurrentStat', 'insertModeUpdate', 'isUpdateNeeded', 'normalModeUpdate', 'removeMark', 'saveCurrentCursorStat', 'saveCurrentStat', 'snapshot', 'updateForLinewiseDeletion', 'updateMarks', 'updateMarksAfter', 'updateMarksAfterLine', 'updateMarksBefore', 'updateWithNewChangeRange', )
fun! s:initBufData()
let nr = changenr()
let b:_xpmark = { 'updateStrategy':'auto', 'stat':{}, 'orderedMarks':[], 'marks':{}, 'markHistory':{}, 'changeLikelyBetween':{ 'start' : '', 'end' : '' }, 'lastMode':'n', 'lastPositionAndLength':[ line( '.' ), col( '.' ), len( getline( '.' ) ) ], 'lastTotalLine':line( '$' ), 'lastChangenr':nr, 'changenrRange':[nr, nr], }
let b:_xpmark.markHistory[ nr ] = { 'dict' : b:_xpmark.marks, 'list' : b:_xpmark.orderedMarks, 'likely' : b:_xpmark.changeLikelyBetween }
call extend( b:_xpmark, s:prototype, 'force' )
exe 'k' . g:xpm_mark
if line( '.' ) < line( '$' )
exe '+1k' . g:xpm_mark_nextline
else
exe 'delmarks ' . g:xpm_mark_nextline
endif
endfunction
fun! s:BufData()
if !exists('b:_xpmark')
call s:initBufData()
endif
return b:_xpmark
endfunction
fun! s:InitBuf()
if !exists('b:_xpmark')
call s:initBufData()
endif
endfunction
fun! s:defaultCompare(d,markA,markB)
let [ma,mb] = [a:d.marks[a:markA],a:d.marks[a:markB]]
let nMarkA = ma[0] * 10000 + ma[1]
let nMarkB = mb[0] * 10000 + mb[1]
return (nMarkA - nMarkB) != 0 ? (nMarkA - nMarkB) : (a:d.marks[a:markA][3] - a:d.marks[a:markB][3])
endfunction
if &ruler && &rulerformat == ""
set rulerformat=%-14.(%l,%c%V%)%=%P
elseif !&ruler
set rulerformat=
endif
set ruler
let &rulerformat .= '%{XPMautoUpdate("ruler")}'
fun! PrintDebug()
let d = s:BufData()
let debugString = changenr()
let debugString .= ' p:' . string( getpos( "'" . g:xpm_mark )[ 1 : 2 ] )
let debugString .= ' ' . string( [[ line( "'[" ), col( "'[" ) ], [ line( "']" ), col( "']" ) ]] ) . " "
let debugString .= " " . mode() . string( [line( "." ), col( "." )] ) . ' last:' .string( d.lastPositionAndLength )
let debugString .= " ll:" . d.lastTotalLine
return substitute( debugString, '\s', '' , 'g' )
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,637 @@
if exists( "g:__XPOPUP_VIM__" ) && g:__XPOPUP_VIM__ >= XPT#ver
finish
endif
let g:__XPOPUP_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
runtime plugin/debug.vim
exe XPT#let_sid
let s:log = CreateLogger( 'warn' )
let s:log = CreateLogger( 'debug' )
fun! s:SetIfNotExist(k,v)
if !exists(a:k)
exe "let ".a:k."=".string(a:v)
endif
endfunction
let s:opt = { 'doCallback':'doCallback', 'enlarge':'enlarge', 'acceptEmpty':'acceptEmpty', 'tabNav':'tabNav', }
let s:CHECK_PUM = 1
let s:errorTolerance = 3
let s:sessionPrototype = { 'callback':{}, 'list':[], 'key':'', 'prefixIndex':{}, 'popupCount':0, 'sessCount':0, 'errorInputCount':0, 'line':0, 'col':0, 'prefix':'', 'ignoreCase':0, 'acceptEmpty':0, 'matchWholeName':0, 'matchPrefix':0, 'strictInput':0, 'tabNav':0, 'last':'', 'currentText':'', 'longest':'', 'matched':'', 'matchedCallback':'', 'currentList':[], }
fun! XPPopupNew(callback,data,...)
let sess = deepcopy(s:sessionPrototype)
let sess.callback = a:callback
let sess.data = a:data
call sess.createPrefixIndex([])
if a:0 > 0
let items = a:1
if type( items ) == type( '' )
call sess.SetTriggerKey(items)
elseif type(items) == type([])
call sess.addList(items)
else
call s:log.Error( 'unsupported items type as pum items:' . str( items ) )
endif
endif
return sess
endfunction
fun! s:popup(start_col,opt) dict
let doCallback = get(a:opt,s:opt.doCallback,1)
let ifEnlarge = get(a:opt,s:opt.enlarge,1)
let self.popupCount += 1
let cursorIndex = col(".") - 1 - 1
let self.line = line(".")
let self.col = a:start_col
let self.prefix = s:GetTextBeforeCursor(self)
let self.ignoreCase = self.prefix !~# '\u'
if self.key != ''
let self.longest = self.prefix
let actions = self.KeyPopup(doCallback,ifEnlarge)
else
let self.currentList = s:filterCompleteList(self)
if ifEnlarge
let self.longest = s:LongestPrefix(self)
else
let self.longest = self.prefix
endif
let actions = self.ListPopup(doCallback,ifEnlarge)
endif
let actions = s:CreateSession(self) . actions
call s:ApplyMapAndSetting()
return actions
endfunction
fun PUMclear()
return "\<C-v>\<C-v>\<BS>"
endfunction
fun! s:CreateSession(sess)
if !exists( 'b:__xpp_sess_count' )
let b:__xpp_sess_count = 0
endif
let action = ''
let b:__xpp_sess_count += 1
let a:sess.sessCount = b:__xpp_sess_count
if exists( 'b:__xpp_current_session' )
call s:End()
if pumvisible()
let action .= PUMclear()
endif
endif
let b:__xpp_current_session = a:sess
return action
endfunction
fun! s:SetAcceptEmpty(acc) dict
let self.acceptEmpty = !!a:acc
return self
endfunction
fun! s:SetMatchWholeName(mwn) dict
let self.matchWholeName = !!a:mwn
return self
endfunction
fun! s:SetOption(opt) dict
if type(a:opt) == type([])
for optname in a:opt
let self[optname] = 1
endfor
elseif type(a:opt) == type({})
for [key,value] in items(a:opt)
let self[key] = value
endfor
endif
endfunction
fun! s:KeyPopup(doCallback,ifEnlarge) dict
let actionList = []
if a:ifEnlarge
let actionList = [ 'clearPum', 'clearPrefix', 'typeLongest', 'triggerKey', 'setLongest' ]
if a:doCallback
let actionList += [ 'checkAndCallback' ]
endif
else
let actionList = [ 'clearPum', 'clearPrefix', 'typeLongest', 'triggerKey', 'removeTrailing', 'forcePumShow' ]
endif
return "\<C-r>=XPPprocess(" . string( actionList ) . ")\<CR>"
endfunction
fun! s:ListPopup(doCallback,ifEnlarge) dict
let actionClosePum = ''
let actionList = []
if self.longest !=# self.prefix
let actionList += ['clearPum', 'clearPrefix', 'clearPum', 'typeLongest' ]
endif
if 0
else
if self.popupCount > 1 && a:ifEnlarge && self.acceptEmpty && self.prefix == ''
let self.matched = ''
let self.matchedCallback = 'onOneMatch'
let actionList = []
let actionList += [ 'clearPum', 'clearPrefix', 'clearPum', 'callback' ]
elseif len(self.currentList) == 0
let self.matched = ''
let self.matchedCallback = 'onEmpty'
let actionList += ['callback']
elseif len(self.currentList) == 1 && a:doCallback
if self.matchPrefix
let self.matched = type(self.currentList[0]) == type({}) ? self.currentList[0].word : self.currentList[0]
let self.matchedCallback = 'onOneMatch'
let actionList += ['clearPum', 'clearPrefix', 'clearPum', 'typeMatched', 'callback']
else
let actionClosePum = PUMclear()
let actionList += [ 'popup', 'fixPopup' ]
endif
elseif self.prefix != "" && self.longest ==? self.prefix
if self.matchPrefix && a:doCallback
let self.matched = ''
for item in self.currentList
let key = type(item) == type({}) ? item.word : item
if key ==? self.prefix
let self.matched = key
let self.matchedCallback = 'onOneMatch'
let actionList += ['clearPum', 'clearPrefix', 'clearPum', 'typeLongest', 'callback']
break
endif
endfor
if self.matched == ''
let actionClosePum = PUMclear()
let actionList += [ 'popup', 'fixPopup' ]
endif
else
let actionClosePum = PUMclear()
let actionList += [ 'popup', 'fixPopup' ]
endif
else
let actionClosePum = PUMclear()
let actionList += [ 'popup', 'fixPopup' ]
endif
endif
let self.matchPrefix = 1
return actionClosePum . "\<C-r>=XPPprocess(" . string( actionList ) . ")\<CR>"
endfunction
fun! s:SetTriggerKey(key) dict
let self.key = a:key
endfunction
fun! s:sessionPrototype.addList(list)
let list = a:list
if list == []
return
endif
if type( list[0] ) == type( '' )
call map( list, '{"word" : v:val, "icase" : 1 }' )
else
call map( list, '{"word" : v:val["word"],' . '"info": get(v:val, "info", ""),' . '"menu": get(v:val, "menu", ""),' . '"icase": 1 }' )
endif
let self.list += list
call self.updatePrefixIndex(list)
endfunction
fun! s:sessionPrototype.createPrefixIndex(list)
let self.prefixIndex = { 'keys' : {}, 'lowerkeys' : {}, 'ori' : {}, 'lower' : {} }
call self.updatePrefixIndex(a:list)
endfunction
fun! s:sessionPrototype.updatePrefixIndex(list)
if g:xptemplate_pum_quick_back == 0
return
endif
for item in a:list
let key = (type(item) == type({})) ?item.word : item
if !has_key(self.prefixIndex.keys,key)
let self.prefixIndex.keys[key] = 1
call s:UpdateIndex(self.prefixIndex.ori,key)
endif
let lowerKey = substitute(key, '.', '\l&', 'g')
if !has_key(self.prefixIndex.lowerkeys,lowerKey)
let self.prefixIndex.lowerkeys[lowerKey] = 1
call s:UpdateIndex(self.prefixIndex.lower,lowerKey)
endif
endfor
endfunction
fun! s:_InitBuffer()
if exists( 'b:__xpp_buffer_init' )
return
endif
let b:_xpp_map_saver = xpt#msvr#New(1)
call xpt#msvr#AddList(b:_xpp_map_saver, 'i_<UP>', 'i_<DOWN>', 'i_<BS>', 'i_<TAB>', 'i_<S-TAB>', 'i_<CR>', 'i_<C-e>', 'i_<C-y>', )
let b:_xpp_setting_switch = xpt#settingswitch#New()
let co = {"menu":1, "menuone":1, "longest":1}
for k in split(&completeopt, ',')
let co[k] = 1
endfor
let new_completeopt = join( keys(co), ',' )
call xpt#settingswitch#AddList(b:_xpp_setting_switch, [ '&l:cinkeys', '' ], [ '&l:indentkeys', '' ], [ '&completeopt', new_completeopt ], )
let b:__xpp_buffer_init = 1
endfunction
fun! XPPprocess(list)
if !exists("b:__xpp_current_session")
call s:log.Error("session does not exist!")
return ""
endif
let sess = b:__xpp_current_session
if len(a:list) == 0
return "\<C-n>\<C-p>"
endif
let actionName = a:list[0]
let nextList = a:list[1 :]
let postAction = ""
if actionName == 'clearPrefix'
let n = col(".") - sess.col
let postAction = repeat( "\<bs>", n )
elseif actionName == 'clearPum'
if pumvisible()
let postAction = "\<C-e>"
endif
elseif actionName == 'triggerKey'
let postAction = sess.key
elseif actionName == 'setLongest'
let current = s:GetTextBeforeCursor(sess)
if len(current) > len(sess.longest)
let postAction = repeat( "\<BS>", len( current ) - len( sess.longest ) ) . current[len(sess.longest) :]
let sess.longest = s:GetTextBeforeCursor(sess)
if pumvisible()
let nextList = [ 'clearPum', 'clearPrefix', 'typeLongest', 'triggerKey' ] + nextList
else
let nextList = [ 'clearPrefix', 'clearPum', 'typeLongest' ] + nextList
endif
endif
elseif actionName == 'removeTrailing'
let current = s:GetTextBeforeCursor(sess)
if len(current) > len(sess.longest)
let postAction = repeat( "\<BS>", len( current ) - len( sess.longest ) )
endif
elseif actionName == 'forcePumShow'
let postAction = "\<C-n>\<C-p>"
elseif actionName == 'checkAndCallback'
if pumvisible()
return "\<C-n>\<C-p>"
else
let current = s:GetTextBeforeCursor(sess)
let sess.matched = current
let sess.matchedCallback = 'onOneMatch'
call s:End()
let postAction = ""
if has_key(sess.callback,sess.matchedCallback)
let postAction = sess.callback[sess.matchedCallback](sess)
return postAction
else
return ''
endif
endif
elseif actionName == 'keymodeEnlarge'
let current = s:GetTextBeforeCursor(sess)
if sess.acceptEmpty && current == ''
let sess.longest = ''
let sess.matched = ''
let sess.matchedCallback = 'onOneMatch'
let nextList = [ 'callback' ]
elseif current !=# sess.currentText
let sess.longest = sess.currentText
let sess.matched = sess.currentText
let sess.matchedCallback = 'onOneMatch'
let nextList = [ 'clearPrefix', 'typeLongest', 'callback' ]
else
return sess.popup(sess.col, { 'doCallback' : 1, 'enlarge':1 } )
endif
elseif actionName == 'enlarge'
let current = s:GetTextBeforeCursor(sess)
if current !=# sess.currentText
let sess.longest = sess.currentText
let sess.matched = sess.currentText
let sess.matchedCallback = 'onOneMatch'
let nextList = [ 'clearPrefix', 'typeLongest', 'callback' ]
else
return sess.popup(sess.col, { 'doCallback' : 1, 'enlarge':1 } )
endif
elseif actionName == 'typeMatched'
let postAction = sess.matched
elseif actionName == 'typeLongest'
let postAction = sess.longest
elseif actionName == 'type'
let postAction = remove(nextList,0)
elseif actionName == 'popup'
call complete(sess.col,sess.currentList)
elseif actionName == 'fixPopup'
let current = s:GetTextBeforeCursor(sess)
let i = 0
let j = -1
for v in sess.currentList
let key = type(v) == type({}) ? v.word : v
if key ==# current
let j = i
break
endif
let i += 1
endfor
if j != -1
let postAction .= repeat( "\<C-p>", j + 1 )
endif
elseif actionName == 'callback'
call s:End()
let postAction = ""
if has_key(sess.callback,sess.matchedCallback)
let postAction = sess.callback[sess.matchedCallback](sess)
return postAction
endif
elseif actionName == 'end'
call s:End()
let postAction = ''
else
endif
if !empty(nextList)
let postAction .= "\<C-r>=XPPprocess(" . string( nextList ) . ")\<CR>"
else
let postAction .= g:xpt_post_action
endif
return postAction
endfunction
fun! s:GetTextBeforeCursor(sess)
let c = col( "." )
if c == 1
return ''
endif
return getline(".")[ a:sess.col - 1 : c - 2 ]
endfunction
fun! XPPcomplete(col,list)
let oldcfu = &completefunc
set completefunc=XPPcompleteFunc
return "\<C-x>\<C-u>"
endfunction
fun! XPPcr()
if !s:PopupCheck(s:CHECK_PUM)
call feedkeys("\<CR>", 'mt')
return ""
endif
return "\<C-r>=XPPaccept()\<CR>"
endfunction
fun! XPPup(key)
if !s:PopupCheck(s:CHECK_PUM)
call feedkeys( a:key, 'mt' )
return ""
endif
return "\<C-p>"
endfunction
fun! XPPdown(key)
if !s:PopupCheck(s:CHECK_PUM)
call feedkeys( a:key, 'mt' )
return ""
endif
return "\<C-n>"
endfunction
fun! XPPcallback()
if !exists("b:__xpp_current_session")
return ""
endif
let sess = b:__xpp_current_session
call s:End()
if has_key(sess.callback,sess.matchedCallback)
let post = sess.callback[sess.matchedCallback](sess)
else
let post = ""
endif
return post
endfunction
fun! XPPshorten()
if !s:PopupCheck(! s:CHECK_PUM)
let s:pos = getpos(".")[ 1 : 2 ]
return "\<C-e>\<C-r>=XPPcorrectPos()\<cr>\<bs>"
endif
if !pumvisible()
return "\<BS>"
endif
let sess = b:__xpp_current_session
let current = s:GetTextBeforeCursor(sess)
if sess.key != ''
return "\<BS>"
endif
if current == ''
call s:End()
return "\<bs>"
endif
let actions = "\<C-y>"
let actions = ""
if g:xptemplate_pum_quick_back == 1
let prefixMap = (sess.ignoreCase) ? sess.prefixIndex.lower : sess.prefixIndex.ori
let shorterKey = s:FindShorter(prefixMap, ( sess.ignoreCase ? substitute(current, '.', '\l&', 'g') : current ))
else
let shorterKey = current[0 : -2]
endif
let action = actions . repeat( "\<bs>", len(current) - len(shorterKey) ) . "\<C-r>=XPPrepopup(0, 'noenlarge')\<cr>"
return action
endfunction
fun! XPPenlarge(key)
if !s:PopupCheck(s:CHECK_PUM)
call feedkeys( a:key, 'm' )
return ""
endif
return "\<C-r>=XPPrepopup(1, 'enlarge')\<cr>"
endfunction
fun! XPPcancel(key)
if !s:PopupCheck()
call feedkeys( a:key, 'mt' )
return ""
endif
return "\<C-r>=XPPprocess(" . string( [ 'clearPum', 'clearPrefix', 'typeLongest', 'end' ] ) . ")\<cr>"
endfunction
fun! XPPaccept()
if !s:PopupCheck()
call feedkeys("\<C-y>", 'mt')
return ""
endif
let sess = b:__xpp_current_session
let beforeCursor = col( "." ) - 2
let beforeCursor = beforeCursor == -1 ? 0 : beforeCursor
let toType = getline(sess.line)[sess.col - 1 : beforeCursor]
return "\<C-r>=XPPprocess(" . string( [ 'clearPum', 'clearPrefix', 'type', toType, 'end' ] ) . ")\<cr>"
endfunction
fun! XPPrepopup(doCallback,ifEnlarge)
if !exists("b:__xpp_current_session")
return ""
endif
let sess = b:__xpp_current_session
if sess.key != ''
let sess.currentText = s:GetTextBeforeCursor(sess)
let action = "\<C-e>" . "\<C-r>=XPPprocess(" . string( [ 'keymodeEnlarge' ] ) . ")\<CR>"
return action
else
let action = sess.popup(sess.col, { 'doCallback' : a:doCallback, 'enlarge':a:ifEnlarge == 'enlarge' } )
return action
endif
endfunction
fun! XPPcorrectPos()
let p = getpos(".")[1:2]
if p != s:pos
unlet s:pos
return "\<bs>"
else
unlet s:pos
return ""
endif
endfunction
fun! s:ApplyMapAndSetting()
call s:_InitBuffer()
if exists( 'b:__xpp_pushed' )
return
endif
let b:__xpp_pushed = 1
call xpt#msvr#Save(b:_xpp_map_saver)
let sess = b:__xpp_current_session
exe 'inoremap <silent> <buffer> <UP>' '<C-r>=XPPup("\<lt>UP>")<CR>'
exe 'inoremap <silent> <buffer> <DOWN>' '<C-r>=XPPdown("\<lt>DOWN>")<CR>'
exe 'inoremap <silent> <buffer> <bs>' '<C-r>=XPPshorten()<cr>'
exe 'inoremap <silent> <buffer> <C-e>' '<C-r>=XPPcancel("\<lt>C-e>")<cr>'
if sess.tabNav
exe 'inoremap <silent> <buffer> <S-tab>' '<C-r>=XPPup("\<lt>S-Tab>")<cr>'
exe 'inoremap <silent> <buffer> <tab>' '<C-r>=XPPdown("\<lt>TAB>")<cr>'
exe 'inoremap <silent> <buffer> <cr>' '<C-r>=XPPenlarge("\<lt>CR>")<cr>'
exe 'inoremap <silent> <buffer> <C-y>' '<C-r>=XPPenlarge("\<lt>C-y>")<cr>'
else
exe 'inoremap <silent> <buffer> <tab>' '<C-r>=XPPenlarge("\<lt>TAB>")<cr>'
exe 'inoremap <silent> <buffer> <cr>' '<C-r>=XPPenlarge("\<lt>CR>")<cr>'
exe 'inoremap <silent> <buffer> <C-y>' '<C-r>=XPPenlarge("\<lt>C-y>")<cr>'
endif
augroup XPpopup
au!
au CursorMovedI * call s:CheckAndFinish()
au InsertEnter * call XPPend()
augroup END
call xpt#settingswitch#Switch(b:_xpp_setting_switch)
if exists( ':AcpLock' )
AcpLock
endif
endfunction
fun! s:ClearMapAndSetting()
call s:_InitBuffer()
if !exists( 'b:__xpp_pushed' )
return
endif
unlet b:__xpp_pushed
augroup XPpopup
au!
augroup END
call xpt#msvr#Restore(b:_xpp_map_saver)
call xpt#settingswitch#Restore(b:_xpp_setting_switch)
if exists( ':AcpUnlock' )
try
AcpUnlock
catch /.*/
endtry
endif
endfunction
fun! s:CheckAndFinish()
if !exists( 'b:__xpp_current_session' )
call s:End()
return ''
endif
let sess = b:__xpp_current_session
if !pumvisible()
if line( "." ) == sess.line
if sess.strictInput
if col(".") > sess.col
call feedkeys( "\<BS>", 'n' )
endif
else
return s:MistakeTypeEnd()
endif
else
return s:MistakeTypeEnd()
endif
endif
return ''
endfunction
fun! s:MistakeTypeEnd()
call s:End()
return PUMclear()
endfunction
fun! XPPhasSession()
return exists("b:__xpp_current_session")
endfunction
fun! XPPend()
call s:End()
if pumvisible()
return PUMclear()
endif
return ''
endfunction
fun! s:End()
call s:ClearMapAndSetting()
if exists("b:__xpp_current_session")
unlet b:__xpp_current_session
endif
endfunction
fun! s:PopupCheck(...)
let checkPum = (a:0 == 0 || a:1)
if !exists("b:__xpp_current_session")
call s:End()
return 0
endif
let sess = b:__xpp_current_session
if sess.line != line(".") || col(".") < sess.col || (checkPum && !pumvisible())
call s:End()
return 0
endif
return 1
endfunction
fun! s:UpdateIndex(map,key)
let [i,len] = [0,len(a:key)]
while i < len
let prefix = a:key[0 : i - 1]
if !has_key(a:map,prefix)
let a:map[prefix] = 1
else
let a:map[prefix] += 1
endif
let i += 1
endwhile
endfunction
fun! s:LongestPrefix(sess)
let longest = ".*"
for e in a:sess.currentList
let key = (type(e) == type({})) ? e.word : e
if longest == ".*"
let longest = a:sess.ignoreCase ? substitute(key, '.', '\l&', 'g') : key
else
while key !~ '^\V' . ( a:sess.ignoreCase ? '\c' : '\C' ) . escape(longest, '\') && len(longest) > 0
let longest = longest[ : -2 ] " remove one char
endwhile
endif
endfor
let longest = ( longest == '.*' ) ? '' : longest
if a:sess.prefix !=# longest[: len(a:sess.prefix) - 1]
let longest = a:sess.prefix . longest[len(a:sess.prefix) :]
endif
return longest
endfunction
fun! s:filterCompleteList(sess)
let list = []
let caseOption = a:sess.ignoreCase ? '\c' : '\C'
if a:sess.matchWholeName
let pattern = '\V\^' . caseOption . a:sess.prefix . '\$'
else
let pattern = '\V\^' . caseOption . a:sess.prefix
endif
for item in a:sess.list
let key = (type(item) == type({})) ? item.word : item
if key =~ pattern
let list += [item]
endif
endfor
return list
endfunction
fun! s:FindShorter(map,key)
let key = a:key
if len(key) == 1
return ''
endif
let nmatch = has_key(a:map,key) ? a:map[key] : 1
if !has_key(a:map,key[: -2])
return key[: -2]
endif
let key = key[: -2]
while key != '' && a:map[key] == nmatch
let key = key[: -2]
endwhile
return key
endfunction
fun! s:ClassPrototype(...)
let p = {}
for name in a:000
let p[ name ] = function( '<SNR>' . s:sid . name )
endfor
return p
endfunction
let s:sessionPrototype2 = s:ClassPrototype( 'popup', 'SetAcceptEmpty', 'SetMatchWholeName', 'SetTriggerKey', 'SetOption', 'KeyPopup', 'ListPopup', )
call extend( s:sessionPrototype, s:sessionPrototype2, 'force' )
let &cpo = s:oldcpo

View file

@ -0,0 +1,197 @@
if exists( "g:__XPREPLACE_VIM__" ) && g:__XPREPLACE_VIM__ >= XPT#ver
finish
endif
let g:__XPREPLACE_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
runtime plugin/debug.vim
runtime plugin/xpmark.vim
let s:log = CreateLogger( 'warn' )
let s:log = CreateLogger( 'debug' )
fun! s:InitBuffer()
if exists( 'b:__xpr_init' )
return
endif
let b:__xpr_init = { 'settingSwitch' : xpt#settingswitch#New() }
call xpt#settingswitch#AddList(b:__xpr_init.settingSwitch, [ '&l:textwidth', '0' ], [ '&l:virtualedit', 'onemore' ], [ '&l:whichwrap' , 'b,s,h,l,<,>,~,[,]' ], [ '&l:selection' , 'exclusive' ], [ '&l:selectmode' , '' ], )
endfunction
fun! XPRstartSession()
call s:InitBuffer()
if exists( 'b:_xpr_session' )
throw "xpreplace session already pushed"
return
endif
let b:_xpr_session = {}
call xpt#settingswitch#Switch(b:__xpr_init.settingSwitch)
let b:_xpr_session.savedReg = @"
let @" = 'XPreplaceInited'
endfunction
fun! XPRendSession()
if !exists( 'b:_xpr_session' )
throw "no setting pushed"
return
endif
let @" = b:_xpr_session.savedReg
call xpt#settingswitch#Restore(b:__xpr_init.settingSwitch)
unlet b:_xpr_session
endfunction
fun! XPreplaceByMarkInternal(startMark,endMark,replacement)
let [start,end] = [XPMpos(a:startMark),XPMpos(a:endMark)]
if start == [0,0] || end == [0,0]
throw 'XPM:' . ' ' . a:startMark . ' or ' . a:endMark . 'is invalid'
endif
let pos = XPreplaceInternal( start, end, a:replacement, { 'doJobs' : 0 } )
call XPMupdateWithMarkRangeChanging(a:startMark,a:endMark,start,pos)
return pos
endfunction
fun! XPreplaceInternal(start,end,replacement,...)
let option = { 'doJobs' : 1, 'saveHoriScroll' : 0 }
if a:0 == 1
call extend( option, a:1, 'force' )
endif
let replacement = a:replacement
let repLines = split( a:replacement, '\n', 1 )
if option.doJobs
call s:doPreJob(a:start,a:end,replacement)
endif
if 0
let [curNrLines,finalNrLines] = [a:end[0] - a:start[0] + 1,len(repLines)]
let [ s, e ] = [ 1, col( [ a:end[ 0 ], '$' ] ) ]
let repLines[0] = XPT#TextInLine(a:start[0],s,a:start[1]) . repLines[0]
let repLines[-1] .= XPT#TextInLine(a:end[0],a:end[1],e)
let positionAfterReplacement = [a:end[0] + (finalNrLines - curNrLines),a:end[1] - len(getline(a:end[0]))]
if curNrLines > finalNrLines
call cursor(a:start)
if curNrLines > finalNrLines + 1
exe 'silent!' 'normal!' 'zOd' ( finalNrLines - curNrLines - 1 ) 'j'
else
silent! normal! zOdd
endif
elseif curNrLines < finalNrLines
call append( a:start[ 0 ], repeat( [ '' ], finalNrLines - curNrLines ) )
endif
call setline(a:start[0],repLines)
let positionAfterReplacement[1] += len(getline(positionAfterReplacement[0]))
call cursor(positionAfterReplacement)
silent! normal! zO
else
call cursor(a:start)
silent! normal! zO
call cursor(a:start)
if a:start != a:end
silent! normal! v
call cursor(a:end)
silent! normal! dzO
call cursor(a:start)
endif
if replacement != ''
let positionAfterReplacement = s:Replace_standard(a:start,a:end,replacement)
else
let positionAfterReplacement = [ line("."), col(".") ]
endif
endif
if option.doJobs
call s:doPostJob(a:start,positionAfterReplacement,replacement)
endif
return positionAfterReplacement
endfunction
fun! s:Replace_standard(start,end,replacement)
let replacement = a:replacement
let bStart = [a:start[0] - line( '$' ), a:start[1] - len(getline(a:start[0]))]
call cursor(a:start)
let ifPasteAtEnd = ( col( [ a:start[0], '$' ] ) == a:start[1] && a:start[1] > 1 )
let @" = replacement . ';'
if ifPasteAtEnd
call cursor(a:start[0],a:start[1] - 1)
let char = matchstr( getline( '.' ), '\v.$' )
let @" = char . replacement . ';'
silent! normal! ""P
else
if col( "." ) == len( getline( line( "." ) ) ) + 1
silent! normal! ""p
else
silent! normal! ""P
endif
endif
let positionAfterReplacement = [ bStart[0] + line( '$' ), 0 ]
let positionAfterReplacement[1] = bStart[1] + len(getline(positionAfterReplacement[0]))
call cursor(a:start)
k'
call cursor(positionAfterReplacement)
silent! '',.foldopen!
if ifPasteAtEnd
call cursor(positionAfterReplacement[0],positionAfterReplacement[1] - 1 - len(char))
silent! normal! DzO
else
call cursor(positionAfterReplacement)
if positionAfterReplacement[1] == len(getline(positionAfterReplacement[0])) + 1 && positionAfterReplacement[1] > 1
call cursor(positionAfterReplacement[0],positionAfterReplacement[1] - 1)
silent! normal! xzO
else
silent! normal! XzO
endif
endif
let positionAfterReplacement = [ bStart[0] + line( '$' ), 0 ]
let positionAfterReplacement[1] = bStart[1] + len(getline(positionAfterReplacement[0]))
return positionAfterReplacement
endfunction
fun! s:Replace_gp(start,end,replacement)
let replacement = a:replacement
let bStart = [a:start[0] - line( '$' ), a:start[1] - len(getline(a:start[0]))]
call cursor(a:start)
let ifPasteAtEnd = ( col( [ a:start[0], '$' ] ) == a:start[1] && a:start[1] > 1 )
let @" = replacement . ';'
call cursor(a:start)
silent! normal! ""gPzOXzO
let positionAfterReplacement = [ line( "." ), col( "." ) ]
return positionAfterReplacement
endfunction
fun! XPreplace(start,end,replacement,...)
let option = { 'doJobs' : 1 }
if a:0 == 1
call extend(option, a:1, 'force')
endif
call XPRstartSession()
let positionAfterReplacement = a:end
try
let positionAfterReplacement = XPreplaceInternal(a:start,a:end,a:replacement,option)
catch /.*/
call XPT#warn(v:exception)
call XPT#warn(v:throwpoint)
finally
call XPRendSession()
endtry
return positionAfterReplacement
endfunction
let s:_xpreplace = { 'post' : {}, 'pre' : {} }
fun! XPRaddPreJob(functionName)
let s:_xpreplace.pre[a:functionName] = function(a:functionName)
endfunction
fun! XPRaddPostJob(functionName)
let s:_xpreplace.post[a:functionName] = function(a:functionName)
endfunction
fun! XPRremovePreJob(functionName)
let d = s:_xpreplace.pre
if has_key(d,a:functionName)
unlet d[a:functionName]
endif
endfunction
fun! XPRremovePostJob(functionName)
let d = s:_xpreplace.post
if has_key(d,a:functionName)
unlet d[a:functionName]
endif
endfunction
fun! s:doPreJob(start,end,replacement)
let d = { 'f' : '' }
for d.f in values(s:_xpreplace.pre)
call d.f(a:start,a:end)
endfor
endfunction
fun! s:doPostJob(start,end,replacement)
let d = { 'f' : '' }
for d.f in values(s:_xpreplace.post)
call d.f(a:start,a:end)
endfor
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,136 @@
if exists( "g:__XPT_PLUGIN_HIGHLIGHT_VIM__" ) && g:__XPT_PLUGIN_HIGHLIGHT_VIM__ >= XPT#ver
finish
endif
let g:__XPT_PLUGIN_HIGHLIGHT_VIM__ = XPT#ver
runtime plugin/xptemplate.vim
if '' == g:xptemplate_highlight
finish
endif
if !hlID( 'XPTcurrentPH' )
hi def link XPTcurrentPH DiffChange
endif
if !hlID( 'XPTfollowingPH' )
hi def link XPTfollowingPH CursorLine
endif
if !hlID( 'XPTnextItem' )
hi def link XPTnextItem IncSearch
endif
fun! s:UpdateHL(x,ctx)
if !a:ctx.processing
return 1
endif
call s:ClearHL(a:x,a:ctx)
if pumvisible()
return 1
endif
if g:xptemplate_highlight =~ 'current' && a:ctx.phase == 'fillin'
let r = s:MarkRange(a:ctx.leadingPlaceHolder.mark)
call s:HL( 'XPTcurrentPH', r[2:] )
endif
if g:xptemplate_highlight =~ 'following' && a:ctx.phase == 'fillin'
let r = ''
for ph in a:ctx.item.placeHolders
let r .= '\|' . s:MarkRange( ph.mark )
endfor
call s:HL( 'XPTfollowingPH', r[2:] )
endif
if g:xptemplate_highlight =~ 'next'
let r = s:PatternOfNext(a:ctx)
if g:xptemplate_highlight_nested
for octx in a:x.stack
let r .= s:PatternOfNext(octx)
endfor
endif
call s:HL( 'XPTnextItem', r[2:] )
endif
return 1
endfunction
fun! s:PatternOfNext(ctx)
let r = ''
for item in a:ctx.itemList
if item.keyPH != {}
let r .= '\|' . s:MarkRange( item.keyPH.innerMarks )
else
let r .= '\|' . s:MarkRange( item.placeHolders[0].mark )
endif
endfor
if a:ctx.itemList == [] || 'cursor' != item.name
let pos = XPMposList(a:ctx.marks.tmpl.end,a:ctx.marks.tmpl.end)
let r .= '\|' . XPTgetStaticRange( pos[0], [ pos[1][0], pos[1][1] + 1 ] )
endif
return r
endfunction
fun! s:MarkRange(marks)
let pos = XPMposList(a:marks.start,a:marks.end)
if pos[0] == pos[1]
let pos[1][1] += 1
endif
return XPTgetStaticRange(pos[0],pos[1])
endfunction
fun! XPTgetStaticRange(p,q)
let posStart = a:p
let posEnd = a:q
if posStart[0] == posEnd[0] && posStart[1] + 1 == posEnd[1]
return '\%' . posStart[0] . 'l' . '\%' . posStart[1] . 'c'
endif
let r = ''
if posStart[0] == posEnd[0]
let r = r . '\%' . posStart[0] . 'l'
if posStart[1] > 1
let r = r . '\%>' . (posStart[1]-1) .'c'
endif
let r = r . '\%<' . posEnd[1] . 'c'
else
if posStart[0] < posEnd[0] - 1
let r = r . '\%>' . posStart[0] .'l' . '\%<' . posEnd[0] . 'l'
else
let r = r . '\%' . ( posStart[0] + 1 ) .'l'
endif
let r = r . '\|' . '\%(' . '\%' . posStart[0] . 'l\%>' . (posStart[1]-1) . 'c\)' . '\|' . '\%(' . '\%' . posEnd[0] . 'l\%<' . (posEnd[1]+0) . 'c\)'
endif
let r = '\%(' . r . '\)'
return '\V'.r
endfunction
if exists( '*matchadd' )
fun! s:HLinit()
if !exists( 'b:__xptHLids' )
let b:__xptHLids = []
endif
endfunction
fun! s:ClearHL(x,ctx)
call s:HLinit()
for id in b:__xptHLids
try
call matchdelete(id)
catch /.*/
endtry
endfor
let b:__xptHLids = []
endfunction
fun! s:HL(grp,ptn)
call s:HLinit()
call add(b:__xptHLids,matchadd(a:grp,a:ptn,30))
endfunction
else
let s:matchingCmd = { 'XPTcurrentPH':'3match', 'XPTfollowingPH':'match', 'XPTnextItem':'2match', }
fun! s:ClearHL(x,ctx)
for cmd in values(s:matchingCmd)
exe cmd 'none'
endfor
endfunction
fun! s:HL(grp,ptn)
let cmd = get( s:matchingCmd, a:grp, '' )
if '' != cmd
exe cmd a:grp '/' . a:ptn . '/'
endif
endfunction
endif
exe XPT#let_sid
let s:FuncUpdate = function( '<SNR>' . s:sid . "UpdateHL" )
let s:FuncClear = function( '<SNR>' . s:sid . "ClearHL" )
call g:XPTaddPlugin("insertenter" , 'after' , s:FuncUpdate )
call g:XPTaddPlugin("start" , 'after' , s:FuncUpdate )
call g:XPTaddPlugin("update" , 'after' , s:FuncUpdate )
call g:XPTaddPlugin("finishSnippet", 'after' , s:FuncUpdate )
call g:XPTaddPlugin("ph_pum" , 'before', s:FuncClear )
call g:XPTaddPlugin("finishAll" , 'after' , s:FuncClear )

View file

@ -0,0 +1,234 @@
if exists( "g:__XPTEMPLATE_CONF_VIM__" ) && g:__XPTEMPLATE_CONF_VIM__ >= XPT#ver
finish
endif
let g:__XPTEMPLATE_CONF_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
exe XPT#importConst
let s:def = function( "XPT#default" )
call s:def('g:xptemplate_key' , '<C-\>' )
call s:def('g:xptemplate_key_force_pum' , '<C-r>' . g:xptemplate_key )
call s:def('g:xptemplate_key_pum_only' , '<C-r><C-r>' . g:xptemplate_key )
call s:def('g:xptemplate_key_visual' , g:xptemplate_key )
call s:def('g:xptemplate_nav_next' , '<Tab>' )
call s:def('g:xptemplate_nav_prev' , '<S-Tab>' )
call s:def('g:xptemplate_nav_cancel' , '<cr>' )
call s:def('g:xptemplate_goback' , '<C-g>' )
call s:def('g:xptemplate_to_right' , '<C-l>' )
call s:def('g:xptemplate_key_2' , g:xptemplate_key )
call s:def('g:xptemplate_nav_next_2' , g:xptemplate_nav_next )
call s:def('g:xptemplate_fallback' , '<Plug>XPTrawKey' )
call s:def('g:xptemplate_key_visual_2' , g:xptemplate_key_visual )
call s:def('g:xptemplate_fallback_condition' , '\V\c<Tab>' )
call s:def('g:xptemplate_move_even_with_pum' , g:xptemplate_nav_next !=? '<Tab>' )
call s:def('g:xptemplate_close_pum' , 0 )
call s:def('g:xptemplate_break_undo' , 0 )
call s:def('g:xptemplate_always_show_pum' , 0 )
call s:def('g:xptemplate_minimal_prefix' , 1 )
call s:def('g:xptemplate_pum_tab_nav' , 0 )
call s:def('g:xptemplate_pum_quick_back' , 1 )
call s:def('g:xptemplate_strict' , 2 )
call s:def('g:xptemplate_highlight' , 'next' )
call s:def('g:xptemplate_highlight_nested' , 0 )
call s:def('g:xptemplate_brace_complete' , 0 )
call s:def('g:xptemplate_strip_left' , 1 )
call s:def('g:xptemplate_ph_pum_accept_empty' , 1 )
call s:def('g:xptemplate_hook_before_cr' , '' )
call s:def('g:xptemplate_debug_log' , '' )
call s:def('g:xptemplate_vars' , '' )
call s:def('g:xptemplate_bundle' , '' )
call s:def('g:xptemplate_snippet_folders' , [] )
runtime! autoload/xpt/option/*
call s:def('g:xpt_post_action', '')
fun! s:ParseXPTVars()
let var_strings = split(g:xptemplate_vars . '&', '\V'.s:nonEscaped.'&\zs')
let vars = {}
for v in var_strings
let key = matchstr(v, '\V\^\[^=]\*\ze=')
if key == ''
continue
endif
if key !~ '^\$'
let key = '$'.key
endif
let val = matchstr(v, '\V\^\[^=]\*=\zs\.\*')
let escaped_val = xpt#util#UnescapeChar(val, '&')
let vars[key] = strpart(escaped_val,0,len(escaped_val)-1)
endfor
return vars
endfunction
if type( g:xptemplate_minimal_prefix ) == type( '' )
if g:xptemplate_minimal_prefix =~ ','
let [ outer, inner ] = split( g:xptemplate_minimal_prefix, ',' )
if outer =~ '\d'
let g:xptemplate_minimal_prefix = outer + 0
else
let g:xptemplate_minimal_prefix = outer
endif
if inner =~ '\d'
let g:xptemplate_minimal_prefix_nested = inner + 0
else
let g:xptemplate_minimal_prefix_nested = inner
endif
endif
endif
call s:def( 'g:xptemplate_minimal_prefix_nested', g:xptemplate_minimal_prefix )
if g:xptemplate_fallback == ''
let g:xptemplate_fallback = '<NOP>'
endif
if g:xptemplate_fallback == g:xptemplate_key || g:xptemplate_fallback == g:xptemplate_key_force_pum
let g:xptemplate_fallback = 'nore:' . g:xptemplate_fallback
endif
if g:xptemplate_brace_complete is 1
let g:xptemplate_brace_complete = '([{"'''
endif
let s:path = expand( "<sfile>" )
let s:filename = 'xptemplate.conf.vim'
let s:path = substitute( s:path, '\', '/', 'g' )
let s:path = matchstr( s:path, '\V\.\*\ze/plugin/' . s:filename )
let &runtimepath .= ',' . s:path . '/personal'
for s:path in g:xptemplate_snippet_folders
let &runtimepath .= ',' . s:path
endfor
unlet s:path
unlet s:filename
let g:XPTmappings = { 'popup_old':"<C-v><C-v><BS><C-r>=XPTemplateStart(0,{'popupOnly':1})<cr>", 'trigger_old':"<C-v><C-v><BS><C-r>=XPTemplateStart(0)<cr>", 'popup':"<C-r>=XPTemplateStart(0,{'k':'%s','popupOnly':1})<cr>", 'force_pum':"<C-r>=XPTemplateStart(0,{'k':'%s','forcePum':1})<cr>", 'trigger':"<C-r>=XPTemplateStart(0,{'k':'%s'})<cr>", 'wrapTrigger':"\"0s<C-r>=XPTemplatePreWrap(@0)<cr>", 'incSelTrigger':"<C-c>`>a<C-r>=XPTemplateStart(0)<cr>", 'excSelTrigger':"<C-c>`>i<C-r>=XPTemplateStart(0)<cr>", 'selTrigger':(&selection == 'inclusive') ? "<C-c>`>a<C-r>=XPTemplateStart(0,{'k':'%s'})<cr>" : "<C-c>`>i<C-r>=XPTemplateStart(0,{'k':'%s'})<cr>", }
if g:xptemplate_break_undo
let g:XPTmappings.trigger = "<C-g>u" . g:XPTmappings.trigger
endif
if g:xptemplate_close_pum
for k in split('popup,force_pum,trigger', ',')
let g:XPTmappings[k] = "<C-v><C-v><BS>" . g:XPTmappings[k]
endfor
end
if g:xptemplate_fallback =~ '\V\^nore:'
let g:xptemplate_fallback = g:xptemplate_fallback[5:]
exe "inoremap <silent> <Plug>XPTfallback" g:xptemplate_fallback
else
exe "imap <silent> <Plug>XPTfallback" g:xptemplate_fallback
endif
exe "inoremap <silent> <Plug>XPTrawKey" g:xptemplate_key
fun! s:EscapeMap(s)
return substitute( a:s, '\V>', '++', 'g' )
endfunction
exe "inoremap <silent>" g:xptemplate_key printf( g:XPTmappings.trigger , s:EscapeMap( g:xptemplate_key ) )
exe "xnoremap <silent>" g:xptemplate_key_visual g:XPTmappings.wrapTrigger
exe "snoremap <silent>" g:xptemplate_key printf( g:XPTmappings.selTrigger , s:EscapeMap( g:xptemplate_key ) )
exe "inoremap <silent>" g:xptemplate_key_pum_only printf( g:XPTmappings.popup , s:EscapeMap( g:xptemplate_key_pum_only ) )
exe "inoremap <silent>" g:xptemplate_key_force_pum printf( g:XPTmappings.force_pum , s:EscapeMap( g:xptemplate_key_force_pum ))
if g:xptemplate_key_2 != g:xptemplate_key
exe "inoremap <silent>" g:xptemplate_key_2 g:XPTmappings.trigger
exe "snoremap <silent>" g:xptemplate_key_2 g:XPTmappings.selTrigger
endif
if g:xptemplate_key_visual_2 != g:xptemplate_key_visual
exe "xnoremap <silent>" g:xptemplate_key_visual_2 g:XPTmappings.wrapTrigger
endif
let g:XPTpvs = s:ParseXPTVars()
if type( g:xptemplate_bundle ) == type( '' )
let s:bundle = split( g:xptemplate_bundle, ',' )
else
let s:bundle = g:xptemplate_bundle
endif
let g:xptBundle = {}
for ftAndBundle in s:bundle
let [ ft; bundle_list ] = split( ftAndBundle, '_' )
let bundle = join( bundle_list, '_' )
if !has_key(g:xptBundle,ft)
let g:xptBundle[ft] = {}
endif
let g:xptBundle[ft][bundle] = 1
endfor
fun! g:XPTaddBundle(ft,bundle)
call XPTemplateInit()
let g:xptBundle[a:ft] = get(g:xptBundle,a:ft,{})
let g:xptBundle[a:ft][a:bundle] = 1
call XPTembed( a:ft . '/' . a:bundle )
endfunction
fun! g:XPTloadBundle(ft,bundle)
if !has_key(g:xptBundle,a:ft)
return 0
elseif !has_key( g:xptBundle[ a:ft ], a:bundle ) && !has_key( g:xptBundle[ a:ft ], '*' )
return 0
else
return 1
endif
endfunction
fun! XPTfiletypeInit()
if !exists( 'b:xptemplateData' )
call XPTemplateInit()
endif
let x = b:xptemplateData
let fts = x.filetypes
for [ft,ftScope] in items(fts)
let f = ftScope.funcs
for [k,v] in items(g:XPTpvs)
let f[k] = v
endfor
if &l:commentstring != ''
let cms = split( &l:commentstring, '\V%s', 1 )
if cms[1] == ''
let f[ '$CS' ] = get( f, '$CS', cms[0] )
else
if !has_key( f, '$CL' ) && !has_key( f, '$CR' )
let [ f[ '$CL' ], f[ '$CR' ] ] = cms
endif
endif
endif
endfor
endfunction
augroup XPTftInit
au!
au FileType * call XPTfiletypeInit()
augroup END
if stridx( g:xptemplate_brace_complete, '(' ) >= 0
inoremap <silent> ( <C-v><C-v><BS><C-r>=XPTtgr('(',{'noliteral':1,'k':'('})<cr>
endif
if stridx( g:xptemplate_brace_complete, '[' ) >= 0
inoremap <silent> [ <C-v><C-v><BS><C-r>=XPTtgr('[',{'noliteral':1,'k':'['})<cr>
endif
if stridx( g:xptemplate_brace_complete, '{' ) >= 0
inoremap <silent> { <C-v><C-v><BS><C-r>=XPTtgr('{',{'noliteral':1,'k':'{'})<cr>
endif
if stridx( g:xptemplate_brace_complete, '''' ) >= 0
inoremap <silent> ' <C-v><C-v><BS><C-r>=XPTtgr('''',{'noliteral':1,'k':''''})<cr>
endif
if stridx( g:xptemplate_brace_complete, '"' ) >= 0
inoremap <silent> " <C-v><C-v><BS><C-r>=XPTtgr('"',{'noliteral':1,'k':'"'})<cr>
endif
fun! XPTinfo()
if !exists( 'b:xptemplateData' )
return 0
endif
let x = b:xptemplateData
if !x.renderContext.processing
return 0
endif
let st = x.stack
let st = st + [x.renderContext]
call map( st, '{"$snipname":v:val.snipObject.name, "$phname":v:val.item.name}' )
return st
endfunction
fun! XPTinfoStr(...)
let data = XPTinfo()
if data is 0
return ''
endif
let fmt = a:000
if len(fmt) == 0
let fmt = [ "$snipname.$phname", " > " ]
elseif len(fmt) == 1
call add( fmt, " > " )
else
let fmt = fmt[0 : 1]
endif
let rst = []
for e in data
let elt = fmt[0]
for k in [ "$snipname", "$phname" ]
let elt = substitute( elt, '\V' . k, e[ k ], 'g' )
endfor
call add(rst,elt)
endfor
return join(rst,fmt[1])
endfunction
let &cpo = s:oldcpo

View file

@ -0,0 +1,22 @@
if exists( "g:__XPTEMPLATE_PARSER_VIM__" ) && g:__XPTEMPLATE_PARSER_VIM__ >= XPT#ver
finish
endif
let g:__XPTEMPLATE_PARSER_VIM__ = XPT#ver
let s:oldcpo = &cpo
set cpo-=< cpo+=B
runtime plugin/xptemplate.conf.vim
exec XPT#importConst
com! -nargs=* XPTemplate if xpt#parser#InitSnippetFile( expand( "<sfile>" ), <f-args> ) == 'finish' | finish | endif
com! -nargs=* XPTemplateDef call xpt#parser#LoadSnippetToParseList(expand("<sfile>")) | finish
com! -nargs=* XPT call xpt#parser#LoadSnippetToParseList(expand("<sfile>")) | finish
com! -nargs=* XPTvar call xpt#parser#SetVar(<q-args>)
com! -nargs=* XPTsnipSet call xpt#parser#SnipSet(<q-args>)
com! -nargs=+ XPTinclude call xpt#parser#Include(<f-args>)
com! -nargs=+ XPTembed call xpt#parser#Embed(<f-args>)
fun! XPTinclude(...)
call xpt#parser#Load(a:000,1)
endfunction
fun! XPTembed(...)
call xpt#parser#Load(a:000,0)
endfunction
let &cpo = s:oldcpo

File diff suppressed because it is too large Load diff