dot_files/vim-plugins/bundle/xptemplate/plugin/xpmark.vim

696 lines
22 KiB
VimL
Raw Normal View History

2017-07-09 00:26:06 +03:00
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