Commits

ZyX_I committed 5479086

@aurum/log: Now also compiling former s:F.glog.graphlog

  • Participants
  • Parent commits 7c0dda9

Comments (0)

Files changed (1)

plugin/aurum/log.vim

         return feedkeys(a:d.input)
     endif
 endfunction
-"▶2 glog.graphlog
-function s:F.glog.graphlog(repo, opts, csiterfuncs, bvar, read)
-    "▶3 Get grapher
-    if get(a:repo, 'has_octopus_merges', 1)
-        let literfuncs=s:iterfuncs.git
-    elseif get(a:repo, 'has_merges', 1)
-        let literfuncs=s:iterfuncs.hg
-    else
-        let literfuncs=s:iterfuncs.simple
-    endif
-    "▶3 Initialize variables
-    let haslimit=(has_key(a:opts, 'limit') && a:opts.limit)
-    if haslimit
-        let limit=a:opts.limit
-    endif
-    let foundfirst=0
-    let csbuf=[]
-    let reqprops=keys(a:opts.reqs)
-    call filter(reqprops, 'index(a:repo.initprops, v:val)==-1')
-    let a:opts.skipchangesets={}
-    let skipchangesets=a:opts.skipchangesets
-    let firstcs=1
-    let lastline=0
-    let r=[]
-    "▶3 Initialize variables not required for reading
-    if !a:read
-        let specials={}
-        let rectangles=[]
-        let csstarts={}
-        let a:bvar.rectangles=rectangles
-        let a:bvar.specials=specials
-        let a:bvar.csstarts=csstarts
-        let sd=s:iterfuncs.csshow.setup(a:bvar.procinput)
-    endif
-    "▶3 Initialize iterator functions
-    let ld=literfuncs.start(a:repo,a:opts,[a:repo.functions.getworkhex(a:repo)])
-    let csd=a:csiterfuncs.start(a:repo, a:opts)
-    let checkd=s:iterfuncs.check.generate(a:repo, a:opts)
-    "▲3
-    while 1 && (!haslimit || limit)
-        let cs=a:csiterfuncs.next(csd)
-        if cs is 0 "▶3
-            return r
-        endif "▲3
-        let skip=!checkd.check(cs)
-        "▶3 Add cs to skipchangesets or get its properties
-        if skip
-            let a:opts.skipchangesets[cs.hex]=cs
-        else
-            call map(copy(reqprops),
-                        \'a:repo.functions.getcsprop(a:repo, cs, v:val)')
-            let foundfirst=1
-            if haslimit
-                let limit-=1
-            endif
-        endif
-        "▲3
-        if foundfirst
-            let csbuf+=[cs]
-            if !skip
-                for cs in csbuf
-                    let [lines, rectangle, special]=literfuncs.proccs(ld, cs)
-                    "▶3 Add various information to bvar
-                    if !a:read && rectangle isnot 0
-                        let rectangle[0][0]=lastline
-                        let lastline+=len(lines)
-                        let rectangle[1][0]=lastline-1
-                        let rectangle+=[cs.hex]
-                        call add(rectangles, rectangle)
-                        let csstarts[cs.hex]=rectangle[0][0]
-                        if special isnot 0
-                            let specials[cs.hex]=special
-                        endif
-                    endif
-                    "▶3 Add lines to returned list if reading
-                    if a:read
-                        let r+=lines
-                    "▶3 Add lines to buffer if not, process user input
-                    else
-                        "▶4 Add lines to buffer
-                        if firstcs
-                            call setline(1, lines)
-                            let firstcs=0
-                        else
-                            call append('$', lines)
-                        endif
-                        "▲4
-                        call s:iterfuncs.csshow.next(sd)
-                    endif
-                    "▲3
-                    unlet rectangle special
-                endfor
-                call remove(csbuf, 0, -1)
-            endif
-        endif
-        unlet cs
-    endwhile
-    if !a:read
-        call s:iterfuncs.csshow.finish(sd)
-    endif
-    return r
-endfunction
 "▶1 iterfuncs: loggers
 "▶2 iterfuncs.git
 let s:iterfuncs.git={}
 " startfunc (here)  :: repo, opts → d
 let s:fcheckpropslist=['renames', 'copies', 'changes', 'files']
 let s:iterfuncs.check={}
