local comment_string = {
actionscript='//', ada='--', adpl='!', ansi_c='/*|*/', antlr='//', apl='#',
applescript='--', asp='\'', autoit=';', awk='#', b_lang='//', bash='#',
batch=':', bibtex='%', boo='#', chuck='//', cmake='#', coffeescript='#',
context='%', cpp='//', crystal='#', csharp='//', css='/*|*/', cuda='//',
desktop='#', django='{#|#}', dmd='//', dockerfile='#', dot='//',
eiffel='--', elixir='#', erlang='%', faust='//', fish='#', forth='|\\',
fortran='!', fsharp='//', gap='#', gettext='#', gherkin='#', glsl='//',
gnuplot='#', go='//', groovy='//', gtkrc='#', haskell='--', html='<!--|-->',
icon='#', idl='//', inform='!', ini='#', Io='#', java='//', javascript='//',
json='/*|*/', jsp='//', latex='%', ledger='#', less='//', lilypond='%',
lisp=';', logtalk='%', lua='--', makefile='#', matlab='#', moonscript='--',
myrddin='//', nemerle='//', nsis='#', objective_c='//', pascal='//',
perl='#', php='//', pico8='//', pike='//', pkgbuild='#', prolog='%',
props='#', protobuf='//', ps='%', pure='//', python='#', rails='#', rc='#',
rebol=';', rest='.. ', rexx='--', rhtml='<!--|-->', rstats='#', ruby='#',
rust='//', sass='//', scala='//', scheme=';', smalltalk='"|"', sml='(*)',
snobol4='#', sql='#', tcl='#', tex='%', text='', toml='#', vala='//',
vb='\'', vbscript='\'', verilog='//', vhdl='--', wsf='<!--|-->',
xml='<!--|-->', yaml='#'
}
-- escape all magic characters with a '%'
local function esc(str)
if not str then return "" end
return (str:gsub('%%', '%%%%')
:gsub('^%^', '%%^')
:gsub('%$$', '%%$')
:gsub('%(', '%%(')
:gsub('%)', '%%)')
:gsub('%.', '%%.')
:gsub('%[', '%%[')
:gsub('%]', '%%]')
:gsub('%*', '%%*')
:gsub('%+', '%%+')
:gsub('%-', '%%-')
:gsub('%?', '%%?'))
end
-- escape only '%' as it is the only magic character in string.format
local function f_esc(str)
if not str then return "" end
return str:gsub('%%', '%%%%')
end
local function toggle_line_comment(lines, lnum, prefix, suffix)
if not lines or not lines[lnum] then return end
local stripped = lines[lnum]:match("^%s*(.+)") -- empty lines: nil
if not stripped then return end
-- remove comment
if lines[lnum]:match("^%s*(.+)"):sub(0, #prefix) == prefix then
local match_str = "^(%s*)" .. esc(prefix) .. "%s?(.*)" .. esc(suffix)
lines[lnum] = table.concat(table.pack(lines[lnum]:match(match_str)))
-- add comment
else
if suffix ~= "" then suffix = " " .. suffix end
local format_str = f_esc(prefix) .. " %s" .. f_esc(suffix)
lines[lnum] = string.format(format_str, lines[lnum])
end
end
vis:map(vis.modes.NORMAL, "gcc", function()
local win = vis.win
local lines = win.file.lines
local lnum = win.selection.line
local col = win.selection.col
local comment = comment_string[win.syntax]
if not comment then return end
local prefix, suffix = comment:match('^([^|]+)|?([^|]*)$')
if not prefix then return end
toggle_line_comment(lines, lnum, prefix, suffix)
win:draw()
win.selection:to(lnum, col) -- restore cursor position
end, "Toggle comment on a the current line")
local function visual_f(i)
return function()
local win = vis.win
local r = win.selection.range
local lnum = win.selection.line -- line number of cursor
local col = win.selection.col -- column of cursor
local comment = comment_string[win.syntax]
if not comment then return end
local prefix, suffix = comment:match('^([^|]+)|?([^|]*)$')
if not prefix then return end
if win.selection.anchored and r then
win.selection.pos = r.start
local a = win.selection.line
win.selection.pos = r.finish
local b = win.selection.line - i
local lines = win.file.lines
for i = a,b do
if not lines[i]:match("^%s*$") then -- ignore empty lines
toggle_line_comment(lines, i, prefix, suffix)
end
end
win:draw()
win.selection:to(lnum, col) -- restore cursor position
vis.mode = vis.modes.NORMAL -- go to normal mode
end
end
end
vis:map(vis.modes.VISUAL_LINE, "gc", visual_f(1), "Toggle comment on the selected lines")
vis:map(vis.modes.VISUAL, "gc", visual_f(0), "Toggle comment on the selected lines")