From 2f1191261953d3401e0fe48be85528863942741a Mon Sep 17 00:00:00 2001 From: Daniel Milde Date: Tue, 13 Feb 2024 00:57:03 +0100 Subject: [PATCH] feat: export with dialog for file name --- cmd/gdu/app/app.go | 7 ----- cmd/gdu/main.go | 1 - tui/actions.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++ tui/keys.go | 26 +++-------------- tui/show.go | 9 +++++- tui/tui.go | 8 ++---- tui/utils.go | 11 +++++++ 7 files changed, 97 insertions(+), 37 deletions(-) diff --git a/cmd/gdu/app/app.go b/cmd/gdu/app/app.go index ca060a9e6..61973500e 100644 --- a/cmd/gdu/app/app.go +++ b/cmd/gdu/app/app.go @@ -43,7 +43,6 @@ type Flags struct { CfgFile string `yaml:"-"` LogFile string `yaml:"log-file"` InputFile string `yaml:"input-file"` - ExportTree string `yaml:"export-file"` OutputFile string `yaml:"output-file"` IgnoreDirs []string `yaml:"ignore-dirs"` IgnoreDirPatterns []string `yaml:"ignore-dir-patterns"` @@ -254,12 +253,6 @@ func (a *App) createUI() (UI, error) { }) } - if a.Flags.ExportTree != "" { - opts = append(opts, func(ui *tui.UI) { - ui.SetExportTree(a.Flags.ExportTree) - }) - } - ui = tui.CreateUI( a.TermApp, a.Screen, diff --git a/cmd/gdu/main.go b/cmd/gdu/main.go index 1f1434765..0c28296c5 100644 --- a/cmd/gdu/main.go +++ b/cmd/gdu/main.go @@ -42,7 +42,6 @@ func init() { flags.StringVarP(&af.LogFile, "log-file", "l", "/dev/null", "Path to a logfile") flags.StringVarP(&af.OutputFile, "output-file", "o", "", "Export all info into file as JSON") flags.StringVarP(&af.InputFile, "input-file", "f", "", "Import analysis from JSON file") - flags.StringVarP(&af.ExportTree, "export-file", "e", "", "Export all info into file as JSON when doing uppercase S") flags.IntVarP(&af.MaxCores, "max-cores", "m", runtime.NumCPU(), fmt.Sprintf("Set max cores that GDU will use. %d cores available", runtime.NumCPU())) flags.BoolVarP(&af.ShowVersion, "version", "v", false, "Print version") diff --git a/tui/actions.go b/tui/actions.go index c9b39d603..1fd2a4d07 100644 --- a/tui/actions.go +++ b/tui/actions.go @@ -2,13 +2,16 @@ package tui import ( "bufio" + "bytes" "fmt" "io" "os" "os/exec" "runtime" "runtime/debug" + "strconv" "strings" + "time" "github.com/dundee/gdu/v5/build" "github.com/dundee/gdu/v5/pkg/analyze" @@ -380,3 +383,72 @@ func (ui *UI) openItem() { ui.showErr("Error opening", err) } } + +func (ui *UI) confirmExport() { + form := tview.NewForm(). + AddInputField("File name", "export.json", 30, nil, func(v string) { + ui.exportName = v + }). + AddButton("Export", ui.exportAnalysis). + SetButtonsAlign(tview.AlignCenter) + form.SetBorder(true). + SetTitle(" Export data to JSON "). + SetInputCapture(func(key *tcell.EventKey) *tcell.EventKey { + if key.Key() == tcell.KeyEsc { + ui.pages.RemovePage("export") + ui.app.SetFocus(ui.table) + return nil + } + return key + }) + flex := modal(form, 50, 7) + ui.pages.AddPage("export", flex, true, true) + ui.app.SetFocus(form) +} + +func (ui *UI) exportAnalysis() { + ui.pages.RemovePage("export") + + text := tview.NewTextView().SetText("Export in progress...").SetTextAlign(tview.AlignCenter) + text.SetBorder(true).SetTitle(" Export data to JSON ") + flex := modal(text, 50, 3) + ui.pages.AddPage("exporting", flex, true, true) + + go func() { + var err error + defer ui.app.QueueUpdateDraw(func() { + ui.pages.RemovePage("exporting") + if err == nil { + ui.app.SetFocus(ui.table) + } + }) + + var buff bytes.Buffer + + buff.Write([]byte(`[1,2,{"progname":"gdu","progver":"`)) + buff.Write([]byte(build.Version)) + buff.Write([]byte(`","timestamp":`)) + buff.Write([]byte(strconv.FormatInt(time.Now().Unix(), 10))) + buff.Write([]byte("},\n")) + + file, err := os.Create(ui.exportName) + if err != nil { + ui.showErrFromGo("Error creating file", err) + return + } + + if err = ui.topDir.EncodeJSON(&buff, true); err != nil { + ui.showErrFromGo("Error encoding JSON", err) + return + } + + if _, err = buff.Write([]byte("]\n")); err != nil { + ui.showErrFromGo("Error writting to buffer", err) + return + } + if _, err = buff.WriteTo(file); err != nil { + ui.showErrFromGo("Error writting to file", err) + return + } + }() +} diff --git a/tui/keys.go b/tui/keys.go index 775ee6af2..1bb475bfa 100644 --- a/tui/keys.go +++ b/tui/keys.go @@ -2,10 +2,6 @@ package tui import ( "fmt" - "bytes" - "strconv" - "time" - "os" "github.com/dundee/gdu/v5/pkg/fs" "github.com/gdamore/tcell/v2" @@ -17,7 +13,7 @@ func (ui *UI) keyPressed(key *tcell.EventKey) *tcell.EventKey { return nil } - if ui.pages.HasPage("file") { + if ui.pages.HasPage("file") || ui.pages.HasPage("export") { return key // send event to primitive } if ui.filtering { @@ -235,23 +231,9 @@ func (ui *UI) handleMainActions(key *tcell.EventKey) *tcell.EventKey { if ui.currentDir != nil { ui.rescanDir() } - case 'S': - var buff bytes.Buffer - - buff.Write([]byte(`[1,2,{"progname":"gdu","progver":"`)) - //~ buff.Write([]byte(build.Version)) - buff.Write([]byte(`","timestamp":`)) - buff.Write([]byte(strconv.FormatInt(time.Now().Unix(), 10))) - buff.Write([]byte("},\n")) - - file, fileErr := os.Create(ui.exportTree) - if fileErr != nil { - fmt.Println(fileErr) - } - - ui.topDir.EncodeJSON(&buff, true) - buff.Write([]byte("]\n")) - buff.WriteTo(file) + case 'E': + ui.confirmExport() + return nil case 's': ui.setSorting("size") case 'C': diff --git a/tui/show.go b/tui/show.go index 4b14b1e0f..abf35cab9 100644 --- a/tui/show.go +++ b/tui/show.go @@ -17,7 +17,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]S [white:black:-]Export actual tree + [::b]E [white:black:-]Export analysis data to file as JSON [::b]/ [white:black:-]Search items by name [::b]a [white:black:-]Toggle between showing disk usage and apparent size [::b]B [white:black:-]Toggle bar alignment to biggest file or directory @@ -234,6 +234,13 @@ func (ui *UI) showErr(msg string, err error) { } ui.pages.AddPage("error", modal, true, true) + ui.app.SetFocus(modal) +} + +func (ui *UI) showErrFromGo(msg string, err error) { + ui.app.QueueUpdateDraw(func() { + ui.showErr(msg, err) + }) } func (ui *UI) showHelp() { diff --git a/tui/tui.go b/tui/tui.go index f3a8fb285..dec7eb750 100644 --- a/tui/tui.go +++ b/tui/tui.go @@ -33,7 +33,6 @@ type UI struct { topDir fs.Item topDirPath string currentDirPath string - exportTree string askBeforeDelete bool showItemCount bool showMtime bool @@ -55,6 +54,7 @@ type UI struct { defaultSortBy string defaultSortOrder string markedRows map[int]struct{} + exportName string } // Option is optional function customizing the bahaviour of UI @@ -96,6 +96,7 @@ func CreateUI( defaultSortBy: "size", defaultSortOrder: "desc", markedRows: make(map[int]struct{}), + exportName: "export.json", } for _, o := range opts { o(ui) @@ -182,11 +183,6 @@ func (ui *UI) SetCurrentItemNameMaxLen(len int) { ui.currentItemNameMaxLen = len } -// SetExportTree set the path where to export when doing the key "S" -func (ui *UI) SetExportTree(path string) { - ui.exportTree = path -} - // UseOldSizeBar uses the old size bar (# chars) instead of the new one (unicode block elements) func (ui *UI) UseOldSizeBar() { ui.useOldSizeBar = true diff --git a/tui/utils.go b/tui/utils.go index f38aa3342..351f679c9 100644 --- a/tui/utils.go +++ b/tui/utils.go @@ -2,6 +2,7 @@ package tui import ( "github.com/dundee/gdu/v5/pkg/device" + "github.com/rivo/tview" ) var ( @@ -65,3 +66,13 @@ func min(a, b int) int { } return b } + +func modal(p tview.Primitive, width, height int) tview.Primitive { + return tview.NewFlex(). + AddItem(nil, 0, 1, false). + AddItem(tview.NewFlex().SetDirection(tview.FlexRow). + AddItem(nil, 0, 1, false). + AddItem(p, height, 1, true). + AddItem(nil, 0, 1, false), width, 1, true). + AddItem(nil, 0, 1, false) +}