mozers Цитата: У Мишеля Форала давно есть подобная. Я давно уже говорил о том что неплохобы выдрать его код в нашу сборку...
Я не видел того что сделал Мишель, но самое главное что сделано в
OnKeyDown это анализируется "
нажатый символ", по этому его можно
использовать вместо OnChar с той лишь разницей что OnChar возникает
уже после того как мы символ ввели, т.е. констатируется факт - OnChar
У меня же говорится что, нажат символ ДО того как он попадает в
редактор, да плюс к тому не все символы вызывают OnChar с OnKeyDown
таких проблем нет.
Еще одна особенность OnChar - возникает после того как снялось выделение у текста, по этому никак не понять был ли выделен текст или нет до нажатия, во всяком случае было проще написать OnKeyDown
Для тех кому совсем туго, поясняю на пальцах: символ '/' можно ввести
3 разными клавишами с клавиатуры, у этих клавиш соответственно разный
"код клавиши"
Короче - наипросторнейшее поле для скриптописателей!
Цитата: Выложить бы сейчас наши доработки - глядишь и включили бы что то в официал...
Нет, не могу - тут-недоделано, тут-недописано.
Высылай что по коду не доделано, доделаю
З.Ы. Ну а все-таки, можно прикрепить первый пост в топике?
mozers Цитата: Нету подсказок
Критических замечаний по коду я так не дождался, так что исходники ушли прямо к тебе приватом.
Цитата: Совсем недавно Нейл согласился добавить его OnKey в официальный дистрибутив.
...
самое главное что сделано в
OnKeyDown это анализируется "нажатый символ"
Ну и чтобы не быть голословным выкладываю первый скрипт основанный на этой фиче (будет доступно всем как только обновится наша сборка)
Итак, [more=наслаждайтесь...]
smartcomment.lua Код: [no]-- SciTE Smart comment[/no] [no]-- Version: 2.4[/no] [no]-- Autor: Dmitry Maslov[/no] [no]---------------------------------------------------[/no] [no]-- Веделяем текст нажимаем на клавиатуре символ [/no] [no]-- с которого начинается комментарий и строка комментируется[/no] [no]-- пример: выделить строку в cpp, нажать на клавишу * или /[/no] [no]---------------------------------------------------[/no] [no]-- Версия 2.4[/no] [no]-- Поправлена обработка { в cpp[/no] [no]---------------------------------------------------[/no] [no]-- Версия 2.3[/no] [no]-- Скрипт сделан полностью автономным[/no] [no]---------------------------------------------------[/no] [no]-- Версия 2.2[/no] [no]-- Исправлен баг, если нажали не печатный символ[/no] [no]-- то скрипт вел себя не предсказуемо[/no] [no]---------------------------------------------------[/no] [no]-- Версия 2.1[/no] [no]-- Закрытие блочным комментирием во всех языках по первому [/no] [no]-- символу блочного комментария во как загнул [/no] [no]-- Благодарность mozers за подсказку в реализации.[/no] [no]---------------------------------------------------[/no] [no]-- Версия 2.0[/no] [no]-- Автозакрытие скобок и текста в скобки[/no] [no]-- Работает, если braces.autoclose=1 [/no] [no]-- (параметр в файле SciTEGlobal.properties)[/no] [no]-- Особая обработка { и } в cpp[/no] [no]---------------------------------------------------[/no] [no]-- Версия 1.0[/no] [no]-- Обработка комментариев в cpp * и / (/**/ и //~ )[/no] [no]-- Обработка коментариев в lua - ( -- )[/no] [no]-- Обработка скобок в lua [ ( [[...]] )[/no] [no]-- Обработка комментария в props # ( #~ )[/no] [no]---------------------------------------------------[/no] [no]-- позиция это начало строки (учитывая отступ)[/no] local function IsLineStartPos
(pos
) return (editor.LineIndentPosition
[editor:LineFromPosition
(pos
)] == pos
) end [no]-- Получить номер текущей строки[/no] local function GetCurrLineNumber
() return editor:LineFromPosition
(editor.CurrentPos
); end [no]-- Получить отступ в троке[/no] local function GetLineIndentation
(num_line
) if num_line
<0 then num_line
=0 end if num_line
>=editor.LineCount
then num_line
=editor.LineCount
-1 end return editor.LineIndentation
[num_line
]/editor.Indent
end [no]-- Возвращает текущий символ перевода строки[/no] local function GetEOL
() local eol
= [no]"\r\n"[/no] if editor.EOLMode
== SC_EOL_CR
then eol
= [no]"\r"[/no] elseif editor.EOLMode
== SC_EOL_LF
then eol
= [no]"\n"[/no] end return eol
end [no]-- сделать текст шаблоном для поиска[/no] [no]-- (фактически экранирование служебных символов)[/no] local function makefind
(text
) local strres
=[no]''[/no] local simbol
for i
=1, string.len(text
), 1 do simbol
= string.format([no]'%c'[/no], string.byte(text
,i
)) if ((simbol
==[no]"("[/no])or(simbol
==[no]"["[/no])or(simbol
==[no]"."[/no])or(simbol
==[no]"%"[/no])or (simbol
==[no]"*"[/no])or(simbol
==[no]"/"[/no])or(simbol
==[no]"-"[/no])or(simbol
==[no]")"[/no])or (simbol
==[no]"]"[/no])or(simbol
==[no]"?"[/no])or(simbol
==[no]"+"[/no])) then simbol
=string.format([no]"%%%s"[/no],simbol
) end strres
= strres
..simbol
end return strres
end [no]-- последний в строке ?[/no] local function IsInLineEnd
(num_line
, text
) local endpos
= editor.LineEndPosition
[num_line
]; if endpos
>=string.len(text
) and string.find(editor:textrange
(endpos
-string.len(text
), endpos
), makefind
(text
)) then return true end return false end [no]-- предыдущий символ позиции конец строки?[/no] local function prevIsEOL
(pos
) if (string.find(editor:textrange
(pos
-string.len(GetEOL
()), pos
),GetEOL
())) then return true end return false end [no]-- следующий символ позиции конец строки?[/no] local function nextIsEOL
(pos
) if (string.find(editor:textrange
(pos
, pos
+string.len(GetEOL
())),GetEOL
())) then return true end return false end [no]-- последний символ в строке - конец строки?[/no] local function IsEOLlast
(text
) [no]-- в луа конец строки всегда один символ[/no] if string.find(text
,GetEOL
(),string.len(text
)-1) then return true end return false end local function StrimComment
(commentbegin
, commentend
) local text
, lenght
= editor:GetSelText
() local selbegin
= editor.SelectionStart
local selend
= editor.SelectionEnd
local b
,e
= string.find(text
,makefind
(commentbegin
)) if (e
and (string.byte(text
, e
+1) == 10 or string.byte(text
, e
+1) == 13)) then e
=e
+1 end if (e
and (string.byte(text
, e
+1) == 10 or string.byte(text
, e
+1) == 13)) then e
=e
+1 end local b2
,e2
if IsEOLlast
(text
) then b2
,e2
= string.find(text
,makefind
(commentend
), string.len(text
)-string.len(commentend
)-string.len(GetEOL
())) else b2
,e2
= string.find(text
,makefind
(commentend
), string.len(text
)-string.len(commentend
)) end if (b2
and (string.byte(text
, b2
-1) == 10 or string.byte(text
, b2
-1) == 13)) then b2
=b2
-1 end if (b2
and (string.byte(text
, b2
-1) == 10 or string.byte(text
, b2
-1) == 13)) then b2
=b2
-1 end editor:BeginUndoAction
() if (b
and b2
) then local add
=[no]''[/no] if (string.find(text
,GetEOL
(),string.len(text
)-string.len(GetEOL
()))) then add
= GetEOL
() end text
= string.sub(text
,e
+1,b2
-1) editor:ReplaceSel
(text
..add
) editor:SetSel
(selbegin
, selbegin
+string.len(text
..add
)) else if (editor:LineFromPosition
(selend
)==editor:LineFromPosition
(selbegin
)) then editor:insert
(selend
, commentend
) editor:insert
(selbegin
, commentbegin
) editor:SetSel
(selbegin
, selend
+string.len(commentbegin
)+string.len(commentend
)) else local eolcount
= 0 if (prevIsEOL
(selend
)) then editor:insert
(selend
, commentend
..GetEOL
()) eolcount
= eolcount
+ 1 else editor:insert
(selend
, commentend
) end if (prevIsEOL
(selbegin
)) then editor:insert
(selbegin
, commentbegin
..GetEOL
()) eolcount
= eolcount
+ 1 else editor:insert
(selbegin
, commentbegin
) end editor:SetSel
(selbegin
, selend
+string.len(commentbegin
)+string.len(commentend
)+string.len(GetEOL
())*eolcount
) end end editor:EndUndoAction
() return true end local function BlockComment
() local selbegin
= editor.SelectionStart
editor:BeginUndoAction
() if (string.find(editor:textrange
(selbegin
-string.len(GetEOL
()), selbegin
),GetEOL
())) then scite.MenuCommand
([no]"IDM_BLOCK_COMMENT"[/no]) editor:SetSel
(selbegin
, editor.SelectionEnd
) else scite.MenuCommand
([no]"IDM_BLOCK_COMMENT"[/no]) editor:SetSel
(editor.SelectionStart
, editor.SelectionEnd
) end editor:EndUndoAction
() return true end local function BlockBraces
(bracebegin
, braceend
) local text
, lenght
= editor:GetSelText
() local selbegin
= editor.SelectionStart
local selend
= editor.SelectionEnd
local b
,e
= string.find(text
,makefind
(bracebegin
)) local b2
,e2
local add
=[no]''[/no] if IsEOLlast
(text
) then b2
,e2
= string.find(text
,makefind
(braceend
), string.len(text
)-string.len(braceend
..GetEOL
())) add
= GetEOL
() else b2
,e2
= string.find(text
,makefind
(braceend
), string.len(text
)-string.len(braceend
)) end editor:BeginUndoAction
() if (b
and b2
) then text
= string.sub(text
,e
+1,b2
-1) editor:ReplaceSel
(text
..add
) editor:SetSel
(selbegin
, selbegin
+string.len(text
..add
)) else editor:insert
(selend
- string.len(add
), braceend
) editor:insert
(selbegin
, bracebegin
) editor:SetSel
(selbegin
, selend
+string.len(bracebegin
..braceend
)) end editor:EndUndoAction
() return true end local function GetIndexFindCharInProps
(value
, findchar
) if findchar
then local resIndex
= string.find(props
[value
], makefind
(findchar
), 1) if (resIndex
~=nil) and (string.sub(props
[value
],resIndex
,resIndex
) == findchar
) then return resIndex
end end return nil end local function GetCharInProps
(value
, index
) return string.sub(props
[value
],index
,index
) end local function SmartComment
(char
) if (editor.SelectionStart
~=editor.SelectionEnd
) then [no]-- делаем проверку на блочный комментарий[/no] if GetIndexFindCharInProps
([no]'comment.block.'[/no]..editor.LexerLanguage
, char
) == 1 then return BlockComment
() end [no]-- делаем индивидуальную обработку по лексерам[/no] if (editor.LexerLanguage
== [no]'cpp'[/no]) then if (char
== [no]'*'[/no] ) then return StrimComment
([no]'/*'[/no], [no]'*/'[/no]) end end if (editor.LexerLanguage
== [no]'lua'[/no]) then if (char
== [no]'['[/no]) then return BlockBraces
([no]'[['[/no],[no]']]'[/no]) end end [no]-- делаем обработку по автозакрытию текста скобками[/no] if (props
[[no]'braces.autoclose'[/no]]==[no]'1'[/no]) then local brIdx
= GetIndexFindCharInProps
([no]'braces.open'[/no], char
) if (brIdx
~=nil) then local brClose
= GetCharInProps
([no]'braces.close'[/no], brIdx
) if (brClose
~=nil) then return BlockBraces
(char
, brClose
) end end end [no]-- автозакрытие скобок[/no] elseif (props
[[no]'braces.autoclose'[/no]]==[no]'1'[/no]) then [no]-- если следующий символ закрывающаяся скобка[/no] [no]-- и мы ее вводим, то ввод проглатываем[/no] local nextSimbol
= string.format([no]"%c"[/no],editor.CharAt
[editor.CurrentPos
]) local endBr
= GetIndexFindCharInProps
([no]'braces.close'[/no],nextSimbol
) if (endBr
~=nil) and (nextSimbol
==char
) then editor:CharRight
() return true end [no]-- если следующий символ конец строки[/no] [no]-- и мы ставим открывающуюся скобку[/no] [no]-- то сразу вставляем закрывающуюся скобку[/no] if (editor.CurrentPos
==editor.Length
) or nextIsEOL
(editor.CurrentPos
) then local brIdx
= GetIndexFindCharInProps
([no]'braces.open'[/no], char
) if (brIdx
~=nil) then editor:BeginUndoAction
() [no]-- по волшебному обрабатываем скобку { в cpp[/no] if (char
== [no]'{'[/no]) and (editor.LexerLanguage
== [no]'cpp'[/no]) then local ln
= GetCurrLineNumber
() if ln
>0 and GetLineIndentation
(ln
)>GetLineIndentation
(ln
-1) then if IsLineStartPos
(editor.CurrentPos
) and not IsInLineEnd
(ln
-1, [no]'{'[/no]) then editor:BackTab
() end end editor:AddText
([no]'{'[/no]) editor:NewLine
() if GetLineIndentation
(ln
)==GetLineIndentation
(ln
+1) then editor:Tab
() end local pos
= editor.CurrentPos
editor:NewLine
() if GetLineIndentation
(ln
+2)==GetLineIndentation
(ln
+1) then editor:BackTab
() end editor:AddText
([no]'}'[/no]) editor:GotoPos
(pos
) [no]-- по волшебному обрабатываем скобку } в cpp[/no] elseif (char
== [no]'}'[/no]) and (editor.LexerLanguage
== [no]'cpp'[/no]) then editor:BackTab
() editor:AddText
([no]'}'[/no]) [no]-- вставляем закрывающуюся скобку[/no] else local symE
= GetCharInProps
([no]'braces.close'[/no],brIdx
) if (symE
==nil) then symE
=[no]''[/no] end editor:InsertText
(editor.CurrentPos
, char
..symE
) editor:CharRight
() end editor:EndUndoAction
() return true end end end return false end [no]-- Add user event handler OnKey[/no] local old_OnKey
= OnKey
function OnKey
(key
, shift
, ctrl
, alt
, char
) if old_OnKey
and old_OnKey
(key
, shift
, ctrl
, alt
, char
) then return true end if editor.Focus
and char
~=[no]''[/no] and SmartComment
(char
) then return true end return false end