一個 ScriptDocument 實例是 Studio 腳本編輯器的文檔代理。它不同於編輯器中打開的 LuaSourceContainer,因為它表示一個打開文檔的短暫狀態,其表示形式更適合閱讀和編輯代碼,而不是執行它。特別是,ScriptDocument 反映了在草稿模式下對打開腳本所做的任何更改,而源屬性則不會。
腳本編輯器本身存在於與任何 DataModel 不同的線程上,因此 ScriptDocument 複製了打開的腳本編輯器,但它不是打開的編輯器。由於複製的原因,編輯器中的文本更改到更新 ScriptDocument 之間有時會有輕微的延遲。這種延遲通常發生是因為 DataModel 正忙,且幾乎總是非常小,但它仍然存在。
ScriptDocument 的存在表明一份文檔在腳本編輯器中是打開的。所有 ScriptDocument 實例都有 ScriptEditorService 作為其父項。每個實例遵循以下編碼約定:
- ScriptDocument 中的所有文本都是 UTF-8 編碼的。
- 所有行索引是 1 索引的。
- 所有字符索引都是 1 索引的,並計算 UTF-8 字節,而不是字形,因此 TextBox.CursorPosition 的相同警告適用:許多 Unicode 字符佔用超過一個字節。
- 所有範圍均包含其起始位置,並不包括其結束位置,因此起始 == 結束意味著一個空範圍。
所有 ScriptDocument 的 API 都在 Plugin 層級安全性下。
概要
方法
請求與此文檔關聯的編輯器關閉。當編輯器對請求作出回應之前,當前線程將會休眠。
- EditTextAsync(newText : string,startLine : number,startCharacter : number,endLine : number,endCharacter : number):Tuple
用 newText 替換指定範圍 (startLine, startColumn) 到 (endLine, endColumn) 的文本。
- ForceSetSelectionAsync(cursorLine : number,cursorCharacter : number,anchorLine : number?,anchorCharacter : number?):Tuple
請求編輯器將其光標選擇設置為參數值。
返回指定行的文本。如果不提供參數,則返回當前光標位置的行。
返回文檔中的行數。
返回底層的 LuaSourceContainer 實例,如果存在,否則返回 nil。
獲取編輯器中選中的文本,如果沒有選中則返回空字符串。
返回腳本編輯器的最後已知選擇,格式為:CursorLine, CursorChar, AnchorLine, AnchorChar。如果腳本編輯器沒有選擇,則 CursorLine == AnchorLine 且 CursorChar == AnchorChar。
獲取光標位置和錨點中較大的值。如果編輯器沒有選擇,那麼它們是相同的值。
獲取光標位置和錨點中較小的值。如果編輯器沒有選擇,那麼它們是相同的值。
- GetText(startLine : number?,startCharacter : number?,endLine : number?,endCharacter : number?):string
返回來自打開編輯器的文本。
返回編輯器更改中當前顯示的行號。
返回編輯器是否有任何選中的文本。
如果 ScriptDocument 代表命令欄,則返回 true。
- RequestSetSelectionAsync(cursorLine : number,cursorCharacter : number,anchorLine : number?,anchorCharacter : number?):Tuple
請求編輯器將其光標選擇設置為參數值。
活動
- SelectionChanged(positionLine : number,positionCharacter : number,anchorLine : number,anchorCharacter : number):RBXScriptSignal
當 ScriptDocument 發生變化時觸發,包括在文本更改後立即。
當編輯器中的顯示行號改變時觸發。
屬性
方法
CloseAsync
請求與此文檔關聯的編輯器關閉。當編輯器對請求作出回應之前,當前線程將會休眠。如果函數成功,它返回 (true, nil)。如果函數失敗,它返回 (false, string) 作為問題的描述。
此函數無法關閉命令欄。
返回
範例程式碼
腳本文件:關閉異步
--!nocheck
-- 在命令列中執行以下程式碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local documents = ScriptEditorService:GetScriptDocuments()
local scriptDocument
-- 找到第一個打開的腳本文件
for _, document in documents do
-- 命令列不能關閉,因此不要選擇它
if not document:IsCommandBar() then
scriptDocument = document
break
end
end
if scriptDocument then
local success, err = scriptDocument:CloseAsync()
if success then
print(`已關閉 {scriptDocument.Name}`)
else
warn(`無法 關閉 {scriptDocument.Name} 原因:{err}`)
end
else
print("沒有打開的 腳本")
end
EditTextAsync
用 newText 替換指定範圍 (startLine, startColumn) 到 (endLine, endColumn) 的文本。如果範圍是空的,那麼函數會在 (startLine, startColumn) 插入文本。如果文本光標在指定範圍內,光標將移動到編輯的結束位置。否則,文本光標不會移動。此函數將當前線程休眠,直到收到來自編輯器的有關編輯的回覆。
如果函數成功,它返回 (true, nil)。
如果函數拋出錯誤,理由可能是:
- 範圍無效。
- 範圍將切割一個 unicode 字符,例如僅替換 unicode 字符的一些字節。
- newText 本身包含無效的 UTF-8。
如果函數失敗,它返回 (false, string)。該字符串是對問題的描述。最常見的失敗類型是版本不匹配。當你在 ScriptDocument 與編輯器內容不同步的時候調用 EditTextAsync 時會發生此情況。如果發生這種情況,你可以重試編輯。
參數
返回
ForceSetSelectionAsync
請求編輯器將其光標選擇設置為參數值。必須傳遞兩個錨點參數,否則都不傳遞。如果都不傳遞,則它們預設為與相應的光標參數相同。如果文檔的文本內容已更改,編輯器可能拒絕更新其光標。與 ScriptDocument:RequestSetSelectionAsync() 不同的是,如果自請求以來光標已移動,編輯器不會拒絕移動其光標。如果光標被更新,返回 (true, nil),如果沒有更新,則返回 (false, string) 並附帶解釋字符串。當前線程將會休眠,直到編輯器回覆。
參數
返回
範例程式碼
ScriptDocument:ForceSetSelectionAsync()
--!nocheck
-- 在腳本打開時在命令欄運行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
-- 獲取光標當前行的文本
local cursorLine = scriptDocument:GetSelection()
local lineText = scriptDocument:GetLine(cursorLine)
-- 強制選擇整行文本
local success, err = scriptDocument:ForceSetSelectionAsync(cursorLine, 1, cursorLine, #lineText + 1)
if success then
print("設置選擇!搞定")
else
print(`無法設置選擇,原因是: {err}`)
end
else
print("沒有打開的腳本")
end
GetLine
返回指定行的文本。如果不提供參數,則返回當前光標位置的行。
參數
返回
範例程式碼
ScriptDocument.SelectionChanged 和 ScriptDocument:GetLine()
--!nocheck
-- 在腳本打開的情況下,在命令欄中運行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
scriptDocument.SelectionChanged:Connect(function(positionLine, positionCharacter, anchorLine, anchorCharacter)
print(`選取: 行 {positionLine}, 字元 {positionCharacter}`)
print(`錨點: 行 {anchorLine}, 字元 {anchorCharacter}`)
local lineText = scriptDocument:GetLine(positionLine)
print(`選取的行文本: {lineText}`)
end)
else
print("沒有打開的腳本")
end
GetLineCount
返回活動文檔中的行數。
返回
範例程式碼
ScriptDocument:獲取行數()
--!nocheck
-- 在命令欄執行以下程式碼,當一個腳本 打開時
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
local lineCount = scriptDocument:GetLineCount()
print(`這個腳本有 {lineCount} 行!`)
else
print("沒有打開的腳本")
end
GetScript
返回底層的 LuaSourceContainer 實例,如果存在,否則返回 nil。
返回
範例程式碼
ScriptDocument:GetScript()
--!nocheck
-- 在 Command Bar 中運行以下代碼,前提是有一個腳本 是打開的
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
local openScript = scriptDocument:GetScript()
print(`當前打開的腳本: {openScript:GetFullName()}`)
else
print("沒有打開的腳本")
end
GetSelectedText
獲取編輯器中選中的文本,如果沒有選中則返回空字符串。
返回
範例程式碼
腳本文件:HasSelectedText() 和 :GetSelectedText()
--!nocheck
-- 當一個腳本打開時,請在命令欄中運行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
scriptDocument.SelectionChanged:Connect(function()
if scriptDocument:HasSelectedText() then
local selectedText = scriptDocument:GetSelectedText()
print(`目前選中的文本: {selectedText}`)
else
print("當前沒有選中文本")
end
end)
else
print("沒有打開的腳本")
end
GetSelection
返回腳本編輯器的最後已知選擇,格式為:CursorLine, CursorChar, AnchorLine, AnchorChar。如果腳本編輯器沒有選擇,則 CursorLine == AnchorLine 且 CursorChar == AnchorChar。
返回
CursorLine, CursorChar, AnchorLine, AnchorChar。
GetSelectionEnd
獲取光標位置和錨點中較大的值。如果編輯器沒有選擇,那麼它們是相同的值。
返回
範例程式碼
ScriptDocument:GetSelectionStart() 和 :GetSelectionEnd()
--!nocheck
-- 在有開啟腳本的情況下,在命令欄運行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
local startLine, startCharacter = scriptDocument:GetSelectionStart()
local endLine, endCharacter = scriptDocument:GetSelectionEnd()
print(`選擇開始: 行 {startLine}, 字元 {startCharacter}`)
print(`選擇結束: 行 {endLine}, 字元 {endCharacter}`)
else
print("沒有開啟任何腳本")
end
GetSelectionStart
獲取光標位置和錨點中較小的值。如果編輯器沒有選擇,那麼它們是相同的值。
返回
範例程式碼
ScriptDocument:GetSelectionStart() 和 :GetSelectionEnd()
--!nocheck
-- 在有開啟腳本的情況下,在命令欄運行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
local startLine, startCharacter = scriptDocument:GetSelectionStart()
local endLine, endCharacter = scriptDocument:GetSelectionEnd()
print(`選擇開始: 行 {startLine}, 字元 {startCharacter}`)
print(`選擇結束: 行 {endLine}, 字元 {endCharacter}`)
else
print("沒有開啟任何腳本")
end
GetText
返回來自打開編輯器的文本。必須以 0、2 或 4 個參數調用:
- 如果以 0 個參數調用,獲取打開編輯器的所有內容。
- 如果以 2 個參數調用,獲取從 (startLine, startColumn) 開始的文檔文本。
- 如果以 4 個參數調用,獲取從 (startLine, startColumn) 開始,並在 (endLine, endColumn) 結束的文檔文本。
參數
返回
範例程式碼
腳本文件:獲取文本()
--!nocheck
-- 在腳本打開時,於命令欄中運行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
local text = scriptDocument:GetText()
print(`腳本內容: {text}`)
else
print("沒有打開的腳本")
end
GetViewport
返回編輯器更改中當前顯示的行號。編輯器顯示 startLine 和 endLine 之間的行,包含這兩行。第一行和最後一行可能僅部分顯示。例如,最後一行的最上方像素可能在屏幕上。此外,代碼折疊可能會隱藏 startLine 和 endLine 之間的行。
返回
範例程式碼
腳本文件:獲取視口
--!nocheck
-- 在命令列中運行以下代碼,當腳本 開啟時
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
local firstLine, lastLine = scriptDocument:GetViewport()
print(`目前查看的行是 {firstLine} 到 {lastLine}`)
else
print("沒有開啟的腳本")
end
HasSelectedText
返回編輯器是否有任何選中的文本。
返回
範例程式碼
腳本文件:HasSelectedText() 和 :GetSelectedText()
--!nocheck
-- 當一個腳本打開時,請在命令欄中運行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
scriptDocument.SelectionChanged:Connect(function()
if scriptDocument:HasSelectedText() then
local selectedText = scriptDocument:GetSelectedText()
print(`目前選中的文本: {selectedText}`)
else
print("當前沒有選中文本")
end
end)
else
print("沒有打開的腳本")
end
IsCommandBar
如果 ScriptDocument 代表命令欄,則返回 true。命令欄在此 API 中有特殊規則和限制:
- Studio 在運行插件之前創建命令欄,因此它不會總是觸發開啟事件,儘管在 Studio 在不同 DataModels 之間轉換時會關閉和重新打開。
- 出於安全原因,您無法使用 EditTextAsync 編輯命令欄。
返回
範例程式碼
ScriptDocument:是命令列嗎()
--!nocheck
-- 在命令列中運行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if document:IsCommandBar() then
print("命令列文檔:", document)
end
end
RequestSetSelectionAsync
請求編輯器將其光標選擇設置為參數值。必須傳遞兩個錨點參數,否則都不傳遞。如果都不傳遞,那麼它們預設為與相應的光標參數相同。如果文檔的文本內容已更改,或者光標在請求提出後已移動,編輯器可能拒絕更新其光標。如果光標被更新,返回 (true, nil),如果沒有更新,則返回 (false, string) 並附帶解釋字符串。當前線程將會休眠,直到編輯器回覆。
參數
返回
範例程式碼
腳本文件:RequestSetSelectionAsync()
--!nocheck
-- 在有開啟的腳本時,在命令欄執行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
-- 獲取光標當前行的文本
local cursorLine = scriptDocument:GetSelection()
local lineText = scriptDocument:GetLine(cursorLine)
-- 強制選擇整行文本
local success, err = scriptDocument:RequestSetSelectionAsync(cursorLine, 1, cursorLine, #lineText + 1)
if success then
print("選擇已設置!")
else
print(`設置選擇失敗,原因:{err}`)
end
else
print("沒有開啟的腳本")
end
活動
SelectionChanged
當 ScriptDocument 發生變化時觸發,包括在文本更改後立即。
參數
範例程式碼
ScriptDocument.SelectionChanged 和 ScriptDocument:GetLine()
--!nocheck
-- 在腳本打開的情況下,在命令欄中運行以下代碼
local ScriptEditorService = game:GetService("ScriptEditorService")
local function getFirstOpenDocument()
local documents = ScriptEditorService:GetScriptDocuments()
for _, document in documents do
if not document:IsCommandBar() then
return document
end
end
return nil
end
local scriptDocument = getFirstOpenDocument()
if scriptDocument then
scriptDocument.SelectionChanged:Connect(function(positionLine, positionCharacter, anchorLine, anchorCharacter)
print(`選取: 行 {positionLine}, 字元 {positionCharacter}`)
print(`錨點: 行 {anchorLine}, 字元 {anchorCharacter}`)
local lineText = scriptDocument:GetLine(positionLine)
print(`選取的行文本: {lineText}`)
end)
else
print("沒有打開的腳本")
end
ViewportChanged
當編輯器中的顯示行號改變時觸發。詳情請參見 ScriptDocument.GetViewport。
參數
範例程式碼
演示使用 ScriptDocument.ViewportChanged 在視口變化時打印腳本的開始和結束行。
要運行:
確保輸出視圖已開啟
在命令欄中運行以下代碼
在打開的腳本窗口中上下滾動
--!nocheck
--[[
要運行:
1. 確保輸出視圖已開啟
2. 在命令欄中運行以下代碼
3. 在打開的腳本窗口中上下滾動
來自 ViewportChanged 事件的打印語句將出現在輸出中
]]
local Workspace = game:GetService("Workspace")
local ScriptEditorService = game:GetService("ScriptEditorService")
-- 創建跨越多行的文本
local dummyText = string.rep("-- 假文本\n", 60)
-- 創建一個包含假文本的腳本並打開它
local otherScript = Instance.new("Script")
otherScript.Source = dummyText
otherScript.Parent = Workspace
local success, err = ScriptEditorService:OpenScriptDocumentAsync(otherScript)
if not success then
warn(`無法打開腳本,因為: {err}`)
return
end
-- 獲取對打開的腳本的引用
local scriptDocument = ScriptEditorService:FindScriptDocument(otherScript)
local function onViewportChanged(startLine: number, endLine: number)
print(`腳本視口已變更 - 開始行: {startLine}, 結束行: {endLine}`)
end
-- 連接視口變更事件到上面的函數,該函數打印更新後視口的開始和結束行
scriptDocument.ViewportChanged:Connect(onViewportChanged)