Commits

ZyX_I committed 603f7a7

Added difftobuffer function (it made aurum able to work with very large diffs), added more mappings to graphlog, replaced json.dumps with own vim_dumps (json has problems with invalid characters)

Comments (0)

Files changed (4)

ftplugin/aurumannotate.vim

 "▶1 AuAnnotate mapping group
 call s:_f.mapgroup.add('AuAnnotate', {
             \    'Enter': {'lhs': '<CR>', 'rhs': s:F.getrhs(   'vimdiff'   )},
-            \    'Diff':  {'lhs':  'd',   'rhs': s:F.getrhs(      'diff'   )},
+            \    'Fdiff': {'lhs': 'gd',   'rhs': s:F.getrhs('rev'.'diff', 1)},
+            \     'Diff': {'lhs':  'd',   'rhs': s:F.getrhs(      'diff'   )},
             \    'Rdiff': {'lhs':  'c',   'rhs': s:F.getrhs('rev'.'diff'   )},
             \    'Vdiff': {'lhs':  'D',   'rhs': s:F.getrhs(   'vimdiff'   )},
             \   'RVdiff': {'lhs':  'C',   'rhs': s:F.getrhs('revvimdiff'   )},
-            \    'Fdiff': {'lhs': 'gd',   'rhs': s:F.getrhs('rev'.'diff', 1)},
             \     'Open': {'lhs':  'o',   'rhs': s:F.getrhs('open'         )},
             \}, {'silent': 1})

ftplugin/aurumgraphlog.vim

 execute frawor#Setup('0.0', {'@aurum': '0.0',
             \            '@/mappings': '0.0',
             \        '@/autocommands': '0.0',
-            \               '@/table': '0.0',})
+            \               '@/table': '0.0',
+            \                  '@/os': '0.0',})
 let s:F.glog={}
 "▶1 bisect :: [a], function + self → a
 function s:F.bisect(list, function)
     elseif spname=~#'\v^file\d+$'
         let file=cs.files[+spname[4:]]
         let cmd='edit '.fnameescape('aurum://file:'.epath.':'.hex.':'.file)
+    "▶3 diff: view diff between changeset and current state
+    elseif spname is# 'diff'
+        let cmd='edit '.fnameescape('aurum://diff:'.epath.'::'.hex)
     "▶3 other: view commit diff
     else
         let cmd='edit '.fnameescape('aurum://diff:'.epath.':'.hex)
     return ''
 endfunction
 "▶1 vimdiff
-function s:F.vimdiff()
+function s:F.vimdiff(...)
     let [hex, file]=s:F.gethexfile()
     let bvar=s:_r.aurum.bufvars[bufnr('%')]
     let cs=bvar.repo.changesets[hex]
