Skip to content

Commit 60727e8

Browse files
authored
Feat: Added basic create/list/add/delete task functionality w/ file saving (#9)
* feat: add/list tasks functionalites * fix: casing perhaps will fix * feat: basic add/list/delete functionality * docs: udpated w/ usage and features
1 parent 8b221d8 commit 60727e8

File tree

6 files changed

+381
-44
lines changed

6 files changed

+381
-44
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,7 @@ Icon
4848
.Spotlight-V100
4949
.Trashes
5050
ehthumbs.db
51-
Thumbs.db
51+
Thumbs.db
52+
53+
# Temporary files
54+
*.json

README.md

+86-42
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,86 @@
1-
TaskWarden
2-
TaskWarden is a powerful, feature-rich CLI-based TODO app designed to manage your tasks with ease and efficiency. Built with Go/Rust, TaskWarden offers advanced task management, integration capabilities, and a customizable user experience, all while being lightweight and secure.
3-
4-
Features
5-
1. Advanced Task Management
6-
Subtasks and Projects: Organize your tasks with subtasks and project groups.
7-
Priority Levels and Due Dates: Set priorities and deadlines for tasks, with colored labels and filtered views.
8-
Recurring Tasks: Create tasks that recur on a daily, weekly, or monthly basis.
9-
Tags/Categories: Tag tasks with custom labels or categories for better organization.
10-
2. Integration with Other Tools
11-
Calendar Syncing: Sync tasks with Google Calendar or Outlook.
12-
API Integration: Interact with tasks programmatically via a REST or GraphQL API.
13-
Notifications and Reminders: Receive notifications via desktop, email, or SMS.
14-
3. Customization and User Experience
15-
Customizable Themes: Choose from light/dark modes and custom color schemes.
16-
Interactive UI Elements: Utilize interactive elements like progress bars and live-updating views with Bubbletea.
17-
Configurable Keybindings: Customize keybindings for a personalized user experience.
18-
4. Collaboration Features
19-
Shared Task Lists: Collaborate on shared task lists with multiple users.
20-
Task Comments and History: Comment on tasks and view a history log of changes.
21-
5. Offline Support and Syncing
22-
Local Storage with Syncing: Work offline with local storage, syncing to the cloud when connected.
23-
Conflict Resolution: Handle conflicts intelligently when syncing across devices or users.
24-
6. Performance and Security
25-
Encrypted Storage: Securely store tasks with encryption.
26-
Fast and Lightweight: Keep the app fast and responsive with minimal dependencies.
27-
Cross-Platform Compatibility: Run smoothly on macOS, Linux, and Windows.
28-
7. Go/Rust Features
29-
Rust: Performance and Safety: Leverage Rust’s memory safety and concurrency features.
30-
Go: Concurrency and Simplicity: Showcase Go’s simplicity and powerful concurrency with background tasks.
31-
8. Extensibility
32-
Plugin System: Extend functionality with a plugin system.
33-
Custom Scripting: Automate workflows with custom scripts interacting with the TODO list.
34-
9. Documentation and Community
35-
Comprehensive Documentation: Clear, detailed documentation with examples.
36-
Contributing Guide: Encourage contributions with a well-written guide.
37-
Community Support: Foster a community with forums or GitHub Discussions.
38-
10. Showcasing Your Skills
39-
Code Quality: Write clean, idiomatic code following best practices.
40-
Testing: Implement a robust suite of tests, including unit, integration, and property-based testing.
41-
CI/CD Pipeline: Automate builds, tests, and deployments with a CI/CD pipeline.
42-
Packaging: Provide clear installation instructions using Homebrew and other package managers.
1+
# TaskWarden
2+
3+
**TaskWarden** is a command-line task management tool written in Go. It allows you to create, list, mark as done, and delete tasks. TaskWarden uses a simple file-based storage system to persist tasks between sessions.
4+
5+
## Features
6+
7+
- **Add a Task**: Create new tasks with a simple command.
8+
- **List Tasks**: Display all tasks, showing their completion status.
9+
- **Mark a Task as Done**: Mark a task as completed by its ID.
10+
- **Delete a Task**: Remove a task by its ID.
11+
- **Persistent Storage**: Tasks are saved to a `tasks.json` file and persist between runs.
12+
13+
## Installation
14+
15+
To use TaskWarden, you need to have [Go](https://golang.org/) installed on your system. Once you have Go set up, you can clone the repository and run the application directly.
16+
17+
```bash
18+
git clone https://github.com/yourusername/TaskWarden.git
19+
cd TaskWarden
20+
```
21+
22+
## Usage
23+
24+
TaskWarden is a CLI tool with the following commands:
25+
26+
### 1. Add a Task
27+
28+
To add a new task, use the `add` command followed by the task description:
29+
30+
```bash
31+
go run cmd/taskwarden/main.go add "Buy groceries"
32+
```
33+
34+
This command will add the task "Buy groceries" to your task list.
35+
36+
### 2. List Tasks
37+
38+
To list all tasks, use the `list` command:
39+
40+
```bash
41+
go run cmd/taskwarden/main.go list
42+
```
43+
44+
This will display all tasks along with their IDs and completion status.
45+
46+
### 3. Mark a Task as Done
47+
48+
To mark a task as done, use the `done` command followed by the task ID:
49+
50+
```bash
51+
go run cmd/taskwarden/main.go done 1
52+
```
53+
54+
This will mark the task with ID 1 as completed.
55+
56+
### 4. Delete a Task
57+
58+
To delete a task, use the `delete` command followed by the task ID:
59+
60+
```bash
61+
go run cmd/taskwarden/main.go delete 1
62+
```
63+
64+
This will delete the task with ID 1 from your list.
65+
66+
## File-Based Storage
67+
68+
Tasks are stored in a file called `tasks.json` located in the root of the project directory. This file is automatically created and updated by TaskWarden as you add, complete, or delete tasks.
69+
70+
## Running Tests
71+
72+
To run the test suite, use the `go test` command. This will execute all tests in the `internal/task` package.
73+
74+
```bash
75+
go test -v ./internal/task
76+
```
77+
78+
The tests cover all the core functionalities of TaskWarden, including adding tasks, listing tasks, marking them as done, and deleting them.
79+
80+
## Contribution
81+
82+
Contributions are welcome! If you have any ideas for new features or improvements, feel free to open an issue or submit a pull request.
83+
84+
## License
85+
86+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

cmd/taskwarden/main.go

+67-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,74 @@ package main
22

33
import (
44
"fmt"
5+
"os"
6+
"strconv"
7+
8+
"github.com/danny-molnar/taskwarden/internal/task"
59
)
610

711
func main() {
8-
fmt.Println("Welcome to TaskWarden")
12+
taskManager, err := task.NewTaskManager("tasks.json")
13+
if err != nil {
14+
fmt.Println("Error initializing TaskManager:", err)
15+
return
16+
}
17+
18+
if len(os.Args) < 2 {
19+
fmt.Println("Usage: taskwarden <command> [arguments]")
20+
return
21+
}
22+
23+
command := os.Args[1]
24+
switch command {
25+
case "add":
26+
if len(os.Args) < 3 {
27+
fmt.Println("Usage: taskwarden add <task>")
28+
return
29+
}
30+
newTask := taskManager.AddTask(os.Args[2])
31+
fmt.Printf("Added task: %d: %s\n", newTask.ID, newTask.Title)
32+
case "list":
33+
tasks := taskManager.ListTasks()
34+
fmt.Println("Tasks:")
35+
for _, task := range tasks {
36+
status := "pending"
37+
if task.Done {
38+
status = "done"
39+
}
40+
fmt.Printf("%d: %s [%s]\n", task.ID, task.Title, status)
41+
}
42+
case "done":
43+
if len(os.Args) < 3 {
44+
fmt.Println("Usage: taskwarden done <task_id>")
45+
return
46+
}
47+
id, err := strconv.Atoi(os.Args[2])
48+
if err != nil {
49+
fmt.Println("Invalid task ID:", os.Args[2])
50+
return
51+
}
52+
if err := taskManager.MarkTaskDone(id); err != nil {
53+
fmt.Println("Error:", err)
54+
return
55+
}
56+
fmt.Printf("Marked task %d as done\n", id)
57+
case "delete":
58+
if len(os.Args) < 3 {
59+
fmt.Println("Usage: taskwarden delete <task_id>")
60+
return
61+
}
62+
id, err := strconv.Atoi(os.Args[2])
63+
if err != nil {
64+
fmt.Println("Invalid task ID:", os.Args[2])
65+
return
66+
}
67+
if err := taskManager.DeleteTask(id); err != nil {
68+
fmt.Println("Error:", err)
69+
return
70+
}
71+
fmt.Printf("Deleted task %d\n", id)
72+
default:
73+
fmt.Println("Unknown command")
74+
}
975
}

cmd/taskwarden/tasks.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]

internal/task/task.go

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package task
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"os"
7+
)
8+
9+
type Task struct {
10+
ID int `json:"id"`
11+
Title string `json:"title"`
12+
Done bool `json:"done"`
13+
}
14+
15+
type TaskManager struct {
16+
tasks []Task
17+
nextID int
18+
file string
19+
}
20+
21+
func NewTaskManager(file string) (*TaskManager, error) {
22+
tm := &TaskManager{
23+
tasks: []Task{},
24+
nextID: 0,
25+
file: file,
26+
}
27+
if err := tm.LoadTasks(); err != nil {
28+
return nil, err
29+
}
30+
return tm, nil
31+
}
32+
33+
func (tm *TaskManager) AddTask(title string) Task {
34+
tm.nextID++
35+
task := Task{ID: tm.nextID, Title: title, Done: false}
36+
tm.tasks = append(tm.tasks, task)
37+
tm.SaveTasks()
38+
return task
39+
}
40+
41+
func (tm *TaskManager) ListTasks() []Task {
42+
return tm.tasks
43+
}
44+
45+
func (tm *TaskManager) MarkTaskDone(id int) error {
46+
for i, task := range tm.tasks {
47+
if task.ID == id {
48+
tm.tasks[i].Done = true
49+
return tm.SaveTasks()
50+
}
51+
}
52+
return errors.New("task not found")
53+
}
54+
55+
func (tm *TaskManager) DeleteTask(id int) error {
56+
for i, task := range tm.tasks {
57+
if task.ID == id {
58+
tm.tasks = append(tm.tasks[:i], tm.tasks[i+1:]...)
59+
return tm.SaveTasks()
60+
}
61+
}
62+
return errors.New("task not found")
63+
}
64+
65+
func (tm *TaskManager) SaveTasks() error {
66+
data, err := json.MarshalIndent(tm.tasks, "", " ")
67+
if err != nil {
68+
return err
69+
}
70+
return os.WriteFile(tm.file, data, 0644)
71+
}
72+
73+
func (tm *TaskManager) LoadTasks() error {
74+
if _, err := os.Stat(tm.file); os.IsNotExist(err) {
75+
return nil
76+
}
77+
78+
data, err := os.ReadFile(tm.file)
79+
if err != nil {
80+
return err
81+
}
82+
83+
if len(data) == 0 {
84+
return nil
85+
}
86+
87+
err = json.Unmarshal(data, &tm.tasks)
88+
if err != nil {
89+
return err
90+
}
91+
92+
for _, task := range tm.tasks {
93+
if task.ID > tm.nextID {
94+
tm.nextID = task.ID
95+
}
96+
}
97+
return nil
98+
}

0 commit comments

Comments
 (0)