2
1
Fork 0
swim/board.go

180 lines
3.5 KiB
Go
Raw Normal View History

package main
import (
"fmt"
"os"
"strings"
"time"
"tildegit.org/sloum/swim/termios"
)
const (
swimLogo string = "\033[7m ▟\033[27m "
cursorHome string = "\033[0;0H"
styleOff string = "\033[0m"
upAndLeft string = "\033[1A\033[500D"
cursorEnd string = "\033[500;500H"
)
type Board struct {
Title string
Body string
Created time.Time
Lanes []Lane
Current int // Index of current lane
Message string
MsgErr bool
Width int
Height int
Zoom int
}
func (b *Board) Run() {
defer termios.Restore()
termios.SetCharMode()
var ch rune
for {
b.Draw()
ch = Getch()
switch ch {
case 'Q':
termios.Restore()
os.Exit(0)
case 'N':
b.CreateLane()
case 'n':
b.CreateStory()
case '\n':
// View current story
case 'h', 'j', 'k', 'l':
// Move cursor, context dependent
// If a story is open, will scroll
// the story, otherwise will select
// a story
case 'c':
// Comment on current story
case 'a':
// Archive the current story
case 'd':
// Delete current story
case 'D':
// Delete current lane
case 'e':
// Edit current story
case ':':
b.EnterCommand()
case '+':
// b.ZoomIn()
case '-':
// b.ZoomOut()
}
}
}
func (b *Board) ClearMessage() {
b.Message = ""
b.MsgErr = false
}
func (b *Board) SetMessage(msg string, isError bool) {
b.Message = msg
b.MsgErr = isError
}
func (b *Board) CreateLane() {
laneTitle, err := GetAndConfirmCommandLine("Lane Title: ")
if err != nil {
b.SetMessage(err.Error(), true)
return
}
b.Lanes = append(b.Lanes, MakeLane(laneTitle))
if b.Current < 0 {
b.Current = 0
}
}
func (b *Board) CreateStory() {
b.Lanes[b.Current].CreateStory(b)
}
func (b Board) PrintHeader() string {
return fmt.Sprintf("%s%s%-*.*s%s\n", style.Header, swimLogo, b.Width-12, b.Width-12, b.Title, styleOff)
}
func (b Board) PrintInputArea() string {
return fmt.Sprintf("%s%-*.*s%s\n", style.Input, b.Width, b.Width, " ", styleOff)
}
func (b Board) PrintLanes() string {
var out strings.Builder
laneWidth := b.Width / b.Zoom
if len(b.Lanes) == 0 {
for i := 0; i < b.Height - 3; i++ {
out.WriteString(fmt.Sprintf("%s%*.*s%s\n", style.Lane, b.Width, b.Width, " ", styleOff))
}
return out.String()
}
laneText := make([][]string, 0, len(b.Lanes))
maxLen := 0
for _, l := range b.Lanes {
s := l.StringSlice(laneWidth)
laneText = append(laneText, s)
if len(s) > maxLen {
maxLen = len(s)
}
}
for i := 0; i < b.Height - 3; i++ {
for li, l := range laneText {
// TODO fix this
if li >= b.Zoom {
out.WriteRune('\n')
break
}
if i < len(l) {
out.WriteString(l[i])
} else {
out.WriteString(fmt.Sprintf("%s%*.*s%s", style.Lane, laneWidth, laneWidth, " ", styleOff))
}
}
}
out.WriteString(styleOff)
return out.String()
}
func (b *Board) EnterCommand() {
var out strings.Builder
out.WriteString(upAndLeft) // Move up one and over all
out.WriteString(style.Input)
fmt.Print(out.String())
command, err := GetLine(":")
if err != nil {
b.SetMessage(err.Error(), true)
}
b.SetMessage(command, false)
}
func (b Board) PrintMessage() string {
var out strings.Builder
if b.MsgErr {
out.WriteString(style.MessageErr)
} else {
out.WriteString(style.Message)
}
out.WriteString(fmt.Sprintf("%-*.*s%s", b.Width, b.Width, b.Message, styleOff))
return out.String()
}
func (b Board) Draw() {
var out strings.Builder
out.WriteString(cursorHome)
out.WriteString(b.PrintHeader())
out.WriteString(b.PrintLanes())
out.WriteString(b.PrintInputArea())
out.WriteString(b.PrintMessage())
fmt.Print(out.String())
}