buffer.ha (2445B)
1 use bufio; 2 use encoding::utf8; 3 use fmt; 4 use io; 5 use strings; 6 7 type Buffer = struct{ 8 filename: str, 9 lines: []*Line, 10 trash: []*Line, 11 hist: []ChangeSeq, 12 cursor: size, 13 modified: bool, 14 redolastchange: bool, 15 }; 16 17 type Line = struct{ 18 text: str, 19 mark: rune, 20 globalmark: bool, 21 }; 22 23 fn buffer_finish(buf: *Buffer) void = { 24 free(buf.filename); 25 // TODO: free other fields? 26 }; 27 28 fn buf_insert(buf: *Buffer, n: size, ls: *Line...) void = { 29 debug("buf_insert(n={}), len(ls)={}", n, len(ls)); 30 // for (let i = 0z; i < len(ls); i += 1) { 31 // debug("buf_insert(): ls[{}].text='{}'", i, ls[i].text); 32 // }; 33 34 insert(buf.lines[n], ls...); 35 36 buf.modified = true; 37 38 hist_append(buf, (n, len(ls)): Addition); 39 40 // debug("buf_insert(): len('last changeseq')={}", len(buf.hist[len(buf.hist) - 1])); 41 }; 42 43 fn buf_deleteall(buf: *Buffer) void = { 44 if (len(buf.lines) > 1) { 45 append(buf.trash, buf.lines[1..]...); 46 delete(buf.lines[1..]); 47 }; 48 buf.modified = true; 49 }; 50 51 fn buf_delete(buf: *Buffer, a: size, b: size) void = { 52 debug("buf_delete(a={}, b={})", a, b); 53 54 append(buf.trash, buf.lines[a..b+1]...); 55 delete(buf.lines[a..b+1]); 56 57 buf.modified = true; 58 59 hist_append(buf, (a, (b + 1 - a)): Deletion); 60 61 // debug("buf_delete(): len('last changeseq')={}", len(buf.hist[len(buf.hist) - 1])); 62 }; 63 64 fn buf_read( 65 buf: *Buffer, 66 src: io::handle, 67 n: size, 68 ) ((size, size) | io::error | encoding::utf8::invalid) = { 69 let lines: []*Line = []; 70 let sz = 0z; 71 for (true) { 72 const bytes = match (bufio::read_line(src)?) { 73 case let bs: []u8 => 74 yield bs; 75 case io::EOF => 76 break; 77 }; 78 79 sz += len(bytes) + 1; // TODO: handle newlines better 80 const text = strings::fromutf8(bytes)?; 81 82 append(lines, alloc(Line{ text = text, ... })); 83 }; 84 const m = len(lines); 85 86 insert(buf.lines[n + 1], lines...); 87 88 hist_append(buf, (n + 1, m): Addition); 89 90 buf.modified = true; 91 92 return (sz, m); 93 }; 94 95 fn buf_write(buf: *Buffer, dest: io::handle, a: size, b: size) (size | io::error) = { 96 let sz = 0z; 97 for (let n = a; n <= b; n += 1) 98 sz += fmt::fprintln(dest, buf.lines[n].text)?; 99 100 return sz; 101 }; 102 103 fn buf_wipetrash(buf: *Buffer) void = { 104 for (let i = 0z; i < len(buf.trash); i += 1) { 105 free(buf.trash[i].text); 106 free(buf.trash[i]); 107 }; 108 delete(buf.trash[..]); 109 }; 110 111 fn buf_prunetrash(buf: *Buffer, keep: size) void = { 112 let upto = len(buf.trash) - keep; 113 for (let i = 0z; i < upto; i += 1) { 114 free(buf.trash[i].text); 115 free(buf.trash[i]); 116 }; 117 delete(buf.trash[ ..upto ]); 118 };