Commits

ZyX_I committed b714b37

@%aurum/record: Added support for {count}undo and {count}redo,
some undo/redo code refactoring

  • Participants
  • Parent commits 3147389

Comments (0)

Files changed (2)

File autoload/aurum/record.vim

             \ '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',
+            \'tooundo': 'Undone too much changes and cannot redo',
             \ 'undona': "Can’t undo changes. Possible reasons:\n".
             \           "  1. Current change is the oldest one\n".
             \           "  2. You did some changes manually and thus buffer ".
     let a:bvar.prevct=b:changedtick
     let a:bvar.reset=1
     if a:bvar.startundo
-        let a:bvar.undolevels=&undolevels
         let a:bvar.startundo=s:F.curundo()
+        let savedundolevels=&undolevels
         setglobal undolevels=-1
+        execute "normal! A \<BS>\e"
+        let &undolevels=savedundolevels
     endif
 endfunction
 "▶1 supdate
     if b:changedtick!=a:bvar.prevct
         let a:bvar.prevct=b:changedtick
         if a:bvar.reset
-            if has_key(a:bvar, 'undolevels')
-                let &g:undolevels=a:bvar.undolevels
-                unlet a:bvar.undolevels
-            endif
             let a:bvar.reset=0
         endif
     endif
     setlocal bufhidden=wipe
     return 1
 endfunction
+"▶1 restorefiles :: bvar, sline, eline → + FS
+function s:F.restorefiles(bvar, sline, eline)
+    for file in map(range(a:sline, a:eline), 'a:bvar.lines[v:val-1][2:]')
+        let fullpath=s:_r.os.path.join(a:bvar.repo.path, file)
+        let backupfile=remove(a:bvar.filesbackup, fullpath)
+        call remove(a:bvar.backupfiles, backupfile)
+        call s:F.restorebackup(fullpath, backupfile)
+    endfor
+endfunction
+"▶1 undoup :: bvar → + bvar
+function s:F.udoup(bvar)
+    for line in range(1, line('$'))
+        let a:bvar.statuses[line-1]=stridx(s:statchars, getline(line)[0])
+    endfor
+endfunction
 "▶1 runstatmap
 let s:statchars='-^+*'
 let s:ntypes={
             \'removed':  'r',
             \'deleted':  'r',
         \}
-function s:F.restorefiles(bvar, sline, eline)
-    for file in map(range(a:sline, a:eline), 'a:bvar.lines[v:val-1][2:]')
-        let fullpath=s:_r.os.path.join(a:bvar.repo.path, file)
-        let backupfile=remove(a:bvar.filesbackup, fullpath)
-        call remove(a:bvar.backupfiles, backupfile)
-        call s:F.restorebackup(fullpath, backupfile)
-    endfor
-endfunction
 function s:F.runstatmap(action, ...)
     "▶2 buf, bvar, reset
     let buf=get(a:000, 0, bufnr('%'))
         setlocal nomodifiable
         return
     endif
+    if a:action[-2:] is# 'do'
+        if !bvar.startundo
+            call s:_f.warn('noundo')
+            return
+        endif
+        if bvar.reset || s:F.curundo()<=bvar.startundo
+            setlocal nomodifiable
+            call s:_f.warn(a:action.'na')
+            return
+        endif
+    endif
     "▶2 add/remove
     if a:action[-3:] is# 'add' || a:action[-6:] is# 'remove'
         if a:action[0] is# 'v'
         return
     "▶2 undo
     elseif a:action is# 'undo'
-        if !bvar.startundo
-            call s:_f.warn('noundo')
-            return
+        execute 'silent normal! '.v:count1.'u'
+        let curundo=s:F.curundo()
+        if curundo<bvar.startundo
+            while curundo<bvar.startundo
+                let prevundo=curundo
+                silent redo
+                let curundo=s:F.curundo()
+                if curundo==prevundo
+                    call s:_f.throw('tooundo')
+                    call s:F.reset(bvar)
+                    setlocal nomodifiable
+                    return
+                endif
+            endwhile
         endif
-        if bvar.reset || s:F.curundo()<=bvar.startundo
-            setlocal nomodifiable
-            call s:_f.warn('undona')
-            return
-        endif
-        silent undo
-        for line in range(1, line('$'))
-            let bvar.statuses[line-1]=stridx(s:statchars, getline(line)[0])
-        endfor
-        if s:F.curundo()<bvar.startundo
-            silent redo
-        endif
+        call s:F.undoup(bvar)
     "▶2 redo
     elseif a:action is# 'redo'
-        if !bvar.startundo
-            call s:_f.warn('noundo')
-            return
-        endif
-        if bvar.reset || s:F.curundo()<=bvar.startundo
-            setlocal nomodifiable
-            call s:_f.warn('redona')
-            return
-        endif
-        silent redo
-        for line in range(1, line('$'))
-            let bvar.statuses[line-1]=stridx(s:statchars, getline(line)[0])
-        endfor
+        execute 'silent normal! '.v:count1."\<C-r>"
+        call s:F.undoup(bvar)
     "▶2 edit
     elseif a:action is# 'edit'
         let [lwnr, rwnr, swnr]=s:F.getwnrs()
         endif
         return
     endif
-    "▶2 bvar.prevct, bvar.reset, bvar.undolevels
+    "▶2 bvar.prevct, bvar.reset
     if bufnr('%')==buf
         call s:F.supdate(bvar)
     endif
                 \          '{})<CR>'
 endfunction
 call s:_f.mapgroup.add('AuRecord', {
-            \   'Edit': {'lhs': 'O', 'rhs': s:F.gm('edit')  },
-            \   'Undo': {'lhs': 'u', 'rhs': s:F.gm('undo')  },
+            \   'Edit': {'lhs': 'O',     'rhs': s:F.gm('edit')},
+            \   'Undo': {'lhs': 'u',     'rhs': s:F.gm('undo')},
+            \   'Redo': {'lhs': '<C-r>', 'rhs': s:F.gm('redo')},
         \}, {'mode': 'n', 'silent': 1, 'dontmap': 1})
 call s:_f.mapgroup.add('AuRecordLeft', {
             \'Discard': {'lhs': 'x', 'rhs': s:F.gml('discard')   },

File doc/aurum.txt

               repository if file in question was removed or deleted).
 Undo      u   Undo adds/removes of the file. Won’t undo changes made to the 
               file using Edit mapping.
+Redo    <C-r> Like above, but redoes.
 :AuRecord also makes some AuStatus mappings change their meaning:
 Mapping                 New meaning ~
 |aurum-m-AuStatus_Track|  select changes made to file(s) for committing