File: highlight.bs

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (115 lines) | stat: -rw-r--r-- 2,708 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
use ui;
use graphics;
use core:io;
use core:lang;
use lang;
use lang:bnf;

// Load and highlight a source file into a Text object.
Text highlightSource(Url file) on Render {
	highlightSource(file, progvis:view:codeFont);
}

Text highlightSource(Url file, Font font) on Render {
	highlightSource(file, file.readAllText(), font);
}

Text highlightSource(Url file, Str text, Font font) on Render {
	TextColor[] colors;

	if (reader = progvisReader(file.ext, [file], rootPkg)) {
		colors = highlightSource(file, reader, text);
	} else if (reader = stdReader(file.ext, [file], rootPkg)) {
		colors = highlightSource(file, reader, text);
	}

	Text result(text, font);
	for (x in colors) {
		result.color(x.begin, x.end, hlColor(x.color));
	}
	result;
}

private value TextColor {
	init(Str:Iter begin, Str:Iter end, TokenColor color) {
		init {
			begin = begin;
			end = end;
			color = color;
		}
	}

	Str:Iter begin;
	Str:Iter end;
	TokenColor color;
}

private Color hlColor(TokenColor color) {
	if (color == TokenColor:tComment) {
		Color(0.69, 0.13, 0.13);
	} else if (color == TokenColor:tDelimiter) {
		black;
	} else if (color == TokenColor:tString) {
		Color(0.54, 0.13, 0.32);
	} else if (color == TokenColor:tConstant) {
		black;
	} else if (color == TokenColor:tKeyword) {
		Color(0.62, 0.12, 0.94);
	} else if (color == TokenColor:tFnName) {
		blue;
	} else if (color == TokenColor:tVarName) {
		Color(0.63, 0.32, 0.18);
	} else if (color == TokenColor:tTypeName) {
		Color(0.13, 0.54, 0.13);
	} else {
		black;
	}
}

private TextColor[] highlightSource(Url file, PkgReader reader, Str text) on Compiler {
	unless (fileReader = reader.readFile(file, text))
		return [];

	TextColor[] result;
	do {
		Str:Iter end = fileReader.info.contents.end;
		var next = fileReader.next(ReaderQuery:parser);
		if (next) {
			end = next.info.start;
		}

		var parser = fileReader.createParser();
		parser.parseApprox(fileReader.info.contents, fileReader.info.url, fileReader.info.start, end);

		var tree = parser.infoTree();
		findColors(result, fileReader.info.start, end, tree);

		if (next)
			fileReader = next;
		else
			break;
	}

	return result;
}

private Str:Iter findColors(TextColor[] to, Str:Iter start, Str:Iter end, InfoNode node) on Compiler {
	if (start >= end)
		return end;

	// We don't need to traverse more than the first color.
	if (node.color != TokenColor:tNone) {
		var end = start + node.length();
		to << TextColor(start, end, node.color);
		return end;
	}

	if (node as InfoInternal) {
		for (Nat i = 0; i < node.count; i++)
			start = findColors(to, start, end, node[i]);
		return start;
	} else {
		// Skip this node. It is a leaf without color.
		return start + node.length();
	}
}