-    if !empty(cs.parents)
+    if a:0 && a:1
+        return ':e '.fnameescape(s:_r.os.path.join(bvar.repo.path, file))."\n".
+                    \':diffsplit '.fnameescape('aurum://file:'.epath.':'.
+                    \                          hex.':'.file)."\n"
+    elseif !empty(cs.parents)
         let epath=escape(bvar.repo.path, ':\')
         return ':e '.fnameescape('aurum://file:'.epath.':'.hex.':'.file)."\n".
                     \':diffsplit '.fnameescape('aurum://file:'.epath.':'.
     return ''
 endfunction
 "▶1 AuGlog mapping group
-call s:_f.mapgroup.add('AuGlog', {'Enter': {'lhs': '<CR>', 'rhs': [],},
-            \                     'Diff':  {'lhs': 'd', 'rhs': ['diff']},
-            \                     'Open':  {'lhs': 'o', 'rhs': s:F.open},
-            \                     'VDiff': {'lhs': 'D', 'rhs': s:F.vimdiff},
-            \                     'Next':  {'lhs': 'K', 'rhs': s:F.next},
-            \                     'Prev':  {'lhs': 'J', 'rhs': s:F.prev},},
-            \          {'func': s:F.cr})
+call s:_f.mapgroup.add('AuGlog', {
+            \   'Enter': {'lhs': '<CR>', 'rhs': [],                          },
+            \    'Open': {'lhs': 'o', 'rhs': s:F.open                        },
+            \    'Diff': {'lhs': 'd', 'rhs': ['diff']                        },
+            \   'RDiff': {'lhs': 'c', 'rhs': ['revdiff']                     },
+            \   'VDiff': {'lhs': 'D', 'rhs': [1],         'func': s:F.vimdiff},
+            \  'RVDiff': {'lhs': 'C', 'rhs': s:F.vimdiff                     },
+            \    'Next': {'lhs': 'K', 'rhs': s:F.next                        },
+            \    'Prev': {'lhs': 'J', 'rhs': s:F.prev                        },
+            \}, {'func': s:F.cr})
 "▶1
 execute frawor#Lockvar(s:, '_r')
         let repo=s:repos[a:path]
         return repo.functions.update(repo)
     endif
-    let repo={'functions': s:F.hg}
+    let repo={}
     try
         execute s:_r.py.cmd 'aurum.new_repo(vim.eval("a:path"))'
     catch
         return 0
     endtry
-    call repo.functions.addchangesets(repo, repo.cslist)
+    call s:F.hg.addchangesets(repo, repo.cslist)
     let repo.work=repo.changesets[repo.work_hex]
     let repo.tip=repo.changesets[repo.tip_hex]
     let repo.type='hg'
                 \                  'vim.eval("a:opts"))'
     return r
 endfunction
+"▶3 hg.difftobuffer :: repo, buf, rev1, rev2, [path], opts → [String]
+function s:F.hg.difftobuffer(repo, buf, rev1, rev2, files, opts)
+    let r=[]
+    let oldbuf=bufnr('%')
+    if oldbuf!=a:buf
+        execute 'buffer' a:buf
+    endif
+    try
+        execute s:_r.py.cmd 'aurum.diffToBuffer(vim.eval("a:repo.path"), '.
+                    \                          'vim.eval("a:rev1"), '.
+                    \                          'vim.eval("a:rev2"), '.
+                    \                          'vim.eval("a:files"), '.
+                    \                          'vim.eval("a:opts"))'
+    finally
+        if oldbuf!=a:buf
+            execute 'buffer' oldbuf
+        endif
+    endtry
+endfunction
 "▶2 comm
-"▶3 comm.hasrepo
-function s:F.comm.hasrepo(path)
-    return s:_r.os.path.isdir(s:_r.os.path.join(a:path, '.hg'))
+"▶3 comm.difftobuffer
+function s:F.comm.difftobuffer(repo, buf, ...)
+    let diff=call(a:repo.functions.diff, [a:repo]+a:000, {})
+    let oldbuf=bufnr('%')
+    if oldbuf!=a:buf
+        execute 'buffer' a:buf
+    endif
+    call setline('.', diff)
+    if oldbuf!=a:buf
+        execute 'buffer' oldbuf
+    endif
+endfunction
+"▶3 comm.repotype
+function s:F.comm.repotype(path)
+    if a:path=~#'\v^\w+%(\+\w+)*\V://' ||
+                \s:_r.os.path.isdir(s:_r.os.path.join(a:path, '.hg'))
+        return 'hg'
+    endif
+    return 0
 endfunction
 "▶3 comm.getrepo
 function s:F.comm.getrepo(path)
     endif
     if path!~#'\v^\w+%(\+\w+)*\V://'
         let olddir=''
-        while path isnot# olddir && !s:F.comm.hasrepo(path)
+        while path isnot# olddir && s:F.comm.repotype(path) is 0
             let olddir=path
             let path=fnamemodify(path, ':h')
         endwhile
     endif
-    return s:F.hg.repo(path)
+    let repotype=s:F.comm.repotype(path)
+    let repo=s:F[repotype].repo(path)
+    let repo.functions=s:F[repotype]
+    if !has_key(repo.functions, 'difftobuffer')
+        let repo.functions.difftobuffer=s:F.comm.difftobuffer
+    endif
+    return repo
 endfunction
 "▶3 comm.globtopattern :: glob → pattern
 function s:F.comm.globtopattern(glob)
                         \                 'index(filelist, v:val)==-1')
         endfor
         "▲5
-        let s:bufvars[bufnr('%')]={'repo': repo, 'rev1': rev1, 'rev2': rev2,
-                    \             'files': filelist,}
+        let buf=bufnr('%')
+        let s:bufvars[buf]={'repo': repo, 'rev1': rev1, 'rev2': rev2,
+                    \       'files': filelist,}
         setlocal buftype=nofile filetype=diff
-        call setline('.', repo.functions.diff(repo, rev1, rev2, filelist, opts))
+        call repo.functions.difftobuffer(repo, buf, rev1, rev2, filelist, opts)
     endif
 endfunction
 "▶3 glogfunc
 function s:glogfunc.function(repo, opts)
+    if type(a:repo)!=type({})
+        return
+    endif
     new aurum://glog:no-op
     if has_key(a:opts, 'rev')
         call map(a:opts.rev,
     setlocal buftype=nofile filetype=aurumgraphlog bufhidden=wipe
     runtime ftplugin/aurumgraphlog.vim
 endfunction
-let s:glogfunc['@FWC']=['[:=(".")(either(path d, match @\v^\w+%(\+\w+)*\V://@)'.
-            \                    '|*F.comm.getrepo)'.
+let s:glogfunc['@FWC']=['[:*F.comm.getrepo(".") '.
+            \            '(either(path d, match @\v^\w+%(\+\w+)*\V://@)'.
+            \                            '|*F.comm.getrepo)]'.
             \           ' { *?files   (type "" |*F.comm.globtopattern)'.
             \           '    ?date    match /\v%(\d\d?|\*)'.
             \                                 '%(\.%(\d\d?|\*)'.
             \           '   !?patch'.
             \           '    ?limit   range 1 inf'.
             \           '   !?stat'.
-            \           '   !?showfiles}]',
+            \           '   !?showfiles}',
             \'filter']
 call add(s:glogcomp,
             \substitute(substitute(s:glogfunc['@FWC'][0],
 
 from mercurial import hg, ui, commands
 import vim
-import json
 import os
 
-vim_dumps=json.dumps
+def vim_dumps(obj):
+    todump=[('dump', obj)]
+    r=''
+    while todump:
+        t, obj = todump.pop(0)
+        if t == 'inject':
+            r+=obj
+        else:
+            tobj=type(obj)
+            if tobj is dict:
+                r+='{'
+                todump.insert(0, ('inject', '}'))
+                for key, value in obj.items():
+                    todump.insert(0, ('inject', ','))
+                    todump.insert(0, ('dump', value))
+                    todump.insert(0, ('inject', ':'))
+                    todump.insert(0, ('dump', key))
+            elif tobj is list:
+                r+='['
+                todump.insert(0, ('inject', ']'))
+                for value in reversed(obj):
+                    todump.insert(0, ('inject', ','))
+                    todump.insert(0, ('dump', value))
+            elif tobj is int:
+                r+=str(obj)
+            elif tobj is float:
+                r += "%1.1e" % obj
+            else:
+                r+='"'+str(obj).replace('\\', '\\\\').replace('"', '\\"')+'"'
+    return r
 
 class CaptureUI(ui.ui):
     def __init__(self):
         self._captured=[]
         return r
 
+class CaptureToBuf(ui.ui):
+    def __init__(self, buf):
+        self._vimbuffer=buf
+        super(CaptureToBuf, self).__init__()
+
+    def write(self, *args, **kwargs):
+        target=self._buffers[-1] if self._buffers else self._vimbuffer
+        for a in args:
+            lines=str(a).split("\n")
+            target[-1]+=lines.pop(0)
+            for line in lines:
+                target.append(line)
+
 def get_repo(path):
     return hg.repository(ui.ui(), path)
 
     vim.eval('extend(r, ['+",".join(['"'+line[0].hex()+'"' for line in ann])+
                        '])')
 
-def diff(path, rev1, rev2, files, opts):
+def dodiff(ui, path, rev1, rev2, files, opts):
     repo=get_repo(path)
-    ui=CaptureUI()
     args=[ui, repo]+files
     kwargs=opts
     if rev1:
     except OSError:
         pass
     commands.diff(*args, **kwargs)
+    os.chdir(workdir)
+
+def diff(*args, **kwargs):
+    ui=CaptureUI()
+    dodiff(ui, *args, **kwargs)
     vim.eval('extend(r, '+vim_dumps(ui._getCaptured())+')')
-    os.chdir(workdir)
+
+def diffToBuffer(*args, **kwargs):
+    ui=CaptureToBuf(vim.current.buffer)
+    dodiff(ui, *args, **kwargs)