Scite Ext Man

lua-users home
wiki

讓腳本可順利一起執行

此最新版本 (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;處理常式 OnOpenOnSwitchFileOnUserListSelection 都已覆寫以追蹤緩衝區變更並顯示緩衝區下拉清單。這類腳本會妨礙任何其他有需要監控這些事件的腳本。

使用 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_OnCharscite_OnSave 等,不過 OnUserListSelection 則不同,處理方式不一樣。

延伸事件

除了標準 SciTE Lua 事件之外,extman 還提供了 OnWordOnEditorLineOnOutputLine。它們建構在基本事件之上,並為了方便起見而納入其中。

以下是以 extman 重新編寫的「懶惰字」替換範例。OnWord 處理常式會接收到一張表格,其中有欄位 wordstartpendpch,它們分別為找到的字、它的起始位置、結束位置以及在字之後立即找到的字元。

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 File System),那麼使用者即使實作已變更,仍可持續使用 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 會將其視為已載入。

啟用腳本選擇性使用 extman

下列程式碼片段允許 Lua 延伸模組選擇性地針對 OnChar 使用 extman,讓能支援 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

--SteveDonovan

使用者意見

Extman 很棒,不過如果我能控制它產生 scite_temp1 檔案的位置會更好。我通常會建立一次檔案,並且註解掉產生程式碼,然後重新導向 extman 到已建立的檔案,在 scite 可執行檔案所在的目錄中開啟該檔案。

曾經嘗試使用 extman.zip 附帶的 switch_headers.lua,並且使用 SciTE 1.74,不過執行時遇到了一些問題。必須變更下列程式碼。從

   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


這裡有一個補丁程式(使用 diff 建立),可用於 switch_buffers.lua,以清除未命名標籤(緩衝清單中的空白行)
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


我遇到了一個 Windows 問題,其中 scite_Filestest.luatest.lua~ 都比對 *.lua,並載入兩者(後者覆寫前者)。後者是 Emacs 保存的臨時備份檔案,並且花了點時間找出為什麼我編輯的 test.lua 雖然被載入,但是卻沒有任何效果。在 Windows 中,我建議使用 dir *.* 來比對目錄中的所有檔案,然後使用 FileGlob 中的 globtopattern 函式來篩選清單。

順便一提,SciteDebug [1] 在 extman.lua 中對 scite_Files 有不同的實作。它會呼叫 scite_Popen,視可用性選擇性包覆 spawner.popenos.execute。我不確定這樣做的確切目的,但確實可以避免呼叫此函數時可能會暫時彈出的 DOS 命令視窗 (至少我在嘗試時如此)。將兩個版本的 extman.lua 合併可能很有用。--DavidManura

-- 回覆於另一版本 extman.lua 的上述評論,如果我沒記錯,spawner.popen 會使用共用程式庫 (在 Windows 上是 dll)。它的創建目的是為了處理 DOS 命令視窗開啟和關閉以及 SciTE 程式因此在 Windows 中失去焦點的問題。執行時仍然會有明顯的視覺副作用,但因為不會失去焦點,所以比 os.execute 好。我個人的偏好是在 lua 目錄中的腳本數量實際改變時生成 scite_temp1 一次,然後直接讀取檔案。這樣就可避免使用任何方法進行 shell 外傳,以及在每次開啟 SciTE 時產生視覺上的中斷。

剛在網路上搜尋 extman.lua 程式碼的最新版本,沒想到現在已經有相當多版本,其中一些具有重大擴充功能。如果有人能彙整一個新 wiki 頁面,其中有一個版本包含所有這些功能的精華,或至少可以在這裡新增一個連結到網路上某個網站上的版本,該版本是最新的,並且能與大部分 lua 腳本最佳相容,那就太好了。 --(Lua User)

依我之見,應該手動包含檔案,而不是包含來自資料夾中的所有檔案。這也可以消除使用 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)

輸入 '--' 接著文字,按下 Enter 鍵,然後 '--' 已經插入在下一行了!如果不想要,只要再按一次 Enter 鍵即可刪除!輸入 '==' 並按 Enter 鍵,即可建立多行註解,然後將游標置於其中!感謝 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!
--]=]


(使用者意見)
最新變更 · 偏好設定
編輯 · 歷史記錄
最後編輯日期 2012 年 11 月 15 日 上午 7:37 GMT (diff)