operation.ha (2518B)
1 use fmt; 2 use fs; 3 use io; 4 use os; 5 6 // 'e' command 7 fn op_edit(buf: *buffer, args: arg...) void = { 8 const scratch = new_buffer(); 9 const n = match (buf.fname) { 10 case void => 11 abort("TODO"); 12 case fname: str => 13 yield match (os::open(fname)) { 14 case err: fs::error => 15 fmt::fatal("Error {}", fs::strerror(err)); 16 case f: io::file => 17 yield buf_read(scratch, f); 18 }; 19 }; 20 21 if (!(buf.head.next.value is tailnode)) { 22 buf_delete(buf, buf.head.next, buf.tail.prev); 23 }; 24 buf_insert(buf, scratch); 25 26 if (!surpress) { 27 fmt::println(n)?; 28 }; 29 }; 30 31 // 'w' command 32 fn op_write(buf: *buffer, args: arg...) void = { 33 const mode = fs::mode::USER_RW | fs::mode::GROUP_R | fs::mode::OTHER_R; 34 const flags = [ 35 fs::flags::WRONLY, 36 fs::flags::TRUNC, 37 fs::flags::NOCTTY, 38 fs::flags::CLOEXEC, 39 ]; 40 const file = match (buf.fname) { 41 case void => 42 abort("TODO"); 43 case fname: str => 44 yield match (os::open(fname, flags...)) { 45 case fs::error => 46 yield match (os::create(fname, mode)) { 47 case err: fs::error => 48 fmt::fatal("Error {}", fs::strerror(err)); 49 case file: io::file => 50 yield file; 51 }; 52 case file: io::file => 53 yield file; 54 }; 55 }; 56 57 const n = buf_write(buf, file); 58 if (!surpress) { 59 fmt::println(n)?; 60 }; 61 62 }; 63 64 // 'r' command 65 fn op_read(buf: *buffer, args: arg...) void = { 66 const scratch = new_buffer(); 67 const n = match (buf.fname) { 68 case void => 69 abort("TODO"); 70 case fname: str => 71 yield match (os::open(fname)) { 72 case err: fs::error => 73 fmt::fatal("Error {}", fs::strerror(err)); 74 case f: io::file => 75 yield buf_read(scratch, f); 76 }; 77 }; 78 79 buf_insert(buf, scratch); 80 81 if (!surpress) { 82 fmt::println(n)?; 83 }; 84 }; 85 86 // 'd' command 87 fn op_delete(buf: *buffer, args: arg...) void = { // TODO 88 const h = buf.cur.node; 89 const t = buf.cur.node; 90 91 buf_delete(buf, h, t); 92 }; 93 94 // 'n' command 95 fn op_numbered(buf: *buffer, args: arg...) void = { 96 const a = buf.range_a; 97 const b = buf.range_b; 98 let ln = a; 99 let n = find_linenum(buf, buf.range_a); 100 101 for (true) { 102 match (ln.value) { 103 case headnode => void; 104 case txt: str => 105 fmt::printfln("{}\t{}", n, txt)?; 106 case tailnode => 107 break; 108 }; 109 110 if (ln == b) { 111 break; 112 }; 113 114 ln = ln.next; 115 n += 1; 116 }; 117 }; 118 119 // 'p' command 120 fn op_print(buf: *buffer, args: arg...) void = { 121 const a = buf.range_a; 122 const b = buf.range_b; 123 let ln = a; 124 125 for (true) { 126 match (ln.value) { 127 case headnode => void; 128 case txt: str => 129 fmt::printfln("{}", txt)?; 130 case tailnode => 131 break; 132 }; 133 134 if (ln == b) { 135 break; 136 }; 137 138 ln = ln.next; 139 }; 140 }; 141