use dirs; use path; use format::ini; use os; use fs; use strings; use io; use fmt; type config = struct { tasksdir: str, context: str, tags: []str, debug: bool, }; type cerror = !(fs::error | path::error | ini::error); fn readconfig() (config | cerror) = { const c = dirs::config("hatask"); const buf = path::init(c, "config.ini")?; const cpath = path::string(&buf); const f = os::open(cpath)?; defer io::close(f)!; const sc = ini::scan(f); const c = config { tasksdir = strings::dup("tasks"), context = strings::dup("*"), tags = [], debug = false, }; for (const en => ini::next(&sc)?) { switch (en.1) { case "tasksdir" => c.tasksdir = strings::dup(strings::trim(en.2)); case "context" => c.context = strings::dup(strings::trim(en.2)); case "tags" => c.tags = strings::dupall(strings::split(strings::trim(en.2), ",")); case "debug" => c.debug = en.2 == "true"; case => void; }; }; return c; }; fn cfinish(cfg: *config) void = { free(cfg.tasksdir); free(cfg.context); strings::freeall(cfg.tags); }; fn strcerror(e: cerror) str = { return match (e) { case let e: fs::error => yield fs::strerror(e); case let e: path::error => yield path::strerror(e); case let e: ini::error => yield ini::strerror(e); case => abort(); }; }; fn printconfig(cfg: config) void = { fmt::errorfln("tasksdir: {}", cfg.tasksdir)!; fmt::errorfln("context: {}", cfg.context)!; const stags = strings::join(",", cfg.tags...); defer free(stags); fmt::errorfln("tags: {}", stags)!; };