From 40521eb64615edc62c7064b4ffccdac896f6e622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lilian=20J=C3=B3nsd=C3=B3ttir?= Date: Wed, 31 Jul 2024 00:53:02 -0700 Subject: [PATCH] handle terminal resize event --- internal/interactive/interactive.go | 132 +++++++++++++++++----------- main.go | 22 ++--- 2 files changed, 86 insertions(+), 68 deletions(-) diff --git a/internal/interactive/interactive.go b/internal/interactive/interactive.go index d02a858..a5c9fa9 100644 --- a/internal/interactive/interactive.go +++ b/internal/interactive/interactive.go @@ -4,6 +4,7 @@ package interactive import ( "fmt" "math" + "os" "path/filepath" "slices" "strings" @@ -12,6 +13,7 @@ import ( "git.burning.moe/celediel/gt/internal/files" "git.burning.moe/celediel/gt/internal/interactive/modes" "git.burning.moe/celediel/gt/internal/interactive/sorting" + "golang.org/x/term" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/table" @@ -84,64 +86,37 @@ type model struct { fltrfiles files.Files } -func newModel(fls []files.File, width, height int, selectall, readonly, once bool, workdir string, mode modes.Mode) model { - var ( - fwidth = int(math.Round(float64(width-woffset) * filenameColumnW)) - owidth = int(math.Round(float64(width-woffset) * pathColumnW)) - dwidth = int(math.Round(float64(width-woffset) * dateColumnW)) - swidth = int(math.Round(float64(width-woffset) * sizeColumnW)) - cwidth = int(math.Round(float64(width-woffset) * checkColumnW)) - theight = min(height-hoffset, len(fls)) +func newModel(fls []files.File, selectall, readonly, once bool, workdir string, mode modes.Mode) (m model) { + m = model{ + keys: defaultKeyMap(), + readonly: readonly, + once: once, + mode: mode, + selected: map[string]bool{}, + selectsize: 0, + files: fls, + } - mdl = model{ - keys: defaultKeyMap(), - readonly: readonly, - once: once, - termheight: height, - termwidth: width, - mode: mode, - selected: map[string]bool{}, - selectsize: 0, - files: fls, - } - ) + m.termwidth, m.termheight = termSizes() if workdir != "" { - mdl.workdir = filepath.Clean(workdir) + m.workdir = filepath.Clean(workdir) } - rows := mdl.freshRows() + rows := m.freshRows() + columns := m.freshColumns() - var datecolumn string - switch mdl.mode { - case modes.Trashing: - datecolumn = modifiedColumn - default: - datecolumn = trashedColumn - } + theight := min(m.termheight-hoffset, len(fls)) + m.table = createTable(columns, rows, theight) - columns := []table.Column{ - {Title: filenameColumn, Width: fwidth}, - {Title: pathColumn, Width: owidth}, - {Title: datecolumn, Width: dwidth}, - {Title: sizeColumn, Width: swidth}, - } - if !mdl.readonly { - columns = append(columns, table.Column{Title: uncheck, Width: cwidth}) - } else { - columns[0].Width += cwidth - } - - mdl.table = createTable(columns, rows, theight) - - mdl.sorting = sorting.Name - mdl.sort() + m.sorting = sorting.Name + m.sort() if selectall { - mdl.selectAll() + m.selectAll() } - return mdl + return } type keyMap struct { @@ -239,6 +214,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } switch msg := msg.(type) { + case tea.WindowSizeMsg: + m.updateTableSize() case tea.KeyMsg: if m.filtering { switch { @@ -612,6 +589,48 @@ func (m *model) filteredFiles() (filteredFiles files.Files) { return } +func (m *model) freshColumns() []table.Column { + var ( + fwidth = int(math.Round(float64(m.termwidth-woffset) * filenameColumnW)) + owidth = int(math.Round(float64(m.termwidth-woffset) * pathColumnW)) + dwidth = int(math.Round(float64(m.termwidth-woffset) * dateColumnW)) + swidth = int(math.Round(float64(m.termwidth-woffset) * sizeColumnW)) + cwidth = int(math.Round(float64(m.termwidth-woffset) * checkColumnW)) + datecolumn string + ) + + switch m.mode { + case modes.Trashing: + datecolumn = modifiedColumn + default: + datecolumn = trashedColumn + } + + columns := []table.Column{ + {Title: filenameColumn, Width: fwidth}, + {Title: pathColumn, Width: owidth}, + {Title: datecolumn, Width: dwidth}, + {Title: sizeColumn, Width: swidth}, + } + + if !m.readonly { + columns = append(columns, table.Column{Title: uncheck, Width: cwidth}) + } else { + columns[0].Width += cwidth + } + + return columns +} + +func (m *model) updateTableSize() { + width, height := termSizes() + m.termheight = height + m.termwidth = width - poffset + m.table.SetWidth(m.termwidth) + m.updateTableHeight() + m.table.SetColumns(m.freshColumns()) +} + func (m *model) updateTableHeight() { h := min(m.termheight-hoffset, len(m.table.Rows())) m.table.SetHeight(h) @@ -620,8 +639,8 @@ func (m *model) updateTableHeight() { } } -func Select(fls files.Files, width, height int, selectall, once bool, workdir string, mode modes.Mode) (files.Files, modes.Mode, error) { - mdl := newModel(fls, width, height, selectall, false, once, workdir, mode) +func Select(fls files.Files, selectall, once bool, workdir string, mode modes.Mode) (files.Files, modes.Mode, error) { + mdl := newModel(fls, selectall, false, once, workdir, mode) endmodel, err := tea.NewProgram(mdl).Run() if err != nil { return fls, 0, err @@ -633,8 +652,8 @@ func Select(fls files.Files, width, height int, selectall, once bool, workdir st return m.selectedFiles(), m.mode, nil } -func Show(fls files.Files, width, height int, once bool, workdir string) error { - mdl := newModel(fls, width, height, false, true, once, workdir, modes.Listing) +func Show(fls files.Files, once bool, workdir string) error { + mdl := newModel(fls, false, true, once, workdir, modes.Listing) if _, err := tea.NewProgram(mdl).Run(); err != nil { return err } @@ -724,3 +743,14 @@ func isMatch(pattern, filename string) bool { f := strings.ToLower(filename) return fuzzy.Match(p, f) } + +func termSizes() (width int, height int) { + // read the term height and width for tables + var err error + width, height, err = term.GetSize(int(os.Stdout.Fd())) + if err != nil { + width = 80 + height = 24 + } + return +} diff --git a/main.go b/main.go index e9477c5..53d258c 100644 --- a/main.go +++ b/main.go @@ -18,7 +18,6 @@ import ( "github.com/adrg/xdg" "github.com/charmbracelet/log" "github.com/urfave/cli/v2" - "golang.org/x/term" ) const ( @@ -46,8 +45,6 @@ var ( askconfirm, all bool workdir, ogdir cli.Path recursive bool - termwidth int - termheight int trashDir = filepath.Join(xdg.DataHome, "Trash") @@ -65,15 +62,6 @@ var ( log.Errorf("unknown log level '%s' (possible values: debug, info, warn, error, fatal, default: warn)", loglvl) } - // read the term height and width for tables - width, height, e := term.GetSize(int(os.Stdout.Fd())) - if e != nil { - width = 80 - height = 24 - } - termwidth = width - termheight = height - // ensure trash directories exist if _, e := os.Stat(trashDir); os.IsNotExist(e) { if err := os.Mkdir(trashDir, executePerm); err != nil { @@ -133,7 +121,7 @@ var ( fmt.Fprintln(os.Stdout, msg) return nil } - selected, mode, err = interactive.Select(infiles, termwidth, termheight, false, false, workdir, modes.Interactive) + selected, mode, err = interactive.Select(infiles, false, false, workdir, modes.Interactive) if err != nil { return err } @@ -234,7 +222,7 @@ var ( filesToTrash = append(filesToTrash, fls...) } - selected, _, err := interactive.Select(filesToTrash, termwidth, termheight, false, false, workdir, modes.Trashing) + selected, _, err := interactive.Select(filesToTrash, false, false, workdir, modes.Trashing) if err != nil { return err } @@ -273,7 +261,7 @@ var ( return err } - return interactive.Show(fls, termwidth, termheight, noInterArg, workdir) + return interactive.Show(fls, noInterArg, workdir) }, } @@ -295,7 +283,7 @@ var ( return err } - selected, _, err := interactive.Select(fls, termwidth, termheight, all, all, workdir, modes.Restoring) + selected, _, err := interactive.Select(fls, all, all, workdir, modes.Restoring) if err != nil { return err } @@ -324,7 +312,7 @@ var ( return err } - selected, _, err := interactive.Select(fls, termwidth, termheight, all, all, workdir, modes.Cleaning) + selected, _, err := interactive.Select(fls, all, all, workdir, modes.Cleaning) if err != nil { return err }