2019-02-15 17:15:26 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
|
2021-03-17 17:37:26 +00:00
|
|
|
todotxt "git.bullercodeworks.com/brian/go-todotxt"
|
|
|
|
termboxScreen "git.bullercodeworks.com/brian/termbox-screen"
|
|
|
|
userConfig "git.bullercodeworks.com/brian/user-config"
|
2019-02-28 13:44:03 +00:00
|
|
|
termbox "github.com/nsf/termbox-go"
|
2019-02-15 17:15:26 +00:00
|
|
|
)
|
|
|
|
|
2019-03-14 15:29:33 +00:00
|
|
|
const (
|
|
|
|
ScreenIdMain = iota
|
|
|
|
ScreenIdTask
|
|
|
|
ScreenIdAbout
|
|
|
|
ScreenIdExit
|
|
|
|
)
|
|
|
|
|
2019-02-15 17:15:26 +00:00
|
|
|
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
|
|
|
|
|
2019-02-26 19:22:37 +00:00
|
|
|
mode ResourceId
|
|
|
|
|
2019-02-15 17:15:26 +00:00
|
|
|
TaskList *todotxt.TaskList
|
|
|
|
DoneList *todotxt.TaskList
|
|
|
|
|
2019-02-26 19:22:37 +00:00
|
|
|
taskListLoaded bool
|
|
|
|
doneListLoaded bool
|
|
|
|
|
2019-02-28 13:44:03 +00:00
|
|
|
uiManager *termboxScreen.Manager
|
2019-02-26 19:22:37 +00:00
|
|
|
|
|
|
|
lang *Translator
|
2019-02-15 17:15:26 +00:00
|
|
|
}
|
|
|
|
|
2019-02-28 13:44:03 +00:00
|
|
|
const (
|
|
|
|
DefaultFg = termbox.ColorWhite
|
|
|
|
DefaultBg = termbox.ColorBlack
|
|
|
|
TitleFg = termbox.ColorWhite
|
|
|
|
TitleBg = termbox.ColorBlue
|
|
|
|
CursorFg = termbox.ColorBlack
|
|
|
|
CursorBg = termbox.ColorGreen
|
|
|
|
)
|
|
|
|
|
2019-02-15 17:15:26 +00:00
|
|
|
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
|
2019-02-26 19:22:37 +00:00
|
|
|
a.mode = ResModeUI
|
2019-02-28 13:44:03 +00:00
|
|
|
a.uiManager = termboxScreen.NewManager()
|
|
|
|
a.uiManager.AddScreen(&MainScreen{})
|
|
|
|
a.uiManager.AddScreen(&TaskScreen{})
|
|
|
|
a.uiManager.AddScreen(&AboutScreen{})
|
|
|
|
|
|
|
|
mainBundle := termboxScreen.Bundle{}
|
|
|
|
mainBundle.SetValue(MainBundleListKey, MainBundleListTodo)
|
|
|
|
|
2019-03-14 15:29:33 +00:00
|
|
|
if err := a.uiManager.InitializeScreen(ScreenIdMain, mainBundle); err != nil {
|
2019-02-28 13:44:03 +00:00
|
|
|
return 1
|
|
|
|
}
|
|
|
|
if err := a.uiManager.Loop(); err != nil {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
return 0
|
2019-02-15 17:15:26 +00:00
|
|
|
}
|
2019-02-26 19:22:37 +00:00
|
|
|
a.mode = ResModeCLI
|
2019-02-15 17:15:26 +00:00
|
|
|
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() {
|
2019-02-26 19:22:37 +00:00
|
|
|
a.initLanguage()
|
|
|
|
|
2019-02-15 17:15:26 +00:00
|
|
|
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")
|
|
|
|
}
|