ZyX_I avatar ZyX_I committed aaeed62

Move undo stuff from @%aurum/record into @%aurum/undo

Comments (0)

Files changed (7)

aurum-addon-info.txt

         "autoload/aurum/status.vim",
         "autoload/aurum/tabutils.vim",
         "autoload/aurum/track.vim",
+        "autoload/aurum/undo.vim",
         "autoload/aurum/update.vim",
         "autoload/aurum/vimdiff.vim",
         "autoload/fuf/aurum.vim",

autoload/aurum/record.vim

             \         '@%aurum/tabutils': '0.0',
             \        '@%aurum/lineutils': '0.0',
             \             '@%aurum/edit': '1.5',
+            \             '@%aurum/undo': '0.0',
             \          '@%aurum/bufvars': '0.0',})
-let s:hasundo=exists('*undotree')
 let s:_options={
             \'recheight': {'default': 0,
             \               'filter': '(if type "" earg _  range 0 inf)'},
-            \'fullundo':  {'default': s:hasundo,
+            \'fullundo':  {'default': 1,
             \               'filter': 'bool'},
         \}
 let s:_messages={
             \ 'bkpmis': 'Backup file %s not found',
             \'delfail': 'Failed to remove file %s',
             \'renfail': 'Failed to move file %s to %s',
-            \ 'uchngs': 'Found changes done manually. Resetting buffer, '.
-            \           'please retry.',
-            \ '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',
             \   'norm': 'Can’t remove file %s as it was not added',
             \   'noad': 'Can’t add file %s as it is already included',
-            \'noutree': 'No such item in saved undo tree. '.
-            \           'If you can reproduce this error file a bug report',
-            \'tooundo': 'Undone too much changes and cannot redo',
-            \ 'undona': "Can’t undo changes. Possible reasons:\n".
-            \           "  1. You did some changes manually and thus buffer ".
-            \                "was reset\n".
-            \           "  2. You edited a file which discards undo ".
-            \                "information unless g:aurum_fullundo is set",
-            \ 'redona': "Can’t redo changes. Possible reasons:\n".
-            \           "  1. You did some changes manually and thus buffer ".
-            \                "was reset\n".
-            \           "  2. You edited a file which discards undo ".
-            \                "information unless g:aurum_fullundo is set",
         \}
 "▶1 commitvimdiffcb
 function s:F.commitvimdiffcb(file, bvar, hex)
         endif
     endfor
     let a:bvar.recopts.message = a:state.description
-    setlocal modifiable
-    call s:F.reset(a:bvar)
-    setlocal nomodifiable
+    call s:_r.undo.reset(a:bvar)
     call cursor(1, 1)
 endfunction
 "▶1 getswheight
 function s:F.getswheight()
     let height=s:_f.getoption('recheight')
     if height<=0
-        return winheight(0)/5
+        return (&lines-&cmdheight-(!!&laststatus))/5
     endif
     return height
 endfunction
     " 2:     included, unmodified
     " 3:     included,   modified
     let bvar.statuses=repeat([0], len(bvar.types))
-    let bvar.prevct=b:changedtick
-    let bvar.reset=0
     let bvar.backupfiles={}
     let bvar.filesbackup={}
     let bvar.newfiles={}
     let bvar.lines=map(copy(bvar.chars), 'v:val." ".bvar.files[v:key]')
-    let bvar.startundo=s:F.curundo()
     let bvar.recopts=extend(copy(a:opts), {'repo': repo})
     let bvar.bufnr=bufnr('%')
     let bvar.oldbufs={}
                 \        'autowrite': &autowrite,
                 \     'autowriteall': &autowriteall,
                 \         'autoread': &autoread,}
-    let bvar.fullundo=(s:hasundo && s:_f.getoption('fullundo'))
-    if bvar.fullundo
-        let bvar.undotree={bvar.startundo : {}}
-    endif
+    let bvar.resetlines=s:F.resetlines
+    let bvar.pulllines=s:F.pulllines
+    let bvar.procundoleaf=s:F.procundoleaf
+    call s:_r.undo.setup(bvar, s:_f.getoption('fullundo'))
     setglobal noautowrite noautowriteall noautoread
     setlocal noreadonly buftype=acwrite
     augroup AuRecordVimLeave
         call s:F.setstate(repo, bvar, state)
     endif
 endfunction
