Commits

ZyX_I committed 48c0b64

Improved :AuRecord, added record tests

  • Participants
  • Parent commits e7a6d2c

Comments (0)

Files changed (4)

File ftplugin/aurumstatus.vim

     return ':call call(<SID>Eval("s:F.runmap"), '.string(a:000).', {})<CR>'
 endfunction
 "▲2
-" TODO Add K/J mappings
+" TODO Add K/J, «,C» (Commit) mappings
 call s:_f.mapgroup.add('AuStatus', {
             \    'Open': {'lhs': '<CR>', 'rhs': s:F.getrhs(       'open')},
             \   'ROpen': {'lhs':  'o',   'rhs': s:F.getrhs(    'revopen')},

File plugin/aurum.vim

             \ 'norev' : 'No revision %s in repository %s',
             \ 'nofile': 'File %s is not present in revision %s '.
             \           'from repository %s',
+            \ 'noundo': 'Your vim is too old, thus undo is not supported. '.
+            \           'Update to version of Vim that has undotree() '.
+            \           'function available',
+            \ 'recnof': 'No files were selected for commiting',
         \}
 "▶1 Вторая загрузка — функции
 "▶2 hg
     endtry
 endfunction
 "▶2 rec
+"▶3 rec.curundo :: () -> UInt
+if exists('*undotree')
+    function s:F.rec.curundo()
+        return undotree().seq_cur
+    endfunction
+else
+    function s:F.rec.curundo()
+        return 0
+    endfunction
+endif
 "▶3 recfunc
 function s:recfunc.function(opts, ...)
+    let files=copy(a:000)
+    if !empty(files) && a:opts.repo isnot# '.'
+        let repo=s:F.comm.getrepo(s:_r.os.path.dirname(files[0]))
+    else
+        let repo=s:F.comm.getrepo(a:opts.repo)
+    endif
+    let epath=escape(repo.path, ':\')
+    call map(files, 'repo.functions.reltorepo(repo, v:val)')
     tabnew
     let t:aurecid='AuRecordTab'
     let w:aurecid='AuRecordLeft'
     rightbelow vsplit
     let w:aurecid='AuRecordRight'
-    let repo=a:opts.repo
-    let epath=escape(repo.path, ':\')
-    let files=copy(a:000)
-    call map(files, 'repo.functions.reltorepo(repo, v:val)')
     let opts='record:1'
     if !empty(files)
         let opts.=',files:'.join(map(copy(files), 'escape(v:val,"\\;:,")'), ';')
     let bvar.newfiles=[]
     let bvar.lines=map(copy(bvar.chars), 'v:val." ".bvar.files[v:key]')
     let bvar.swheight=height
-    let bvar.startundo=undotree().seq_cur
+    let bvar.startundo=s:F.rec.curundo()
+    let bvar.recopts=extend(copy(a:opts), {'repo': repo})
+    let bvar.bufnr=bufnr('%')
+    let bvar.oldbufs={}
+    if !bvar.startundo
+        setlocal undolevels=-1
+    endif
     augroup AuRecordStatus
+        " XXX Workaround for the fact that
+        autocmd BufWriteCmd <buffer>
+                    \ :call feedkeys("\<C-\>\<C-n>:call ".
+                    \      "call(<SNR>".s:_sid."_Eval('s:F.rec.runstatmap'), ".
+                    \           "['commit', ".expand('<abuf>')."], {})\n", 'n')
         autocmd BufUnload <buffer> :call s:F.rec.unload(
                     \                               s:bufvars[expand('<abuf>')])
     augroup END
+    setlocal buftype=acwrite noreadonly
     if empty(bvar.chars)
         bwipeout!
     endif
 endfunction
 let s:_augroups+=['AuRecordStatus']
+" XXX options message, user, date and closebranch are used by com.commit
 let s:recfunc['@FWC']=['-onlystrings '.
-            \          '{ repo '.s:repoarg.
-            \          ' !addremove   :=(0)'.
-            \          ' ?message           type ""'.
-            \          ' ?date              type ""'.
-            \          ' ?user              type ""'.
-            \          ' !closebranch :=(0)'.
+            \          '{  repo '.s:nogetrepoarg.
+            \          '  ?message           type ""'.
+            \          '  ?date              type ""'.
+            \          '  ?user              type ""'.
+            \          ' !?closebranch'.
             \          '} '.
             \          '+ type ""', 'filter']
 call add(s:reccomp,
     endfor
     let a:bvar.prevct=b:changedtick
     let a:bvar.reset=1
-    let a:bvar.undolevels=&undolevels
-    let a:bvar.startundo=undotree().seq_cur
-    setlocal undolevels=-1
+    if a:bvar.startundo
+        let a:bvar.undolevels=&undolevels
+        let a:bvar.startundo=s:F.rec.curundo()
+        setlocal undolevels=-1
+    endif
+endfunction
+"▶3 rec.supdate
+function s:F.rec.supdate(bvar)
+    if b:changedtick!=a:bvar.prevct
+        let a:bvar.prevct=b:changedtick
+        if a:bvar.reset
+            if has_key(a:bvar, 'undolevels')
+                let &l:undolevels=a:bvar.undolevels
+                unlet a:bvar.undolevels
+            endif
+            let a:bvar.reset=0
+        endif
+    endif
+    setlocal nomodifiable
+endfunction
+"▶3 rec.restorebackup
+function s:F.rec.restorebackup(file, backupfile)
+    if a:backupfile isnot 0
+        if !filereadable(a:backupfile)
+            call s:_f.warn('bkpmis', a:backupfile)
+            return
+        endif
+    endif
+    if delete(a:file)
+        call s:_f.warn('delfail', a:file)
+    endif
+    if a:backupfile isnot 0
+        if rename(a:backupfile, a:file)
+            call s:_f.warn('renfail', a:backupfile, a:file)
+        endif
+    endif
 endfunction
 "▶3 rec.unload
 function s:F.rec.unload(bvar)
+    if bufexists(a:bvar.bufnr)
+        call setbufvar(a:bvar.bufnr, '&modified', 0)
+    endif
+    setlocal nomodified
     if exists('t:aurecid') && t:aurecid is# 'AuRecordTab'
         unlet t:aurecid
-        tabclose!
+        if tabpagenr('$')>1
+            tabclose!
+        else
+            for wnr in filter(range(1, winnr('$')),
+                        \     '!empty(getwinvar(wnr, "aurecid"))')
+                execute wnr.'wincmd w'
+                close!
+            endfor
+        endif
     else
         return
     endif
-    for [backupfile, file] in items(a:bvar.backupfiles)
-        if !filereadable(backupfile)
-            call s:_f.warn('bkpmis', backupfile)
-            continue
-        endif
-        if delete(file)
-            call s:_f.warn('delfail', file)
-        endif
-        if rename(backupfile, file)
-            call s:_f.warn('renfail', backupfile, file)
-        endif
-    endfor
-    for file in a:bvar.newfiles
-        if delete(file)
-            call s:_f.warn('delfail', file)
-        endif
+    call map(copy(a:bvar.backupfiles), 's:F.rec.restorebackup(v:val, v:key)')
+    call map(copy(a:bvar.newfiles),    's:F.rec.restorebackup(v:val,   0  )')
+    for [buf, savedopts] in items(filter(a:bvar.oldbufs, 'bufexists(v:key)'))
+        for [opt, optval] in items(savedopts)
+            call setbufvar(buf, '&'.opt, optval)
+        endfor
     endfor
 endfunction
 "▶3 rec.getwnrs
     endfor
     if lwnr is 0 || rwnr is 0
         execute swnr.'wincmd w'
-        wincmd o
-        topleft split
+        let bvar=s:bufvars[bufnr('%')]
+        if winnr('$')>1
+            only!
+        endif
+        topleft new
         let w:aurecid='AuRecordLeft'
-        vsplit
+        let lwnr=winnr()
+        rightbelow vnew
         let w:aurecid='AuRecordRight'
+        let rwnr=winnr()
         wincmd j
+        let swnr=winnr()
         execute 'resize' bvar.swheight
-        let lwnr=1
-        let rwnr=2
     endif
     return [lwnr, rwnr, swnr]
 endfunction
+"▶3 rec.edit
+function s:F.rec.edit(bvar, fname, ro, ...)
+    let existed=bufexists(a:fname)
+    if a:0 && a:1
+        execute 'silent write!' fnameescape(a:fname)
+    endif
+    execute 'silent edit' fnameescape(a:fname)
+    let buf=bufnr('%')
+    if existed
+        let a:bvar.oldbufs[buf]={'readonly': &readonly,
+                    \          'modifiable': &modifiable,}
+    else
+        setlocal bufhidden=wipe
+    endif
+    if a:ro
+        setlocal   readonly nomodifiable
+    else
+        setlocal noreadonly   modifiable
+    endif
+    if getwinvar(0, 'aurecid') is# 'AuRecordLeft'
+        call s:_f.mapgroup.map('AuRecordLeft')
+    endif
+endfunction
 "▶3 rec.runstatmap
 let s:statchars='-^+*'
-function s:F.rec.runstatmap(action)
+function s:F.rec.runstatmap(action, ...)
     "▶4 buf, bvar, reset
-    let buf=bufnr('%')
+    let buf=get(a:000, 0, bufnr('%'))
     let bvar=s:bufvars[buf]
-    setlocal modifiable noreadonly
+    setlocal modifiable
     if b:changedtick!=bvar.prevct
         call s:_f.warn('uchngs')
         call s:F.rec.reset(bvar)
-        setlocal readonly nomodifiable
+        setlocal nomodifiable
         return
     endif
     "▶4 add/ignore
         let add=(a:action[-3:] is# 'add')
         for line in range(sline, eline)
             let status=bvar.statuses[line-1]
-            if add && status<2
-                let status+=2
-            elseif status>1
-                let status-=2
+            if add
+                if status<2
+                    let status+=2
+                endif
+            else
+                if status>1
+                    let status-=2
+                endif
             endif
+            let bvar.statuses[line-1]=status
             call setline(line, s:statchars[status].bvar.lines[line-1])
         endfor
     "▶4 discard
         return
     "▶4 undo
     elseif a:action is# 'undo'
-        if bvar.reset || undotree().seq_cur<=bvar.startundo
-            setlocal readonly nomodifiable
+        if !bvar.startundo
+            call s:_f.warn('noundo')
+            return
+        endif
+        if bvar.reset || s:F.rec.curundo()<=bvar.startundo
+            setlocal nomodifiable
             return
         endif
         silent undo
         for line in range(1, line('$'))
             let bvar.statuses[line-1]=stridx(s:statchars, getline(line)[0])
         endfor
-        if undotree().seq_cur<bvar.startundo
+        if s:F.rec.curundo()<bvar.startundo
             silent redo
         endif
         " TODO Undo modified files
     "▶4 redo
     elseif a:action is# 'redo'
-        if bvar.reset || undotree().seq_cur<=bvar.startundo
-            setlocal readonly nomodifiable
+        if !bvar.startundo
+            call s:_f.warn('noundo')
+            return
+        endif
+        if bvar.reset || s:F.rec.curundo()<=bvar.startundo
+            setlocal nomodifiable
             return
         endif
         silent redo
         let modified=status%2
         execute lwnr.'wincmd w'
         let fullpath=s:_r.os.path.join(bvar.repo.path, file)
-        if !modified && (type is# 'modified' || type is# 'added' ||
-                    \    type is# 'unknown')
-            let backupfile=fullpath.'.orig'
-            let i=0
-            while s:_r.os.path.exists(backupfile)
-                let backupfile=fullpath.'.'.i.'.orig'
-                let i+=1
-            endwhile
+        if !modified
+            if (type is# 'modified' || type is# 'added' || type is# 'unknown')
+                let backupfile=fullpath.'.orig'
+                let i=0
+                while s:_r.os.path.exists(backupfile)
+                    let backupfile=fullpath.'.'.i.'.orig'
+                    let i+=1
+                endwhile
+            elseif type is# 'removed' || type is# 'deleted'
+                let newfiles+=[fullpath]
+            endif
         endif
         if type is# 'modified' || type is# 'added'   || type is# 'unknown'
                     \          || type is# 'removed' || type is# 'deleted'
-            if !modified
+            if modified
+                call s:F.rec.edit(bvar, fullpath, 0)
+            else
                 execute swnr.'wincmd w'
                 let status=3
                 let bvar.statuses[line('.')-1]=status
                 call s:F.rec.reset(bvar)
-                setlocal readonly nomodifiable
+                setlocal nomodifiable
                 execute lwnr.'wincmd w'
-            else
-                execute 'edit' fnameescape(fullpath)
-                setlocal bufhidden=wipe
             endif
             if type is# 'modified'
                 if !modified
-                    execute 'edit' fnameescape('aurum://file:'.epath.':.:'.file)
-                    setlocal noreadonly modifiable bufhidden=wipe
+                    call s:F.rec.edit(bvar, 'aurum://file:'.epath.':.:'.file, 0)
                 endif
                 diffthis
                 execute rwnr.'wincmd w'
-                execute 'edit' fnameescape('aurum://copy:'.fullpath)
-                setlocal readonly nomodifiable bufhidden=wipe
+                call s:F.rec.edit(bvar, 'aurum://copy:'.fullpath, 1)
                 diffthis
                 wincmd p
             elseif !modified
                 if type is# 'added' || type is# 'unknown'
-                    execute 'edit' fnameescape('aurum://copy:'.fullpath)
-                    setlocal noreadonly modifiable bufhidden=wipe
+                    call s:F.rec.edit(bvar, 'aurum://copy:'.fullpath, 0)
                 elseif type is# 'removed' || type is# 'deleted'
-                    execute 'edit' fnameescape('aurum://file:'.epath.':.:'.file)
-                    setlocal noreadonly modifiable bufhidden=wipe
+                    call s:F.rec.edit(bvar, 'aurum://file:'.epath.':.:'.file, 0)
                 endif
             endif
             if !modified
                     if rename(fullpath, backupfile)
                         call s:_f.warn('renfail', fullpath, backupfile)
                         setlocal readonly nomodifiable
+                        execute swnr.'wincmd w'
                         return
                     endif
                     let bvar.backupfiles[backupfile]=fullpath
                 else
                     let isexe=0
                 endif
-                augroup AuRecordLeft
-                    execute 'autocmd BufWriteCmd <buffer> write! '.
-                                \fnameescape(fullpath).' | setlocal nomodified'
-                augroup END
-                setlocal buftype=acwrite
-                write
+                let diff=&diff
+                call s:F.rec.edit(bvar, fullpath, 0, 1)
+                if diff
+                    diffthis
+                endif
                 if isexe && s:_r.os.name is# 'posix'
                     call s:_r.os.run(['chmod', '+x', fullpath])
                 endif
             endif
+            if !has_key(s:bufvars, bufnr('%'))
+                let s:bufvars[bufnr('%')]={}
+            endif
+            call extend(s:bufvars[bufnr('%')], {'recfile': file,
+                        \                   'recmodified': modified,
+                        \                   'recfullpath': fullpath,
+                        \                    'recnewfile': 0,})
+            if exists('backupfile')
+                let s:bufvars[bufnr('%')].recbackupfile=backupfile
+            else
+                let s:bufvars[bufnr('%')].recnewfile=1
+            endif
         endif
     "▶4 commit
     elseif a:action is# 'commit'
         let epath=escape(bvar.repo.path, ':\')
         let files=filter(copy(bvar.files), 'bvar.statuses[v:key]>1')
-        aboveleft execute 'new' fnameescape('aurum://commit:'.epath.'::::'.
-                    \join(map(copy(files), 'escape(v:val, "\\;")'), ';'))
-        let cbvar=s:bufvars[bufnr('%')]
-        let cbvar.sbvar=bvar
-        startinsert
+        if empty(files)
+            call s:_f.warn('recnof')
+            return
+        endif
+        aboveleft let r=s:F.com.commit(bvar.repo, bvar.recopts, files)
+        if r
+            call s:F.rec.unload(bvar)
+        else
+            let w:aurecid='AuRecordCommitMessage'
+            let cbvar=s:bufvars[bufnr('%')]
+            let cbvar.sbvar=bvar
+        endif
         return
     endif
     "▶4 bvar.prevct, bvar.reset, bvar.undolevels
     if bufnr('%')==buf
-        if b:changedtick!=bvar.prevct
-            let bvar.prevct=b:changedtick
-            if bvar.reset
-                let &l:undolevels=bvar.undolevels
-                unlet bvar.undolevels
-                let bvar.reset=0
-            endif
-        endif
-        setlocal readonly nomodifiable
+        call s:F.rec.supdate(bvar)
     endif
 endfunction
 let s:_augroups+=['AuRecordLeft']
 "▶3 rec.runleftmap
 function s:F.rec.runleftmap(action)
     let [lwnr, rwnr, swnr]=s:F.rec.getwnrs()
-    execute swnr.'wincmd w'
+    let bvar=s:bufvars[bufnr('%')]
+    if a:action is# 'discard'
+        execute lwnr.'wincmd w'
+        execute rwnr.'wincmd w'
+        close!
+        close!
+        let [lwnr, rwnr, swnr]=s:F.rec.getwnrs()
+        execute swnr.'wincmd w'
+        if !bvar.recmodified
+            let sbvar=s:bufvars[bufnr('%')]
+            if bvar.recnewfile
+                call s:F.rec.restorebackup(bvar.recfullpath, 0)
+                call filter(sbvar.newfiles, 'v:val isnot# bvar.recfullpath')
+            else
+                call s:F.rec.restorebackup(bvar.recfullpath, bvar.recbackupfile)
+                unlet sbvar.backupfiles[bvar.recbackupfile]
+            endif
+            let fidx=index(sbvar.files, bvar.recfile)
+            let sbvar.statuses[fidx]=0
+            setlocal modifiable
+            call setline(fidx+1, s:statchars[0].sbvar.lines[fidx])
+            call s:F.rec.supdate(sbvar)
+            setlocal nomodifiable
+        endif
+    elseif a:action is# 'commit'
+        silent update
+        execute swnr.'wincmd w'
+        return s:F.rec.runstatmap('commit')
+    elseif a:action is# 'discardall'
+        execute swnr.'wincmd w'
+        return s:F.rec.runstatmap('discard')
+    elseif a:action is# 'ignore'
+        call s:F.rec.runleftmap('discard')
+        let sbvar=s:bufvars[bufnr('%')]
+        let fidx=index(sbvar.files, bvar.recfile)
+        if sbvar.statuses[fidx]>1
+            let sbvar.statuses[fidx]-=2
+            setlocal modifiable
+            call setline(fidx+1, s:statchars[sbvar.statuses[fidx]].
+                        \        sbvar.lines[fidx])
+            call s:F.rec.supdate(sbvar)
+            setlocal nomodifiable
+        endif
+    endif
 endfunction
 "▶3 rec mappings
 function s:F.rec.gm(...)
             \ 'ignore': {'lhs': 'I', 'rhs': s:F.rec.gm('ignore') },
             \   'edit': {'lhs': 'O', 'rhs': s:F.rec.gm('edit')   },
             \'discard': {'lhs': 'X', 'rhs': s:F.rec.gm('discard')},
-            \ 'commit': {'lhs': 'C', 'rhs': s:F.rec.gm('commit') },
+            \ 'commit': {'lhs': 'i', 'rhs': s:F.rec.gm('commit') },
             \   'undo': {'lhs': 'u', 'rhs': s:F.rec.gm('undo')   },
             \   'vadd': {'lhs': 'A', 'rhs': s:F.rec.gm('vadd'),    'mode': 'v'},
             \'vignore': {'lhs': 'I', 'rhs': s:F.rec.gm('vignore'), 'mode': 'v'},
         \}, {'mode': 'n', 'silent': 1, 'dontmap': 1})
 call s:_f.mapgroup.add('AuRecordLeft', {
-            \   'save': {'lhs': ',A', 'rhs': s:F.rec.gml('save')},
+            \'discard'   : {'lhs': 'x', 'rhs': s:F.rec.gml('discard')   },
+            \'discardall': {'lhs': 'X', 'rhs': s:F.rec.gml('discardall')},
+            \    'commit': {'lhs': 'i', 'rhs': s:F.rec.gml('commit')    },
+            \    'ignore': {'lhs': 'I', 'rhs': s:F.rec.gml('ignore')    },
         \}, {'mode': 'n', 'silent': 1, 'dontmap': 1, 'leader': ','})
 "▶2 com
 "▶3 com.parsedate string -> [year, month, day, hour, minute, second]
         call s:F.rec.unload(bvar.sbvar)
     endif
 endfunction
+"▶3 com.commit :: repo, opts, files -> + repo
+" XXX Do not change names of options used here, see :AuRecord
+function s:F.com.commit(repo, opts, files)
+    let user=''
+    let date=''
+    let message=''
+    let cb=get(a:opts, 'closebranch', 0)
+    for key in filter(['user', 'date', 'message'], 'has_key(a:opts, v:val)')
+        let l:{key}=a:opts[key]
+    endfor
+    "▶4 Normalize date
+    if has_key(a:opts, 'date')
+        let date=substitute(date, '_', ' ', '')
+        let dparts=map(s:F.com.parsedate(date), 'v:val is 0 ? '.
+                    \                               'eval(s:defdate[v:key]) : '.
+                    \                               'v:val')
+        let date=join(dparts[:2], '-').' '.join(dparts[3:], ':')
+    endif
+    "▲4
+    if empty(message)
+        let epath=escape(a:repo.path, ':\')
+        let euser=escape(user, ':\')
+        execute 'silent new'
+                    \fnameescape('aurum://commit:'.epath.':'.euser.':'.date.':'.
+                    \                                        cb.':'.
+                    \            join(map(copy(a:files), 'escape(v:val,"\\;")'),
+                    \                 ';'))
+        startinsert
+        return 0
+    else
+        call a:repo.functions.commit(a:repo, message, a:files, user, date, cb)
+        return 1
+    endif
+endfunction
 "▶3 comfunc
 let s:defdate=['strftime("%Y")',
             \  'strftime("%m")',
         call s:_f.throw('nocfile')
     endif
     "▲4
-    let user=''
-    let date=''
-    let message=''
-    let cb=get(a:opts, 'closebranch', 0)
-    for key in filter(['user', 'date', 'message'], 'has_key(a:opts, v:val)')
-        let l:{key}=a:opts[key]
-    endfor
-    "▶4 Normalize date
-    if has_key(a:opts, 'date')
-        let date=substitute(date, '_', ' ', '')
-        let dparts=map(s:F.com.parsedate(date), 'v:val is 0 ? '.
-                    \                               'eval(s:defdate[v:key]) : '.
-                    \                               'v:val')
-        let date=join(dparts[:2], '-').' '.join(dparts[3:], ':')
-    endif
-    "▲4
-    if empty(message)
-        let epath=escape(repo.path, ':\')
-        let euser=escape(user, ':\')
-        execute 'silent new'
-                    \fnameescape('aurum://commit:'.epath.':'.euser.':'.date.':'.
-                    \                                        cb.':'.
-                    \            join(map(copy(files), 'escape(v:val, "\\;")'),
-                    \                 ';'))
-        startinsert
-    else
-        call repo.functions.commit(repo, message, files, user, date,
-                    \              get(a:opts, 'closebranch', 0))
-    endif
+    return s:F.com.commit(repo, a:opts, files)
 endfunction
 let s:comfunc['@FWC']=['-onlystrings '.
             \          '{  repo '.substitute(s:repoarg, '\V"."', '":"', '').

File test/record.in

+:W{{{1 i mapping
+:R AuRecord
+/M
+AiAbc:write
+:WT
+:W{{{1 BufWriteCmd event
+:R AuRecord
+A:write
+Def:write
+:WT
+:W{{{1 AIiX
+:R AuRecord
+AIiX:WT
+:W{{{1 2A2IiX
+:R AuRecord
+2A2IiX:WT
+:W{{{1 message, {count}A
+:R AuRecord message Ghi
+2Ai:WT
+:W{{{1 message, user, date
+:R AuRecord message Jkl user B\ <b@example.org> date 2008-01-21
+Ai:WT!
+:W{{{1 edit-discard
+:R silent edit nohglinesrev.lst
+:call append('$', 'This is a new text')
+:silent write
+:bwipeout!
+:R AuRecord message Mno
+OGdo:silent write
+,xiX:WT
+:W{{{1 edit-discardall
+:R AuRecord message Mno
+OGdo:silent write
+,X:WT
+:W{{{1 edit-edit-ignore
+:R AuRecord message Mno
+OGdo:silent write
+jOzRggdd,IiX:WT
+:W{{{1 edit-commit
+:R AuRecord message Mno
+OGdo,i:WT
+:source addmessages.vim

File test/record.ok

+{{{1 i mapping
+@  Changeset 23
+|  Tag: tip
+|    Abc
+{{{1 BufWriteCmd event
+@  Changeset 24
+|  Tag: tip
+|    Def
+{{{1 AIiX
+@  Changeset 24
+|  Tag: tip
+|    Def
+{{{1 2A2IiX
+@  Changeset 24
+|  Tag: tip
+|    Def
+{{{1 message, {count}A
+@  Changeset 25
+|  Tag: tip
+|    Ghi
+{{{1 message, user, date
+@  Changeset 26
+|  Commited 21 Jan 2008 00:00 by B <b@example.org>
+|  Tag: tip
+|    Jkl
+{{{1 edit-discard
+@  Changeset 26
+|  Tag: tip
+|    Jkl
+{{{1 edit-discardall
+@  Changeset 26
+|  Tag: tip
+|    Jkl
+{{{1 edit-edit-ignore
+@  Changeset 26
+|  Tag: tip
+|    Jkl
+{{{1 edit-commit
+@  Changeset 27
+|  Tag: tip
+|    Mno
+>>> Messages:
+Frawor:plugin/aurum:recnof:No files were selected for commiting
+Frawor:plugin/aurum:recnof:No files were selected for commiting
+Frawor:plugin/aurum:recnof:No files were selected for commiting
+Frawor:plugin/aurum:recnof:No files were selected for commiting
+<<< Messages^