vis-config

lua scripts to configure vis editor

git clone https://9o.is/git/vis-config.git

commentary.lua

(4520B)


      1 --
      2 -- vis-commentary
      3 --
      4 
      5 local vis = _G.vis
      6 
      7 local comment_string = {
      8 	actionscript='//', ada='--', ansi_c='/*|*/', antlr='//', apdl='!', apl='#',
      9 	applescript='--', asp='\'', autoit=';', awk='#', b_lang='//', bash='#',
     10 	batch=':', bibtex='%', boo='#', chuck='//', cmake='#', coffeescript='#',
     11 	context='%', cpp='//', crystal='#', csharp='//', css='/*|*/', cuda='//',
     12 	dart='//', desktop='#', django='{#|#}', dmd='//', dockerfile='#', dot='//',
     13 	eiffel='--', elixir='#', erlang='%', faust='//', fennel=';;', fish='#',
     14 	forth='|\\', fortran='!', fsharp='//', gap='#', gettext='#', gherkin='#',
     15 	glsl='//', gnuplot='#', go='//', groovy='//', gtkrc='#', haskell='--',
     16 	html='<!--|-->', icon='#', idl='//', inform='!', ini='#', Io='#',
     17 	java='//', javascript='//', json='/*|*/', jsp='//', latex='%', ledger='#',
     18 	less='//', lilypond='%', lisp=';', logtalk='%', lua='--', makefile='#',
     19 	markdown='<!--|-->', matlab='#', moonscript='--', myrddin='//',
     20 	nemerle='//', nsis='#', objective_c='//', pascal='//', perl='#', php='//',
     21 	pico8='//', pike='//', pkgbuild='#', prolog='%', props='#', protobuf='//',
     22 	ps='%', pure='//', python='#', rails='#', rc='#', rebol=';', rest='.. ',
     23 	rexx='--', rhtml='<!--|-->', rstats='#', ruby='#', rust='//', sass='//',
     24 	scala='//', scheme=';', smalltalk='"|"', sml='(*)', snobol4='#', sql='#',
     25 	tcl='#', tex='%', text='', toml='#', vala='//', vb='\'', vbscript='\'',
     26 	verilog='//', vhdl='--', wsf='<!--|-->', xml='<!--|-->', yaml='#', zig='//',
     27 	nim='#', julia='#', rpmspec='#', caml='(*|*)'
     28 }
     29 
     30 -- escape all magic characters with a '%'
     31 local function esc(str)
     32 	if not str then return "" end
     33 	return (str:gsub('[[.+*?$^()%%%]-]', '%%%0'))
     34 end
     35 
     36 -- escape '%'
     37 local function pesc(str)
     38 	if not str then return "" end
     39 	return str:gsub('%%', '%%%%')
     40 end
     41 
     42 local function rtrim(s)
     43 	local n = #s
     44 	while n > 0 and s:find("^%s", n) do n = n - 1 end
     45 	return s:sub(1, n)
     46 end
     47 
     48 local function comment_line(lines, lnum, prefix, suffix)
     49 	if suffix ~= "" then suffix = " " .. suffix end
     50 	lines[lnum] = string.gsub(lines[lnum],
     51 	"(%s*)(.*)",
     52 	"%1" .. pesc(prefix) .. " %2" .. pesc(suffix))
     53 end
     54 
     55 local function uncomment_line(lines, lnum, prefix, suffix)
     56 	local match_str = "^(%s*)" .. esc(prefix) .. "%s?(.*)" .. esc(suffix)
     57 	local m = table.pack(lines[lnum]:match(match_str))
     58 	lines[lnum] = m[1] .. rtrim(m[2])
     59 end
     60 
     61 local function is_comment(line, prefix)
     62 	return (line:match("^%s*(.+)"):sub(0, #prefix) == prefix)
     63 end
     64 
     65 local function toggle_line_comment(lines, lnum, prefix, suffix)
     66 	if not lines or not lines[lnum] then return end
     67 	if not lines[lnum]:match("^%s*(.+)") then return end -- ignore empty lines
     68 	if is_comment(lines[lnum], prefix) then
     69 		uncomment_line(lines, lnum, prefix, suffix)
     70 	else
     71 		comment_line(lines, lnum, prefix, suffix)
     72 	end
     73 end
     74 
     75 -- if one line inside the block is not a comment, comment the block.
     76 -- only uncomment, if every single line is comment.
     77 local function block_comment(lines, a, b, prefix, suffix)
     78 	local uncomment = true
     79 	for i=a,b do
     80 		if lines[i]:match("^%s*(.+)") and not is_comment(lines[i], prefix) then
     81 			uncomment = false
     82 		end
     83 	end
     84 
     85 	if uncomment then
     86 		for i=a,b do
     87 			if lines[i]:match("^%s*(.+)") then
     88 				uncomment_line(lines, i, prefix, suffix)
     89 			end
     90 		end
     91 	else
     92 		for i=a,b do
     93 			if lines[i]:match("^%s*(.+)") then
     94 				comment_line(lines, i, prefix, suffix)
     95 			end
     96 		end
     97 	end
     98 end
     99 
    100 vis:operator_new("gc", function(file, range, pos)
    101 	local comment = comment_string[vis.win.syntax]
    102 	local prefix, suffix = comment:match('^([^|]+)|?([^|]*)$')
    103 	if not prefix then return end
    104 
    105 	local c = 0
    106 	local i = 1
    107 	local a = -1
    108 	local b = -1
    109 	for line in file:lines_iterator() do
    110 		local line_start = c
    111 		local line_finish = c + #line + 1
    112 		if line_start < range.finish and line_finish > range.start then
    113 			if a == -1 then
    114 				a = i
    115 				b = i
    116 			else
    117 				b = i
    118 			end
    119 		end
    120 		c = line_finish
    121 		if c > range.finish then break end
    122 		i = i + 1
    123 	end
    124 	block_comment(file.lines, a, b, prefix, suffix)
    125 
    126 	return range.start
    127 end, "Toggle comment on selected lines")
    128 
    129 vis:map(vis.modes.NORMAL, "gcc", function()
    130 	local win = vis.win
    131 	local lines = win.file.lines
    132 	local comment = comment_string[win.syntax]
    133 	if not comment then return end
    134 	local prefix, suffix = comment:match('^([^|]+)|?([^|]*)$')
    135 	if not prefix then return end
    136 
    137 	for sel in win:selections_iterator() do
    138 		local lnum = sel.line
    139 		local col = sel.col
    140 
    141 		toggle_line_comment(lines, lnum, prefix, suffix)
    142 		sel:to(lnum, col)  -- restore cursor position
    143 	end
    144 
    145 	win:draw()
    146 end, "Toggle comment on a the current line")
    147