-"▶1 curundo :: () → UInt
-if s:hasundo
-    function s:F.curundo()
-        return undotree().seq_cur
-    endfunction
-else
-    function s:F.curundo()
-        return 0
-    endfunction
-endif
-"▶1 reset
-function s:F.reset(bvar)
+"▶1 resetlines
+function s:F.resetlines(bvar)
     for idx in range(len(a:bvar.lines))
         call setline(idx+1, s:statchars[a:bvar.statuses[idx]].a:bvar.lines[idx])
     endfor
-    let a:bvar.prevct=b:changedtick
-    let a:bvar.reset=1
-    if s:hasundo
-        let a:bvar.startundo=s:F.curundo()
-        let savedundolevels=&undolevels
-        setglobal undolevels=-1
-        execute "normal! A \<BS>\e"
-        let &undolevels=savedundolevels
-        if a:bvar.fullundo
-            let a:bvar.undotree={a:bvar.startundo : {}}
-        endif
-    endif
-endfunction
-"▶1 supdate
-function s:F.supdate(bvar, prevundo)
-    if b:changedtick!=a:bvar.prevct
-        let a:bvar.prevct=b:changedtick
-        if a:bvar.reset
-            let a:bvar.reset=0
-        endif
-        let curundo=s:F.curundo()
-        if              a:bvar.fullundo
-                    \&& has_key(a:bvar.undotree, a:prevundo)
-                    \&& curundo!=a:prevundo
-                    \&& !has_key(a:bvar.undotree, curundo)
-            let a:bvar.undotree[curundo]=copy(a:bvar.undotree[a:prevundo])
-        endif
-    endif
-    setlocal nomodifiable
 endfunction
 "▶1 restorebackup
 function s:F.restorebackup(file, backupfile)
         call s:F.restorebackup(fullpath, backupfile)
     endfor
 endfunction
-"▶1 undoup :: bvar → + bvar
-function s:F.undoup(bvar)
+"▶1 pulllines
+function s:F.pulllines(bvar)
     for line in range(1, line('$'))
         let a:bvar.statuses[line-1]=stridx(s:statchars, getline(line)[0])
     endfor
-    if a:bvar.fullundo
-        let curundo=s:F.curundo()
-        if !has_key(a:bvar.undotree, curundo)
-            call s:F.reset(a:bvar)
-            call s:_f.throw('noutree')
+endfunction
+"▶1 procundoleaf
+function s:F.procundoleaf(bvar, undoleaf)
+    for [file, contents] in items(a:undoleaf)
+        if contents is 0 && filereadable(file)
+            call delete(file)
+        else
+            call writefile(contents, file, 'b')
         endif
-        for [file, contents] in items(a:bvar.undotree[curundo])
-            if contents is 0 && filereadable(file)
-                call delete(file)
-            else
-                call writefile(contents, file, 'b')
-            endif
-            unlet contents
-        endfor
-    endif
+        unlet contents
+    endfor
 endfunction
 "▶1 undoleafwrite :: bvar, lines::[String], path → + bvar, FS
 function s:F.undoleafwrite(bvar, lines, file)
     endif
     return backupfile
 endfunction
+"▶1 updateline
+function s:F.updateline(bvar, ...)
+    let line=get(a:000, 0, line('.'))
+    call setline(line, s:statchars[a:bvar.statuses[line-1]].a:bvar.lines[line-1])
+    return 0
+endfunction
 "▶1 sactions
 let s:F.sactions={}
 "▶2 sactions.[v]add, sactions.[v]remove
 "▶2 sactions.undo
 function s:F.sactions.undo(action, bvar, buf)
     execute 'silent normal! '.v:count1.'u'
