ncdu: add support for modification time

This commit is contained in:
albertony 2022-11-04 14:19:25 +01:00 committed by Nick Craig-Wood
parent 528fc899fb
commit 64cdbb67b5
2 changed files with 66 additions and 18 deletions

View File

@ -89,11 +89,12 @@ func helpText() (tr []string) {
" ↑,↓ or k,j to Move",
" →,l to enter",
" ←,h to return",
" c toggle counts",
" g toggle graph",
" c toggle counts",
" a toggle average size in directory",
" m toggle modified time",
" u toggle human-readable format",
" n,s,C,A sort by name,size,count,average size",
" n,s,C,A,M sort by name,size,count,asize,mtime",
" d delete file/directory",
" v select file/directory",
" V enter visual select mode",
@ -131,12 +132,14 @@ type UI struct {
showGraph bool // toggle showing graph
showCounts bool // toggle showing counts
showDirAverageSize bool // toggle average size
showModTime bool // toggle showing timestamps
humanReadable bool // toggle human-readable format
visualSelectMode bool // toggle visual selection mode
sortByName int8 // +1 for normal, 0 for off, -1 for reverse
sortBySize int8
sortByName int8 // +1 for normal (lexical), 0 for off, -1 for reverse
sortBySize int8 // +1 for normal (largest first), 0 for off, -1 for reverse (smallest first)
sortByCount int8
sortByAverageSize int8
sortByModTime int8 // +1 for normal (newest first), 0 for off, -1 for reverse (oldest first)
dirPosMap map[string]dirPos // store for directory positions
selectedEntries map[string]dirPos // selected entries of current directory
}
@ -332,6 +335,7 @@ func (u *UI) hasEmptyDir() bool {
// Draw the current screen
func (u *UI) Draw() error {
ctx := context.Background()
w, h := termbox.Size()
u.dirListHeight = h - 3
@ -365,7 +369,13 @@ func (u *UI) Draw() error {
if y >= h-1 {
break
}
attrs, err := u.d.AttrI(u.sortPerm[n])
var attrs scan.Attrs
var err error
if u.showModTime {
attrs, err = u.d.AttrWithModTimeI(ctx, u.sortPerm[n])
} else {
attrs, err = u.d.AttrI(u.sortPerm[n])
}
_, isSelected := u.selectedEntries[entry.String()]
fg := termbox.ColorWhite
if attrs.EntriesHaveErrors {
@ -421,6 +431,9 @@ func (u *UI) Draw() error {
extras += strings.Repeat(" ", len(ss))
}
}
if u.showModTime {
extras += attrs.ModTime.Local().Format("2006-01-02 15:04:05") + " "
}
if showEmptyDir {
if attrs.IsDir && attrs.Count == 0 && fileFlag == ' ' {
fileFlag = 'e'
@ -656,8 +669,15 @@ type ncduSort struct {
// Less is part of sort.Interface.
func (ds *ncduSort) Less(i, j int) bool {
var iAvgSize, jAvgSize float64
iattrs, _ := ds.d.AttrI(ds.sortPerm[i])
jattrs, _ := ds.d.AttrI(ds.sortPerm[j])
var iattrs, jattrs scan.Attrs
if ds.u.sortByModTime != 0 {
ctx := context.Background()
iattrs, _ = ds.d.AttrWithModTimeI(ctx, ds.sortPerm[i])
jattrs, _ = ds.d.AttrWithModTimeI(ctx, ds.sortPerm[j])
} else {
iattrs, _ = ds.d.AttrI(ds.sortPerm[i])
jattrs, _ = ds.d.AttrI(ds.sortPerm[j])
}
iname, jname := ds.entries[ds.sortPerm[i]].Remote(), ds.entries[ds.sortPerm[j]].Remote()
if iattrs.Count > 0 {
iAvgSize = iattrs.AverageSize()
@ -679,6 +699,14 @@ func (ds *ncduSort) Less(i, j int) bool {
if iattrs.Size != jattrs.Size {
return iattrs.Size > jattrs.Size
}
case ds.u.sortByModTime < 0:
if iattrs.ModTime != jattrs.ModTime {
return iattrs.ModTime.Before(jattrs.ModTime)
}
case ds.u.sortByModTime > 0:
if iattrs.ModTime != jattrs.ModTime {
return iattrs.ModTime.After(jattrs.ModTime)
}
case ds.u.sortByCount < 0:
if iattrs.Count != jattrs.Count {
return iattrs.Count < jattrs.Count
@ -847,8 +875,9 @@ func NewUI(f fs.Fs) *UI {
showCounts: false,
showDirAverageSize: false,
humanReadable: true,
sortByName: 0, // +1 for normal, 0 for off, -1 for reverse
sortBySize: 1,
sortByName: 0,
sortBySize: 1, // Sort by largest first
sortByModTime: 0,
sortByCount: 0,
dirPosMap: make(map[string]dirPos),
selectedEntries: make(map[string]dirPos),
@ -937,6 +966,8 @@ outer:
u.enter()
case 'c':
u.showCounts = !u.showCounts
case 'm':
u.showModTime = !u.showModTime
case 'g':
u.showGraph = !u.showGraph
case 'a':
@ -945,6 +976,8 @@ outer:
u.toggleSort(&u.sortByName)
case 's':
u.toggleSort(&u.sortBySize)
case 'M':
u.toggleSort(&u.sortByModTime)
case 'v':
u.toggleSelectForCursor()
case 'V':

View File

@ -6,6 +6,7 @@ import (
"fmt"
"path"
"sync"
"time"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/walk"
@ -31,6 +32,7 @@ type Dir struct {
// in the total count. They are not included in the size, i.e. treated
// as empty files, which means the size may be underestimated.
type Attrs struct {
ModTime time.Time
Size int64
Count int64
CountUnknownSize int64
@ -193,20 +195,33 @@ func (d *Dir) Attr() (size int64, count int64) {
return d.size, d.count
}
// attrI returns the size, count and flags for the i-th directory entry
func (d *Dir) attrI(i int) (attrs Attrs, err error) {
subDir, isDir := d.getDir(i)
if !isDir {
return Attrs{time.Time{}, d.entries[i].Size(), 0, 0, false, true, d.entriesHaveErrors}, d.readError
}
if subDir == nil {
return Attrs{time.Time{}, 0, 0, 0, true, false, false}, nil
}
size, count := subDir.Attr()
return Attrs{time.Time{}, size, count, subDir.countUnknownSize, true, true, subDir.entriesHaveErrors}, subDir.readError
}
// AttrI returns the size, count and flags for the i-th directory entry
func (d *Dir) AttrI(i int) (attrs Attrs, err error) {
d.mu.Lock()
defer d.mu.Unlock()
subDir, isDir := d.getDir(i)
return d.attrI(i)
}
if !isDir {
return Attrs{d.entries[i].Size(), 0, 0, false, true, d.entriesHaveErrors}, d.readError
}
if subDir == nil {
return Attrs{0, 0, 0, true, false, false}, nil
}
size, count := subDir.Attr()
return Attrs{size, count, subDir.countUnknownSize, true, true, subDir.entriesHaveErrors}, subDir.readError
// AttrWithModTimeI returns the modtime, size, count and flags for the i-th directory entry
func (d *Dir) AttrWithModTimeI(ctx context.Context, i int) (attrs Attrs, err error) {
d.mu.Lock()
defer d.mu.Unlock()
attrs, err = d.attrI(i)
attrs.ModTime = d.entries[i].ModTime(ctx)
return
}
// Scan the Fs passed in, returning a root directory channel and an