dot_files/vim-plugins/bundle/xptemplate/plugin/xpmark.vim
2017-07-09 00:26:06 +03:00

695 lines
22 KiB
VimL
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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