-"▶2 getcid :: opts → cid
-function s:F.getcid(opts)
+"▶2 getcheckcid :: opts → cid
+function s:F.getcheckcid(opts)
     let r    =   get(a:opts, 'merges', 2).
                 \get(a:opts, 'date', '').'D'
     for o in ['branch', 'search', 'user']
         \}
 let s:datechars='YmdHM'
 function s:iterfuncs.check.generate(repo, opts)
-    let cid=s:F.getcid(a:opts)
+    let cid=s:F.getcheckcid(a:opts)
     let r={}
     if has_key(a:opts, 'files')
         let r.csfiles={}
     endif
     if has_key(s:checkcache, cid)
         let r.check=s:checkcache[cid]
+        if r.check is 0
+            return 0
+        endif
         return r
     endif
-    let function=['function r.check(cs)']
+    let function=[]
     let precond=join(values(map(filter(copy(a:opts),
                 \                      'has_key(s:keytoexpr, v:key)'),
                 \               'eval(s:keytoexpr[v:key])')), '||')
                     \]
     endif
     "▲3
+    if empty(function)
+        let s:checkcache[cid]=0
+        return 0
+    endif
+    call insert(function, 'function r.check(cs)')
     let function+=['    return 1', 'endfunction']
     execute join(function, "\n")
     let s:checkcache[cid]=r.check
     return r
 endfunction
