Scite Ext Man |
|
最新版本(2006-11-10)修复了 Linux 版本中的一个严重错误,并使用更强大的方案来确定输入的行是在编辑器中还是在输出窗格中。它还允许您使用“重新加载脚本”(Ctrl+Shift+R)重新加载由 extman 控制的 Lua 脚本。还包含一些额外的示例:* prompt.lua,它提供了一个简单的交互式 Lua 提示符。* select_string.lua,它允许您双击选择整个字符串(或注释)* select_block.lua,它允许您通过折叠线旁边的边距点击选择块。
您可以在 Files:wiki_insecure/editors/SciTE/extman.lua 找到 extman;示例和代码在 Files:wiki_insecure/editors/SciTE/extman.zip 中;它完全用 Lua 编写,适用于任何最近的 SciTE 版本。
SciTE Lua 接口非常强大,但目前没有办法让非平凡的脚本“和谐共处”。考虑 SciteBufferSwitch;处理程序 OnOpen
、OnSwitchFile
和 OnUserListSelection
都被覆盖以跟踪缓冲区更改并显示一个缓冲区下拉列表。这样的脚本会干扰任何需要监视这些事件的其他脚本。
使用 extman,此脚本看起来像这样(函数 buffer_switch
相同)
scite_OnOpen(buffer_switch) scite_OnSwitchFile(buffer_switch) scite_Command 'Switch Buffer|do_buffer_list|Ctrl+J' function do_buffer_list() scite_UserListShow(buffers,2,scite.Open) end
(extman 的最新版本还提供了 OnOpenSwitch
,它在文件被激活时调用,无论是通过打开还是通过切换缓冲区。请查看 switch_buffers.lua
示例)
在内部,extman 保持处理程序列表。例如,scite_OnOpen
将向 OnOpen
事件调用的处理程序列表中添加一个函数。现在,另一个脚本可以监听 OnOpen
事件,而不会造成冲突。类似地,有 scite_OnChar
、scite_OnSave
等 - 除了 OnUserListSelection
,它的处理方式不同。
除了标准的 SciTE Lua 事件之外,extman 还提供了 OnWord
、OnEditorLine
和 OnOutputLine
。它们建立在基本事件之上,为了方便而包含在内。
以下是为 extman 重写的“懒惰”词语替换示例。OnWord
处理程序接收一个表,该表具有字段 word
、startp
、endp
、ch
,它们分别是找到的词、它的初始位置、最终位置以及在词之后找到的字符。
function on_word(w) local subst = word_substitute(w.word) if subst ~= w.word then editor:SetSel(w.startp-1,w.endp-1) local was_whitespace = string.find(w.ch,'%s') if was_whitespace then subst = subst..w.ch end editor:ReplaceSel(subst) local word_end = editor.CurrentPos if not was_whitespace then editor:GotoPos(word_end + 1) end end end scite_OnWord(on_word)
OnOutputLine
仅在输出窗格中输入一行时触发。这是一个简单但有效的 SciTE Lua 控制台
local prompt = '> ' print 'Scite/Lua' trace(prompt) scite_OnOutputLine (function (line) local sub = string.sub if sub(line,1,2) == prompt then line = sub(line,3) end if sub(line,1,1) == '=' then line = 'print('..sub(line,2)..')' end local f,err = loadstring(line,'local') if not f then print(err) else local ok,res = pcall(f) if ok then if res then print('result= '..res) end else print(res) end end trace(prompt) return true end)
OnEditorLine
是一个类似的事件,只是它发生在用户在编辑器窗格中输入一行时。一个关键的区别是它永远不会干扰正常的字符处理。可以使用它来跟踪输入的任何声明等。以下示例相当奇怪,但展示了如何将快捷键后跟一个字母绑定到一个操作。
scite_Command 'AltX|do_altx_commands|Alt+X' function do_altx_commands() editor:BeginUndoAction() scite_OnChar('once',function (ch) editor:EndUndoAction() editor:Undo() if ch == 's' then print('ess') elseif ch == 'f' then editor:BeginUndoAction() scite_OnEditorLine(handle_line) end return true end) end
在您键入 Alt+X 后,此功能会安装一个只运行一次的 OnChar
处理程序。它只对 's' 或 'f' 感兴趣,但始终会“吃掉”下一个按下的字符。Emacs 用户可能会发现这种键组合相当自然,而且它们可能比 Alt+Ctrl+Shift 组合更容易键入。OnChar
不会看到特殊字符,因此您只能使用字母和标点符号。(我的手指仍然记得在 Borland 环境中使用 Ctrl+Q 后跟一个数字来移动到标记 - 请参阅 SciteNumberedBookmarks)。
Alt+X 后跟 'f' 的目的是允许用户在缓冲区中输入文件名!文件名会立即被 editor:Undo
删除,然后打开文件。
local function handle_line(line) editor:EndUndoAction() editor:Undo() scite_OnEditorLine(handle_line,'remove') scite.Open(line) end
extman 还提供了一些有用的实用程序函数。在某些情况下(例如文件访问),它们弥补了 Lua 库中缺少的功能。例如,如果 SciTE 包含 lfs(Lua 文件系统),那么即使实现发生变化,用户也可以继续使用 scite_Files
。
scite_UserListShow(list,start,fn)
是一种访问 Scintilla 用户列表的简化方法 - 它将构建一个正确分隔的字符串等。您可以为列表指定一个起始索引 - 在这里我使用它来避免显示当前缓冲区。
scite_GetProp(key,default)
是对 props
伪表的简单包装。如果属性 key
不存在,则 props[key]
将返回一个空字符串,而不是 nil;如果未指定 default
,则此函数确实会在属性不存在时返回 nil。
scite_Files(mask)
返回提供的路径+掩码中的所有文件(例如“d:/downloads/scite_lua/*.lua” - Windows 上也接受正斜杠)。如果找到 SciteOther 库,则它将使用静默的 Execute
,否则将使用 os.execute
。
scite_FileExists(f)
如果可以打开文件以供读取,则返回 true。
scite_dofile(f)
与 dofile
相似,不同之处在于它始终相对于 SciTE 的默认主目录加载文件,并且会静默失败。
scite_Command(cmds)
是一个非常有用的函数,用于将 Lua 函数与工具菜单项和快捷键关联。您可以向它传递一个字符串或一个字符串列表;该字符串的格式为 <name>|<function>|<shortcut>,其中 <shortcut> 是可选的。
将文件解压缩到您的 SciTE 目录中,请记住保留文件夹名称。Extman 应该是主要的 Lua 启动脚本(当然,您也可以将其放在其他地方)。
ext.lua.startup.script=$(SciteDefaultHome)/extman.lua
启动时,它将在scite_lua
目录中查找所有扩展名为.lua的文件,该目录默认位于默认主目录中。您可以使用ext.lua.directory
强制将其放在其他位置。
这些文件将被加载,因此您*不应该*将extman.lua放在该目录中!它们将有机会调用scite_Command
来注册其函数。它们可能需要提前加载其他脚本,因此添加了scite_require()
。如果一个文件已使用此函数显式加载,则extman将认为它已加载。
下面的代码片段允许 Lua 扩展可选地使用 extman 来处理OnChar
,使支持 extman 的脚本即使没有 extman 也可以正常工作。
它首先检查是否已存在处理程序。接下来,如果缺少 extman 函数,例如scite_OnChar
,则会创建一个非常简单的替换。当然,此 extman 测试并非万无一失。代码的其余部分可以像往常一样使用 extman 函数。简单的scite_OnChar
函数只能处理一个处理程序;任何更复杂的操作,您都可能需要强制用户安装 extman。
if OnChar and not scite_OnChar then error("Please use extman if you want to run more than one handler") elseif not scite_OnChar then local _OnChar scite_OnChar = function(f, remove) if remove then _OnChar = nil else _OnChar = f end end OnChar = function(c) if _OnChar then return _OnChar(c) end end end
Extman 很好,但我希望能够控制它生成 scite_temp1 文件的位置。我通常只创建它一次,并注释掉生成代码,然后将 extman 重定向到在 scite 可执行文件所在的目录中打开预先创建的文件。
我尝试使用 SciTE 1.74 运行 extman.zip 附带的 switch_headers.lua,遇到了一些问题。我不得不更改以下几行。从
for i,v in list do到
for i,v in pairs(list) do以及从
for i,ext in extensions do到
for i,ext in pairs (extensions) do
9a10 > if string.find(f,'[\\/]$') then return end 11a13 > if (f ~= "") then 20a23 > end 30c33,35 < scite_UserListShow(buffers,2,scite.Open) --- > if (table.getn(buffers) > 0) then > scite_UserListShow(buffers,1,scite.Open) > end
scite_Files
使用 *.lua
匹配了 test.lua
和 test.lua~
,并加载了这两个文件(后者覆盖了前者)。后者是 Emacs 保存的临时备份文件,我花了一些时间才确定为什么我对 test.lua
的编辑被加载了,但没有生效。在 Windows 上,我建议使用 dir *.*
来匹配目录中的所有文件,然后使用 FileGlob 中的 globtopattern
函数过滤列表。
顺便说一下,SciteDebug [1] 在 extman.lua 中有不同的 scite_Files
实现。它调用 scite_Popen
,根据可用性选择性地包装 spawner.popen
或 os.execute
。我不确定它的全部目的,但它确实避免了调用此函数时可能短暂出现的 DOS 命令窗口(至少在我尝试时是这样)。将两个版本的 extman.lua 合并可能很有用。--DavidManura
-- 针对上面关于 extman.lua 另一个版本的评论,如果我没记错的话,spawner.popen 使用共享库(Windows 上的 dll)。它被创建来处理 DOS 命令窗口打开和关闭以及 SciTE 程序在 Windows 中失去焦点的問題。它在运行时仍然有明显的视觉副作用,但比 os.execute 好,因为不会失去焦点。我个人更喜欢在 lua 目录中的脚本数量实际发生变化时生成一次 scite_temp1,并直接读取该文件。这样可以避免使用任何一种方法进行 shell 操作,并在每次打开 SciTE 时产生某种视觉干扰。
我刚刚在网上搜索了最新的 extman.lua 代码,才意识到现在有很多版本,其中一些版本有重大扩展。如果有人能创建一个新的维基页面,其中包含一个包含所有这些功能的最佳版本的版本,或者至少在这里添加一个链接到网络上某个地方的版本,该版本是最新的,并且最适合大多数 lua 脚本,那就太好了。--(Lua 用户)
我认为,应该手动包含文件,而不是从文件夹中包含所有文件。 这也消除了使用 spawner dll 或查看临时命令提示符的需要。 例如,您可以在 SciteReadTags 中看到我的 extman.lua 的迷你版本。 --ParsKorata
这是一个脚本,... 嗯,自动继续注释!
将其保存在 ../scite_lua/ 文件夹中,命名为 <filename>.lua,然后重启 SciTE。(它应该是平台无关的!)
--auto_continue_comments.lua --determine correct eol marker (later) from this lookup table local eol_tbl = {[0]="\r\n", [1]="\r", [2]="\n"} function auto_continue_comment(line) -- Multiline comment continue local multi = line:match("^(%s*)==%s*$") if multi then --line contains "==", start multiline comment local eol = eol_tbl[editor.EOLMode] editor:BeginUndoAction() editor:LineUp() editor:LineDelete() editor:AddText("--[=[" .. eol .. eol .. "--]=]" .. eol) editor:LineUp(); editor:LineUp() editor:AddText(multi) editor:EndUndoAction() -- block comment continue elseif line:find("^%s*%-%-%s*$") then --line is only '--', terminate comment editor:LineUp() editor:LineDelete() elseif line:find("^%s*%-%-") then --line is comment, auto continue it editor:AddText("-- ") end return false --allow other methods to respond to event end --register handler with extman scite_OnEditorLine(auto_continue_comment)
输入 '--' 后面跟着文本,按回车键,下一行就会自动插入 '--'! 如果您不想要它,只需再次按回车键,它就会消失! 输入 '==' 并按回车键创建多行注释,并将光标放在里面! 感谢 SirAlaran? 的灵感。 请参见下面的示例会话。 --PeterMacDonald
-- <- followed by text starts a block comment -- and it carries on until a line with only "--" -- A tab or spaces before "-- some text", will -- start an indented block comment, like this! --[=[ Entering "==" on a line, like this: == will start a multiline comment, like this one! --]=] --[=[ A tab or spaces before the "==" will start an indented multiline comment, like this! --]=]