basic box drawing and moving in gim
This commit is contained in:
parent
d700390b54
commit
b4bf8f6c5a
280
gim/main.go
Normal file
280
gim/main.go
Normal file
@ -0,0 +1,280 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/buger/goterm"
|
||||
)
|
||||
|
||||
const (
|
||||
// Reset all custom styles
|
||||
ansiReset = "\033[0m"
|
||||
|
||||
// Reset to default color
|
||||
ansiResetColor = "\033[32m"
|
||||
|
||||
// Return curor to start of line and clean it
|
||||
ansiResetLine = "\r\033[K"
|
||||
)
|
||||
|
||||
// List of possible colors
|
||||
const (
|
||||
black = iota
|
||||
red
|
||||
green
|
||||
yellow
|
||||
blue
|
||||
magenta
|
||||
cyan
|
||||
white
|
||||
)
|
||||
|
||||
func getFgColor(code int) string {
|
||||
return fmt.Sprintf("\033[3%dm", code)
|
||||
}
|
||||
|
||||
func getBgColor(code int) string {
|
||||
return fmt.Sprintf("\033[4%dm", code)
|
||||
}
|
||||
|
||||
func fgColor(str string, color int) string {
|
||||
return fmt.Sprintf("%s%s%s", getFgColor(color), str, ansiReset)
|
||||
}
|
||||
|
||||
func bgColor(str string, color int) string {
|
||||
return fmt.Sprintf("%s%s%s", getBgColor(color), str, ansiReset)
|
||||
}
|
||||
|
||||
type xy [2]int
|
||||
|
||||
func (p xy) x() int {
|
||||
return p[0]
|
||||
}
|
||||
|
||||
func (p xy) y() int {
|
||||
return p[1]
|
||||
}
|
||||
|
||||
func (p xy) add(p2 xy) xy {
|
||||
p[0] += p2[0]
|
||||
p[1] += p2[1]
|
||||
return p
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type terminal struct {
|
||||
cursorPos xy
|
||||
}
|
||||
|
||||
func (t *terminal) moveAbs(to xy) {
|
||||
t.cursorPos = to
|
||||
goterm.MoveCursor(to.x()+1, to.y()+1)
|
||||
}
|
||||
|
||||
func (t *terminal) size() xy {
|
||||
return xy{goterm.Width(), goterm.Height()}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const (
|
||||
boxBorderHoriz = iota
|
||||
boxBorderVert
|
||||
boxBorderTL
|
||||
boxBorderTR
|
||||
boxBorderBL
|
||||
boxBorderBR
|
||||
)
|
||||
|
||||
var boxDefault = []string{
|
||||
"─",
|
||||
"│",
|
||||
"┌",
|
||||
"┐",
|
||||
"└",
|
||||
"┘",
|
||||
}
|
||||
|
||||
type box struct {
|
||||
pos xy
|
||||
size xy // if unset, auto-determined
|
||||
body string
|
||||
|
||||
transparent bool
|
||||
}
|
||||
|
||||
func (b box) lines() []string {
|
||||
lines := strings.Split(b.body, "\n")
|
||||
// if the last line is empty don't include it, it means there was a trailing
|
||||
// newline (or the whole string is empty)
|
||||
if lines[len(lines)-1] == "" {
|
||||
lines = lines[:len(lines)-1]
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
func (b box) getSize() xy {
|
||||
if b.size != (xy{}) {
|
||||
return b.size
|
||||
}
|
||||
var size xy
|
||||
for _, line := range b.lines() {
|
||||
size[1]++
|
||||
if l := len(line); l > size[0] {
|
||||
size[0] = l
|
||||
}
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func (b box) draw(term *terminal) {
|
||||
chars := boxDefault
|
||||
pos := b.pos
|
||||
size := b.getSize()
|
||||
w, h := size.x(), size.y()
|
||||
|
||||
// draw top line
|
||||
term.moveAbs(pos)
|
||||
goterm.Print(chars[boxBorderTL])
|
||||
for i := 0; i < w; i++ {
|
||||
goterm.Print(chars[boxBorderHoriz])
|
||||
}
|
||||
goterm.Print(chars[boxBorderTR])
|
||||
|
||||
drawLine := func(line string) {
|
||||
pos[1]++
|
||||
term.moveAbs(pos)
|
||||
goterm.Print(chars[boxBorderVert])
|
||||
if len(line) > w {
|
||||
line = line[:w]
|
||||
}
|
||||
goterm.Print(line)
|
||||
if b.transparent {
|
||||
term.moveAbs(pos.add(xy{w + 1, 0}))
|
||||
} else {
|
||||
goterm.Print(strings.Repeat(" ", w-len(line)))
|
||||
}
|
||||
goterm.Print(chars[boxBorderVert])
|
||||
}
|
||||
|
||||
// truncate lines if necessary
|
||||
lines := b.lines()
|
||||
if len(lines) > h {
|
||||
lines = lines[:h]
|
||||
}
|
||||
|
||||
// draw body
|
||||
for _, line := range lines {
|
||||
drawLine(line)
|
||||
}
|
||||
|
||||
// draw empty lines
|
||||
for i := 0; i < h-len(lines); i++ {
|
||||
drawLine("")
|
||||
}
|
||||
|
||||
// draw bottom line
|
||||
pos[1]++
|
||||
term.moveAbs(pos)
|
||||
goterm.Print(chars[boxBorderBL])
|
||||
for i := 0; i < w; i++ {
|
||||
goterm.Print(chars[boxBorderHoriz])
|
||||
}
|
||||
goterm.Print(chars[boxBorderBR])
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const (
|
||||
framerate = 30
|
||||
frameperiod = time.Second / time.Duration(framerate)
|
||||
)
|
||||
|
||||
func debugf(str string, args ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, str, args...)
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
{ // exit signal handling, cause ctrl-c doesn't work with goterm otherwise
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
go func() {
|
||||
<-c
|
||||
goterm.Clear()
|
||||
goterm.Flush()
|
||||
os.Stdout.Sync()
|
||||
os.Exit(0)
|
||||
}()
|
||||
}
|
||||
|
||||
term := new(terminal)
|
||||
|
||||
type movingBox struct {
|
||||
box
|
||||
xRight bool
|
||||
yDown bool
|
||||
}
|
||||
|
||||
randBox := func() movingBox {
|
||||
tsize := term.size()
|
||||
return movingBox{
|
||||
box: box{
|
||||
pos: xy{rand.Intn(tsize[0]), rand.Intn(tsize[1])},
|
||||
},
|
||||
xRight: rand.Intn(1) == 0,
|
||||
yDown: rand.Intn(1) == 0,
|
||||
}
|
||||
}
|
||||
|
||||
boxes := []movingBox{
|
||||
randBox(),
|
||||
randBox(),
|
||||
randBox(),
|
||||
randBox(),
|
||||
randBox(),
|
||||
}
|
||||
|
||||
for range time.Tick(frameperiod) {
|
||||
goterm.Clear()
|
||||
|
||||
termSize := term.size()
|
||||
now := time.Now()
|
||||
for i := range boxes {
|
||||
b := &boxes[i]
|
||||
b.body = fmt.Sprintf("%d\n%s", now.Unix(), now.String())
|
||||
|
||||
size := b.getSize()
|
||||
if b.pos[0] <= 0 {
|
||||
b.xRight = true
|
||||
} else if b.pos[0]+size[0]+2 > termSize[0] {
|
||||
b.xRight = false
|
||||
}
|
||||
if b.pos[1] <= 0 {
|
||||
b.yDown = true
|
||||
} else if b.pos[1]+size[1]+2 > termSize[1] {
|
||||
b.yDown = false
|
||||
}
|
||||
|
||||
if b.xRight {
|
||||
b.pos[0] += 3
|
||||
} else {
|
||||
b.pos[0] -= 3
|
||||
}
|
||||
if b.yDown {
|
||||
b.pos[1]++
|
||||
} else {
|
||||
b.pos[1]--
|
||||
}
|
||||
|
||||
b.draw(term)
|
||||
}
|
||||
goterm.Flush()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user