typescript - 如何通过语言服务器扩展在工作区中创建和编辑新文件
问题描述
如何获得语言服务器扩展来触发新文件的创建、编辑并在附加客户端的工作区中显示它?
我在 node.js 中有一个用 vscode-languageserver 编写的 LSP 扩展,它通过 onExecuteCommand在服务器上执行命令。我希望这个服务器端命令触发客户端创建一个新的文本文件,用一些文本填充它,所以它出现在客户端的打开文件的工作区列表中。
查看https://github.com/microsoft/vscode-languageserver-node/blob/master/client-tests/src/helpers.test.ts我相信我需要做的是创建一个 WorkspaceChange 对象,运行 createFile() ,应用一些更改(.insert),然后告诉客户端通过 connection.workspace.applyEdit() 应用编辑,但这不起作用 - 没有创建文件,也没有在调试器中引发错误。
这是我在服务器的 onExecuteCommand 中的代码:
//add some text
const textToAdd: string = "test string";
//create new WorkspaceChange obj
let workspaceChange = new WorkspaceChange();
//uri of the file we want to create
let newuri = 'file:///c:/temp/create.txt';
//make a TextEditChange obj. Fails if you do not supply version
let change = workspaceChange.getTextEditChange({ uri: newuri, version: 10 });
// give it some text
change.insert(Position.create(0, 1), textToAdd);
// add a createFile documentChange to the workspaceChange
workspaceChange.createFile(newuri);
// pass these edits to the client to apply:
let reply = connection.workspace.applyEdit(workspaceChange.edit);
console.log(reply); //always <Pending>
如果我提供了一个不存在的文件名,那么该过程将失败 - 没有在工作区中创建或打开任何文件。
但是,如果我提供现有文件名,则会应用编辑并按预期在工作区中打开文件。
我认为这是因为我在 createFile 之前提供了编辑,但是如果我在createFile( )之前运行getTextEditChange() ,则该过程将失败并出现错误“工作区编辑未配置为文档更改”
解决方案
谢谢你的踢,是的,我过了一段时间才开始工作
它在这里实现: https ://github.com/proclaimforum/vscode-proclaimscript-language/blob/master/server/src/server.ts
第 476 行以后值得注意,其中:
- 构造一个 CreateFile 变量,保存要创建的文件的路径 (uri),并形成一个 CreateFiles 数组(第 476-482 行)
- 创建一个 WorkspaceEdit 变量,为 documentChanges 属性指定我们上面的 CreateFile 数组(485)
- 我们通过workspace.applyEdit(488)将它传递给客户端以应用。这实际上创建了文件。
- 要添加到新文档的文本首先形成一个 TextEdit 对象数组,由范围 (range:) 和内容 (newText:) 组成 (491-498)
- 构造了一个 TextDocumentEdit 数组,其中包含我们的 TextEdit (500-503)
- 我们更新我们的 workspaceEdit 变量属性以引用这个 TextDocumentEdits 数组(506)
- 最后要求我们连接的客户端应用编辑(510)
我复制下面的相关代码部分以供参考,但请查看 github 链接以获得完整的实现,包括设置客户端连接等,设置功能等。
//uri of new file
let currentPath :string = (thisdoc.uri).substr(0,thisdoc.uri.lastIndexOf('/'));
let newuri = currentPath+'/syntaxcheck.txt';
//construct a CreateFile variable
let createFile: CreateFile = { kind: 'create', uri: newuri };
//and make into array
let createFiles: CreateFile[] = [];
createFiles.push(createFile);
//make a new workspaceEdit variable, specifying a createFile document change
var workspaceEdit: WorkspaceEdit = { documentChanges: createFiles };
//pass to client to apply this edit
await connection.workspace.applyEdit(workspaceEdit);
//To insert the text (and pop up the window), create array of TextEdit
let textEdit: TextEdit[] = [];
//let document = documents.get(newuri);
let documentRange: Range = Range.create(0, 0, Number.MAX_VALUE, Number.MAX_VALUE);
//populate with the text, and where to insert (surely this is what workspaceChange.insert is for?)
let textEdits: TextEdit = { range: documentRange, newText: syntaxmessage };
textEdit.push(textEdits);
//make a new array of textDocumentEdits, containing our TextEdit (range and text)
let textDocumentEdit = TextDocumentEdit.create({ uri: newuri, version: 1 }, textEdit);
let textDocumentEdits: TextDocumentEdit[] = [];
textDocumentEdits.push(textDocumentEdit);
//set our workspaceEdit variable to this new TextDocumentEdit
workspaceEdit = { documentChanges: textDocumentEdits };
//and finally apply this to our workspace.
// we can probably do this some more elegant way
connection.workspace.applyEdit(workspaceEdit);
推荐阅读
- python - Pyside QTablewidget qcheckbox 点击事件
- javascript - 如何将 Jquery 函数重写为 Angular 4?
- android - 如何将动态创建的 EditText 和 Spinner 放在一个 LinearLayout 中?
- php - PHP & MYSQL:为什么 mysql 不能读取 !empty?
- sql - 带有双引号字符串条件的 SQL Select 语句
- amazon-web-services - 主账户内的 Amazon S3 存储桶未在成员账户中列出
- c# - 不同控制器的不同WebAPiConfig
- php - 收到警告: implode(): 在收到 var 值后
- typescript - Ionic 3 - 在警报控制器中设置 id 值
- sorting - 在vuejs中对两个方向进行排序