在VS Code插件开发中调用编辑器的内置搜索功能,并且获取到它的搜索结果,这个需求很明确,也是插件开发中比较实用的场景。
实现思路
VS Code的API并没有直接提供"获取搜索结果"的现成方法,但我们可以通过两种方式实现:
- 调用VS Code的搜索命令并监听结果 (推荐):通过
vscode.commands.executeCommand调用内置搜索命令,结合vscode.window.onDidChangeActiveTextEditor或自定义面板来捕获结果。 - 手动实现搜索逻辑 :使用VS Code的
vscode.workspace.findFiles和文本匹配逻辑,完全自定义搜索过程,这种方式能完全掌控搜索结果。
下面提供完整的可运行插件代码示例(基于第二种方式,更稳定且可控):
完整插件代码
1. package.json(插件配置)
json
{
"name": "search-result-demo",
"displayName": "Search Result Demo",
"version": "0.0.1",
"engines": {
"vscode": "^1.80.0"
},
"categories": [
"Other"
],
"activationEvents": [
"onCommand:search-result-demo.searchFiles"
],
"main": "./extension.js",
"contributes": {
"commands": [
{
"command": "search-result-demo.searchFiles",
"title": "Search Files and Get Results"
}
]
}
}
2. extension.js(核心逻辑)
javascript
const vscode = require('vscode');
/**
* @param {vscode.ExtensionContext} context
*/
function activate(context) {
// 注册命令:触发搜索并获取结果
let disposable = vscode.commands.registerCommand('search-result-demo.searchFiles', async function () {
try {
// 1. 弹出输入框让用户输入搜索关键词
const searchText = await vscode.window.showInputBox({
prompt: '请输入要搜索的关键词',
placeHolder: '例如:console.log',
validateInput: (value) => {
return value.trim() ? null : '关键词不能为空';
}
});
if (!searchText) { return; } // 用户取消输入
// 2. 定义搜索范围(可自定义,这里是工作区所有文件)
const searchPattern = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], '**/*');
// 3. 第一步:查找符合条件的文件(先过滤文件,再匹配内容)
const files = await vscode.workspace.findFiles(
searchPattern,
'**/node_modules/**', // 排除node_modules
100 // 最多返回100个文件
);
if (files.length === 0) {
vscode.window.showInformationMessage('未找到任何文件');
return;
}
// 4. 第二步:读取文件内容并匹配关键词
const searchResults = [];
for (const file of files) {
try {
// 读取文件内容(UTF-8编码)
const document = await vscode.workspace.openTextDocument(file);
const text = document.getText();
// 匹配关键词(支持正则)
const regex = new RegExp(searchText, 'gi');
let match;
const lines = text.split('\n');
// 遍历所有匹配项,记录行号和内容
while ((match = regex.exec(text)) !== null) {
// 计算匹配位置所在的行号
const charIndex = match.index;
let lineNumber = 0;
let charCount = 0;
for (const line of lines) {
charCount += line.length + 1; // +1 是换行符
if (charCount > charIndex) {
break;
}
lineNumber++;
}
// 收集结果
searchResults.push({
filePath: file.fsPath,
lineNumber: lineNumber + 1, // VS Code行号从1开始
lineContent: lines[lineNumber]?.trim() || '',
matchText: match[0]
});
}
} catch (error) {
console.error(`读取文件失败: ${file.fsPath}`, error);
}
}
// 5. 处理并展示搜索结果
if (searchResults.length === 0) {
vscode.window.showInformationMessage(`未找到包含"${searchText}"的内容`);
return;
}
// 打印结果到控制台(你可以根据需求处理这些结果)
console.log('搜索结果:', JSON.stringify(searchResults, null, 2));
// 向用户展示结果数量
vscode.window.showInformationMessage(
`找到 ${searchResults.length} 个匹配项(详见开发者控制台)`
);
// 可选:在VS Code中展示结果列表
const items = searchResults.map(result => ({
label: `${result.filePath} (第${result.lineNumber}行)`,
description: result.matchText,
detail: result.lineContent,
data: result
}));
// 展示结果选择面板
const selected = await vscode.window.showQuickPick(items, {
matchOnDescription: true,
matchOnDetail: true,
placeHolder: `共${items.length}个匹配项,选择查看`
});
// 打开选中的文件并定位到对应行
if (selected) {
const uri = vscode.Uri.file(selected.data.filePath);
const document = await vscode.workspace.openTextDocument(uri);
await vscode.window.showTextDocument(document);
// 定位到匹配行
const position = new vscode.Position(selected.data.lineNumber - 1, 0);
vscode.window.activeTextEditor.selection = new vscode.Selection(position, position);
vscode.window.activeTextEditor.revealRange(
new vscode.Range(position, position),
vscode.TextEditorRevealType.InCenter
);
}
} catch (error) {
console.error('搜索失败:', error);
vscode.window.showErrorMessage(`搜索出错:${error.message}`);
}
});
context.subscriptions.push(disposable);
}
function deactivate() {}
module.exports = {
activate,
deactivate
};
代码关键部分解释
- 输入处理 :通过
vscode.window.showInputBox获取用户输入的搜索关键词,包含输入验证。 - 文件查找 :使用
vscode.workspace.findFiles查找工作区内的文件,支持排除指定目录(如node_modules)。 - 内容匹配 :
- 读取文件内容并按行分割
- 使用正则表达式匹配关键词
- 计算匹配位置对应的行号(VS Code行号从1开始)
- 结果处理 :
- 收集所有匹配结果(文件路径、行号、行内容、匹配文本)
- 打印到控制台供后续处理
- 展示交互式列表,支持点击跳转到对应位置
运行插件的前置条件
-
确保已安装Node.js(v14+)和VS Code
-
安装VS Code插件开发工具:
bashnpm install -g yo generator-code -
创建插件项目:
yo code→ 选择New Extension (JavaScript) -
替换生成的
package.json和extension.js为上面的代码 -
按F5启动扩展开发宿主窗口,在新窗口中按Ctrl+Shift+P,执行命令
Search Files and Get Results
总结
- 核心方法 :通过
vscode.workspace.findFiles查找文件,结合文件内容读取和正则匹配,实现可控的搜索并获取结果。 - 结果格式:搜索结果包含文件路径、行号、匹配行内容和匹配文本,可直接用于后续处理(如展示、过滤、导出等)。
- 扩展方向:你可以基于这个基础逻辑,添加正则搜索、大小写敏感、文件类型过滤等功能,或把结果展示在自定义Webview面板中。
这种方式相比直接调用内置搜索命令,优势在于完全掌控搜索过程和结果格式,更适合插件开发中的定制化需求。