gask/app_state.go

251 lines
5.8 KiB
Go

package main
import (
"fmt"
"os"
"strings"
todotxt "github.com/br0xen/go-todotxt"
"github.com/br0xen/termbox-screen"
"github.com/br0xen/user-config"
termbox "github.com/nsf/termbox-go"
)
const (
ScreenIdMain = iota
ScreenIdTask
ScreenIdAbout
ScreenIdExit
)
type AppState struct {
Name string
Version int
config *userConfig.Config
directory string
fileTodo string
fileDone string
fileReport string
ValidOperations map[string][]string
OpFuncs map[string]func([]string) int
mode ResourceId
TaskList *todotxt.TaskList
DoneList *todotxt.TaskList
taskListLoaded bool
doneListLoaded bool
uiManager *termboxScreen.Manager
lang *Translator
}
const (
DefaultFg = termbox.ColorWhite
DefaultBg = termbox.ColorBlack
TitleFg = termbox.ColorWhite
TitleBg = termbox.ColorBlue
CursorFg = termbox.ColorBlack
CursorBg = termbox.ColorGreen
)
func NewApp() *AppState {
app := &AppState{Name: AppName, Version: AppVersion}
app.initialize()
app.doVersionCheck()
if err := app.LoadTaskList(); err != nil {
if len(os.Args) > 1 && os.Args[1] != "--reinit" {
panic(err)
}
}
return app
}
func (a *AppState) run(parms []string) int {
if len(parms) == 0 || parms[0] == "ui" {
// UI Mode
a.mode = ResModeUI
a.uiManager = termboxScreen.NewManager()
a.uiManager.AddScreen(&MainScreen{})
a.uiManager.AddScreen(&TaskScreen{})
a.uiManager.AddScreen(&AboutScreen{})
mainBundle := termboxScreen.Bundle{}
mainBundle.SetValue(MainBundleListKey, MainBundleListTodo)
if err := a.uiManager.InitializeScreen(ScreenIdMain, mainBundle); err != nil {
return 1
}
if err := a.uiManager.Loop(); err != nil {
return 1
}
return 0
}
a.mode = ResModeCLI
if fn, ok := a.OpFuncs[parms[0]]; ok {
return fn(parms[1:])
}
fmt.Println("Unknown Command")
return 1
}
func (a *AppState) filterList(list *todotxt.TaskList, filter string) *todotxt.TaskList {
return list.Filter(a.getFilterPredicate(filter))
}
func (a *AppState) getFilteredList(filter string) *todotxt.TaskList {
return a.TaskList.Filter(a.getFilterPredicate(filter))
}
func (a *AppState) getFilteredDoneList(filter string) *todotxt.TaskList {
return a.DoneList.Filter(a.getFilterPredicate(filter))
}
func (a *AppState) getTodoFile() string {
return a.directory + a.fileTodo
}
func (a *AppState) getDoneFile() string {
return a.directory + a.fileDone
}
func (a *AppState) getReportFile() string {
return a.directory + a.fileReport
}
func (a *AppState) addOperation(name string, desc []string, fn func([]string) int) {
a.ValidOperations[name] = desc
a.OpFuncs[name] = fn
}
func (a *AppState) getTaskString(task todotxt.Task) string {
var completed string
completed = " "
if task.Completed {
completed = "X"
}
return fmt.Sprintf("%d. [%s] %s", task.Id, completed, strings.TrimPrefix(task.String(), "x "))
}
func (a *AppState) getDoneTaskString(task todotxt.Task) string {
var completed string
completed = " "
if task.Completed {
completed = "X"
}
return fmt.Sprintf("0. [%s] %s", completed, strings.TrimPrefix(task.String(), "x "))
}
func (a *AppState) doVersionCheck() {
confVer, _ := a.config.GetInt("version")
for confVer < a.Version {
confVer = a.migrate(confVer, a.Version)
}
a.config.SetInt("version", confVer)
}
func (a *AppState) migrate(from, to int) int {
if from == to {
return to
}
switch from {
case 0:
a.initializeConfig()
return 1
}
// If we get all the way down here, we _must_ be done.
return to
}
func (a *AppState) initialize() {
a.initLanguage()
var err error
a.config, err = userConfig.NewConfig(a.Name)
if err != nil {
panic(err)
}
a.ValidOperations = make(map[string][]string)
a.OpFuncs = make(map[string]func([]string) int)
a.addOperation("ls",
[]string{"ls - List Tasks"},
a.opListTasks,
)
a.addOperation("lsa",
[]string{"lsa - The same as 'ls -a'"},
func(args []string) int {
return a.opListTasks(append([]string{"-a"}, args...))
},
)
a.addOperation("add",
[]string{"add - Add a task"},
a.opAddTask,
)
a.addOperation("new",
[]string{"new - Same as 'add'"},
a.opAddTask,
)
a.addOperation("x",
[]string{"x - Toggle a task's complete flag on/off"},
a.opToggleTaskComplete,
)
a.addOperation("done",
[]string{"done - The same as 'x'"},
a.opToggleTaskComplete,
)
a.addOperation("archive",
[]string{"archive [id1 id2 ...] - Archive completed tasks"},
a.opArchiveTasks,
)
a.addOperation("--reinit",
[]string{"--reinit - Reset all Configuration Settings"},
func(args []string) int {
a.initializeConfig()
return 0
},
)
a.addOperation("-h",
[]string{"-h - Print this message"},
a.opPrintUsage,
)
a.addOperation("help",
[]string{"help - Print this message"},
a.opPrintUsage,
)
a.addOperation("--h",
[]string{"--h - Print this message"},
a.opPrintUsage,
)
a.directory = a.config.Get("directory")
a.fileTodo = a.config.Get("todofile")
a.fileDone = a.config.Get("donefile")
a.fileReport = a.config.Get("reportfile")
}
func (a *AppState) initializeConfig() {
fmt.Println("Initializing " + a.Name)
for {
var add string
if a.directory != "" {
add = " (" + a.directory + ")"
}
fmt.Println("Path to todo.txt" + add + ":")
var resp string
fmt.Scanln(&resp)
if resp == "" && a.directory != "" {
resp = a.directory
}
if resp != "" {
if !strings.HasSuffix(resp, "/") {
resp = resp + "/"
}
fmt.Println("Setting todo.txt directory to: " + resp)
a.config.Set("directory", resp)
break
}
}
a.config.Set("todofile", "todo.txt")
a.config.Set("donefile", "done.txt")
a.config.Set("reportfile", "report.txt")
}