diff --git a/Makefile b/Makefile index 76e380703..1bf873534 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ NAME := gdu -MAJOR_VER := v4 +MAJOR_VER := v5 PACKAGE := github.com/dundee/$(NAME)/$(MAJOR_VER) CMD_GDU := cmd/gdu VERSION := $(shell git describe --tags 2>/dev/null) diff --git a/README.md b/README.md index cc61c36d9..568fd53e7 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Using curl: [Go](https://pkg.go.dev/github.com/dundee/gdu): - go get -u github.com/dundee/gdu/v4/cmd/gdu + go get -u github.com/dundee/gdu/v5/cmd/gdu ## Usage diff --git a/cmd/gdu/app/app.go b/cmd/gdu/app/app.go index d67bc459f..ad483ffe1 100644 --- a/cmd/gdu/app/app.go +++ b/cmd/gdu/app/app.go @@ -7,12 +7,12 @@ import ( "os" "runtime" - "github.com/dundee/gdu/v4/build" - "github.com/dundee/gdu/v4/internal/common" - "github.com/dundee/gdu/v4/pkg/analyze" - "github.com/dundee/gdu/v4/pkg/device" - "github.com/dundee/gdu/v4/stdout" - "github.com/dundee/gdu/v4/tui" + "github.com/dundee/gdu/v5/build" + "github.com/dundee/gdu/v5/internal/common" + "github.com/dundee/gdu/v5/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/device" + "github.com/dundee/gdu/v5/stdout" + "github.com/dundee/gdu/v5/tui" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) diff --git a/cmd/gdu/app/app_test.go b/cmd/gdu/app/app_test.go index bfea6b246..70082f338 100644 --- a/cmd/gdu/app/app_test.go +++ b/cmd/gdu/app/app_test.go @@ -6,10 +6,10 @@ import ( "strings" "testing" - "github.com/dundee/gdu/v4/internal/testapp" - "github.com/dundee/gdu/v4/internal/testdev" - "github.com/dundee/gdu/v4/internal/testdir" - "github.com/dundee/gdu/v4/pkg/device" + "github.com/dundee/gdu/v5/internal/testapp" + "github.com/dundee/gdu/v5/internal/testdev" + "github.com/dundee/gdu/v5/internal/testdir" + "github.com/dundee/gdu/v5/pkg/device" "github.com/stretchr/testify/assert" ) diff --git a/cmd/gdu/main.go b/cmd/gdu/main.go index 9052af81a..e7f312c0c 100644 --- a/cmd/gdu/main.go +++ b/cmd/gdu/main.go @@ -5,8 +5,8 @@ import ( "os" "runtime" - "github.com/dundee/gdu/v4/cmd/gdu/app" - "github.com/dundee/gdu/v4/pkg/device" + "github.com/dundee/gdu/v5/cmd/gdu/app" + "github.com/dundee/gdu/v5/pkg/device" "github.com/gdamore/tcell/v2" "github.com/mattn/go-isatty" "github.com/rivo/tview" diff --git a/go.mod b/go.mod index 0ab1bee52..1329bc5fd 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/dundee/gdu/v4 +module github.com/dundee/gdu/v5 go 1.16 diff --git a/internal/common/ignore.go b/internal/common/ignore.go index 96aa21d2e..fccc2141f 100644 --- a/internal/common/ignore.go +++ b/internal/common/ignore.go @@ -5,7 +5,7 @@ import ( "regexp" "strings" - "github.com/dundee/gdu/v4/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/analyze" ) // CreateIgnorePattern creates one pattern from all path patterns diff --git a/internal/common/ignore_test.go b/internal/common/ignore_test.go index 6d93797bb..5238b19dc 100644 --- a/internal/common/ignore_test.go +++ b/internal/common/ignore_test.go @@ -3,7 +3,7 @@ package common_test import ( "testing" - "github.com/dundee/gdu/v4/internal/common" + "github.com/dundee/gdu/v5/internal/common" "github.com/stretchr/testify/assert" ) diff --git a/internal/common/ui.go b/internal/common/ui.go index f486f2f49..3d8c0bd66 100644 --- a/internal/common/ui.go +++ b/internal/common/ui.go @@ -4,7 +4,7 @@ import ( "io/fs" "regexp" - "github.com/dundee/gdu/v4/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/analyze" ) // UI struct diff --git a/internal/testanalyze/analyze.go b/internal/testanalyze/analyze.go index 19bb27a6f..3cb0609bb 100644 --- a/internal/testanalyze/analyze.go +++ b/internal/testanalyze/analyze.go @@ -3,7 +3,7 @@ package testanalyze import ( "errors" - "github.com/dundee/gdu/v4/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/analyze" ) // MockedAnalyzer returns dir with files with diferent size exponents diff --git a/internal/testapp/app.go b/internal/testapp/app.go index f3fc1b8d8..4429edd8d 100644 --- a/internal/testapp/app.go +++ b/internal/testapp/app.go @@ -4,7 +4,7 @@ import ( "errors" "sync" - "github.com/dundee/gdu/v4/internal/common" + "github.com/dundee/gdu/v5/internal/common" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) diff --git a/internal/testdev/dev.go b/internal/testdev/dev.go index 4f7160797..5d77298ee 100644 --- a/internal/testdev/dev.go +++ b/internal/testdev/dev.go @@ -1,6 +1,6 @@ package testdev -import "github.com/dundee/gdu/v4/pkg/device" +import "github.com/dundee/gdu/v5/pkg/device" // DevicesInfoGetterMock is mock of DevicesInfoGetter type DevicesInfoGetterMock struct { diff --git a/pkg/analyze/dir_test.go b/pkg/analyze/dir_test.go index 13444332c..188d24b06 100644 --- a/pkg/analyze/dir_test.go +++ b/pkg/analyze/dir_test.go @@ -5,7 +5,7 @@ import ( "sort" "testing" - "github.com/dundee/gdu/v4/internal/testdir" + "github.com/dundee/gdu/v5/internal/testdir" "github.com/stretchr/testify/assert" ) diff --git a/pkg/analyze/file_test.go b/pkg/analyze/file_test.go index f38d5adb3..a92fcba2a 100644 --- a/pkg/analyze/file_test.go +++ b/pkg/analyze/file_test.go @@ -4,7 +4,7 @@ import ( "os" "testing" - "github.com/dundee/gdu/v4/internal/testdir" + "github.com/dundee/gdu/v5/internal/testdir" "github.com/stretchr/testify/assert" ) diff --git a/stdout/stdout.go b/stdout/stdout.go index 5d0a84ff9..7da9f7b6b 100644 --- a/stdout/stdout.go +++ b/stdout/stdout.go @@ -10,9 +10,9 @@ import ( "sync" "time" - "github.com/dundee/gdu/v4/internal/common" - "github.com/dundee/gdu/v4/pkg/analyze" - "github.com/dundee/gdu/v4/pkg/device" + "github.com/dundee/gdu/v5/internal/common" + "github.com/dundee/gdu/v5/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/device" "github.com/fatih/color" ) diff --git a/stdout/stdout_test.go b/stdout/stdout_test.go index e5a9d1eff..11ae9f781 100644 --- a/stdout/stdout_test.go +++ b/stdout/stdout_test.go @@ -4,10 +4,10 @@ import ( "bytes" "testing" - "github.com/dundee/gdu/v4/internal/testanalyze" - "github.com/dundee/gdu/v4/internal/testdev" - "github.com/dundee/gdu/v4/internal/testdir" - "github.com/dundee/gdu/v4/pkg/device" + "github.com/dundee/gdu/v5/internal/testanalyze" + "github.com/dundee/gdu/v5/internal/testdev" + "github.com/dundee/gdu/v5/internal/testdir" + "github.com/dundee/gdu/v5/pkg/device" "github.com/stretchr/testify/assert" ) diff --git a/tui/actions.go b/tui/actions.go index 104625d09..74f4f524d 100644 --- a/tui/actions.go +++ b/tui/actions.go @@ -6,8 +6,8 @@ import ( "path/filepath" "runtime" - "github.com/dundee/gdu/v4/pkg/analyze" - "github.com/dundee/gdu/v4/pkg/device" + "github.com/dundee/gdu/v5/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/device" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) diff --git a/tui/actions_test.go b/tui/actions_test.go index af79ff1d3..a8655e741 100644 --- a/tui/actions_test.go +++ b/tui/actions_test.go @@ -4,11 +4,11 @@ import ( "runtime" "testing" - "github.com/dundee/gdu/v4/internal/testanalyze" - "github.com/dundee/gdu/v4/internal/testapp" - "github.com/dundee/gdu/v4/internal/testdir" - "github.com/dundee/gdu/v4/pkg/analyze" - "github.com/dundee/gdu/v4/pkg/device" + "github.com/dundee/gdu/v5/internal/testanalyze" + "github.com/dundee/gdu/v5/internal/testapp" + "github.com/dundee/gdu/v5/internal/testdir" + "github.com/dundee/gdu/v5/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/device" "github.com/gdamore/tcell/v2" "github.com/stretchr/testify/assert" ) diff --git a/tui/format.go b/tui/format.go index 5280f392e..d2568a49c 100644 --- a/tui/format.go +++ b/tui/format.go @@ -3,7 +3,7 @@ package tui import ( "fmt" - "github.com/dundee/gdu/v4/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/analyze" ) // file size constants @@ -17,6 +17,16 @@ const ( EB ) +// file count constants +const ( + K int = 1e3 + M int = 1e6 + G int = 1e9 + T int = 1e12 + P int = 1e15 + E int = 1e18 +) + func (ui *UI) formatFileRow(item analyze.Item) string { var part int @@ -42,6 +52,15 @@ func (ui *UI) formatFileRow(item analyze.Item) string { row += getUsageGraph(part) + if ui.showItemCount { + if ui.UseColors { + row += "[#e67100::b]" + } else { + row += "[::b]" + } + row += fmt.Sprintf("%11s ", ui.formatCount(item.GetItemCount())) + } + if item.IsDir() { if ui.UseColors { row += "[#3498db::b]/" @@ -88,3 +107,26 @@ func (ui *UI) formatSize(size int64, reverseColor bool, transparentBg bool) stri return fmt.Sprintf("%d%s B", size, color) } } + +func (ui *UI) formatCount(count int) string { + row := "" + color := "[-::]" + + switch { + case count >= E: + row += fmt.Sprintf("%.1f%sE", float64(count)/float64(E), color) + case count >= P: + row += fmt.Sprintf("%.1f%sP", float64(count)/float64(P), color) + case count >= T: + row += fmt.Sprintf("%.1f%sT", float64(count)/float64(T), color) + case count >= G: + row += fmt.Sprintf("%.1f%sG", float64(count)/float64(G), color) + case count >= M: + row += fmt.Sprintf("%.1f%sM", float64(count)/float64(M), color) + case count >= K: + row += fmt.Sprintf("%.1f%sk", float64(count)/float64(K), color) + default: + row += fmt.Sprintf("%d%s", count, color) + } + return row +} diff --git a/tui/format_test.go b/tui/format_test.go index 646fd7fab..ba25ade6c 100644 --- a/tui/format_test.go +++ b/tui/format_test.go @@ -3,7 +3,7 @@ package tui import ( "testing" - "github.com/dundee/gdu/v4/internal/testapp" + "github.com/dundee/gdu/v5/internal/testapp" "github.com/stretchr/testify/assert" ) @@ -19,3 +19,16 @@ func TestFormatSize(t *testing.T) { assert.Equal(t, "1.0[white:black:-] PiB", ui.formatSize(1<<50, false, false)) assert.Equal(t, "1.0[white:black:-] EiB", ui.formatSize(1<<60, false, false)) } + +func TestFormatCount(t *testing.T) { + app := testapp.CreateMockedApp(true) + ui := CreateUI(app, false, false) + + assert.Equal(t, "1[-::]", ui.formatCount(1)) + assert.Equal(t, "1.0[-::]k", ui.formatCount(1<<10)) + assert.Equal(t, "1.0[-::]M", ui.formatCount(1<<20)) + assert.Equal(t, "1.1[-::]G", ui.formatCount(1<<30)) + assert.Equal(t, "1.1[-::]T", ui.formatCount(1<<40)) + assert.Equal(t, "1.1[-::]P", ui.formatCount(1<<50)) + assert.Equal(t, "1.2[-::]E", ui.formatCount(1<<60)) +} diff --git a/tui/keys.go b/tui/keys.go index d26eabaca..482687953 100644 --- a/tui/keys.go +++ b/tui/keys.go @@ -1,7 +1,7 @@ package tui import ( - "github.com/dundee/gdu/v4/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/analyze" "github.com/gdamore/tcell/v2" ) @@ -53,13 +53,20 @@ func (ui *UI) keyPressed(key *tcell.EventKey) *tcell.EventKey { ui.showDir() ui.table.Select(row, column) } + case 'c': + ui.showItemCount = !ui.showItemCount + if ui.currentDir != nil { + row, column := ui.table.GetSelection() + ui.showDir() + ui.table.Select(row, column) + } case 'r': if ui.currentDir != nil { ui.rescanDir() } case 's': ui.setSorting("size") - case 'c': + case 'C': ui.setSorting("itemCount") case 'n': ui.setSorting("name") diff --git a/tui/keys_test.go b/tui/keys_test.go index 884a05275..bf2a79b0b 100644 --- a/tui/keys_test.go +++ b/tui/keys_test.go @@ -3,10 +3,10 @@ package tui import ( "testing" - "github.com/dundee/gdu/v4/internal/testanalyze" - "github.com/dundee/gdu/v4/internal/testapp" - "github.com/dundee/gdu/v4/internal/testdir" - "github.com/dundee/gdu/v4/pkg/analyze" + "github.com/dundee/gdu/v5/internal/testanalyze" + "github.com/dundee/gdu/v5/internal/testapp" + "github.com/dundee/gdu/v5/internal/testdir" + "github.com/dundee/gdu/v5/pkg/analyze" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" "github.com/stretchr/testify/assert" @@ -242,6 +242,48 @@ func TestSortByApparentSize(t *testing.T) { assert.True(t, ui.ShowApparentSize) } +func TestShowFileCount(t *testing.T) { + app := testapp.CreateMockedApp(true) + ui := CreateUI(app, true, false) + ui.Analyzer = &testanalyze.MockedAnalyzer{} + ui.PathChecker = testdir.MockedPathChecker + ui.done = make(chan struct{}) + ui.AnalyzePath("test_dir", nil) + + <-ui.done // wait for analyzer + + assert.Equal(t, "test_dir", ui.currentDir.Name) + + for _, f := range ui.app.(*testapp.MockedApp).UpdateDraws { + f() + } + + ui.keyPressed(tcell.NewEventKey(tcell.KeyRune, 'c', 0)) + + assert.True(t, ui.showItemCount) +} + +func TestShowFileCountBW(t *testing.T) { + app := testapp.CreateMockedApp(true) + ui := CreateUI(app, false, false) + ui.Analyzer = &testanalyze.MockedAnalyzer{} + ui.PathChecker = testdir.MockedPathChecker + ui.done = make(chan struct{}) + ui.AnalyzePath("test_dir", nil) + + <-ui.done // wait for analyzer + + assert.Equal(t, "test_dir", ui.currentDir.Name) + + for _, f := range ui.app.(*testapp.MockedApp).UpdateDraws { + f() + } + + ui.keyPressed(tcell.NewEventKey(tcell.KeyRune, 'c', 0)) + + assert.True(t, ui.showItemCount) +} + func TestRescan(t *testing.T) { parentDir := &analyze.Dir{ File: &analyze.File{ @@ -297,7 +339,7 @@ func TestSorting(t *testing.T) { ui.keyPressed(tcell.NewEventKey(tcell.KeyRune, 's', 0)) assert.Equal(t, "size", ui.sortBy) - ui.keyPressed(tcell.NewEventKey(tcell.KeyRune, 'c', 0)) + ui.keyPressed(tcell.NewEventKey(tcell.KeyRune, 'C', 0)) assert.Equal(t, "itemCount", ui.sortBy) ui.keyPressed(tcell.NewEventKey(tcell.KeyRune, 'n', 0)) assert.Equal(t, "name", ui.sortBy) diff --git a/tui/sort_test.go b/tui/sort_test.go index 1a853cf77..b18561678 100644 --- a/tui/sort_test.go +++ b/tui/sort_test.go @@ -3,9 +3,9 @@ package tui import ( "testing" - "github.com/dundee/gdu/v4/internal/testanalyze" - "github.com/dundee/gdu/v4/internal/testapp" - "github.com/dundee/gdu/v4/internal/testdir" + "github.com/dundee/gdu/v5/internal/testanalyze" + "github.com/dundee/gdu/v5/internal/testapp" + "github.com/dundee/gdu/v5/internal/testdir" "github.com/stretchr/testify/assert" ) diff --git a/tui/tui.go b/tui/tui.go index 147929a82..082546dc1 100644 --- a/tui/tui.go +++ b/tui/tui.go @@ -7,9 +7,9 @@ import ( "sort" "time" - "github.com/dundee/gdu/v4/internal/common" - "github.com/dundee/gdu/v4/pkg/analyze" - "github.com/dundee/gdu/v4/pkg/device" + "github.com/dundee/gdu/v5/internal/common" + "github.com/dundee/gdu/v5/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/device" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) @@ -23,9 +23,10 @@ const helpTextColorized = ` [red]v [white]Show content of selected file [red]r [white]Rescan current directory [red]a [white]Toggle between showing disk usage and apparent size + [red]c [white]Show/hide file count [red]n [white]Sort by name (asc/desc) [red]s [white]Sort by size (asc/desc) - [red]c [white]Sort by items (asc/desc) + [red]C [white]Sort by file count (asc/desc) [red]q [white]Quit gdu ` const helpText = ` @@ -37,9 +38,10 @@ const helpText = ` [::b]v [white:black:-]Show content of selected file [::b]r [white:black:-]Rescan current directory [::b]a [white:black:-]Toggle between showing disk usage and apparent size + [::b]c [white:black:-]Show/hide file count [::b]n [white:black:-]Sort by name (asc/desc) [::b]s [white:black:-]Sort by size (asc/desc) - [::b]c [white:black:-]Sort by items (asc/desc) + [::b]C [white:black:-]Sort by file count (asc/desc) [::b]q [white:black:-]Quit gdu ` @@ -60,6 +62,7 @@ type UI struct { topDirPath string currentDirPath string askBeforeDelete bool + showItemCount bool sortBy string sortOrder string done chan struct{} @@ -76,6 +79,7 @@ func CreateUI(app common.TermApplication, useColors bool, showApparentSize bool) PathChecker: os.Stat, }, askBeforeDelete: true, + showItemCount: false, sortBy: "size", sortOrder: "desc", remover: analyze.RemoveItemFromDir, diff --git a/tui/tui_test.go b/tui/tui_test.go index 4b71d4c7c..541765f2d 100644 --- a/tui/tui_test.go +++ b/tui/tui_test.go @@ -4,12 +4,12 @@ import ( "errors" "testing" - "github.com/dundee/gdu/v4/internal/testanalyze" - "github.com/dundee/gdu/v4/internal/testapp" - "github.com/dundee/gdu/v4/internal/testdev" - "github.com/dundee/gdu/v4/internal/testdir" - "github.com/dundee/gdu/v4/pkg/analyze" - "github.com/dundee/gdu/v4/pkg/device" + "github.com/dundee/gdu/v5/internal/testanalyze" + "github.com/dundee/gdu/v5/internal/testapp" + "github.com/dundee/gdu/v5/internal/testdev" + "github.com/dundee/gdu/v5/internal/testdir" + "github.com/dundee/gdu/v5/pkg/analyze" + "github.com/dundee/gdu/v5/pkg/device" "github.com/gdamore/tcell/v2" "github.com/stretchr/testify/assert" ) diff --git a/tui/utils.go b/tui/utils.go index 95fcf9362..9ba87b347 100644 --- a/tui/utils.go +++ b/tui/utils.go @@ -1,7 +1,7 @@ package tui import ( - "github.com/dundee/gdu/v4/pkg/device" + "github.com/dundee/gdu/v5/pkg/device" ) func getDeviceUsagePart(item *device.Device) string {