handle terminal resize event
This commit is contained in:
parent
dd6d3421b0
commit
40521eb646
|
@ -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
22
main.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue