Skip to content

Instantly share code, notes, and snippets.

@bethropolis
Created September 28, 2023 03:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bethropolis/a2f503b2aa46aaf16d4669aee3a2f2b8 to your computer and use it in GitHub Desktop.
Save bethropolis/a2f503b2aa46aaf16d4669aee3a2f2b8 to your computer and use it in GitHub Desktop.
a todo app written in go with menu, list, add and remove features
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
"time"
)
const (
todoFile = "todo.txt"
)
func StoreTodo(todo string) {
todoFile, err := os.OpenFile(todoFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
defer todoFile.Close()
todoFile.WriteString(todo + " | " + time.Now().Format("2006-01-02 15:04:05") + "\n")
}
func addTodo() {
fmt.Printf("\nEnter your todo: ")
reader := bufio.NewReader(os.Stdin)
todo, _ := reader.ReadString('\n')
todo = strings.TrimSpace(todo)
StoreTodo(todo)
fmt.Printf("Todo added: %s\n", todo)
fmt.Printf("\n back to main menu (enter)")
fmt.Scanln()
}
func listTodo() {
var i int
todoFile, err := os.Open(todoFile)
if err != nil {
panic(err)
}
defer todoFile.Close()
fmt.Printf("\nLIST OF TODOS: \n")
scannedTodos := bufio.NewScanner(todoFile)
for scannedTodos.Scan() {
fmt.Println(i+1, ">", scannedTodos.Text())
i++
}
if err := scannedTodos.Err(); err != nil {
panic(err)
}
fmt.Printf("\n%d Todo(s) saved \n", i)
}
func list() {
listTodo()
fmt.Printf("\n back to main menu (enter)")
fmt.Scanln()
}
func removeTodo() {
var i int
i = getUserChoice("Enter the number of the todo you want to remove: ")
TODOFile, err := os.OpenFile(todoFile, os.O_RDWR, 0644)
if err != nil {
panic(err)
}
defer TODOFile.Close()
todos, err := io.ReadAll(TODOFile)
if err != nil {
panic(err)
}
lines := strings.Split(string(todos), "\n")
if i < 1 || i > len(lines) {
fmt.Println("Invalid todo number")
return
}
lines = append(lines[:i-1], lines[i:]...)
err = TODOFile.Truncate(0)
if err != nil {
panic(err)
}
_, err = TODOFile.Seek(0, 0)
if err != nil {
panic(err)
}
_, err = TODOFile.WriteString(strings.Join(lines, "\n"))
if err != nil {
panic(err)
}
fmt.Printf("Todo removed\n")
}
func remove() {
listTodo()
removeTodo()
fmt.Printf("\n back to main menu (enter)")
fmt.Scanln()
}
func getUserChoice(prompt string) int {
var choice int
for {
fmt.Print(prompt)
_, err := fmt.Scanln(&choice)
if err == nil {
break // Input is valid, exit the loop
}
fmt.Println("Invalid input. Please enter a valid number.")
}
return choice
}
func main() {
for {
fmt.Println("\nWhat do you want to do? ")
fmt.Println("1. Add a todo")
fmt.Println("2. List all todos")
fmt.Println("3. Remove a todo")
fmt.Println("4. Exit")
action := getUserChoice("Enter your choice: ")
switch action {
case 1:
addTodo()
case 2:
list()
case 3:
remove()
case 4:
fmt.Println("Goodbye!")
return // Exit the program gracefully
default:
fmt.Printf("Invalid action: %v\n", action)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment