ed

[hare] The standard editor
Log | Files | Refs | README | LICENSE

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 };