use path; use dirs; use midi; use made; use io; use fs; use os; use fmt; use strconv; use strings; use shlex; export fn main() void = { static let buf = path::buffer { ... }; path::set(&buf, dirs::data("climidi"), "history")!; let hist = made::histfile(path::string(&buf))!; let ctx = made::context { complete = &made::complete_fs, hint = &made::hint_history, hist = &hist, prompt = &made::prompt_string("> "), split = made::split_sh, cfg = match (made::config_default("climidi")) { case let cfg: made::config => yield cfg; case let e: made::error => fmt::fatal(made::strerror(e)); }, ... }; defer made::config_free(ctx.cfg); defer made::ctx_finish(&ctx)!; const f = os::create("f.mid", fs::mode::USER_RW | fs::mode::GROUP_RW)!; defer io::close(f)!; const th = midi::hchunk { chk = midi::HEADERCHUNK, format = 0, ntrks = 1, division = 4, }; let tc = midi::newtrack(); defer midi::finishtrack(tc); for (const line => made::line(&ctx)!) { match (line) { case void => fmt::println("^C")!; case let s: str => const spl = shlex::split(s)!; defer strings::freeall(spl); if (len(spl) != 3) { abort(); }; const dt = strconv::stou32(spl[0])!; const runes = strings::torunes(spl[1]); defer free(runes); if (len(runes) == 0) { abort(); }; const note = runetonote(runes[0]); const pitch = strconv::stou32(spl[2])!; const tp = midi::playnote(dt, note, 64, pitch); append(tc.ev, tp.0); append(tc.ev, tp.1); }; }; midi::writeheader(os::stdout, th); midi::writechunk(os::stdout, tc); }; fn runetonote(r: rune) midi::note = { switch (r) { case 'a' => return midi::note::A; case 'A' => return midi::note::AS; case 'b' => return midi::note::B; case 'B' => return midi::note::BS; case 'c' => return midi::note::C; case 'C' => return midi::note::CS; case 'd' => return midi::note::D; case 'D' => return midi::note::DS; case 'e' => return midi::note::E; case 'E' => return midi::note::ES; case 'f' => return midi::note::F; case 'F' => return midi::note::FS; case 'g' => return midi::note::G; case 'G' => return midi::note::GS; case => abort(); }; };