Add a command and message for getting terminal size

There may be too much rigamarole around this (it's simpler to get the size
imperatively and synchronously) but adding it for now.
This commit is contained in:
Christian Rocha 2020-05-14 10:49:08 -04:00
parent 0e39761525
commit db4600aeb2
No known key found for this signature in database
GPG Key ID: D6CC7A16E5878018
2 changed files with 60 additions and 34 deletions

34
boba.go
View File

@ -4,7 +4,6 @@ import (
"io" "io"
"os" "os"
"strings" "strings"
"time"
"github.com/muesli/termenv" "github.com/muesli/termenv"
) )
@ -179,36 +178,3 @@ func AltScreen() {
func ExitAltScreen() { func ExitAltScreen() {
termenv.ExitAltScreen() termenv.ExitAltScreen()
} }
// Every is a command that ticks in sync with the system clock. So, if you
// wanted to tick with the system clock every second, minute or hour you
// could use this. It's also handy for having different things tick in sync.
//
// Note that because we're ticking with the system clock the tick will likely
// not run for the entire specified duration. For example, if we're ticking for
// one minute and the clock is at 12:34:20 then the next tick will happen at
// 12:35:00, 40 seconds later.
func Every(duration time.Duration, fn func(time.Time) Msg) Cmd {
return func() Msg {
n := time.Now()
d := n.Truncate(duration).Add(duration).Sub(n)
t := time.NewTimer(d)
select {
case now := <-t.C:
return fn(now)
}
}
}
// Tick is a subscription that at an interval independent of the system clock
// at the given duration. That is, the timer begins when precisely when invoked,
// and runs for its entire duration.
func Tick(d time.Duration, fn func(time.Time) Msg) Cmd {
return func() Msg {
t := time.NewTimer(d)
select {
case now := <-t.C:
return fn(now)
}
}
}

60
commands.go Normal file
View File

@ -0,0 +1,60 @@
package boba
import (
"os"
"time"
"golang.org/x/crypto/ssh/terminal"
)
// Every is a command that ticks in sync with the system clock. So, if you
// wanted to tick with the system clock every second, minute or hour you
// could use this. It's also handy for having different things tick in sync.
//
// Note that because we're ticking with the system clock the tick will likely
// not run for the entire specified duration. For example, if we're ticking for
// one minute and the clock is at 12:34:20 then the next tick will happen at
// 12:35:00, 40 seconds later.
func Every(duration time.Duration, fn func(time.Time) Msg) Cmd {
return func() Msg {
n := time.Now()
d := n.Truncate(duration).Add(duration).Sub(n)
t := time.NewTimer(d)
select {
case now := <-t.C:
return fn(now)
}
}
}
// Tick is a command that at an interval independent of the system clock at the
// given duration. That is, the timer begins when precisely when invoked, and
// runs for its entire duration.
func Tick(d time.Duration, fn func(time.Time) Msg) Cmd {
return func() Msg {
t := time.NewTimer(d)
select {
case now := <-t.C:
return fn(now)
}
}
}
// TerminalSizeMsg defines an interface for a message that contains terminal
// sizing as sent by GetTerminalSize.
type TerminalSizeMsg interface {
// Size returns the terminal width and height, in that order
Size() (int, int)
// Error returns the error, if any, received when fetching the terminal size
Error() error
}
// GetTerminalSize is used to get
func GetTerminalSize(newMsgFunc func(int, int, error) TerminalSizeMsg) Cmd {
w, h, err := terminal.GetSize(int(os.Stdout.Fd()))
return func() Msg {
return newMsgFunc(w, h, err)
}
}