File: editctx.ha

package info (click to toggle)
hare-update 0.25.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 516 kB
  • sloc: makefile: 31; sh: 14
file content (88 lines) | stat: -rw-r--r-- 1,968 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use bufio;
use common::{location};
use fmt;
use io;
use memio;
use sort;
use sort::cmp;
use strings;
use types;

type edit_context = struct {
	buffer: []u8,
	loc: location,
	first_line: size,
	last_line: size,
};

fn ndigit(i: size) size = {
	let digits = 1z;
	for (i > 0; digits += 1) {
		i /= 10;
	};
	return digits;
};

fn edit_getcontext(
	ctx: *context,
	loc: location,
	nlines: int = 3,
) edit_context = {
	let first_line = sort::lbisect(ctx.newlines,
		size(io::off), &loc.off, &cmp::i64s);
	let last_line = first_line;
	for (let i = 0; i < nlines && first_line > 0; i += 1) {
		first_line -= 1;
	};
	for (let i = 0; i < nlines && last_line + 1 < len(ctx.newlines); i += 1) {
		last_line += 1;
	};
	if (last_line >= len(ctx.newlines)) {
		last_line = len(ctx.newlines) - 1;
	};

	const min = ctx.newlines[first_line + 1];
	const max = ctx.newlines[last_line];

	const offs = io::tell(ctx.buffer)!;
	defer io::seek(ctx.buffer, offs, io::whence::SET)!;
	io::seek(ctx.buffer, 0, io::whence::END)!;
	const buffer = memio::buffer(ctx.buffer);

	return edit_context {
		first_line = first_line + 1,
		last_line = last_line + 1,
		loc = loc,
		buffer = alloc(buffer[min..max]...)!,
	};
};

fn edit_context_finish(ectx: *edit_context) void = {
	free(ectx.buffer);
};

fn edit_context_show(ctx: *context, ectx: *edit_context) void = {
	const buf = memio::fixed(ectx.buffer);
	const scan = bufio::newscanner(&buf);
	defer bufio::finish(&scan);

	const lineno_mods = fmt::mods {
		pad = ' ',
		width = ndigit(ectx.last_line),
		...
	};
	if (lineno_mods.width == 1) {
		lineno_mods.width += 1; // =>
	};

	fmt::fprintfln(ctx.engine.tty, "{}:{}", ctx.path, ectx.first_line)!;
	let lineno = ectx.first_line;
	for (let line => bufio::scan_line(&scan)!) {
		if (lineno == ectx.loc.line) {
			fmt::fprintfln(ctx.engine.tty, "{%} | {}", "=>", &lineno_mods, line)!;
		} else {
			fmt::fprintfln(ctx.engine.tty, "{%} | {}", lineno, &lineno_mods, line)!;
		};
		lineno += 1;
	};
};