vis
a vi-like editor based on Plan 9's structural regular expressions
git clone https://9o.is/git/vis.git
vis-std.lua
(3998B)
1 -- standard vis event handlers
2
3 vis.events.subscribe(vis.events.INIT, function()
4 if os.getenv("TERM_PROGRAM") == "Apple_Terminal" then
5 vis:command("set change256colors false")
6 end
7 vis:command("set theme default")
8 end)
9
10 vis:option_register("theme", "string", function(name)
11 if name ~= nil then
12 local theme = 'themes/'..name
13 package.loaded[theme] = nil
14 require(theme)
15 end
16
17 local lexers = vis.lexers
18 lexers.lexers = {}
19
20 if not lexers.load then return false end
21 if not lexers.property then lexers.load("text") end
22 local colors = lexers.colors
23 local default_colors = { "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white" }
24 for _, c in ipairs(default_colors) do
25 if not colors[c] or colors[c] == '' then
26 colors[c] = c
27 end
28 end
29
30 for win in vis:windows() do
31 win:set_syntax(win.syntax)
32 end
33 return true
34 end, "Color theme to use, filename without extension")
35
36 vis:option_register("syntax", "string", function(name)
37 if not vis.win then return false end
38 if not vis.win:set_syntax(name) then
39 vis:info(string.format("Unknown syntax definition: `%s'", name))
40 return false
41 end
42 return true
43 end, "Syntax highlighting lexer to use")
44
45 vis:option_register("horizon", "number", function(horizon)
46 if not vis.win then return false end
47 vis.win.horizon = horizon
48 return true
49 end, "Number of bytes to consider for syntax highlighting")
50
51 vis.events.subscribe(vis.events.WIN_HIGHLIGHT, function(win)
52 if not win.syntax or not vis.lexers.load then return end
53 local lexer = vis.lexers.load(win.syntax, nil, true)
54 if not lexer then return end
55
56 -- TODO: improve heuristic for initial style
57 local viewport = win.viewport.bytes
58 if not viewport then return end
59 local horizon_max = win.horizon or 32768
60 local horizon = viewport.start < horizon_max and viewport.start or horizon_max
61 local view_start = viewport.start
62 local lex_start = viewport.start - horizon
63 viewport.start = lex_start
64 local data = win.file:content(viewport)
65 local token_styles = lexer._TAGS
66 local tokens = lexer:lex(data, 1)
67 local token_end = lex_start + (tokens[#tokens] or 1) - 1
68
69 for i = #tokens - 1, 1, -2 do
70 local token_start = lex_start + (tokens[i-1] or 1) - 1
71 if token_end < view_start then
72 break
73 end
74 local name = tokens[i]
75 local style = token_styles[name]
76 if style ~= nil then
77 win:style(style, token_start, token_end)
78 end
79 token_end = token_start - 1
80 end
81 end)
82
83 local modes = {
84 [vis.modes.NORMAL] = '',
85 [vis.modes.OPERATOR_PENDING] = '',
86 [vis.modes.VISUAL] = 'VISUAL',
87 [vis.modes.VISUAL_LINE] = 'VISUAL-LINE',
88 [vis.modes.INSERT] = 'INSERT',
89 [vis.modes.REPLACE] = 'REPLACE',
90 }
91
92 vis.events.subscribe(vis.events.WIN_STATUS, function(win)
93 local left_parts = {}
94 local right_parts = {}
95 local file = win.file
96 local selection = win.selection
97
98 local mode = modes[vis.mode]
99 if mode ~= '' and vis.win == win then
100 table.insert(left_parts, mode)
101 end
102
103 table.insert(left_parts, (file.name or '[No Name]') ..
104 (file.modified and ' [+]' or '') .. (vis.recording and ' @' or ''))
105
106 local count = vis.count
107 local keys = vis.input_queue
108 if keys ~= '' then
109 table.insert(right_parts, keys)
110 elseif count then
111 table.insert(right_parts, count)
112 end
113
114 if #win.selections > 1 then
115 table.insert(right_parts, selection.number..'/'..#win.selections)
116 end
117
118 local size = file.size
119 local pos = selection.pos
120 if not pos then pos = 0 end
121 table.insert(right_parts, (size == 0 and "0" or math.ceil(pos/size*100)).."%")
122
123 if not win.large then
124 local col = selection.col
125 table.insert(right_parts, selection.line..', '..col)
126 if size > 33554432 or col > 65536 then
127 win.large = true
128 end
129 end
130
131 local left = ' ' .. table.concat(left_parts, " » ") .. ' '
132 local right = ' ' .. table.concat(right_parts, " « ") .. ' '
133 win:status(left, right);
134 end)
135
136 -- default plugins
137
138 require('plugins/filetype')
139 require('plugins/textobject-lexer')
140 require('plugins/digraph')
141 require('plugins/number-inc-dec')
142 require('plugins/complete-word')
143 require('plugins/complete-filename')