Skip to content

Commit

Permalink
search items by name
Browse files Browse the repository at this point in the history
closes #80
  • Loading branch information
dundee committed Aug 1, 2021
1 parent 91acb89 commit 8ff4249
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 26 deletions.
4 changes: 2 additions & 2 deletions tui/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (ui *UI) ListDevices(getter device.DevicesInfoGetter) error {
}

ui.table.Select(1, 0)
ui.footer.SetText("")
ui.footerLabel.SetText("")
ui.table.SetSelectedFunc(ui.deviceItemSelected)

return nil
Expand Down Expand Up @@ -292,7 +292,7 @@ func (ui *UI) showFile() *tview.TextView {
grid.AddItem(ui.header, 0, 0, 1, 1, 0, 0, false).
AddItem(ui.currentDirLabel, 1, 0, 1, 1, 0, 0, false).
AddItem(file, 2, 0, 1, 1, 0, 0, true).
AddItem(ui.footer, 3, 0, 1, 1, 0, 0, false)
AddItem(ui.footerLabel, 3, 0, 1, 1, 0, 0, false)

ui.pages.HidePage("background")
ui.pages.AddPage("file", grid, true, true)
Expand Down
50 changes: 50 additions & 0 deletions tui/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package tui

import (
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)

func (ui *UI) hideFilterInput() {
ui.filterValue = ""
ui.footer.Clear()
ui.footer.AddItem(ui.footerLabel, 0, 1, false)
ui.app.SetFocus(ui.table)
ui.filteringInput = nil
ui.filtering = false
}

func (ui *UI) showFilterInput() {
if ui.filteringInput == nil {
ui.filteringInput = tview.NewInputField()

if !ui.UseColors {
ui.filteringInput.SetFieldBackgroundColor(
tcell.NewRGBColor(100, 100, 100),
)
ui.filteringInput.SetFieldTextColor(
tcell.NewRGBColor(255, 255, 255),
)
}

ui.filteringInput.SetChangedFunc(func(text string) {
ui.filterValue = text
ui.showDir()
})
ui.filteringInput.SetDoneFunc(func(key tcell.Key) {
if key == tcell.KeyESC {
ui.hideFilterInput()
ui.showDir()
} else {
ui.app.SetFocus(ui.table)
ui.filtering = false
}
})

ui.footer.Clear()
ui.footer.AddItem(ui.filteringInput, 0, 1, true)
ui.footer.AddItem(ui.footerLabel, 0, 5, false)
}
ui.app.SetFocus(ui.filteringInput)
ui.filtering = true
}
115 changes: 115 additions & 0 deletions tui/filter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package tui

import (
"testing"

"github.com/dundee/gdu/v5/internal/testanalyze"
"github.com/dundee/gdu/v5/internal/testapp"
"github.com/dundee/gdu/v5/internal/testdir"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"github.com/stretchr/testify/assert"
)

func TestFiltering(t *testing.T) {
app := testapp.CreateMockedApp(false)
ui := CreateUI(app, true, true)
ui.Analyzer = &testanalyze.MockedAnalyzer{}
ui.done = make(chan struct{})
err := ui.AnalyzePath("test_dir", nil)
assert.Nil(t, err)

<-ui.done // wait for analyzer

for _, f := range ui.app.(*testapp.MockedApp).UpdateDraws {
f()
}

ui.showFilterInput()
ui.filterValue = ""
ui.showDir()

assert.Contains(t, ui.table.GetCell(0, 0).Text, "aaa") // nothing is filtered

ui.filterValue = "cc"
ui.showDir()

assert.Contains(t, ui.table.GetCell(0, 0).Text, "ccc") // shows only cccc

ui.hideFilterInput()
ui.showDir()

assert.Contains(t, ui.table.GetCell(0, 0).Text, "aaa") // filtering reset
}

func TestSwitchToTable(t *testing.T) {
fin := testdir.CreateTestDir()
defer fin()

app := testapp.CreateMockedApp(false)
ui := CreateUI(app, false, true)
ui.done = make(chan struct{})
err := ui.AnalyzePath("test_dir", nil)
assert.Nil(t, err)

<-ui.done // wait for analyzer

for _, f := range ui.app.(*testapp.MockedApp).UpdateDraws {
f()
}

ui.keyPressed(tcell.NewEventKey(tcell.KeyRune, '/', 0)) // open filtering input
handler := ui.filteringInput.InputHandler()
handler(tcell.NewEventKey(tcell.KeyRune, 'n', 0), func(p tview.Primitive) {})
handler(tcell.NewEventKey(tcell.KeyRune, 'e', 0), func(p tview.Primitive) {})
handler(tcell.NewEventKey(tcell.KeyRune, 's', 0), func(p tview.Primitive) {})

ui.table.Select(0, 0)
ui.keyPressed(tcell.NewEventKey(tcell.KeyRight, 'l', 0)) // we are filtering, should do nothing

assert.Contains(t, ui.table.GetCell(0, 0).Text, "nested")

handler(
tcell.NewEventKey(tcell.KeyTAB, ' ', 0), func(p tview.Primitive) {},
) // switch focus to table
ui.keyPressed(tcell.NewEventKey(tcell.KeyTAB, ' ', 0)) // switch back to input
handler(
tcell.NewEventKey(tcell.KeyEnter, ' ', 0), func(p tview.Primitive) {},
) // switch back to table

ui.keyPressed(tcell.NewEventKey(tcell.KeyRight, 'l', 0)) // open nested dir

assert.Contains(t, ui.table.GetCell(1, 0).Text, "subnested")
assert.Empty(t, ui.filterValue) // filtering reset
}

func TestExitFiltering(t *testing.T) {
fin := testdir.CreateTestDir()
defer fin()

app := testapp.CreateMockedApp(false)
ui := CreateUI(app, true, true)
ui.done = make(chan struct{})
err := ui.AnalyzePath("test_dir", nil)
assert.Nil(t, err)

<-ui.done // wait for analyzer

for _, f := range ui.app.(*testapp.MockedApp).UpdateDraws {
f()
}

ui.keyPressed(tcell.NewEventKey(tcell.KeyRune, '/', 0)) // open filtering input
handler := ui.filteringInput.InputHandler()
ui.filterValue = "xxx"
ui.showDir()

assert.Equal(t, ui.table.GetCell(0, 0).Text, "") // nothing is filtered

handler(
tcell.NewEventKey(tcell.KeyEsc, ' ', 0), func(p tview.Primitive) {},
) // exit filtering

assert.Contains(t, ui.table.GetCell(0, 0).Text, "nested")
assert.Empty(t, ui.filterValue) // filtering reset
}
12 changes: 12 additions & 0 deletions tui/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ func (ui *UI) keyPressed(key *tcell.EventKey) *tcell.EventKey {
if ui.pages.HasPage("file") {
return key // send event to primitive
}
if ui.filtering {
return key
}

if key.Key() == tcell.KeyEsc || key.Rune() == 'q' {
if ui.pages.HasPage("help") {
Expand Down Expand Up @@ -37,6 +40,7 @@ func (ui *UI) keyPressed(key *tcell.EventKey) *tcell.EventKey {
ui.pages.HasPage("progress") ||
ui.pages.HasPage("deleting") ||
ui.pages.HasPage("emptying") ||
ui.pages.HasPage("help") ||
ui.pages.HasPage("info") {
return key
}
Expand All @@ -51,6 +55,12 @@ func (ui *UI) keyPressed(key *tcell.EventKey) *tcell.EventKey {
return nil
}

if key.Key() == tcell.KeyTab && ui.filteringInput != nil {
ui.filtering = true
ui.app.SetFocus(ui.filteringInput)
return nil
}

switch key.Rune() {
case 'd':
ui.handleDelete(false)
Expand Down Expand Up @@ -84,6 +94,8 @@ func (ui *UI) keyPressed(key *tcell.EventKey) *tcell.EventKey {
ui.setSorting("itemCount")
case 'n':
ui.setSorting("name")
case '/':
ui.showFilterInput()
default:
return key
}
Expand Down
51 changes: 40 additions & 11 deletions tui/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const helpText = ` [::b]up/down, k/j [white:black:-]Move cursor up/down
[::b]left, h [white:black:-]Go to parent directory
[::b]r [white:black:-]Rescan current directory
[::b]/ [white:black:-]Search items by name
[::b]a [white:black:-]Toggle between showing disk usage and apparent size
[::b]c [white:black:-]Show/hide file count
[::b]q [white:black:-]Quit gdu
Expand All @@ -43,19 +44,23 @@ type UI struct {
*common.UI
app common.TermApplication
header *tview.TextView
footer *tview.TextView
footer *tview.Flex
footerLabel *tview.TextView
currentDirLabel *tview.TextView
pages *tview.Pages
progress *tview.TextView
help *tview.Flex
table *tview.Table
filteringInput *tview.InputField
currentDir *analyze.Dir
devices []*device.Device
topDir *analyze.Dir
topDirPath string
currentDirPath string
askBeforeDelete bool
showItemCount bool
filtering bool
filterValue string
sortBy string
sortOrder string
done chan struct{}
Expand Down Expand Up @@ -118,10 +123,13 @@ func CreateUI(app common.TermApplication, useColors bool, showApparentSize bool)
Background(tcell.ColorGray).Bold(true))
}

ui.footer = tview.NewTextView().SetDynamicColors(true)
ui.footer.SetTextColor(textColor)
ui.footer.SetBackgroundColor(textBgColor)
ui.footer.SetText(" No items to display. ")
ui.footerLabel = tview.NewTextView().SetDynamicColors(true)
ui.footerLabel.SetTextColor(textColor)
ui.footerLabel.SetBackgroundColor(textBgColor)
ui.footerLabel.SetText(" No items to display. ")

ui.footer = tview.NewFlex()
ui.footer.AddItem(ui.footerLabel, 0, 1, false)

grid := tview.NewGrid().SetRows(1, 1, 0, 1).SetColumns(0)
grid.AddItem(ui.header, 0, 0, 1, 1, 0, 0, false).
Expand Down Expand Up @@ -152,6 +160,12 @@ func (ui *UI) rescanDir() {
}

func (ui *UI) showDir() {
var (
totalUsage int64
totalSize int64
itemCount int
)

ui.currentDirPath = ui.currentDir.GetPath()
ui.currentDirLabel.SetText("[::b] --- " +
strings.TrimPrefix(ui.currentDirPath, build.RootPathPrefix) +
Expand All @@ -171,6 +185,17 @@ func (ui *UI) showDir() {
ui.sortItems()

for i, item := range ui.currentDir.Files {
if ui.filterValue != "" && !strings.Contains(
strings.ToLower(item.GetName()),
strings.ToLower(ui.filterValue),
) {
continue
}

totalUsage += item.GetUsage()
totalSize += item.GetSize()
itemCount += item.GetItemCount()

cell := tview.NewTableCell(ui.formatFileRow(item))
cell.SetStyle(tcell.Style{}.Foreground(tcell.ColorDefault))
cell.SetReference(ui.currentDir.Files[i])
Expand All @@ -188,20 +213,23 @@ func (ui *UI) showDir() {
footerTextColor = "[black:white:-]"
}

ui.footer.SetText(
ui.footerLabel.SetText(
" Total disk usage: " +
footerNumberColor +
ui.formatSize(ui.currentDir.Usage, true, false) +
ui.formatSize(totalUsage, true, false) +
" Apparent size: " +
footerNumberColor +
ui.formatSize(ui.currentDir.Size, true, false) +
" Items: " + footerNumberColor + fmt.Sprint(ui.currentDir.ItemCount) +
ui.formatSize(totalSize, true, false) +
" Items: " + footerNumberColor + fmt.Sprint(itemCount) +
footerTextColor +
" Sorting by: " + ui.sortBy + " " + ui.sortOrder)

ui.table.Select(0, 0)
ui.table.ScrollToBeginning()
ui.app.SetFocus(ui.table)

if !ui.filtering {
ui.app.SetFocus(ui.table)
}
}

func (ui *UI) sortItems() {
Expand Down Expand Up @@ -244,6 +272,7 @@ func (ui *UI) fileItemSelected(row, column int) {
}

ui.currentDir = selectedDir.(*analyze.Dir)
ui.hideFilterInput()
ui.showDir()

if selectedDir == origDir.Parent {
Expand Down Expand Up @@ -391,7 +420,7 @@ func (ui *UI) showHelp() {
AddItem(nil, 0, 1, false).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(nil, 0, 1, false).
AddItem(text, 26, 1, false).
AddItem(text, 27, 1, false).
AddItem(nil, 0, 1, false), 80, 1, false).
AddItem(nil, 0, 1, false)

Expand Down
Loading

0 comments on commit 8ff4249

Please sign in to comment.