12 var dir_arg : byte[:] = [][:]
13 var a_file_arg : byte[:] = [][:]
14 var b_file_arg : byte[:] = [][:]
15 var a_string_arg : byte[:] = [][:]
16 var b_string_arg : byte[:] = [][:]
17 var name_arg : byte[:] = [][:]
18 var basedir : byte[:] = [][:]
19 var dir_checked = false
20 var cmd : std.optparsed = std.optparse(args, &[
24 [ .opt = 'd', .arg = "dir", .desc = "base directory", .optional = true ],
25 [ .opt = 'n', .arg = "name", .desc = "card name (for uniqueness)", .optional = false ],
26 [ .opt = 'a', .arg = "a-file", .desc = "file for A-side" ],
27 [ .opt = 'A', .arg = "a-string", .desc = "string for A-side" ],
28 [ .opt = 'b', .arg = "b-file", .desc = "file for B-side" ],
29 [ .opt = 'B', .arg = "b-string", .desc = "string for B-side" ],
35 | ('d', dir): dir_arg = dir
36 | ('n', name): name_arg = name
37 | ('a', arg): a_file_arg = arg
38 | ('b', arg): b_file_arg = arg
39 | ('A', arg): a_string_arg = arg
40 | ('B', arg): b_string_arg = arg
41 | _: std.fatal("impossible {}\n", opt)
45 match get_basedir(dir_arg)
46 | `std.Err e: std.fatal("{}\n", e)
47 | `std.Ok b: basedir = b
49 auto (basedir : t.doomed_str)
52 std.fatal("-n is required\n")
53 elif (a_file_arg.len == 0) && (a_string_arg.len == 0)
54 std.fatal("One of -a or -A is required\n")
55 elif (a_file_arg.len != 0) && (a_string_arg.len != 0)
56 std.fatal("Only one of -a or -A is permitted\n")
57 elif (b_file_arg.len == 0) && (b_string_arg.len == 0)
58 std.fatal("One of -b or -B is required\n")
59 elif (b_file_arg.len != 0) && (b_string_arg.len != 0)
60 std.fatal("Only one of -b or -B is permitted\n")
63 match choose_arg(a_string_arg, a_file_arg)
64 | `std.Ok str: a_string_arg = str
65 | `std.Err e: std.fatal("{}\n", e)
68 match choose_arg(b_string_arg, b_file_arg)
69 | `std.Ok str: b_string_arg = str
70 | `std.Err e: std.fatal("{}\n", e)
73 var card_dir : byte[:] = std.pathjoin([basedir, "cards", name_arg][:])
75 match std.diropen(card_dir)
78 std.fatal("card \"{}\" already exists\n", name_arg)
82 match std.mkpath(card_dir)
84 | e: std.fatal("mkdir(\"{}\"): {}\n", card_dir, e)
87 var sched_dir_path = std.pathjoin([basedir, "schedule"][:])
88 match std.mkpath(sched_dir_path)
90 | e: std.fatal("mkdir(\"{}\"): {}\n", sched_dir_path, e)
93 var a_path : byte[:] = std.pathjoin([card_dir, "side_A"][:])
94 var b_path : byte[:] = std.pathjoin([card_dir, "side_B"][:])
95 var level_path : byte[:] = std.pathjoin([card_dir, "level"][:])
96 var next_review : date.instant = date.subperiod(date.utcnow(), `date.Day 7)
97 var sched_path = std.pathjoin([sched_dir_path, std.fmt("{f=%Y-%m-%d}", next_review)][:])
99 match std.open(sched_path, std.Owrite | std.Ocreat | std.Oappend)
100 | `std.Err e: std.fput(std.Err, "std.open(\"{}\"): {}\n", sched_path, e)
102 std.fput(fd, "{}\n", name_arg)
106 match std.open(level_path, std.Owrite | std.Ocreat | std.Oappend)
107 | `std.Err e: std.fput(std.Err, "std.open(\"{}\"): {}\n", level_path, e)
113 match std.open(a_path, std.Owrite | std.Ocreat | std.Oappend)
114 | `std.Err e: std.fput(std.Err, "std.open(\"{}\"): {}\n", a_path, e)
116 std.fput(fd, "{}", a_string_arg)
120 match std.open(b_path, std.Owrite | std.Ocreat | std.Oappend)
121 | `std.Err e: std.fput(std.Err, "std.open(\"{}\"): {}\n", b_path, e)
123 std.fput(fd, "{}", b_string_arg)
128 const choose_arg = {str : byte[:], path : byte[:]
130 -> `std.Ok std.fmt("{}\n", str)
133 match std.slurp(path)
139 -> `std.Err std.fmt("file \"{}\" seems empty", path)
141 -> `std.Err std.fmt("std.slurp(\"{}\"): {}", path, e)