diff --git a/dir_entry.go b/dir_entry.go index e693f86..dd01171 100644 --- a/dir_entry.go +++ b/dir_entry.go @@ -2,6 +2,7 @@ package main import ( "errors" + "fmt" "os" "path/filepath" "sort" @@ -9,9 +10,14 @@ import ( ) type DirectoryEntry struct { - path string + path string + size *uint64 modSize *uint64 + + fileCount *uint64 + modFileCount *uint64 + entries []Entry parent Entry @@ -54,13 +60,34 @@ func (e *DirectoryEntry) Entries() []Entry { func (e *DirectoryEntry) String() string { if e.removal { - return ColorRed.Sprintf("%s %s (%s)", icon("folder"), e.Name(), fmtSize(e.SizeModified())) + return ColorRed.Sprintf("%s %s (%s, %s)", + icon("folder"), + e.Name(), + fmtSize(e.SizeModified()), + Translate("%s files", Translate("fileCountFormat", e.FileCountModified())), + ) } if e.Size() == e.SizeModified() { - return ColorBlue.Sprintf("%s %s (%s)", icon("folder"), e.Name(), fmtSize(e.Size())) + return ColorBlue.Sprintf("%s %s (%s, %s)", + icon("folder"), + e.Name(), + fmtSize(e.Size()), + Translate("%s files", Translate("fileCountFormat", e.FileCount())), + ) } else { - return ColorBlue.Sprintf("%s %s (%s / %s)", icon("folder"), e.Name(), ColorRed.Sprintf(fmtSize(e.SizeModified())), fmtSize(e.Size())) + return ColorBlue.Sprintf("%s %s (%s / %s, %s)", + icon("folder"), + e.Name(), + ColorRed.Sprintf(fmtSize(e.SizeModified())), + fmtSize(e.Size()), + Translate("%s files", + fmt.Sprintf("%s / %s", + ColorRed.Sprintf(Translate("fileCountFormat", e.FileCountModified())), + Translate("fileCountFormat", e.FileCount()), + ), + ), + ) } } @@ -155,10 +182,12 @@ func (e *DirectoryEntry) SizeModified() uint64 { return *e.modSize } -func (e *DirectoryEntry) modifySize(modifier uint64) { - *e.modSize += modifier +func (e *DirectoryEntry) modify(size uint64, fileCount uint64) { + *e.modSize += size + *e.modFileCount += fileCount + if e.parent != nil { - e.parent.modifySize(modifier) + e.parent.modify(size, fileCount) // recalculate order of parent entries pentries := e.Parent().Entries() @@ -180,3 +209,26 @@ func (e *DirectoryEntry) RemovalStats(stats *RemovalStats) { entry.RemovalStats(stats) } } + +func (e *DirectoryEntry) FileCount() uint64 { + if e.fileCount == nil { + fileCount := uint64(0) + for _, c := range e.Entries() { + fileCount += c.FileCount() + } + e.fileCount = &fileCount + + e.modFileCount = new(uint64) + *e.modFileCount = *e.fileCount + } + + return *e.fileCount +} + +func (e *DirectoryEntry) FileCountModified() uint64 { + if e.fileCount == nil { + e.FileCount() + } + + return *e.modFileCount +} diff --git a/entry.go b/entry.go index 88a9391..fd211b7 100644 --- a/entry.go +++ b/entry.go @@ -15,8 +15,13 @@ type Entry interface { Name() string Path() string + Size() uint64 SizeModified() uint64 + + FileCount() uint64 + FileCountModified() uint64 + Entries() []Entry Entry(path string) Entry @@ -24,7 +29,7 @@ type Entry interface { RemovalMark() bool RemovalStats(stats *RemovalStats) - modifySize(modifier uint64) + modify(size uint64, fileCount uint64) IsDir() bool diff --git a/file_entry.go b/file_entry.go index 95bf23a..4556141 100644 --- a/file_entry.go +++ b/file_entry.go @@ -10,10 +10,15 @@ import ( ) type FileEntry struct { - path string + path string + size *uint64 modSize *uint64 - parent Entry + + fileCount *uint64 + modFileCount *uint64 + + parent Entry removal bool noPerm bool @@ -93,10 +98,15 @@ func (e *FileEntry) Scan(ch chan<- string, mounts map[string]struct{}) { } else if errors.Is(err, os.ErrPermission) { e.noPerm = true } - e.size = &s + e.size = &s e.modSize = new(uint64) *e.modSize = *e.size + + f := uint64(1) + e.fileCount = &f + e.modFileCount = new(uint64) + *e.modFileCount = *e.fileCount } func (e *FileEntry) Parent() Entry { @@ -114,9 +124,9 @@ func (e *FileEntry) IsDir() bool { func (e *FileEntry) SetRemovalMark(mark bool) { e.removal = mark if mark { - e.modifySize(-*e.size) + e.modify(-*e.size, -*e.fileCount) // underflow that is cancelling out perfectly } else { - e.modifySize(*e.size) + e.modify(*e.size, *e.fileCount) } // recalculate order of parent entries @@ -138,10 +148,11 @@ func (e *FileEntry) SizeModified() uint64 { return *e.modSize } -func (e *FileEntry) modifySize(modifier uint64) { - *e.modSize += modifier +func (e *FileEntry) modify(size uint64, fileCount uint64) { + *e.modSize = *e.modSize + size + *e.modFileCount = *e.modFileCount + fileCount if e.parent != nil { - e.parent.modifySize(modifier) + e.parent.modify(size, fileCount) } } @@ -154,3 +165,11 @@ func (e *FileEntry) RemovalStats(stats *RemovalStats) { } } } + +func (e *FileEntry) FileCount() uint64 { + return *e.fileCount +} + +func (e *FileEntry) FileCountModified() uint64 { + return *e.modFileCount +} diff --git a/translate.go b/translate.go index cc4d469..e67f17d 100644 --- a/translate.go +++ b/translate.go @@ -7,7 +7,13 @@ import ( ) var Languages = map[string]map[string]string{ - "de": map[string]string{ + "en": { + "fileCountFormat": "%d", + }, + + "de": { + "fileCountFormat": "%d", + "%s files": "%s Dateien", "Scanning ": "Verarbeite ", "Scanning took %s": "Verarbeitung dauerte %s", "'%s' is not a directory": "'%s' ist kein Verzeichnis", @@ -29,7 +35,9 @@ var Languages = map[string]map[string]string{ "Use command 'exit' for exiting properly": "Nutze den Befehl 'exit', um das Programm ordnungsgemäß zu beenden", "exit? [y/N]: ": "Beenden? [y/N]: ", }, - "ja": map[string]string{ + "ja": { + "fileCountFormat": "%d個", + "%s files": "%s", "Scanning ": "処理 ", "Scanning took %s": "処理が %s かかりました", "'%s' is not a directory": "「%s」はディレクトリではありません",