我想在浏览器中突出显示 Python 语法错误。
我发现有Python 的 LSP 实现和Monaco 编辑器的 LSP 客户端。
有没有办法将它们连接在一起?
有一种方法可以将它们连接在一起!
这都是关于语言服务器协议的。
您需要的第一件事是一个正在运行的服务器,它将提供特定于语言的逻辑(例如自动完成、验证等)。
如您的问题中所述,您可以使用palantir 的 python-language-server。
您还可以在langserver.org上按语言找到现有语言服务器实现的列表。
在 LSP 中,客户端和服务器旨在通过JSON-RPC websocket 进行通信。
您可以使用此 Python 脚本在您的设备上启动 Python 语言服务器:
python langserver_ext.py
这将在ws://localhost:3000/python
.
Monaco 最初是 VSCode 的一部分。因此,大多数现有的摩纳哥 LSP 客户端部分最初都是为 VSCode 设计的,因此您需要使用一些 nodejs 和 npm。
有很多模块可以连接 monaco 和 LSP 客户端,有些带有 vscode,有些则没有 - 解决这个问题变得非常耗时。
这是我使用并最终开始工作的模块列表:
现在,整洁的部分:节点模块是服务器端的javascript。这意味着,您不能直接在浏览器中使用它们(请参阅无法在客户端(浏览器)上使用 RequireJS 来访问来自 node_modules 的文件。)。
您需要使用构建工具,例如browserify来转换您的节点模块以供浏览器使用:
.../node_modules/@codingame/monaco-languageclient/lib$ browserify monaco-language-client.js monaco-services.js connection.js ../../monaco-jsonrpc/lib/connection.js -r ./vscode-compatibility.js:vscode > monaco-jsonrpc-languageclient.js
这将创建一个名为 的文件monaco-jsonrpc-languageclient.js
,我们将把它用作 monaco-languageclient 和 monaco-jsonrpc 的包。
笔记:
-r ./vscode-compatibility.js:vscode
告诉browserify 为模块的每个依赖项使用该文件(请参阅包装vscode-compatibility.js
monaco -languageclient 时未解决的对 'vscode' 的依赖项)。vscode
现在您有了一个与浏览器兼容的 javascript 文件,您需要使所需的组件可见(即,将它们导出为window
属性)。
在monaco-jsonrpc-languageclient.js
中,搜索导出 MonacoLanguageClient、createConnection、MonacoServices、listen、ErrorAction 和 CloseAction 的地方。在那里,添加一行以将它们导出:
(...)
exports.MonacoLanguageClient = MonacoLanguageClient;
window.MonacoLanguageClient = MonacoLanguageClient; // Add this line
(...)
exports.createConnection = createConnection;
window.createConnection = createConnection; // Add this line
(...)
(MonacoServices = exports.MonacoServices || (exports.MonacoServices = {}));
window.MonacoServices = MonacoServices; // Add this line
(...)
etc.
对 normalize-url 执行相同的操作:
.../node_modules/normalize-url/lib$ browserify index.js > normalizeurl.js
在normalizeurl.js
中,搜索导出 normalizeUrl 的地方。在那里(或者,默认情况下,在文件末尾),添加一行以全局导出它:
window.normalizeUrl = normalizeUrl;
你可以对reconnecting-websocket做同样的操作,或者使用模块自带的amd版本。
在您的页面上包含monaco-jsonrpc-languageclient.js
,normalizeurl.js
和 browserified 或 AMD reconnecting-websocket 模块。
为了加快加载速度,您还可以使用缩小工具(如uglify-js)缩小它们。
最后,我们可以创建并连接客户端:
// From https://github.com/TypeFox/monaco-languageclient/blob/master/example/src/client.ts
/* --------------------------------------------------------------------------------------------
* Copyright (c) 2018 TypeFox GmbH (http://www.typefox.io). All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
MonacoServices.install(monaco); // This is what links everything with your monaco editors.
var url = 'ws://localhost:3000/python';
// Create the web socket.
var webSocket = new ReconnectingWebSocket(normalizeUrl(url), [], {
maxReconnectionDelay: 10000,
minReconnectionDelay: 1000,
reconnectionDelayGrowFactor: 1.3,
connectionTimeout: 10000,
maxRetries: Infinity,
debug: false
});
// Listen when the web socket is opened.
listen({
webSocket,
onConnection: function(connection) {
// create and start the language client
var languageClient = new MonacoLanguageClient({
name: 'Python Language Client',
clientOptions: {
// use a language id as a document selector
documentSelector: ['python'],
// disable the default error handler
errorHandler: {
error: () => ErrorAction.Continue,
closed: () => CloseAction.DoNotRestart
}
},
// create a language client connection from the JSON RPC connection on demand
connectionProvider: {
get: (errorHandler, closeHandler) => {
return Promise.resolve(createConnection(connection, errorHandler, closeHandler));
}
}
});
var disposable = languageClient.start();
connection.onClose(() => disposable.dispose());
}
});