File: prompt.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 (118 lines) | stat: -rw-r--r-- 2,519 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
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
use bufio;
use common::{location};
use errors;
use fmt;
use io;
use memio;
use os;
use sort;
use sort::cmp;
use types;
use strings;

def REMEMBER_UNDEF: int = -1;
def REMEMBER_NO: int = 0;
def REMEMBER_YES: int = 1;

// Presents an [[editgroup]] for user approval. Returns true if the edits should
// be merged with the context.
export fn present(
	ctx: *context,
	proposal: *editgroup,
	explanation: str,
) (bool | errors::cancelled) = {
	if (ctx.engine.yes) {
		return true;
	};

	let rule = proposal.rule;
	switch (rule.remember) {
	case REMEMBER_NO =>
		return false;
	case REMEMBER_YES =>
		return true;
	case => void;
	};

	let ctxlines = 3u;
	show_context(ctx, proposal, explanation, ctxlines);
	fmt::fprint(ctx.engine.tty, "\n")!;

	const scan = bufio::newscanner(ctx.engine.tty);
	defer bufio::finish(&scan);

	for (true) {
		fmt::fprint(ctx.engine.tty,
			"[y]es [n]o [Y]es (always) [N]o (always) [q]uit [?] (y): ")!;

		const choice = match (bufio::scan_line(&scan)!) {
		case let line: str =>
			yield line;
		case io::EOF =>
			fmt::fatal("Aborted");
		};

		switch (choice) {
		case "", "y" =>
			return true;
		case "Y" =>
			rule.remember = REMEMBER_YES;
			return true;
		case "n" =>
			return false;
		case "N" =>
			rule.remember = REMEMBER_NO;
			return false;
		case "?" =>
			prompt_show_help(ctx);
		case "+" =>
			ctxlines += 2;
			show_context(ctx, proposal, explanation, ctxlines);
			fmt::fprint(ctx.engine.tty, "\n")!;
		case "q" =>
			fmt::errorln("Warning! Edits to some files may have already been written.")!;
			return errors::cancelled;
		case => void;
		};
	};
};

fn prompt_show_help(ctx: *context) void = {
	fmt::fprint(ctx.engine.tty, `[y]es: accept edit once
[Y]es: always accept proposed edit for this rule
[n]o: reject edit once
[N]o: always reject proposed edit for this rule
[+]: add more lines of context
[q]: quit, without saving changes to the current file
[?]: show this help
`)!;
};

fn show_rule(ctx: *context, rule: *rule) void = {
	fmt::fprintfln(ctx.engine.tty, "{}{}-{:.3}{}: {}{}{}\n",
		C_BLUE,
		ctx.engine.ver.name,
		rule.serial,
		C_RESET,
		C_BOLD, rule.name, C_RESET)!;
};

fn show_context(
	ctx: *context,
	proposal: *editgroup,
	explanation: str,
	ctxlines: uint,
) void = {
	show_rule(ctx, proposal.rule);

	const doc = document_clone(ctx);
	defer document_destroy(&doc);

	for (let edit &.. proposal.edits) {
		apply(&doc, edit);
	};

	diff(&doc, ctx.engine.tty, ctxlines)!;

	fmt::fprintf(ctx.engine.tty, "\n{}{}?{}", C_BOLD, explanation, C_RESET)!;
};