handle terminal resize event

This commit is contained in:
Lilian Jónsdóttir 2024-07-31 00:53:02 -07:00
parent dd6d3421b0
commit 40521eb646
2 changed files with 86 additions and 68 deletions

View file

@ -4,6 +4,7 @@ package interactive
import ( import (
"fmt" "fmt"
"math" "math"
"os"
"path/filepath" "path/filepath"
"slices" "slices"
"strings" "strings"
@ -12,6 +13,7 @@ import (
"git.burning.moe/celediel/gt/internal/files" "git.burning.moe/celediel/gt/internal/files"
"git.burning.moe/celediel/gt/internal/interactive/modes" "git.burning.moe/celediel/gt/internal/interactive/modes"
"git.burning.moe/celediel/gt/internal/interactive/sorting" "git.burning.moe/celediel/gt/internal/interactive/sorting"
"golang.org/x/term"
"github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/table" "github.com/charmbracelet/bubbles/table"
@ -84,64 +86,37 @@ type model struct {
fltrfiles files.Files fltrfiles files.Files
} }
func newModel(fls []files.File, width, height int, selectall, readonly, once bool, workdir string, mode modes.Mode) model { func newModel(fls []files.File, selectall, readonly, once bool, workdir string, mode modes.Mode) (m model) {
var ( m = model{
fwidth = int(math.Round(float64(width-woffset) * filenameColumnW)) keys: defaultKeyMap(),
owidth = int(math.Round(float64(width-woffset) * pathColumnW)) readonly: readonly,
dwidth = int(math.Round(float64(width-woffset) * dateColumnW)) once: once,
swidth = int(math.Round(float64(width-woffset) * sizeColumnW)) mode: mode,
cwidth = int(math.Round(float64(width-woffset) * checkColumnW)) selected: map[string]bool{},
theight = min(height-hoffset, len(fls)) selectsize: 0,
files: fls,
}
mdl = model{ m.termwidth, m.termheight = termSizes()
keys: defaultKeyMap(),
readonly: readonly,
once: once,
termheight: height,
termwidth: width,
mode: mode,
selected: map[string]bool{},
selectsize: 0,
files: fls,
}
)
if workdir != "" { if workdir != "" {
mdl.workdir = filepath.Clean(workdir) m.workdir = filepath.Clean(workdir)
} }
rows := mdl.freshRows() rows := m.freshRows()
columns := m.freshColumns()
var datecolumn string theight := min(m.termheight-hoffset, len(fls))
switch mdl.mode { m.table = createTable(columns, rows, theight)
case modes.Trashing:
datecolumn = modifiedColumn
default:
datecolumn = trashedColumn
}
columns := []table.Column{ m.sorting = sorting.Name
{Title: filenameColumn, Width: fwidth}, m.sort()
{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()
if selectall { if selectall {
mdl.selectAll() m.selectAll()
} }
return mdl return
} }
type keyMap struct { type keyMap struct {
@ -239,6 +214,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.updateTableSize()
case tea.KeyMsg: case tea.KeyMsg:
if m.filtering { if m.filtering {
switch { switch {
@ -612,6 +589,48 @@ func (m *model) filteredFiles() (filteredFiles files.Files) {
return 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() { func (m *model) updateTableHeight() {
h := min(m.termheight-hoffset, len(m.table.Rows())) h := min(m.termheight-hoffset, len(m.table.Rows()))
m.table.SetHeight(h) 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) { func Select(fls files.Files, selectall, once bool, workdir string, mode modes.Mode) (files.Files, modes.Mode, error) {
mdl := newModel(fls, width, height, selectall, false, once, workdir, mode) mdl := newModel(fls, selectall, false, once, workdir, mode)
endmodel, err := tea.NewProgram(mdl).Run() endmodel, err := tea.NewProgram(mdl).Run()
if err != nil { if err != nil {
return fls, 0, err 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 return m.selectedFiles(), m.mode, nil
} }
func Show(fls files.Files, width, height int, once bool, workdir string) error { func Show(fls files.Files, once bool, workdir string) error {
mdl := newModel(fls, width, height, false, true, once, workdir, modes.Listing) mdl := newModel(fls, false, true, once, workdir, modes.Listing)
if _, err := tea.NewProgram(mdl).Run(); err != nil { if _, err := tea.NewProgram(mdl).Run(); err != nil {
return err return err
} }
@ -724,3 +743,14 @@ func isMatch(pattern, filename string) bool {
f := strings.ToLower(filename) f := strings.ToLower(filename)
return fuzzy.Match(p, f) 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
}

22
main.go
View file

@ -18,7 +18,6 @@ import (
"github.com/adrg/xdg" "github.com/adrg/xdg"
"github.com/charmbracelet/log" "github.com/charmbracelet/log"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"golang.org/x/term"
) )
const ( const (
@ -46,8 +45,6 @@ var (
askconfirm, all bool askconfirm, all bool
workdir, ogdir cli.Path workdir, ogdir cli.Path
recursive bool recursive bool
termwidth int
termheight int
trashDir = filepath.Join(xdg.DataHome, "Trash") 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) 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 // ensure trash directories exist
if _, e := os.Stat(trashDir); os.IsNotExist(e) { if _, e := os.Stat(trashDir); os.IsNotExist(e) {
if err := os.Mkdir(trashDir, executePerm); err != nil { if err := os.Mkdir(trashDir, executePerm); err != nil {
@ -133,7 +121,7 @@ var (
fmt.Fprintln(os.Stdout, msg) fmt.Fprintln(os.Stdout, msg)
return nil 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 { if err != nil {
return err return err
} }
@ -234,7 +222,7 @@ var (
filesToTrash = append(filesToTrash, fls...) 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 { if err != nil {
return err return err
} }
@ -273,7 +261,7 @@ var (
return err return err
} }
return interactive.Show(fls, termwidth, termheight, noInterArg, workdir) return interactive.Show(fls, noInterArg, workdir)
}, },
} }
@ -295,7 +283,7 @@ var (
return err 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 { if err != nil {
return err return err
} }
@ -324,7 +312,7 @@ var (
return err 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 { if err != nil {
return err return err
} }