-    let curundo=s:F.curundo()
-    if curundo<a:bvar.startundo
-        while curundo<a:bvar.startundo
-            let pundo=curundo
-            silent redo
-            let curundo=s:F.curundo()
-            if curundo==pundo
-                call s:_f.throw('tooundo')
-                call s:F.reset(a:bvar)
-                setlocal nomodifiable
-                return 0
-            endif
-        endwhile
-    endif
-    return 1
+    return s:_r.undo.postundo(a:bvar)
 endfunction
 "▶2 sactions.redo, sactions.earlier, sactions.later
 let s:uactkey={
             let status=3
             let a:bvar.statuses[line('.')-1]=status
         endif
-        if a:bvar.fullundo
-            let prevundo=s:F.curundo()
-            let line=line('.')
-            call setline(line, s:statchars[status].a:bvar.lines[line-1])
-            call s:F.supdate(a:bvar, prevundo)
-            let curundo=s:F.curundo()
+        if a:bvar.undo_full
+            call s:_r.undo.doaction(a:bvar, 0, s:F.updateline)
+            let undoleaf=s:_r.undo.getundoleaf(a:bvar)
         else
-            call s:F.reset(a:bvar)
+            call s:_r.undo.reset(a:bvar)
         endif
-        setlocal nomodifiable
         execute lwnr.'wincmd w'
         call s:F.edit(a:bvar, 'aurum://edit:'.fullpath, 0)
-        if a:bvar.fullundo
+        if a:bvar.undo_full
             let ebvar=s:_r.bufvars[bufnr('%')]
-            let undoleaf=a:bvar.undotree[curundo]
             let ebvar.undoleaf=undoleaf
             let ebvar.fullpath=fullpath
             let ebvar.ewrite=ebvar.write
                 endif
                 let a:bvar.backupfiles[backupfile]=fullpath
                 let a:bvar.filesbackup[fullpath]=backupfile
-                if a:bvar.fullundo
+                if a:bvar.undo_full
                     let undoleaf[fullpath]=0
                     let undoleaf[backupfile]=readfile(backupfile, 'b')
                     let oundoleafpart={fullpath   : copy(undoleaf[backupfile]),
                                 \      backupfile : 0}
-                    call map(a:bvar.undotree,
-                                \'extend(v:val, oundoleafpart, "keep")')
+                    call s:_r.undo.updatetree(a:bvar, oundoleafpart)
                 endif
             else
                 let isexe=0
             \'removed':  'r',
             \'deleted':  'r',
         \}
-let s:uactions=['undo', 'redo', 'earlier', 'later']
+let s:uactions={
+            \   'undo': 'undo',
+            \   'redo': 'redo',
+            \'earlier': 'undo',
+            \  'later': 'redo',
+        \}
 function s:F.runstatmap(action, ...)
     "▶2 buf, bvar, reset
     let buf=get(a:000, 0, bufnr('%'))
     let bvar=s:_r.bufvars[buf]
-    setlocal modifiable
-    if !a:0 && b:changedtick!=bvar.prevct
-        if bvar.fullundo && has_key(bvar.undotree, s:F.curundo())
-            call s:F.undoup(bvar)
-        else
-            call s:_f.warn('uchngs')
-            call s:F.reset(bvar)
-            setlocal nomodifiable
+    if !a:0
+        if !s:_r.undo.preaction(bvar)
             return
         endif
     endif
     "▶2 undo
-    let isundo=(index(s:uactions, a:action)!=-1)
+    let isundo=has_key(s:uactions, a:action)
     if isundo
-        if !s:hasundo
-            call s:_f.warn('noundo')
-            return
-        endif
-        if bvar.reset
-            setlocal nomodifiable
-            call s:_f.warn(a:action.'na')
+        if !s:_r.undo.preundoaction(bvar, s:uactions[a:action])
             return
         endif
     endif
-    let prevundo=s:F.curundo()
     "▶2 action
-    if s:F.sactions[a:action](a:action, bvar, buf)
-        if bufnr('%')==buf
-            if isundo && s:F.curundo()!=prevundo
-                call s:F.undoup(bvar)
-            endif
-            call s:F.supdate(bvar, prevundo)
-        endif
+    call s:_r.undo.doaction(bvar, 1, s:F.runaction, a:action,buf,isundo)
+endfunction
+"▶1 runaction
+function s:F.runaction(bvar, action, buf, isundo)
+    if s:F.sactions[a:action](a:action, a:bvar, a:buf)
+        return a:isundo
     endif
+    return 0
 endfunction
 "▶1 runleftmap
 function s:F.runleftmap(action)
             endif
             let fidx=index(sbvar.files, bvar.recfile)
             let sbvar.statuses[fidx]=0
