aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAakarsh Kashyap <[email protected]>2026-07-07 00:54:14 +0530
committerAakarsh Kashyap <[email protected]>2026-07-07 00:54:14 +0530
commit464b56c73354d9add568fa65dd179866a8d238f1 (patch)
treed07b771239bdd3a39a52a484ef2e3bbdf4511e1b
[feat]: toradora prototype complete
-rw-r--r--Makefile29
-rw-r--r--README.md46
-rw-r--r--shell.nix4
-rw-r--r--toradora.c290
4 files changed, 369 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0544e5a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,29 @@
+##
+# toradora
+#
+# @file
+# @version 0.1.0
+
+CC = gcc
+CFLAGS = -Wall -Wextra -std=c99
+LDLIBS = -l sqlite3
+TARGET = toradora
+SRC = toradora.c
+
+.PHONY: all clean install uninstall
+
+all: $(TARGET)
+
+$(TARGET): $(SRC)
+ $(CC) $(CFLAGS) $(SRC) -o $(TARGET) $(LDLIBS)
+
+clean:
+ rm -rf $(TARGET)
+
+install: $(TARGET)
+ install -Dm755 $(TARGET) $(HOME)/.local/bin/$(TARGET)
+
+uninstall:
+ rm $(HOME)/.toradora.db $(HOME)/.local/bin/$(TARGET)
+
+# end
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..55776d3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,46 @@
+# toradora - A terminal based todo list
+
+## Getting started
+
+**Requirements**
+
+1. sqlite library
+2. make
+3. gcc/clang
+
+**Compiling**
+
+```bash
+make
+```
+
+**Installing**
+
+```bash
+make install
+```
+
+**Uninstalling**
+
+``` bash
+make uninstall
+```
+
+## /** FEATURES **/
+ 1. Able to add tasks. (toradora -a "The task I want to add")
+ 2. Able to complete those tasks. (toradora -c 1 )
+ 3. Able to edit those tasks. (toradora -e 1 "The previous task edited")
+ 4. Able to manifest those tasks. (toradora)
+ > ===============================
+ > >>> Today's Task <<<
+ > 1. "task one"
+ > 2. "task two"
+
+ > >>> Backlogs <<<
+ > 3. "task three"
+ > ===============================
+ 5. Able to manifest all the tasks in database. (toradora -z)
+
+## Notes
+
+The DB is currently stored at `~/.toradora.db`
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000..c797e6a
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,4 @@
+{ pkgs ? import <nixpkgs> {} }:
+pkgs.mkShell {
+ buildInputs = [ pkgs.sqlite.dev ];
+}
diff --git a/toradora.c b/toradora.c
new file mode 100644
index 0000000..4032b35
--- /dev/null
+++ b/toradora.c
@@ -0,0 +1,290 @@
+/* toradora.c - A terminal based todo list */
+/* Using a sqlite database at ~/.toradora.db we will keep track of all the
+ * entries */
+
+/** FEATURES **/
+/*
+ * 1. Able to add tasks. (toradora -a "The task I want to add")
+ * 2. Able to complete those tasks. (toradora -c 1 )
+ * 3. Able to edit those tasks. (toradora -e 1 "The previous task edited")
+ * 4. Able to manifest those tasks. (toradora)
+ * ===============================
+ * >>> Today's Task <<<
+ * 1. "task one"
+ * 2. "task two"
+ *
+ * >>> Backlogs <<<
+ * 3. "task three"
+ * ===============================
+ * 5. Able to manifest all the tasks in database. (toradora -z)
+ *
+ */
+
+#include <sqlite3.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define VERSION "0.1.0"
+
+#define MAX_PATH_LENGTH 4096
+
+static void
+manifest_usage()
+{
+ printf("toradora - a terminal based todo list\n\n");
+ printf("Usage:\n");
+ printf(" toradora Show today's tasks and backlog\n");
+ printf(" toradora -z Show all tasks ever recorded\n");
+ printf(" toradora -a \"task\" Add a new task\n");
+ printf(" toradora -c <id> Mark task <id> as complete\n");
+ printf(" toradora -e <id> \"new task\" Edit task <id>\n\n");
+ printf("Examples:\n");
+ printf(" toradora -a \"write usage function\"\n");
+ printf(" toradora -c 3\n");
+ printf(" toradora -e 3 \"write usage function (done)\"\n");
+}
+
+static int
+callback_manifest(void *data, int argc, char **argv, char **az_col_name)
+{
+ /* fprintf(stderr, "%s: ", (const char *)data); */
+ printf("%s. %s\n", argv[0], argv[1]);
+ printf("\n");
+ return 0;
+}
+
+
+static void
+manifest_active_tasks(sqlite3 *DB)
+{
+ int query_status;
+ char *message_error_1;
+ char *message_error_2;
+ printf("----------------------------------------------\n");
+ printf(">>> Today's Task <<<\n");
+ char *manifest_query_1 = "SELECT ID, TASK FROM tasks WHERE STATUS = 0 "
+ "AND created_at = CURRENT_DATE;";
+ query_status = sqlite3_exec(DB, manifest_query_1, callback_manifest, "Manifest callback", &message_error_1);
+ if (query_status != SQLITE_OK) {
+ printf("[Error]: Unexpected error during execution of query\n");
+ printf("%s\n", message_error_1);
+ printf("[Help]: Check database sanity\n");
+ return;
+ }
+
+ printf(">>> Backlog <<<\n");
+ char *manifest_query_2 = "SELECT ID, TASK FROM tasks WHERE STATUS = 0 "
+ "AND created_at != CURRENT_DATE;";
+ query_status = sqlite3_exec(DB, manifest_query_2, callback_manifest, "Manifest callback", &message_error_2);
+ if (query_status != SQLITE_OK) {
+ printf("[Error]: Unexpected error during execution of query\n");
+ printf("%s\n", message_error_2);
+ printf("[Help]: Check database sanity\n");
+ return;
+ }
+ printf("----------------------------------------------\n");
+}
+
+static void
+manifest_all_tasks(sqlite3 *DB)
+{
+ int query_status;
+ char *message_error;
+ printf("----------------------------------------------\n");
+ printf(">>> All tasks ever recorded\n");
+ char *manifest_query = "SELECT ID, TASK FROM tasks;";
+ query_status = sqlite3_exec(DB, manifest_query, callback_manifest, "Manifest callback", &message_error);
+ if (query_status != SQLITE_OK) {
+ printf("[Error]: Unexpected error during execution of query\n");
+ printf("%s\n", message_error);
+ printf("[Help]: Check database sanity\n");
+ return;
+ }
+ printf("----------------------------------------------\n");
+}
+
+static void
+toradora_add_task(sqlite3 *DB, const char *todo)
+{
+ sqlite3_stmt *stmt = NULL;
+ int query_status;
+
+ const char *add_query = "INSERT INTO TASKS (task) VALUES (?);";
+
+ query_status = sqlite3_prepare_v2(DB, add_query, -1, &stmt, NULL);
+ if (query_status != SQLITE_OK) {
+ printf("[Error]: Unexpected error during execution of query\n");
+ printf("[Help]: Check database sanity\n");
+ goto error;
+ }
+
+ sqlite3_bind_text(stmt, 1, todo, -1, SQLITE_STATIC);
+ query_status = sqlite3_step(stmt);
+ if (query_status != SQLITE_DONE) {
+ printf("[Error]: Unexpected error during execution of query\n");
+ printf("[Help]: Check database sanity\n");
+ goto error;
+ }
+ error:
+ sqlite3_finalize(stmt);
+
+}
+
+static void
+toradora_complete_task(sqlite3 *DB, const char *id)
+{
+ sqlite3_stmt *stmt = NULL;
+ int query_status;
+ int curr;
+ char *end_ptr;
+ int row_affected;
+ const char *complete_query = "UPDATE TASKS SET status = 1 WHERE id = ?;";
+
+ query_status = sqlite3_prepare_v2(DB, complete_query, -1, &stmt, NULL);
+ if (query_status != SQLITE_OK) {
+ printf("[Error]: Unexpected error during execution of query\n");
+ printf("[Help]: Check database sanity\n");
+ goto error;
+ }
+ curr = (int)strtol(id, &end_ptr, 10);
+ if (*end_ptr != '\0') {
+ printf("[Error]: Invalid argument");
+ manifest_usage();
+ goto error;
+ }
+ sqlite3_bind_int(stmt, 1, curr);
+ query_status = sqlite3_step(stmt);
+ if (query_status != SQLITE_DONE) {
+ printf("[Error]: Unexpected error during execution of query\n");
+ printf("[Help]: Check database sanity\n");
+ goto error;
+ }
+ row_affected = sqlite3_changes(DB);
+ if (row_affected == 0) {
+ printf("[Info]: No rows were affected\n");
+ printf("[Help]: Did you entered valid task id?\n");
+ }
+ error:
+ sqlite3_finalize(stmt);
+}
+
+
+static void
+toradora_edit_task(sqlite3 *DB, const char *id, const char *new_task)
+{
+ sqlite3_stmt *stmt = NULL;
+ int query_status;
+ int curr;
+ char *end_ptr;
+ int row_affected;
+ const char *complete_query = "UPDATE TASKS SET task = ? WHERE id = ?;";
+
+ query_status = sqlite3_prepare_v2(DB, complete_query, -1, &stmt, NULL);
+ if (query_status != SQLITE_OK) {
+ printf("[Error]: Unexpected error during execution of query\n");
+ printf("[Help]: Check database sanity\n");
+ goto error;
+ }
+ curr = (int)strtol(id, &end_ptr, 10);
+ if (*end_ptr != '\0') {
+ printf("[Error]: Invalid argument");
+ manifest_usage();
+ goto error;
+ }
+ sqlite3_bind_text(stmt, 1, new_task, -1, SQLITE_STATIC);
+ sqlite3_bind_int(stmt, 2, curr);
+ query_status = sqlite3_step(stmt);
+ if (query_status != SQLITE_DONE) {
+ printf("[Error]: Unexpected error during execution of query\n");
+ printf("[Help]: Check database sanity\n");
+ goto error;
+ }
+ row_affected = sqlite3_changes(DB);
+ if (row_affected == 0) {
+ printf("[Info]: No rows were affected\n");
+ printf("[Help]: Did you entered valid task id?\n");
+ }
+ error:
+ sqlite3_finalize(stmt);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *home_path = getenv("HOME");
+ char *file_path = "/.toradora.db";
+ char database_path[MAX_PATH_LENGTH];
+ sqlite3 *DB;
+ int db_exit = 0;
+ int tab_exit = 0;
+ char *message_error;
+
+ if (home_path == NULL) {
+ printf("[Error]: HOME environment variable not set.\n");
+ return -1;
+ }
+ snprintf(database_path, sizeof(database_path), "%s%s", home_path, file_path);
+
+
+ db_exit = sqlite3_open(database_path, &DB);
+ if (db_exit) {
+ printf("[Error]: Database corrupted\n");
+ printf("[Help]: Delete database file and rerun the application");
+ return -1;
+ }
+
+ char *create_table = "CREATE TABLE IF NOT EXISTS tasks ("
+ "id INTEGER PRIMARY KEY NOT NULL,"
+ "task TEXT NOT NULL,"
+ "status INTEGER NOT NULL DEFAULT 0,"
+ "created_at TEXT NOT NULL DEFAULT CURRENT_DATE"
+ ");";
+
+ tab_exit = sqlite3_exec(DB, create_table, NULL, 0, &message_error);
+
+ if (tab_exit != SQLITE_OK) {
+ printf("[Error]: Table creation failed\n");
+ printf("%s\n", message_error);
+ return -1;
+ }
+
+ switch (argc) {
+ case 1:
+ manifest_active_tasks(DB);
+ break;
+ case 2:
+ if (0 == strcmp(argv[1], "-z")) {
+ manifest_all_tasks(DB);
+ } else {
+ manifest_usage();
+ return 1;
+ }
+ break;
+ case 3:
+ if (0 == strcmp(argv[1], "-a")) {
+ toradora_add_task(DB, argv[2]);
+ } else if (0 == strcmp(argv[1], "-c")) {
+ toradora_complete_task(DB, argv[2]);
+ } else if (0 == strcmp(argv[1], "-h")) {
+ manifest_usage();
+ } else {
+ manifest_usage();
+ return 1;
+ }
+ break;
+ case 4:
+ if (0 == strcmp(argv[1], "-e")) {
+ toradora_edit_task(DB, argv[2], argv[3]);
+ } else {
+ manifest_usage();
+ return 1;
+ }
+ break;
+ default:
+ manifest_usage();
+ return 1;
+ }
+ sqlite3_close(DB);
+ return 0;
+}