Browse Source

working on stuff

aeth 1 month ago
parent
commit
5620faba5f
5 changed files with 245 additions and 5 deletions
  1. 2 0
      .gitignore
  2. 3 1
      cmd/main.go
  3. 2 1
      go.mod
  4. 185 0
      pkg/savestate.go
  5. 53 3
      pkg/userinterface.go

+ 2 - 0
.gitignore

@@ -24,3 +24,5 @@ _testmain.go
 *.test
 *.prof
 
+build/*
+

+ 3 - 1
cmd/main.go

@@ -4,11 +4,13 @@ import (
 	"fmt"
 	"os"
 
+	itashi "git.aetherial.dev/aeth/itashi/pkg"
 	tea "github.com/charmbracelet/bubbletea"
 )
 
 func main() {
-	p := tea.NewProgram(itashi.initialModel())
+	p := tea.NewProgram(itashi.InitialModel())
+
 	if _, err := p.Run(); err != nil {
 		fmt.Printf("Alas, there's been an error: %v", err)
 		os.Exit(1)

+ 2 - 1
go.mod

@@ -2,9 +2,10 @@ module git.aetherial.dev/aeth/itashi
 
 go 1.22.3
 
+require github.com/charmbracelet/bubbletea v0.26.2
+
 require (
 	github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
-	github.com/charmbracelet/bubbletea v0.26.2 // indirect
 	github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
 	github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
 	github.com/mattn/go-isatty v0.0.18 // indirect

+ 185 - 0
pkg/savestate.go

@@ -0,0 +1,185 @@
+package itashi
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"os"
+	"strconv"
+	"strings"
+	"text/template"
+	"time"
+)
+
+const SHELF_LINE_DELIM = "\n----    ----    ----    ----\n"
+const SHELF_COL_DELIM = "    "
+const TIME_FORMAT = "2006-01-02T15:04:05 -07:00:00"
+const FS_SAVE_LOCATION = "./todo.ta"
+const SHELF_TEMPLATE = "{{.Id}}    {{.Title}}    {{.Desc}}    {{.Due}}    {{.Done}}    {{.Priority}}"
+
+type Task struct {
+	Id       int
+	Title    string
+	Desc     string
+	Due      time.Time
+	Done     bool
+	Priority int
+}
+
+type TaskShelf interface {
+	// Modify the due date of an existing task
+	ModifyDue(id int, due time.Time)
+	// Modify the description field of an existing task
+	ModifyDesc(id int, desc string)
+	// Modify the priority of an existing task
+	ModifyPriority(id int, pri int)
+	// modify the title of an existing task
+	ModifyTitle(id int, title string)
+	// delete an existing task from the shelf
+	DeleteTask(id int)
+	// Mark a task as complete
+	MarkDone(id int)
+	// hopefully you dont need to call this! ;)
+	ResetDone(id int)
+	// Add a task to the shelf
+	AddTask(t Task)
+	// Retrieve all tasks in the shelf
+	GetAll() []Task
+}
+
+/*
+Retrieve all the tasks from the designated TaskShelf
+*/
+func GetTaskList(taskio TaskShelf) []Task {
+	return taskio.GetAll()
+}
+
+/*
+Grab all of the names of the tasks from the TaskShelf
+
+	    :param t: a list of Task structs
+		:returns: A list of the task names
+*/
+func GetTaskNames(t []Task) []string {
+	var taskn []string
+	for i := range t {
+		taskn = append(taskn, t[i].Title)
+	}
+	return taskn
+}
+
+type FilesystemShelf struct {
+	SaveLocation string
+	Template     *template.Template
+	Tasks        []Task
+}
+
+/*
+Create a new filesystem shelf struct to reflect the filesystem shelf
+
+	    :param save: the save location to store the shelf in
+		:returns: a pointer to a FilesystemShelf struct
+*/
+func NewFilesystemShelf(save string) *FilesystemShelf {
+	tmpl, err := template.New("task").Parse(SHELF_TEMPLATE)
+	if err != nil {
+		log.Fatal("Could not parse the shelf template! ", err)
+	}
+	return &FilesystemShelf{
+		SaveLocation: save,
+		Template:     tmpl,
+		Tasks:        []Task{},
+	}
+
+}
+
+// Retrieve all the tasks from the filesystem shelf
+func (f *FilesystemShelf) GetAll() []Task {
+	b, err := os.ReadFile(f.SaveLocation)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return parseFilesystemShelf(b)
+}
+
+/*
+Add a task to the filesystem shelf
+
+	:param t: the Task struct to add
+*/
+func (f *FilesystemShelf) AddTask(t Task) {
+	f.Tasks = append(f.Tasks, t)
+
+	err := os.WriteFile(f.SaveLocation, marshalTaskToShelf(f.Tasks, f.Template), os.ModePerm)
+	if err != nil {
+		log.Fatal("Need to fix later, error writing to fs ", err)
+	}
+}
+
+// Boiler plate so i can implement later
+func (f *FilesystemShelf) ModifyDue(id int, due time.Time)  {}
+func (f *FilesystemShelf) ModifyDesc(id int, desc string)   {}
+func (f *FilesystemShelf) ModifyPriority(id int, pri int)   {}
+func (f *FilesystemShelf) ModifyTitle(id int, title string) {}
+func (f *FilesystemShelf) DeleteTask(id int)                {}
+func (f *FilesystemShelf) MarkDone(id int)                  {}
+func (f *FilesystemShelf) ResetDone(id int)                 {}
+
+// private function for parsing the byte stream from the filesystem
+func parseFilesystemShelf(data []byte) []Task {
+	var filestring string
+	filestring = string(data)
+	items := strings.Split(filestring, SHELF_LINE_DELIM)
+	var shelf []Task
+	for i := range items {
+		sect := strings.Split(items[i], SHELF_COL_DELIM)
+		fmt.Println(sect)
+		var id int
+		var due time.Time
+		var done bool
+		var pri int
+		var err error
+		id, err = strconv.Atoi(sect[0])
+		due, err = time.Parse(TIME_FORMAT, sect[3])
+		done, err = strconv.ParseBool(sect[4])
+		pri, err = strconv.Atoi(sect[5])
+		if err != nil {
+			log.Fatal("Couldnt parse from filesystem shelf", err)
+		}
+
+		shelf = append(shelf, Task{
+			Id:       id,
+			Title:    sect[1],
+			Desc:     sect[2],
+			Due:      due,
+			Done:     done,
+			Priority: pri,
+		})
+
+	}
+	return shelf
+
+}
+
+/*
+Helper function to marshal the tasks to the custom format
+
+	     :param tasks: an array of Task structs
+		 :returns: a byte array
+*/
+func marshalTaskToShelf(tasks []Task, templ *template.Template) []byte {
+	var bw bytes.Buffer
+	for i := range tasks {
+		err := templ.Execute(&bw, tasks[i])
+		if err != nil {
+			log.Fatal("Error parsing data into template: ", err)
+		}
+		// dynamically allocating, no need for the read delim
+		_, err = bw.Write([]byte(SHELF_LINE_DELIM))
+		if err != nil {
+			log.Fatal("Error parsing data into template: ", err)
+		}
+
+	}
+	return bw.Bytes()
+}

