print.ha (1780B)
1 use ascii; 2 use fmt; 3 use io; 4 use strings; 5 6 fn printmode(s: *Session, cmd: *Command) (size | io::error) = { 7 let n = s.buf.cursor; 8 switch (cmd.printmode) { 9 case PrintMode::NONE => 10 return 0z; 11 case PrintMode::PLAIN => 12 return printplain(s.buf, n, n)?; 13 case PrintMode::NUMBER => 14 return printnumber(s.buf, n, n)?; 15 case PrintMode::LIST => 16 return printlist(s.buf, n, n)?; 17 }; 18 }; 19 20 fn printplain(buf: *Buffer, a: size, b: size) (size | io::error) = { 21 let sz = 0z; 22 for (let n = a; n <= b; n += 1) { 23 sz += fmt::println(buf.lines[n].text)?; 24 }; 25 return sz; 26 }; 27 28 fn printnumber(buf: *Buffer, a: size, b: size) (size | io::error) = { 29 let sz = 0z; 30 for (let n = a; n <= b; n += 1) { 31 sz += fmt::printfln("{}\t{}", n, buf.lines[n].text)?; 32 }; 33 return sz; 34 }; 35 36 fn printlist(buf: *Buffer, a: size, b: size) (size | io::error) = { 37 let sz = 0z; 38 for (let n = a; n <= b; n += 1) { 39 sz += printlistline(buf.lines[n].text)?; 40 }; 41 return sz; 42 }; 43 44 fn printlistline(text: str) (size | io::error) = { 45 // TODO: handle wrapping (see ed(1) > list command) 46 const t = strings::iter(text); 47 let sz = 0z; 48 49 for (true) { 50 const r = match (strings::next(&t)) { 51 case void => 52 break; 53 case let r: rune => 54 yield r; 55 }; 56 57 sz += switch (r) { 58 case '\\' => 59 yield fmt::print("\\\\")?; 60 case '\a' => 61 yield fmt::print("\\a")?; 62 case '\b' => 63 yield fmt::print("\\b")?; 64 case '\f' => 65 yield fmt::print("\\f")?; 66 case '\r' => 67 yield fmt::print("\\r")?; 68 case '\t' => 69 yield fmt::print("\\t")?; 70 case '\v' => 71 yield fmt::print("\\v")?; 72 case '$' => 73 yield fmt::print("\\$")?; 74 case => 75 if (!ascii::isprint(r)) 76 // XXX: assuming r is ascii 77 yield fmt::printf("\\{:o.3}", r: u32)? 78 else 79 yield fmt::print(r)?; 80 }; 81 }; 82 83 sz += fmt::println('$')?; 84 return sz; 85 };