summaryrefslogtreecommitdiffstats
path: root/617-vis-highlight.patch
blob: 6d278fb25b91bb80957db3feed13b43c47021e1b (plain) (blame)
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
From 207fc803e1ceffb384ef9d0c6b2f2614bc8fdb67 Mon Sep 17 00:00:00 2001
From: "David B. Lamkins" <david@lamkins.net>
Date: Sun, 1 Oct 2017 10:43:56 -0700
Subject: [PATCH] Add vis-highlight command.

---
 README.md           |    2 +
 man/vis-highlight.1 |   41 +++++++++++++++++++++++
 vis-highlight       |   89 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 132 insertions(+)
 create mode 100644 man/vis-highlight.1
 create mode 100755 vis-highlight

--- a/README.md
+++ b/README.md
@@ -53,6 +53,8 @@ compatible environment as well as:
  * [Lua](http://www.lua.org/) >= 5.2 (optional)
  * [LPeg](http://www.inf.puc-rio.br/~roberto/lpeg/) >= 0.12
    (optional runtime dependency required for syntax highlighting)
+ * [lua-term](https://github.com/hoelzro/lua-term) >= 0.07
+   (optional runtime dependency required for CLI highlighting using vis-highlight)
  * [TRE](http://laurikari.net/tre/) (optional for more memory efficient regex search)
 
 Assuming these dependencies are met, execute:
--- /dev/null
+++ b/man/vis-highlight.1
@@ -0,0 +1,41 @@
+.Dd October 1, 2017
+.Dt VIS-HIGHLIGHT 1
+.Os Vis VERSION
+.
+.Sh NAME
+.Nm vis-highlight
+.Nd Highlight files using vis' lexers
+.
+.Sh SYNOPSIS
+.Nm vis-highlight
+.Ar lexer
+.Ar files
+.
+.Sh DESCRIPTION
+.Nm vis-highlight
+applies a vis lexer to highlight one or more files to standard output.
+.
+.Sh ENVIRONMENT
+.
+The following environment variables affect the operation of
+.Nm vis-highlight :
+.
+.Bl -tag -width Ev
+.It Ev VIS_PATH
+The default path to use to load Lua support files.
+.El
+.
+.Sh EXIT STATUS
+.Ex -std vis-highlight
+.
+.Sh EXAMPLES
+Highlight the visrc.lua file:
+.Bd -literal -offset indent
+vis-highlight lua ~/.config/vis/visrc.lua
+.Ed
+.
+.Sh BUGS
+An ANSI-compatible terminal is assumed.
+.
+.Sh SEE ALSO
+.Xr vis 1
--- /dev/null
+++ b/vis-highlight
@@ -0,0 +1,89 @@
+#! /usr/bin/env lua
+
+-- Standalone syntax highlighter uses the lexers provided by `vis`.
+
+if #arg < 2 then
+	print('usage: ' .. arg[0] .. ' LEXER-NAME FILE...')
+	return 1
+end
+
+vis_path = os.getenv('VIS_PATH')
+if vis_path ~= nil then
+	package.path = package.path .. ';' .. vis_path .. '/?.lua'
+end
+package.path = package.path .. ';/usr/local/share/vis/?.lua'
+package.path = package.path .. ';/usr/share/vis/?.lua'
+
+local syntax = arg[1]
+local lexers = require('lexer')
+local lexer = lexers.load(syntax)
+
+if not lexer then
+	print(string.format('Failed to load lexer: `%s`', syntax))
+	return 1
+end
+
+local term = require('term')
+local colors = term.colors
+
+local token_styles = {
+	-- bold => bright
+	-- italics => underscore
+	['default'] = colors.default .. colors.onblack .. colors.white,
+	['nothing'] = colors.default .. colors.onblack,
+	['class'] = colors.default .. colors.yellow .. colors.bright,
+	['comment'] = colors.default .. colors.blue .. colors.bright,
+	['constant'] = colors.default .. colors.cyan .. colors.bright,
+	['definition'] = colors.default .. colors.blue .. colors.bright,
+	['error'] = colors.default .. colors.red .. colors.underscore,
+	['function'] = colors.default .. colors.blue .. colors.bright,
+	['keyword'] = colors.default .. colors.yellow .. colors.bright,
+	['label'] = colors.default .. colors.green .. colors.bright,
+	['number'] = colors.default .. colors.red .. colors.bright,
+	['operator'] = colors.default .. colors.cyan .. colors.bright,
+	['regex'] = colors.default .. colors.green .. colors.bright,
+	['string'] = colors.default .. colors.red .. colors.bright,
+	['preprocessor'] = colors.default .. colors.magenta .. colors.bright,
+	['tag'] = colors.default .. colors.red .. colors.bright,
+	['type'] = colors.default .. colors.green .. colors.bright,
+	['variable'] = colors.default .. colors.blue .. colors.bright,
+	['whitespace'] = '',
+	['embedded'] = colors.default .. colors.onblue .. colors.bright,
+	['identifier'] = colors.default .. colors.white,
+}
+
+for i = 2, #arg do
+	local filename = arg[i]
+	local file = assert(io.open(filename, 'r'))
+	local text = file:read('*all')
+	file:close()
+	local tokens = lexer:lex(text, 1)
+	local token_start = 1
+	local last = ''
+
+	for i = 1, #tokens, 2 do
+		local token_end = tokens[i+1] - 1
+		local name = tokens[i]
+		local style = token_styles[name]
+		if style ~= nil then
+			-- Whereas the lexer reports all other syntaxes over
+			-- the entire span of a token, it reports 'default'
+			-- byte-by-byte. We emit only the first 'default' of
+			-- a series in order to properly display multibyte
+			-- UTF-8 characters.
+			if not (last == 'default' and name == 'default') then
+				io.write(tostring(style))
+			end
+			last = name
+		end
+		local token = text:sub(token_start, token_end)
+		if style ~= nil then
+			-- Replicate the style after every newline within
+			-- the token, because less -R forgets attributes
+			-- with each newline.
+			token = token:gsub("\n", "\n" .. tostring(style))
+		end
+		io.write(token)
+		token_start = token_end + 1
+	end
+end