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')