174 lines
4.3 KiB
Go
174 lines
4.3 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bufio"
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
"log/slog"
|
||
|
|
"os"
|
||
|
|
"strconv"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"gitea.kleinsense.nl/DariusKlein/kleinTodo/common"
|
||
|
|
"github.com/urfave/cli/v3"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Todo Command
|
||
|
|
func Todo() *cli.Command {
|
||
|
|
return &cli.Command{
|
||
|
|
Name: "todo",
|
||
|
|
Usage: "print todo items and allow for updating",
|
||
|
|
Action: todo,
|
||
|
|
HideHelpCommand: true,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func todo(context context.Context, c *cli.Command) error {
|
||
|
|
// bufio.Scanner is a great way to read user input line by line.
|
||
|
|
scanner := bufio.NewScanner(os.Stdin)
|
||
|
|
|
||
|
|
store, err := common.GetTodoDataStore()
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
todos := store.GetTodoList(cfg.Server.Credentials.Username)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
// This is the main application loop for the interactive mode.
|
||
|
|
for {
|
||
|
|
clearScreen()
|
||
|
|
printTodos(todos)
|
||
|
|
|
||
|
|
fmt.Print("What would you like to do? (update, delete, add, quit) [u/d/a/q]: ")
|
||
|
|
|
||
|
|
// Wait for and read the user's next command.
|
||
|
|
scanner.Scan()
|
||
|
|
command := strings.ToLower(strings.TrimSpace(scanner.Text()))
|
||
|
|
|
||
|
|
switch command {
|
||
|
|
case "u", "update":
|
||
|
|
todos = handleUpdate(scanner, todos, store)
|
||
|
|
case "d", "delete":
|
||
|
|
todos = handleDelete(scanner, todos, store)
|
||
|
|
case "a", "add":
|
||
|
|
todos = handleAdd(scanner, todos, store)
|
||
|
|
case "q", "quit":
|
||
|
|
fmt.Println("Goodbye!")
|
||
|
|
return nil // Exit the program
|
||
|
|
default:
|
||
|
|
fmt.Println("Invalid command. Please try again.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func clearScreen() {
|
||
|
|
fmt.Print("\033[H\033[2J")
|
||
|
|
}
|
||
|
|
|
||
|
|
func printTodos(todos []common.Todo) {
|
||
|
|
fmt.Printf("Todo items:\n")
|
||
|
|
for i, t := range todos {
|
||
|
|
t.PrintIndexed(i + 1)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// handleDelete prompts for an index and removes the item.
|
||
|
|
func handleDelete(scanner *bufio.Scanner, todos []common.Todo, store *common.BoltStore) []common.Todo {
|
||
|
|
fmt.Print("Enter the number of the item to delete: ")
|
||
|
|
scanner.Scan()
|
||
|
|
input := strings.TrimSpace(scanner.Text())
|
||
|
|
index, err := strconv.Atoi(input)
|
||
|
|
|
||
|
|
if err != nil || index < 1 || index > len(todos) {
|
||
|
|
fmt.Println("Invalid number. Returning to main menu.")
|
||
|
|
return todos
|
||
|
|
}
|
||
|
|
|
||
|
|
removedItem := todos[index-1]
|
||
|
|
|
||
|
|
err = store.RemoveValueFromBucket(cfg.Server.Credentials.Username, removedItem.Name)
|
||
|
|
if err != nil {
|
||
|
|
slog.Error(err.Error())
|
||
|
|
return todos
|
||
|
|
}
|
||
|
|
fmt.Printf("Item '%s' deleted.\n", removedItem.Name)
|
||
|
|
|
||
|
|
todos = append(todos[:index-1], todos[index:]...)
|
||
|
|
return todos
|
||
|
|
}
|
||
|
|
|
||
|
|
// handleUpdate prompts for an index and new values.
|
||
|
|
func handleUpdate(scanner *bufio.Scanner, todos []common.Todo, store *common.BoltStore) []common.Todo {
|
||
|
|
fmt.Print("Enter the number of the item to update: ")
|
||
|
|
scanner.Scan()
|
||
|
|
input := strings.TrimSpace(scanner.Text())
|
||
|
|
index, err := strconv.Atoi(input)
|
||
|
|
|
||
|
|
if err != nil || index < 1 || index > len(todos) {
|
||
|
|
fmt.Println("Invalid number. Returning to main menu.")
|
||
|
|
return todos
|
||
|
|
}
|
||
|
|
|
||
|
|
// Adjust for 0-based slice index
|
||
|
|
itemToUpdate := todos[index-1]
|
||
|
|
|
||
|
|
fmt.Printf("Updating '%s'. Press Enter to keep current value.\n", itemToUpdate.Name)
|
||
|
|
|
||
|
|
fmt.Printf("New name [%s]: ", itemToUpdate.Name)
|
||
|
|
scanner.Scan()
|
||
|
|
newName := strings.TrimSpace(scanner.Text())
|
||
|
|
if newName != "" {
|
||
|
|
itemToUpdate.Name = newName
|
||
|
|
}
|
||
|
|
|
||
|
|
fmt.Printf("New description [%s]: ", itemToUpdate.Description)
|
||
|
|
scanner.Scan()
|
||
|
|
newDescription := strings.TrimSpace(scanner.Text())
|
||
|
|
if newDescription != "" {
|
||
|
|
itemToUpdate.Description = newDescription
|
||
|
|
}
|
||
|
|
|
||
|
|
fmt.Printf("New status [%s]: ", itemToUpdate.Status)
|
||
|
|
scanner.Scan()
|
||
|
|
newStatus := strings.TrimSpace(scanner.Text())
|
||
|
|
if newStatus != "" {
|
||
|
|
itemToUpdate.Status = newStatus
|
||
|
|
}
|
||
|
|
|
||
|
|
err = itemToUpdate.Store(store, cfg.Server.Credentials.Username)
|
||
|
|
if err != nil {
|
||
|
|
slog.Error(err.Error())
|
||
|
|
return todos
|
||
|
|
}
|
||
|
|
|
||
|
|
fmt.Println("Item updated.")
|
||
|
|
todos[index-1] = itemToUpdate
|
||
|
|
return todos
|
||
|
|
}
|
||
|
|
|
||
|
|
// handleAdd prompts for the details of a new item.
|
||
|
|
func handleAdd(scanner *bufio.Scanner, todos []common.Todo, store *common.BoltStore) []common.Todo {
|
||
|
|
fmt.Print("Enter the name of the new task: ")
|
||
|
|
scanner.Scan()
|
||
|
|
name := strings.TrimSpace(scanner.Text())
|
||
|
|
|
||
|
|
fmt.Print("Enter the description: ")
|
||
|
|
scanner.Scan()
|
||
|
|
description := strings.TrimSpace(scanner.Text())
|
||
|
|
|
||
|
|
newTodo := common.Todo{
|
||
|
|
Name: name, Description: description, Status: common.NotStarted, Owner: cfg.Server.Credentials.Username,
|
||
|
|
}
|
||
|
|
err := newTodo.Store(store, cfg.Server.Credentials.Username)
|
||
|
|
if err != nil {
|
||
|
|
slog.Error(err.Error())
|
||
|
|
return todos
|
||
|
|
}
|
||
|
|
|
||
|
|
fmt.Println("New item added.")
|
||
|
|
return append(todos, newTodo)
|
||
|
|
}
|