+"▶1 iterfuncs.glog
+let s:iterfuncs.glog={}
+let s:glogcache={}
+"▶2 iterfuncs.glog.generate
+function s:iterfuncs.glog.generate(repo, opts, csiterfuncs, bvar, read)
+    let r={}
+    "▶3 Get grapher
+    if get(a:repo, 'has_octopus_merges', 1)
+        let r.literfuncs=s:iterfuncs.git
+    elseif get(a:repo, 'has_merges', 1)
+        let r.literfuncs=s:iterfuncs.hg
+    else
+        let r.literfuncs=s:iterfuncs.simple
+    endif
+    "▶3 Initialize variables
+    let r.csbuf=[]
+    let reqprops=keys(a:opts.reqs)
+    call filter(reqprops, 'index(a:repo.initprops, v:val)==-1')
+    if !empty(reqprops)
+        let r.repo=a:repo
+    endif
+    let a:opts.skipchangesets={}
+    let skipchangesets=a:opts.skipchangesets
+    let firstcs=1
+    let r.lastline=0
+    if a:read
+        let r.lines=[]
+    endif
+    "▶3 Initialize variables not required for reading
+    if !a:read
+        let r.specials={}
+        let r.rectangles=[]
+        let r.csstarts={}
+        let a:bvar.rectangles=r.rectangles
+        let a:bvar.specials=r.specials
+        let a:bvar.csstarts=r.csstarts
+        let r.sd=s:iterfuncs.csshow.setup(a:bvar.procinput)
+    endif
+    "▶3 Initialize iterator functions
+    let r.ld=r.literfuncs.start(a:repo, a:opts,
+                \               [a:repo.functions.getworkhex(a:repo)])
+    let r.csiterfuncs=a:csiterfuncs
+    let r.csd=a:csiterfuncs.start(a:repo, a:opts)
+    let r.checkd=s:iterfuncs.check.generate(a:repo, a:opts)
+    let hascheck=(r.checkd isnot 0)
+    if !hascheck
+        unlet r.checkd
+    endif
+    let r.opts=a:opts
+    "▶3 Try to use cache
+    let cid=hascheck.a:read.(join(reqprops, ';'))
+    if has_key(s:glogcache, cid)
+        let [r.next, r.ffnext]=s:glogcache[cid]
+        return r
+    endif
+    "▲3
+    let fflines=[]
+    let function=['function r.next()',
+                \ '    let cs=self.csiterfuncs.next(self.csd)',
+                \ '    if cs is 0 | return -1 | endif',]
+    if hascheck
+        let function+=['    let skip=!self.checkd.check(cs)',
+                    \  '    if skip',
+                    \  '        let self.opts.skipchangesets[cs.hex]=cs',
+                    \  '        return 0',
+                    \  '    else',]
+        let fflines+=[len(function)-2]
+    endif
+    if empty(reqprops)
+        if hascheck
+            let fflines+=[len(function)-1]
+        endif
+    else
+        let function+=['        call map('.string(reqprops).', '.
+                \                       '"self.repo.functions.getcsprop('.
+                \                                 'self.repo, cs, v:val)")']
+    endif
+    let fflines+=[len(function)]
+    let function+=['        let self.next=self.ffnext']
+    if hascheck
+        let function+=['    endif',
+                    \  '    let self.csbuf+=[cs]',
+                    \  '    if skip | return 0 | endif',
+                    \  '    for cs in self.csbuf',]
+    endif
+    let function+=['        let [lines, rectangle, special]='.
+                \                     'self.literfuncs.proccs(self.ld, cs)']
+    if a:read
+        let function+=['        let self.lines+=lines']
+    else
+        let function+=['        if rectangle isnot 0',
+                    \  '            let rectangle[0][0]=self.lastline',
+                    \  '            let self.lastline+=len(lines)',
+                    \  '            let rectangle[1][0]=self.lastline-1',
+                    \  '            let rectangle+=[cs.hex]',
+                    \  '            call add(self.rectangles, rectangle)',
+                    \  '            let self.csstarts[cs.hex]=rectangle[0][0]',
+                    \  '            if special isnot 0',
+                    \  '                let self.specials[cs.hex]=special',
+                    \  '            endif',
+                    \  '        endif']
+        let fflines+=[len(function), len(function)+2]
+        let function+=['        if 1 | call setline(1, lines) | else',
+                    \  '        call append("$", lines)',
+                    \  '        endif',
+                    \  '        call s:iterfuncs.csshow.next(self.sd)']
+    endif
+    if hascheck
+        let function+=['        unlet lines rectangle special',
+                    \  '    endfor',
+                    \  '    call remove(self.csbuf, 0, -1)']
+    endif
+    let function+=['    return 1', 'endfunction']
+    let fffunction=copy(function)
+    let fffunction[0]=substitute(fffunction[0], 'next', 'ffnext', '')
+    call map(reverse(fflines), 'remove(fffunction, v:val)') | unlet fflines
+    execute join(function, "\n")
+    execute join(fffunction, "\n")
+    let s:glogcache[cid]=[r.next, r.ffnext]
+    return r
+endfunction
+"▶2 iterfuncs.glog.iterate
+function s:iterfuncs.glog.iterate(...)
+    let limit=a:2.limit
+    let haslimit=(!!limit)
+    let gd=call(s:iterfuncs.glog.generate, a:000, {})
+    let r=0
+    while r!=-1 && (!haslimit || limit)
+        let r=gd.next()
+        let limit-=r
+    endwhile
+    if !a:5
+        call s:iterfuncs.csshow.finish(gd.sd)
+    endif
+    return get(gd, 'lines', [])
+endfunction
 "▶1 getblock :: bvar + cursor, bvar → block
 "▶2 bisect :: [a], function + self → a
 function s:F.bisect(list, function)
         endif
     endif
     let bvar.cw=s:_f.getoption('closelogwindow')
-    let text=s:F.glog.graphlog(a:repo, opts, csiterfuncs, bvar, a:read)
+    let text=s:iterfuncs.glog.iterate(a:repo, opts, csiterfuncs, bvar, a:read)
     if a:read
         call s:_r.lineutils.setlines(text, a:read)
     elseif bufnr('%')==buf
             \'requiresbvar': 1,
             \})
 "▶1
-call frawor#Lockvar(s:, '_r,checkcache')
+call frawor#Lockvar(s:, '_r,checkcache,glogcache')
 " vim: ft=vim ts=4 sts=4 et fmr=▶,▲