-            setlocal modifiable
-            let prevundo=s:F.curundo()
-            call setline(fidx+1, s:statchars[0].sbvar.lines[fidx])
-            call s:F.supdate(sbvar, prevundo)
+            call s:_r.undo.doaction(sbvar, 0, s:F.updateline, fidx+1)
         endif
     elseif a:action is# 'commit'
         silent update
         let fidx=index(sbvar.files, bvar.recfile)
         if sbvar.statuses[fidx]>1
             let sbvar.statuses[fidx]-=2
-            setlocal modifiable
-            let prevundo=s:F.curundo()
-            call setline(fidx+1, s:statchars[sbvar.statuses[fidx]].
-                        \        sbvar.lines[fidx])
-            call s:F.supdate(sbvar, prevundo)
+            call s:_r.undo.doaction(sbvar, 0, s:F.updateline, fidx)
         else
             call s:_f.warn('norm', bvar.recfile)
         endif

autoload/aurum/tabutils.vim

 function s:F.getids(layout)
     return a:layout.top + [a:layout.bottom]
 endfunction
-"▶1 settoplayout
+"▶1 r.settoplayout
 function s:r.settoplayout(layout)
     let w:aurum_winid=a:layout.top[0]
     for id in a:layout.top[1:]

autoload/aurum/undo.vim

