ed.ha (1538B)
1 use bufio; 2 use fmt; 3 use getopt; 4 use io; 5 use os; 6 7 let prompt: str = ""; 8 9 let surpress: bool = false; 10 11 type filename = (str | void); 12 13 export fn main() void = { 14 const help: [_]getopt::help = [ 15 "standard line editor", 16 ('p', "prompt", "set the command prompt"), 17 ('s', "suppress byte counts and '!' prompt"), 18 "[file]", 19 ]; 20 const cmd = getopt::parse(os::args, help...); 21 defer getopt::finish(&cmd); 22 23 for (let i = 0z; i < len(cmd.opts); i += 1) { 24 const opt = cmd.opts[i]; 25 switch (opt.0) { 26 case 'p' => 27 prompt = opt.1; 28 case 's' => 29 surpress = true; 30 }; 31 }; 32 33 if (len(cmd.args) > 1) { 34 exit_usage(help); 35 }; 36 37 let fname: filename = switch (len(cmd.args) == 1) { 38 case false => 39 void; 40 case true => 41 switch (cmd.args[0]) { 42 case "-" => 43 fmt::fatal("Invalid filename '-'"); 44 case "" => 45 fmt::fatal("Invalid filename ''"); 46 case => 47 cmd.args[0]; 48 }; 49 }; 50 51 const buf = new_buffer(); 52 buf.fname = fname; 53 54 if (buf.fname is str) { 55 op_edit(buf); 56 }; 57 58 for (true) :repl { 59 fmt::error(prompt)!; 60 61 const rawline = match (bufio::scanline(os::stdin)) { 62 case rawline: []u8 => 63 yield rawline; 64 case io::EOF => 65 break; 66 case => 67 abort(); 68 }; 69 defer free(rawline); 70 71 const input = fmt::bsprint(rawline); 72 const cmd = parse_input(input); 73 const ops = construct_ops(cmd); 74 75 for (let i = 0z; i < len(ops); i += 1) :ops { 76 const op = ops[i]; 77 op.func(buf, op.args...); 78 }; 79 }; 80 }; 81 82 @noreturn fn exit_usage(help: []getopt::help) void = { 83 getopt::printusage(os::stderr, os::args[0], help); 84 os::exit(1); 85 }; 86