summaryrefslogtreecommitdiff
path: root/cmd/il.ha
blob: 3afbb377577d30b1ffaab72d8906bc70f0ad7896 (plain)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use tui;
use tui::widget::list;
use tui::layout;
use bufio;
use os;
use strings;
use fmt;
use io;

export fn main() void = {
	const scanner = bufio::newscanner(os::stdin);
	defer bufio::finish(&scanner);
	let items: []str = [];
	for (let line: const str => bufio::scan_line(&scanner)!) {
		append(items, strings::dup(line))!;
	};
	defer strings::freeall(items);
	const state = tui::init()!;
	defer tui::finish(&state);
	let li = list::newscrolllist(
		&state,
		(1, 1),
		void,
		void,
		items...
	)!;
	let vl = layout::newvlayout(&li);
	defer layout::finishvlayout(&vl);

	vl.layout.print(&vl);

	let term: (str | void) = void;
	defer if (term is str) free(term as str) else void;
	let revsearch = false;
	for (true) {
		const r = tui::read(&state)!;
		if (r == 'j') {
			list::down(&li);
		};
		if (r == 'k') {
			list::up(&li);
		};
		if (r == 'J') {
			list::framedown(&li);
		};
		if (r == 'K') {
			list::frameup(&li);
		};
		if (r == 'g') {
			list::top(&li);
		};
		if (r == 'G') {
			list::bottom(&li);
		};
		if (r == 'q') {
			break;
		};
		if (r == 'l') {
			fmt::println(li.items[li.cursor])!;
			break;
		};
		if (r == '/' || r == '?') {
			revsearch = r == '?';
			term = search(&state, &li, r as rune);
			if (revsearch) prevsearch(&li, term) else nextsearch(&li, term);
		};
		if (r == 'n') {
			if (revsearch) prevsearch(&li, term) else nextsearch(&li, term);
		};
		if (r == 'N') {
			if (!revsearch) prevsearch(&li, term) else nextsearch(&li, term);
		};
		vl.layout.print(&vl);
	};
};

fn search(state: *tui::tui, li: *list::scrolllist, prefix: (str | rune) = '/') (str | void) = {
	tui::unraw(state);
	defer tui::raw(state)!;
	fmt::fprint(state.out, prefix)!;
	const uline = match (bufio::read_line(state.out)!) {
	case let u: []u8 =>
		yield u;
	case io::EOF =>
		return;
	};
	defer free(uline);
	return strings::dup(strings::fromutf8(uline)!);
};

fn nextsearch(li: *list::scrolllist, term: (str | void)) void = {
	const term = match (term) {
	case let term: str =>
		yield term;
	case void =>
		return;
	};
	for (let i = li.cursor + 1; i < len(li.items): int; i += 1) {
		if (strings::contains(li.items[i], term)) {
			list::setcursor(li, i);
			return;
		};
	};
};

fn prevsearch(li: *list::scrolllist, term: (str | void)) void = {
	const term = match (term) {
	case let term: str =>
		yield term;
	case void =>
		return;
	};
	for (let i: int = li.cursor: int - 1; i >= 0; i -= 1) {
		if (strings::contains(li.items[i], term)) {
			list::setcursor(li, i);
			return;
		};
	};
};