+"▶1 
+scriptencoding utf-8
+execute frawor#Setup('0.0', {'@/resources': '0.0'})
+let s:_messages={
+            \'noutree': 'No such item in saved undo tree. '.
+            \           'If you can reproduce this error file a bug report',
+            \'tooundo': 'Undone too much changes and cannot redo',
+            \ 'undona': "Can’t undo changes. Possible reasons:\n".
+            \           "  1. You did some changes manually and thus buffer ".
+            \                "was reset\n".
+            \           "  2. You edited a file which discards undo ".
+            \                "information unless g:aurum_fullundo is set",
+            \ 'redona': "Can’t redo changes. Possible reasons:\n".
+            \           "  1. You did some changes manually and thus buffer ".
+            \                "was reset\n".
+            \           "  2. You edited a file which discards undo ".
+            \                "information unless g:aurum_fullundo is set",
+            \ 'uchngs': 'Found changes done manually. Resetting buffer, '.
+            \           'please retry.',
+            \ 'noundo': 'Your vim is too old, thus undo is not supported. '.
+            \           'Update to version of Vim that has undotree() '.
+            \           'function available',
+        \}
+let s:r={}
+let s:hasundo=exists('*undotree')
+"▶1 curundo :: () → UInt
+if s:hasundo
+    function s:F.curundo()
+        return undotree().seq_cur
+    endfunction
+else
+    function s:F.curundo()
+        return 0
+    endfunction
+endif
+"▶1 r.setup
+function s:r.setup(bvar, undo_full)
+    let a:bvar.undo_start=s:F.curundo()
+    let a:bvar.undo_ct=b:changedtick
+    let a:bvar.undo_full=(s:hasundo && a:undo_full)
+    if a:bvar.undo_full
+        let a:bvar.undo_tree={a:bvar.undo_start : {}}
+    endif
+    let a:bvar.undo_reset=0
+endfunction
+"▶1 r.reset
+function s:r.reset(bvar)
+    setlocal modifiable
+    call a:bvar.resetlines(a:bvar)
+    let a:bvar.undo_ct=b:changedtick
+    let a:bvar.undo_reset=1
+    if s:hasundo
+        let a:bvar.undo_start=s:F.curundo()
+        let savedundolevels=&undolevels
+        setglobal undolevels=-1
+        try
+            execute "normal! A \<BS>\e"
+        finally
+            let &undolevels=savedundolevels
+        endtry
+        if a:bvar.undo_full
+            let a:bvar.undo_tree={a:bvar.undo_start : {}}
+        endif
+    endif
+    setlocal nomodifiable
+endfunction
+"▶1 supdate
+function s:F.supdate(bvar, prevundo)
+    if b:changedtick!=a:bvar.undo_ct
+        let a:bvar.undo_ct=b:changedtick
+        if a:bvar.undo_reset
+            let a:bvar.undo_reset=0
+        endif
+        let curundo=s:F.curundo()
+        if              a:bvar.undo_full
+                    \&& has_key(a:bvar.undo_tree, a:prevundo)
+                    \&& curundo!=a:prevundo
+                    \&& !has_key(a:bvar.undo_tree, curundo)
+            let a:bvar.undo_tree[curundo]=copy(a:bvar.undo_tree[a:prevundo])
+        endif
+    endif
+endfunction
+"▶1 r.doaction
+function s:r.doaction(bvar, update, fun, ...)
+    let prevundo=s:F.curundo()
+    setlocal modifiable
+    let buf=bufnr('%')
+    try
+        let supdate=call(a:fun, [a:bvar]+a:000, {})
+    finally
+        call setbufvar(buf, '&modifiable', 0)
+    endtry
+    if buf==bufnr('%')
+        if a:update && supdate && s:F.curundo()!=prevundo
+            call s:F.undoup(a:bvar)
+        endif
+        call s:F.supdate(a:bvar, prevundo)
+    endif
+endfunction
+"▶1 undoup
+function s:F.undoup(bvar)
+    call a:bvar.pulllines(a:bvar)
+    if a:bvar.undo_full
+        let curundo=s:F.curundo()
+        if !has_key(a:bvar.undo_tree, curundo)
+            call s:r.reset(a:bvar)
+            call s:_f.throw('noutree')
+        endif
+        call a:bvar.procundoleaf(a:bvar, a:bvar.undo_tree[curundo])
+    endif
+endfunction
+"▶1 r.postundo
+function s:r.postundo(bvar)
+    let curundo=s:F.curundo()
+    if curundo<a:bvar.undo_start
+        while curundo<a:bvar.undo_start
+            let pundo=curundo
+            silent redo
+            let curundo=s:F.curundo()
+            if curundo==pundo
+                call s:_f.throw('tooundo')
+                call s:r.reset(a:bvar)
+                setlocal nomodifiable
+                return 0
+            endif
+        endwhile
+    endif
+    return 1
+endfunction
+"▶1 r.updatetree
+function s:r.updatetree(bvar, oundoleafpart)
+    call map(a:bvar.undo_tree, 'extend(v:val, a:oundoleafpart, "keep")')
+endfunction
+"▶1 r.preaction
+function s:r.preaction(bvar)
+    if b:changedtick!=a:bvar.undo_ct
+        if a:bvar.undo_full && has_key(a:bvar.undo_tree, s:F.curundo())
+            call s:F.undoup(a:bvar)
+        else
+            call s:_f.warn('uchngs')
+            call s:r.reset(a:bvar)
+            return 0
+        endif
+    endif
+    return 1
+endfunction
+"▶1 r.preundoaction
+function s:r.preundoaction(bvar, action)
+    if !s:hasundo
+        call s:_f.warn('noundo')
+        return 0
+    endif
+    if a:bvar.undo_reset
+        setlocal nomodifiable
+        call s:_f.warn(a:action.'na')
+        return 0
+    endif
+    return 1
+endfunction
+"▶1 r.getundoleaf
+function s:r.getundoleaf(bvar)
+    return a:bvar.undo_tree[s:F.curundo()]
+endfunction
+"▶1 Post resource
+call s:_f.postresource('undo', s:r)
+"▶1
+call frawor#Lockvar(s:, '_r,_pluginloaded')
+" vim: ft=vim ts=4 sts=4 et fmr=▶,▲

test/cmd-record.in

 OGdo:silent write
 :
 :
-,xiX
+,xi:Run:
+X
 :
 :
 :WT

test/cmd-record.ok

 |  Tags: tip
 |  @ Jkl
 {{{1 edit-discard
+-M nohglinesrev.lst
 @  Changeset 30
 |  Tags: tip
 |  @ Jkl

test/maps-record-undo.in

 :command -nargs=1 -bar WGF  :WG * | WF <args>
 :command -nargs=* -bar WGFs :WG * | for file in [<f-args>] | execute 'WF' file | endfor
 :W{{{1 no fullundo
+:let g:aurum_fullundo=0
 :AuRecord
 uAi:RZC{{{2 Add
 ui:RZ{{{2 Undo
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.