From 4792b321eb3bf7b58fdddcc101a15bd83dad5d0f Mon Sep 17 00:00:00 2001 From: Julian Hurst Date: Fri, 15 Nov 2024 01:14:07 +0100 Subject: Add write, show and filter commands --- cmd.ha | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hatask.ha | 50 +++++++++++++++++++++++------ 2 files changed, 146 insertions(+), 10 deletions(-) create mode 100644 cmd.ha diff --git a/cmd.ha b/cmd.ha new file mode 100644 index 0000000..ff37c79 --- /dev/null +++ b/cmd.ha @@ -0,0 +1,106 @@ +use fmt; +use strings; +use getopt; +use os; +use io; +use path; +use os::exec; +use strconv; + +type error = !(io::error | path::error | exec::error); + +type func = fn(tasks: []task, args: str...) (void | task | error); + +type command = struct { + names: []str, + func: *func, +}; + +const PADDING: size = 30z; + +const commands: [_]command = [ + command { + names = ["f", "filter"], + func = &filter, + }, + command { + names = ["s", "show"], + func = &show, + }, + command { + names = ["w", "write"], + func = &write, + }, +]; + +fn execcommand(name: str, tasks: []task, args: str...) (void | error) = { + for (const c .. commands) { + for (const n .. c.names) { + if (n == name) { + c.func(tasks, args...)?; + }; + }; + }; +}; + +fn write(tasks: []task, args: str...) (void | task | error) = { + const cmdname = "task write"; + const cmdhelp: []getopt::help = ["write a task", ""]; + if (len(args) == 0z) { + getopt::printhelp(os::stderr, cmdname, cmdhelp)?; + return; + }; + const cmd = getopt::parse(args, + cmdname: getopt::help, + cmdhelp[0], + cmdhelp[1], + ); + defer getopt::finish(&cmd); + + if (len(args) != 1z) { + getopt::printhelp(os::stderr, cmdname, cmdhelp)?; + return; + }; + + let buf = path::init()?; + const p = path::push(&buf, "tasks", args[0])?; + const c = exec::cmd("vim", p)?; + exec::exec(&c); +}; + +fn show(tasks: []task, args: str...) (void | task | error) = { + for (const t .. tasks) { + for (const s .. args) { + if (t.name == s) { + fmt::println(t.content)!; + }; + }; + }; +}; + +fn printtask(t: task) (void | error) = { + const pad = PADDING - len(t.name) + len(strconv::utos(t.priority)); + fmt::printfln("{}{%}", t.name, t.priority, &fmt::mods { + pad = ' ', + width = pad, ... + })!; +}; + +fn filter(tasks: []task, args: str...) (void | task | error) = { + const headpad = PADDING - len("name") + len("priority"); + fmt::printfln("name{%}", "priority", &fmt::mods { + pad = ' ', + width = headpad, + ... + })!; + for (const t .. tasks) { + if (len(args) == 0z) { + printtask(t)?; + }; + for (const s .. args) { + if (strings::contains(t.name, s)) { + printtask(t)?; + }; + }; + }; +}; diff --git a/hatask.ha b/hatask.ha index 291f17e..3984165 100644 --- a/hatask.ha +++ b/hatask.ha @@ -10,12 +10,14 @@ use strings; use format::ini; use strconv; use encoding::utf8; +use getopt; type task = struct { name: str, context: (str | void), tags: ([]str | void), priority: uint, + content: str, }; def METADATASEP: str = "----"; @@ -35,12 +37,10 @@ fn listtasks(root: str = "tasks", context: str = "*") ([]task | rtaskerror | const p = path::push(&buf, root, dirent.name)?; listtasks(p)?; } else { - fmt::println(dirent.name)!; let buf = path::init()?; const p = path::push(&buf, root, dirent.name)?; let t = readtask(p)?; - defer freetask(&t); - fmt::println(t.name)!; + append(tasks, t); }; }; }; @@ -52,15 +52,19 @@ fn readtask(taskpath: str) (task | rtaskerror) = { defer io::close(f)!; const sc = bufio::newscanner(f); defer bufio::finish(&sc); + const content = memio::dynamic(); + defer io::close(&content)!; const meta = memio::dynamic(); defer io::close(&meta)!; + + let currentst = &meta; for (let line => bufio::scan_line(&sc)?) { line = strings::trim(line); if (line == METADATASEP) { - break; + currentst = &content; + continue; }; - memio::concat(&meta, line, "\n")?; - //append(inilines, strings::dup(line)); + memio::concat(currentst, line, "\n")?; }; // seek to start of memio buffer io::seek(&meta, 0, io::whence::SET)?; @@ -74,18 +78,23 @@ fn readtask(taskpath: str) (task | rtaskerror) = { for (let entry: ini::entry => ini::next(&sc)?) { switch (entry.1) { case "name" => - t.name = strings::dup(entry.2); + t.name = strings::dup(strings::trim(entry.2)); case "priority" => t.priority = strconv::stou(entry.2)?; case => void; }; }; + if (t.name == "") { + t.name = strings::dup(path::basename(taskpath)); + }; + t.content = strings::dup(strings::trim(memio::string(&content)?)); return t; }; fn freetask(t: *task) void = { free(t.name); + free(t.content); if (t.context is str) { free(t.context as str); }; @@ -94,13 +103,34 @@ fn freetask(t: *task) void = { }; }; +fn finishall(tasks: []task) void = { + for (const task .. tasks) { + freetask(&task); + }; +}; + export fn main() void = { - match (listtasks()) { + const cmd = getopt::parse(os::args, + "tasklist", + "cmd", + ); + defer getopt::finish(&cmd); + + const com: []str = if (len(cmd.args) > 0) { + yield cmd.args; + } else { + yield ["filter"]; + }; + + const tasks = match (listtasks()) { case let e: fs::error => fmt::fatal(fs::strerror(e)); case let e: path::error => fmt::fatal(path::strerror(e)); - case => - void; + case let tasks: []task => + yield tasks; }; + defer finishall(tasks); + + execcommand(com[0], tasks, com[1..]...)!; }; -- cgit v1.2.3