VSCode擴展

原網站地址:http://www.qingpingshan.com/m/view.php?aid=364895

首先來看怎麼獲取文本。在 Hello World 範例 這篇文章中,我們能簡單瞭解到以下幾種對象:

Window 對象 - 表示當前 VS Code 的整個窗口,用 vscode.window 得到這個 Window 對象。
TextEditor 對象 - VS Code 的整個窗口中可能打開了多個 tab,每一個 tab 就是一個 TextEditor 對象,但我們只需要那個當前激活的 tab,我們用 window.activeTextEditor 屬性來取得當前工作中的 tab,即 TextEditor 對象。
TextDocument 對象 - 每個 TextEditor 中都有一個文檔,這個文檔就是 TextDocument 對象,我們用 editor.document 屬性來取得 TextEditor 對象中的 TextDocument 對象。TextDocument 對象有一個 getText() 方法來取得其中的所有文本。
最終,我們通過

const originText = vscode.window.activeTextEditor.document.getText()
取得當前正在編輯的文檔的所有文本。

既然拿到了原始文本,處理就很好辦了 (此處忽略了通過 npm 安裝 pangu 的過程):

const refinedText = pangu.spacing(originText)

TextEdit 對象 (注意,不是 TextEditor)。一個 TextEdit 對象就表示對文本的一次操作。

對文本的操作無外乎三種:增加,刪除,替換,但其實歸結起來,增加和刪除,也算是替換操作。增加,用新的字符串,替換空字符串;刪除,用空字符串替換原來的字符串。

對於要換替換的對象,既原來的字符串,我們要知道它在文檔中所處的位置,這個位置包括起始位置和結束位置,每個位置都應該包括它所在的行號和所在行內的編號,這兩個位置組成了一個區間。

VS Code 用 Position 對象來表徵文檔內一個字符所在的位置,它有兩個屬性:

line - 行號
character - 所在行內的編號
一個起始 Position 和一個結尾 Position,兩個 Position 組成了 Range 對象,這個 Range 對象就代表了一串連續的字符。

這樣,我們有了要替換的對象,又有新的字符串,我們就可以定義出一個 TextEdit 對象來表示這樣一次替換操作。

const aTextReplace = new vscode.TextEdit(range, newText)
比如,我們要把第 2 行第 3 個字符,到第 5 行第 6 個字符,刪除掉,即用空字符串替換它,代碼如下:

const start = new vscode.Position(2, 3)
const end = new vscode.Position(5, 6)
const range = new vscode.Range(start, end)
const aTextDel = new vscode.TextEdit(range, ‘’)
上面前三行代碼可以簡化成

const range = new vscode.Range(2, 3, 5, 6)
第四行代碼 TextEdit 對象可以用 TextEdit.delete(range) 靜態方法生成:

const aTextDel = vscode.TextEdit.delete(range)
Range 和 TextEdit,我認爲是操作文本的核心概念,理解它這兩個對象,其它的也就沒什麼難的了。

但是,到目前爲止,TextEdit 還只是定義了一個將被應用的操作,但還沒有真正地被應用到文本上,那怎麼來把這個操作真正執行呢。

這裏又涉及到一個新的對象 - WorkspaceEdit 對象。WorkspaceEdit 可以理解成 TextEdit 的容器。TextEdit 只是對文本的一次操作,如果我們需要對這個文本同時進行多次操作,比如全局替換,我們就要定義多個 TextEdit 對象,並把這些對象放到一個數組裏,再把這個數組放到 WorkspaceEdit 對象中。

更強大的在於,WorkspaceEdit 支持對多個文檔同時進行多次操作,因此,每個 TextEdit 數組必然需要對應一個文檔對象,WorkspaceEdit 使用 uri 來表徵一個文檔,uri 可以從 document.uri 屬性獲得。

我們前面得到了 document 對象,我們又定義了一些 TextEdit 對象,我們把它放到 WorkspaceEdit 對象中:

let textEdits = []
textEdits.push(aTextDel)
// push more TextEdit
// textEdits.push(…)

let workspaceEdit = new vscode.WorkspaceEdit()
workspaceEdit.set(document.uri, textEdits)
最後,我們終於可以真正地執行這些操作了,使用 vscode.workspace.applyEdit() 方法來使這些操作生效:

vscode.workspace.applyEdit(workspaceEdit)

來看看我們這個插件是如何實現的:

const editor = vscode.window.activeTextEditor
if (!editor) {
return // No open text editor
}

const document = editor.document
const lineCount = document.lineCount

let textEdits = []
for (let i=0; i<lineCount; i++) {
const textLine = document.lineAt(i)
const oriTrimText = textLine.text.trimRight()

if (oriTrimText.length === 0) {
    textEdits.push(new vscode.TextEdit(textLine.range, ''))
} else {
    const panguText = pangu.spacing(oriTrimText)
    textEdits.push(new vscode.TextEdit(textLine.range, panguText))
}

}
let workspaceEdit = new vscode.WorkspaceEdit()
workspaceEdit.set(document.uri, textEdits)
vscode.workspace.applyEdit(workspaceEdit)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章