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