如何通过语言服务器扩展在工作区中创建和编辑新文件 [英] How to create and edit a new file in the workspace via Language Server Extension
问题描述
如何获取语言服务器扩展以触发新文件的创建、编辑并将其显示在附加客户端的工作区中?
How do I get a Language Server Extension to trigger the creation of a new file , edit it, and display it in the attached client's workspace?
我在 node.js 中有一个用 vscode-languageserver 编写的 LSP 扩展,它通过 onExecuteCommand 在服务器上执行命令.我希望这个服务器端命令触发客户端创建一个新的文本文件,用一些文本填充它,这样它就会出现在客户端的打开文件的工作区列表中.
I have a LSP extension written with vscode-languageserver in node.js that executes a Command on the server via onExecuteCommand. I want this server-side command to trigger the client to create a new text file, populate it with some text, so it appears on the client's workspace list of open files.
看https://github.com/microsoft/vscode-languageserver-node/blob/master/client-tests/src/helpers.test.ts 我相信我需要做的是创建一个 WorkspaceChange 对象,运行 createFile(),应用一些更改 (.insert),然后告诉客户端通过 connection.workspace.applyEdit() 应用编辑,但这不起作用 - 没有创建文件,也没有在调试器中抛出错误.
Looking at https://github.com/microsoft/vscode-languageserver-node/blob/master/client-tests/src/helpers.test.ts I believe what I need to do is create a WorkspaceChange object, run createFile(), apply some changes (.insert) then tell the client to apply the edits via connection.workspace.applyEdit() but this does not work - no file is created and no errors are thrown in debugger.
这是我在服务器的 onExecuteCommand 中的代码:
Here is my code inside my server's 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>
如果我提供了一个不存在的文件名,则该过程将失败 - 没有在工作区中创建或打开文件.
If I supply a non-existent file name, then the process fails - no file is created or opened in the workspace.
但是,如果我提供现有文件名,则会应用编辑并按预期在工作区中打开文件.
However if I supply an existing filename, the edits are applied and the file is opened in the workspace as expected.
我认为这是因为我在 createFile 之前提供了一个编辑,但是如果我在 createFile() 之前运行 getTextEditChange() 则该过程失败并出现错误 "没有为文档更改配置工作区编辑
I thought it was because I was supplying an edit prior to a createFile, but if I run getTextEditChange() before createFile() then the process fails with error "Workspace edit is not configured for document changes"
推荐答案
谢谢你的支持,是的,我稍后就搞定了
Thanks for the kick, yes I got this working some time later
它在这里实现:https://github.com/proclaimforum/vscode-proclaimscript-language/blob/master/server/src/server.ts
第 476 行以后值得注意,其中:
Lines 476 onwards are of note, where:
- 构造一个 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链接以获得完整实现,包括设置客户端连接等,设置功能等.
I copy the relevant code section below for reference, but have a look at the github link for full implementation, including setting up the client connection etc, setting capabilities etc.
//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);
这篇关于如何通过语言服务器扩展在工作区中创建和编辑新文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!