+ 53 - 3
pkg/userinterface.go

@@ -4,20 +4,55 @@ package itashi
 
 import (
 	"fmt"
+	"time"
 
 	tea "github.com/charmbracelet/bubbletea"
 )
 
+const SPRING_EQUINOX = 81
+const SUMMER_SOLSTICE = 173
+const AUTUMN_EQUINOX = 265
+const WINTER_SOLSTICE = 356
+
+func getSeason(dayofyear int) string {
+	if dayofyear > 365 {
+		return "[REDACTED]"
+	}
+	if dayofyear < 0 {
+		return "[REDACTED]"
+	}
+	if dayofyear > 0 && dayofyear < SPRING_EQUINOX {
+		return "Winter"
+	}
+	if dayofyear > SPRING_EQUINOX && dayofyear < SUMMER_SOLSTICE {
+		return "Spring"
+	}
+	if dayofyear > SUMMER_SOLSTICE && dayofyear < AUTUMN_EQUINOX {
+		return "Summer"
+	}
+	if dayofyear > AUTUMN_EQUINOX && dayofyear < WINTER_SOLSTICE {
+		return "Autumn"
+	}
+	if dayofyear > WINTER_SOLSTICE && dayofyear < 365 {
+		return "Winter"
+	}
+	return "Dont know how you got here...."
+
+}
+
 type model struct {
 	choices  []string
 	cursor   int
 	selected map[int]struct{}
 }
 
-func initialModel() model {
+func InitialModel() model {
+	shelf := NewFilesystemShelf(FS_SAVE_LOCATION)
+	//shelf.AddTask(Task{Id: 1, Title: "This is a sample task", Desc: "Quick sample task that im testing the storage with",
+	//	Due: time.Now().AddDate(0, 0, 2), Done: false, Priority: 1})
 	return model{
 		// Our to-do list is a grocery list
-		choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},
+		choices: GetTaskNames(shelf.GetAll()),
 
 		// A map which indicates which choices are selected. We're using
 		// the  map like a mathematical set. The keys refer to the indexes
@@ -75,7 +110,22 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 
 func (m model) View() string {
 	// The header
-	s := "What should we buy at the market?\n\n"
+	rn := time.Now()
+	rnString := fmt.Sprintf("%s %v, %v", rn.Month().String(), rn.Day(), rn.Year())
+	season := getSeason(rn.YearDay())
+	solsticeDiff := 10
+	day := rn.Weekday()
+	timenow := fmt.Sprintf("%v:%v %s", rn.Hour(), rn.Minute(), "AM")
+	toEod := 5
+	toSd := 6
+
+	s := fmt.Sprintf(
+		`
+%s                                 %s, %v days until the next solstice.  
+%s    
+%s (%vH, %vM -> EoD, %vH, %vM -> sunset)
+
+`, rnString, season, solsticeDiff, day, timenow, toEod, toEod, toSd, toSd)
 
 	// Iterate over our choices
 	for i, choice := range m.choices {