--[[-------------------------------------------- xComment Version: 1.4.1 Author: mozers™, VladVRO ------------------------------------------------- C блеском заменяет стандартную комбинацию Ctrl+Q (комментирование|снятие комментария) Вид комментария зависит от выделения текста: * Если выделен поток текста, то скрипт ставит|снимает потоковый комментарий. * Если выделена целая строка(включая символ перевода строки) или несколько строк, то то скрипт ставит|снимает блочный комментарий. * Если выделение отсутствует, то ставится|снимается блочный комментарий на текущую строку. * Если параметры comment.stream.* отсутсвуют, то независимо от способа выделения ставится|снимается блочный комментарий. Снятие/установка комментария зависит от первого символа выделения: * Если первый символ в выделении закомментированн, то комментарий снимается со всего выделения. * Если - нет, то на все выделение ставится комментарий. Подключение: В файл SciTEStartup.lua добавьте строку: dofile (props["SciteDefaultHome"].."\\tools\\xComment.lua") Задайте в файле .properties используемых вами языков параметры: comment.block.lexer comment.block.at.line.start.lexer comment.stream.start.lexer comment.stream.end.lexer И забудьте навсегда про этот атавизм "~". Тильда вам больше никогда не понадобится! Внимание: В скрипте используется функция IsComment (обязательно подключение COMMON.lua) --]]-------------------------------------------- -- local iDEBUG = true -- включается при отладке скрипта local lexer = "" local sel_text = "" local sel_start = 0 local sel_end = 0 local line_sel_start = 0 local line_sel_end = 0 local comment_block = "" local comment_block_at_line_start = 0 local comment_block_use_space = 1 -- можно задать кол-во пробелов, отделяющих коммент от кода local comment_stream_start = "" local comment_stream_end = "" local PatternStream = "" -------------------------------------------------- local function Pattern(text) -- Получение паттерна для поиска символов комментария в тексте local pat = "" for i = 1, string.len(text) do pat = pat.."%"..string.sub(text,i,i) end return pat end --------------------------------------------- local function FirstLetterFromBlock() -- Возвращает позицию первого не пробельного символа в блоке local text_line = sel_text if sel_text == "" then text_line = editor:GetLine(line_sel_start) sel_start = editor:PositionFromLine(line_sel_start) end local first_letter, _, _ = string.find(text_line, "[^%s]", 1) if first_letter ~= nil then first_letter = sel_start + first_letter - 1 else first_letter = -1 end if iDEBUG then print("FirstLetterFromBlock = "..first_letter) end return first_letter end -------------------------------------------------- local function IsBlock() -- Определение что выделено - блок или поток if sel_text == "" then return true end if sel_end > 0 and editor.CharAt[sel_end - 1] == 10 then if iDEBUG then print ("This Block") end return true end if iDEBUG then print ("This NOT Block") end return false end -------------------------------------------------- local function IsStreamComment() -- Определение что выделено - потоковый комментарий или закомментированные строки if PatternStream ~= "" then if string.find(sel_text,PatternStream) then if iDEBUG then print ("This Stream Comment") end return true end end if iDEBUG then print ("This NOT Stream Comment") end return false end -------------------------------------------------- local function LineComment() -- Комментирование одной невыделенной строки if iDEBUG then print ("Line Comment") end if comment_block == "" then print("! Отсутствует параметр ".."comment.block."..lexer) else comment_block = comment_block..string.rep(" ", comment_block_use_space) local cur_pos = editor.CurrentPos if comment_block_at_line_start == 1 then editor:GotoPos(editor:PositionFromLine(line_sel_start)) else editor:GotoPos(editor.LineIndentPosition[line_sel_start]) end editor:ReplaceSel(comment_block) editor:GotoPos(cur_pos + string.len(comment_block)) end end -------------------------------------------------- local function BlockComment() -- Комментирование нескольких выделенных строк if iDEBUG then print ("Block Comment") end if comment_block == "" then print("! Отсутствует параметр ".."comment.block."..lexer) else comment_block = comment_block..string.rep(" ", comment_block_use_space) local text_comment = "" for i = line_sel_start, line_sel_end-1 do local text_line = editor:GetLine(i) if string.find(text_line,"[^%s]") then if comment_block_at_line_start == 1 then text_comment = text_comment..comment_block..text_line else text_comment = text_comment..string.gsub(text_line,"([^%s])",comment_block.."%1",1) end sel_end = sel_end + string.len(comment_block) else text_comment = text_comment..text_line end end editor:ReplaceSel(text_comment) -- восстанавливаем выделение editor:SetSel(sel_start, sel_end) end end -------------------------------------------------- local function LineUnComment() -- Снятие комментария с одной невыделенной строки if iDEBUG then print ("Line UnComment") end if comment_block == "" then print("! Отсутствует параметр ".."comment.block."..lexer) else local cur_pos = editor.CurrentPos local text_line = editor:GetCurLine() local comment_pos, _ = string.find(text_line,Pattern(comment_block).."~? ?", 1) local line_uncomment = string.gsub(text_line,Pattern(comment_block).."~? ?","",1) local line_pos_start = editor:PositionFromLine(line_sel_start) local line_pos_end = line_pos_start + string.len(text_line) editor:SetSel(line_pos_start, line_pos_end) editor:ReplaceSel(line_uncomment) if comment_pos and cur_pos > (line_pos_start + comment_pos) then editor:GotoPos(cur_pos - string.len(text_line) + string.len(line_uncomment)) else editor:GotoPos(cur_pos) end end end -------------------------------------------------- local function BlockUnComment() -- Снятие комментария с нескольких выделенных строк if iDEBUG then print ("Block UnComment") end if comment_block == "" then print("! Отсутствует параметр ".."comment.block."..lexer) else local text_uncomment = "" for i = line_sel_start, line_sel_end-1 do local text_line = editor:GetLine(i) local line_uncomment = string.gsub(text_line,Pattern(comment_block).."~? ?","",1) text_uncomment = text_uncomment..line_uncomment if line_uncomment ~= text_line then sel_end = sel_end - string.len(text_line) + string.len(line_uncomment) end end editor:ReplaceSel(text_uncomment) -- восстанавливаем выделение editor:SetSel(sel_start, sel_end) end end -------------------------------------------------- local function StreamComment() -- Комментирование выделенного потока текста if iDEBUG then print ("Stream Comment") end if comment_stream_start == "" or comment_stream_end == "" then print("! Отсутствуют параметры ".."comment.stream.start."..lexer.." и ".."comment.stream.end."..lexer) else local text_comment = comment_stream_start..sel_text..comment_stream_end editor:ReplaceSel(text_comment) if sel_text ~= "" then -- восстанавливаем выделение editor:SetSel(sel_start, sel_end + string.len(comment_stream_start) + string.len(comment_stream_end)) end end end -------------------------------------------------- local function StreamUnComment() -- Снятие комментария с выделенного потока текста if iDEBUG then print ("Stream UnComment") end if PatternStream == "" then print("! Отсутствуют параметры ".."comment.stream.start."..lexer.." и ".."comment.stream.end."..lexer) else local text_uncomment = string.gsub(sel_text,PatternStream,"%1",1) editor:ReplaceSel(text_uncomment) if sel_text ~= "" then -- восстанавливаем выделение editor:SetSel(sel_start, sel_end - string.len(comment_stream_start) - string.len(comment_stream_end)) end end end --------------------------------------------- local function xComment() -- Обработка нажатия на Ctrl+Q lexer = editor.LexerLanguage sel_text = editor:GetSelText() sel_start = editor.SelectionStart sel_end = editor.SelectionEnd line_sel_start = editor:LineFromPosition(sel_start) line_sel_end = editor:LineFromPosition(sel_end) comment_block = props["comment.block."..lexer] comment_block_at_line_start = tonumber(props["comment.block.at.line.start."..lexer]) comment_stream_start = props["comment.stream.start."..lexer] comment_stream_end = props["comment.stream.end."..lexer] if sel_text == "" then -- This Line if IsComment(FirstLetterFromBlock()) then LineUnComment() else LineComment() end return true end if IsBlock() then -- This Block if IsComment(FirstLetterFromBlock()) then BlockUnComment() else BlockComment() end else -- This Stream if comment_stream_start ~= "" and comment_stream_end ~= "" then PatternStream = Pattern(comment_stream_start).."(.-)"..Pattern(comment_stream_end) else -- если параметры comment.stream.* отсутствуют, то расширяем выделение потока до блока -- и комментируем|сниманием блочный комментарий -- (предложение frs ) line_sel_end = line_sel_end + 1 editor:SetSel(editor:PositionFromLine(line_sel_start), editor:PositionFromLine(line_sel_end)) -- This Block if IsComment(FirstLetterFromBlock()) then BlockUnComment() else BlockComment() end return true end if IsStreamComment() then StreamUnComment() else StreamComment() end end return true end -------------------------------------------------- -- Add user event handler OnMenuCommand local old_OnMenuCommand = OnMenuCommand function OnMenuCommand (msg, source) local result if old_OnMenuCommand then result = old_OnMenuCommand(msg, source) end if msg == IDM_BLOCK_COMMENT then -- (Ctrl+Q) if xComment() then return true end end return result end