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
|
use fmt;
use os;
use io;
use unix::tty;
use errors;
use bufio;
use encoding::utf8;
use strings;
// A listener on a rune input that returns if the ui needs to terminate or not
export type listener = *fn(ui: *ttyui, r: rune) bool;
export type ttyui = struct {
term: tty::termios,
f: io::file,
listeners: []listener,
};
export fn init() ttyui = {
let f = match (tty::open()) {
case let f: io::file =>
yield f;
case let e: tty::error =>
fmt::fatal(tty::strerror(e));
};
if (!tty::isatty(f)) {
fmt::fatal("/dev/tty is not a tty");
};
let term = match (tty::termios_query(f)) {
case let t: tty::termios =>
yield t;
case let e: errors::error =>
fmt::fatal(errors::strerror(e));
};
tty::makeraw(&term)!;
tty::noecho(&term)!;
return ttyui {
term = term,
f = f,
listeners = [],
};
};
export fn getwinsize(ui: ttyui) (tty::ttysize | tty::error) = {
return tty::winsize(ui.f);
};
export fn suspend(ui: *ttyui) void = {
tty::termios_restore(&ui.term);
};
export fn resume(ui: *ttyui) void = {
tty::makeraw(&ui.term)!;
};
export fn finish(ui: *ttyui) void = {
tty::termios_restore(&ui.term);
io::close(ui.f)!;
free(ui.listeners);
};
export fn scan(ui: ttyui) (rune | utf8::invalid | io::EOF | io::error) = {
return bufio::scanrune(ui.f);
};
export fn notify(ui: *ttyui, r: rune) bool = {
for (let i = 0z; i < len(ui.listeners); i += 1) {
if (ui.listeners[i](ui, r)) {
return true;
};
};
return false;
};
fn loop(ui: *ttyui) void = {
for (true) {
let r = match (bufio::scanrune(ui.f)) {
case let r: rune =>
yield r;
case utf8::invalid =>
fmt::fatal("Invalid utf8 sequence found");
case io::EOF =>
fmt::fatal("EOF");
case let e: io::error =>
fmt::fatal(io::strerror(e));
};
for (let i = 0z; i < len(ui.listeners); i += 1) {
if (ui.listeners[i](ui, r)) {
return;
};
};
};
};
export fn addlistener(ui: *ttyui, l: listener) void = {
append(ui.listeners, l);
};
export fn print(ui: ttyui, arg: (str | rune)) void = {
fmt::fprintf(ui.f, "{}\r\n", arg)!;
};
export fn clear(ui: ttyui) void = {
fmt::fprintf(ui.f, "\x1B[2J\x1B[1;1H\r")!;
};
//export @symbol("wcwidth") fn wcwidth(r: rune) int;
|