main.ha (2281B)
1 use bufio; 2 use fmt; 3 use getopt; 4 use io; 5 use os; 6 use strings; 7 use types; 8 9 type Session = struct{ 10 input: *bufio::scanner, 11 buf: *Buffer, 12 13 prompt: str, 14 promptmode: bool, 15 suppressmode: bool, 16 helpmode: bool, 17 undomode: UndoMode, 18 19 warned: bool, 20 lasterror: (void | Error), 21 lastregex: (void | str), 22 lastshcmd: (void | str), 23 }; 24 25 def proghelp: [_]getopt::help = [ 26 "standard line editor", 27 ('p', "prompt", "set the command prompt"), 28 ('s', "suppress byte counts and '!' prompt"), 29 "[file]", 30 ]; 31 32 export fn main() void = { 33 const progcmd = getopt::parse(os::args, proghelp...); 34 defer getopt::finish(&progcmd); 35 36 const input = bufio::newscanner(os::stdin, types::SIZE_MAX); 37 defer bufio::finish(&input); 38 39 const buffer = Buffer{ 40 lines = alloc([ alloc(Line{ ... }) ]...), 41 trash = alloc([]: []*Line...), 42 hist = alloc([]: History...), 43 ... 44 }; 45 defer buffer_finish(&buffer); 46 47 let s = Session{ 48 input = &input, 49 buf = &buffer, 50 prompt = "*", 51 lasterror = void, 52 lastregex = void, 53 lastshcmd = void, 54 ... 55 }; 56 57 for (let i = 0z; i < len(progcmd.opts); i += 1) { 58 const opt = progcmd.opts[i]; 59 switch (opt.0) { 60 case 'p' => 61 s.prompt = opt.1; 62 s.promptmode = true; 63 case 's' => 64 s.suppressmode = true; 65 case => 66 abort(); 67 }; 68 }; 69 70 if (len(progcmd.args) > 1) 71 exit_usage(); 72 73 if (len(progcmd.args) == 1) 74 switch (progcmd.args[0]) { 75 case "-" => 76 return fmt::errorln("Invalid filename '-'"): void; 77 case "" => 78 return fmt::errorln("Invalid filename ''"): void; 79 case => 80 s.buf.filename = strings::dup(progcmd.args[0]); 81 }; 82 83 if (s.buf.filename != "") 84 execute(&s, &Command{ 85 name = 'e', 86 arg1 = strings::dup(s.buf.filename), 87 ... 88 }): void; 89 90 for (true) :repl { 91 if (s.promptmode) 92 fmt::error(s.prompt)!; 93 94 const cmd = match (parse(&input)) { 95 case let c: Command => 96 yield c; 97 case io::EOF => 98 yield Command{ name = 'q', ... }; 99 case let e: ParseError => 100 errormsg(&s, strerror(e)); 101 continue; 102 }; 103 defer command_finish(&cmd); 104 105 if (cmd.name == '&') { 106 errormsg(&s, '&': UnknownCommand); 107 continue; 108 }; 109 110 match (execute(&s, &cmd)) { 111 case Quit => 112 debug("main() Quit"); 113 break; 114 case => 115 void; 116 }; 117 }; 118 }; 119 120 fn exit_usage() never = { 121 getopt::printusage(os::stderr, os::args[0], proghelp)!; 122 os::exit(1); 123 };