New (incomplete) LSP client plugin
-
First of all, many thanks for the testing and the detailed experience report.
But I would hope the auto-created config would not have syntax errors. :-)
The error comes from the TOML linter. From the plugin’s point of view, an initial configuration is not usable because it does not contain an lspserver configuration. I am currently not sure if I can simply overwrite the error message, but a check for this specific text and then a more meaningful message should always be possible.
Why did you pick a config language that Notepad++ doesn’t recognize out-of-the-box?
I wanted to have a configuration file format that could use comments and that was already supported by V at the time, hence my choice of toml. I am currently using a very experimental toml lexer, but previously I used the udl lexer.
… at least when the source is saved
That should already work, symbols are queried every time you save a document.
Can you give a simple test case?“Goto declaration/implementation/definition” doesn’t seem to do anything for me
It could be that this is not supported by the server or you have discovered a bug.
Right now I’m just returning from the function, maybe I should log something in the console window to alert the user that the current operation is not supported by the server.Is there something specific at >= v8.6.3 that causes it to “not work”,
Yes, certain events have been disabled that the plugin requires.
See here for more information) for more information. Everything seems to work with 8.6.5 so far.By the way, if you enable debugging via the configuration, the communication between the lsp client and the servers is logged which can be helpful for root cause analysis.
The log is created in the plugin\config\npplspclient directory with the respective Npp process ID.
Caution, the respective log is also deleted when Npp is closed.LSP communication currently recognizes 3 message types that can be sent by the client or any server.
Requests, responses and notifications.
Each request must be sent with a unique ID and answered by the other side with a response and this ID.
Notifications are only received and do not have this ID. -
because it does not contain an lspserver configuration
Ah, okay. I can confirm, I can remove my dummy
[lspservers]
section once I have[lspservers.perl]
, and it won’t flag that error.hence my choice of toml.
My question was actually meant as a “tongue-in-cheek” joke. Sorry if that didn’t translate. TOML is a standards-based similar to INI, so I can definitely see why one would want to use it (and why it would be a pre-implemented for your language of choice, as opposed to trying to implement an INI library, given the multitude of INI variations)
I am currently using a very experimental toml lexer, but previously I used the udl lexer.
Okay, I’ll probably snag the UDL, then.
That should already work, symbols are queried every time you save a document.
Can you give a simple test case?Apparently, I cannot, because the same experiments I tried yesterday are working today.
It could be that this is not supported by the server or you have discovered a bug.
PerlNavigator claims to support “Go to definition”, whether it needs to go elsewhere in the same file or into a
use
d module.Right now I’m just returning from the function, maybe I should log something in the console window to alert the user that the current operation is not supported by the server.
… or maybe the Diagnostics window (unless that has a different meaning… I don’t know what all the specifics are for LSP yet, and what is expected to go where4)
I selected the name of a function that comes from an external module, and then started the LSP server and did Goto definition, and nothing happened. I then grabbed the log at that point:
2024-04-03 06:18:31.141685 [INFO][ThreadId(1)] - process arguments provided are: "--stdio" !! 2024-04-03 06:18:31.540531 [INFO][ThreadId(1)] - start_server perl started. 2024-04-03 06:18:31.540748 [INFO][ThreadId(1)] - {"id":0,"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{"general":{"positionEncodings":["utf-8"]},"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["quickfix"]}}},"completion":{"completionItem":{"commitCharactersSupport":false,"deprecatedSupport":false,"documentationFormat":["plaintext"],"insertReplaceSupport":false,"preselectSupport":false,"snippetSupport":false},"completionItemKind":{},"dynamicRegistration":false,"insertTextMode":1},"formatting":{"dynamicRegistration":false},"hover":{"contentFormat":["plaintext","markdown"],"dynamicRegistration":false},"publishDiagnostics":{"codeDescriptionSupport":false,"dataSupport":false,"relatedInformation":true,"versionSupport":false},"rangeFormatting":{"dynamicRegistration":false},"signatureHelp":{"contextSupport":false,"dynamicRegistration":false,"signatureInformation":{"activeParameterSupport":false,"documentationFormat":["plaintext"],"parameterInformation":{"labelOffsetSupport":false}}},"synchronization":{"didSave":true,"dynamicRegistration":false,"willSave":true,"willSaveWaitUntil":false}},"window":{"showDocument":{"support":true},"showMessage":{"messageActionItem":{"additionalPropertiesSupport":true}},"workDoneProgress":true},"workspace":{"executeCommand":{"dynamicRegistration":true},"workspaceFolders":true}},"clientInfo":{"name":"","version":"-alpha"},"processId":27088,"rootUri":"file:///C:/usr/local/apps/npp/npp862.ps3","workspaceFolders":[{"name":"npp862.ps3","uri":"file:///C:/usr/local/apps/npp/npp862.ps3"}]}} 2024-04-03 06:18:31.541009 [INFO][ThreadId(10)] - <<< {"id":0,"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{"general":{"positionEncodings":["utf-8"]},"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["quickfix"]}}},"completion":{"completionItem":{"commitCharactersSupport":false,"deprecatedSupport":false,"documentationFormat":["plaintext"],"insertReplaceSupport":false,"preselectSupport":false,"snippetSupport":false},"completionItemKind":{},"dynamicRegistration":false,"insertTextMode":1},"formatting":{"dynamicRegistration":false},"hover":{"contentFormat":["plaintext","markdown"],"dynamicRegistration":false},"publishDiagnostics":{"codeDescriptionSupport":false,"dataSupport":false,"relatedInformation":true,"versionSupport":false},"rangeFormatting":{"dynamicRegistration":false},"signatureHelp":{"contextSupport":false,"dynamicRegistration":false,"signatureInformation":{"activeParameterSupport":false,"documentationFormat":["plaintext"],"parameterInformation":{"labelOffsetSupport":false}}},"synchronization":{"didSave":true,"dynamicRegistration":false,"willSave":true,"willSaveWaitUntil":false}},"window":{"showDocument":{"support":true},"showMessage":{"messageActionItem":{"additionalPropertiesSupport":true}},"workDoneProgress":true},"workspace":{"executeCommand":{"dynamicRegistration":true},"workspaceFolders":true}},"clientInfo":{"name":"","version":"-alpha"},"processId":27088,"rootUri":"file:///C:/usr/local/apps/npp/npp862.ps3","workspaceFolders":[{"name":"npp862.ps3","uri":"file:///C:/usr/local/apps/npp/npp862.ps3"}]}} 2024-04-03 06:18:31.541807 [INFO][ThreadId(1)] - Storing on_buffer_activated request for C:\usr\local\apps\npp\npp862.ps3\lsp-test.pl [2058226367408] 2024-04-03 06:18:31.724127 [INFO][ThreadId(9)] - >>> {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"textDocumentSync":2,"completionProvider":{"resolveProvider":true,"triggerCharacters":["$","@","%","-",">",":"]},"definitionProvider":true,"documentSymbolProvider":true,"workspaceSymbolProvider":true,"hoverProvider":true,"documentFormattingProvider":true,"documentRangeFormattingProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",",",")"]},"workspace":{"workspaceFolders":{"supported":true}}}}} 2024-04-03 06:18:31.724411 [INFO][ThreadId(1)] - ServerCapabilities { position_encoding: None, text_document_sync: Some(Kind(Incremental)), selection_range_provider: None, hover_provider: Some(Simple(true)), completion_provider: Some(CompletionOptions { resolve_provider: Some(true), trigger_characters: Some(["$", "@", "%", "-", ">", ":"]), all_commit_characters: None, work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, completion_item: None }), signature_help_provider: Some(SignatureHelpOptions { trigger_characters: Some(["(", ",", ")"]), retrigger_characters: None, work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None } }), definition_provider: Some(Left(true)), type_definition_provider: None, implementation_provider: None, references_provider: None, document_highlight_provider: None, document_symbol_provider: Some(Left(true)), workspace_symbol_provider: Some(Left(true)), code_action_provider: None, code_lens_provider: None, document_formatting_provider: Some(Left(true)), document_range_formatting_provider: Some(Left(true)), document_on_type_formatting_provider: None, rename_provider: None, document_link_provider: None, color_provider: None, folding_range_provider: None, declaration_provider: None, execute_command_provider: None, workspace: Some(WorkspaceServerCapabilities { workspace_folders: Some(WorkspaceFoldersServerCapabilities { supported: Some(true), change_notifications: None }), file_operations: None }), call_hierarchy_provider: None, semantic_tokens_provider: None, moniker_provider: None, linked_editing_range_provider: None, inline_value_provider: None, inlay_hint_provider: None, diagnostic_provider: None, experimental: None } 2024-04-03 06:18:31.724480 [INFO][ThreadId(1)] - Handling stored file C:\usr\local\apps\npp\npp862.ps3\lsp-test.pl [2058226367408] 2024-04-03 06:18:31.724488 [INFO][ThreadId(10)] - <<< {"jsonrpc":"2.0","method":"initialized","params":{}} 2024-04-03 06:18:31.724572 [INFO][ThreadId(10)] - <<< {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"perl","text":"#!/usr/bin/perl\r\n\r\nuse warnings;\r\nuse strict;\r\nuse lib '.';\r\nuse myModule;\r\n\r\nprint \"Hello World\\n\";\r\n\r\n=head2 ThisHereFunction\r\n\r\nPOD description\r\n\r\n=cut\r\n\r\n# Comment before sub\r\nsub ThisHereFunction {\r\n # comment as first line of sub\r\n my ($x,$y,$z) = @_;\r\n return 0;\r\n}\r\n\r\nsub second { 1; }\r\n\r\nmy $t = ThisHereFunction();\r\n\r\nmy $f = myModule::func();\r\n","uri":"file:///C:/usr/local/apps/npp/npp862.ps3/lsp-test.pl","version":0}}} 2024-04-03 06:18:31.724604 [INFO][ThreadId(10)] - <<< {"id":1,"jsonrpc":"2.0","method":"textDocument/documentSymbol","params":{"textDocument":{"uri":"file:///C:/usr/local/apps/npp/npp862.ps3/lsp-test.pl"}}} 2024-04-03 06:18:31.726886 [INFO][ThreadId(9)] - >>> {"jsonrpc":"2.0","id":0,"method":"workspace/workspaceFolders"} 2024-04-03 06:18:31.726966 [ERROR][ThreadId(1)] - Unhandled request { "id": 0, "jsonrpc": "2.0", "method": "workspace/workspaceFolders" } 2024-04-03 06:18:31.727015 [INFO][ThreadId(9)] - >>> {"jsonrpc":"2.0","id":1,"method":"workspace/workspaceFolders"} 2024-04-03 06:18:31.727046 [ERROR][ThreadId(1)] - Unhandled request { "id": 1, "jsonrpc": "2.0", "method": "workspace/workspaceFolders" } 2024-04-03 06:18:31.780060 [INFO][ThreadId(9)] - >>> {"jsonrpc":"2.0","id":1,"result":[{"kind":12,"location":{"range":{"start":{"line":16,"character":0},"end":{"line":20,"character":100}},"uri":"file:///C:/usr/local/apps/npp/npp862.ps3/lsp-test.pl"},"name":"ThisHereFunction"},{"kind":12,"location":{"range":{"start":{"line":22,"character":0},"end":{"line":22,"character":100}},"uri":"file:///C:/usr/local/apps/npp/npp862.ps3/lsp-test.pl"},"name":"second"}]} 2024-04-03 06:18:32.738187 [INFO][ThreadId(9)] - >>> {"jsonrpc":"2.0","id":2,"method":"workspace/workspaceFolders"} 2024-04-03 06:18:32.738469 [ERROR][ThreadId(1)] - Unhandled request { "id": 2, "jsonrpc": "2.0", "method": "workspace/workspaceFolders" } 2024-04-03 06:18:58.116894 [INFO][ThreadId(10)] - <<< {"id":2,"jsonrpc":"2.0","method":"textDocument/definition","params":{"position":{"character":8,"line":26},"textDocument":{"uri":"file:///C:/usr/local/apps/npp/npp862.ps3/lsp-test.pl"}}} 2024-04-03 06:18:58.117730 [INFO][ThreadId(9)] - >>> {"jsonrpc":"2.0","id":2,"result":null}
It looks like the server replies with
"result":null
…stopping the server, clearing out the log, and simplifying the code to
#!/usr/bin/perl use warnings; use strict; use lib '.'; use myModule; print "Hello World\n"; sub ThisHereFunction { my ($x,$y,$z) = @_; return 0; } my $t = ThisHereFunction();
… with my cursor in the middle of the
sH
fromThisHereFunction()
on the last lineThen I start the LSP server again, and do Goto definition, and even though the definition is just a few lines above in the same file, it doesn’t go anywhere, and the pair of commands in the log shows:
2024-04-03 06:36:09.405503 [INFO][ThreadId(13)] - <<< {"id":3,"jsonrpc":"2.0","method":"textDocument/definition","params":{"position":{"character":12,"line":14},"textDocument":{"uri":"file:///C:/usr/local/apps/npp/npp862.ps3/lsp-test.pl"}}} 2024-04-03 06:36:09.406479 [INFO][ThreadId(12)] - >>> {"jsonrpc":"2.0","id":3,"result":null}
So it’s still returning null. :-(
I am hoping that @Michael-Vincent , who knows Perl, and has tried your plugin earlier in this conversation with other languages, and seems to understand how it should behave, will be able to try some experiments with Perl and the PerlNavigator, so that he can supply differences of behavior between what he’s already seen with other languages and what he sees in Perl … or so that he can tell me what I’m doing wrong with my what-I-thought-were-simple Perl experiments. It might just be that I’m not doing things in the right order, or not using the right steps to activate features.
Everything seems to work with 8.6.5 so far.
Oh, good. I was thinking of updating to that version for my daily use anyway, since it seems to be stable. But it will be nice to be able to play with this plugin without having to jump to a different N++ instance.
-
@PeterJones said in New (incomplete and x64 only) LSP client plugin:
I am hoping that @Michael-Vincent , who knows Perl, and has tried your plugin earlier in this conversation with other languages,
I should note: Notepad++ 8.6.5 64-bit with NppLspClient v.0.0.26-alpha
Trying with Perl setup as @PeterJones , I get the same results - it seems like it’s not working.
With this Python setup:
[lspservers.python] mode = "io" executable = 'c:\Users\VinsWorldcom\AppData\Roaming\Python\Scripts\pylsp.exe' args = '--check-parent-process --log-file c:\Users\VinsWorldcom\tmp\pylsp.log -vvv' auto_start_server = false
and this simple Python script:
#!python import os import sys def myadd(n1, n2): return n1 + n2 t = myadd(1, 2)
Putting my caret between the
y
anda
of themyadd()
call on the last line and selecting Plugins => NppLspClient => Goto definition, it moves my caret to just before them
in thedef myadd( ...
line - as expected. Log shows:2024-04-03 10:44:09.702659 [INFO][ThreadId(4)] - <<< {"id":75,"jsonrpc":"2.0","method":"textDocument/definition","params":{"position":{"character":6,"line":8},"textDocument":{"uri":"file:///C:/Users/VinsWorldcom/tmp/crapps/test.py"}}} 2024-04-03 10:44:09.705734 [INFO][ThreadId(3)] - >>> {"jsonrpc":"2.0","id":75,"result":[{"uri":"file:\/\/\/c:\/Users\/VinsWorldcom\/tmp\/crapps\/test.py","range":{"start":{"line":5,"character":4},"end":{"line":5,"character":9}}}]}
Cheers.
-
@PeterJones said in New (incomplete and x64 only) LSP client plugin:
{“jsonrpc”:“2.0”,“id”:2,“result”:null}
That’s a valid response from the server if it can’t specify the location … but … why can’t it!
What version of Perl are you using?
Maybe it’s related to the unhandled “workspace/workspaceFolders” request that the NppLspClient plugin seems to ignore … again … why? … dooh - typo …
I must have been hungry to wait for a “workspace/wokspaceFolders” request …… or maybe the Diagnostics window
No, this is reserved for exclusively handle diagnostics.
Perhaps a temporary (3-5 sec) pop-up window that overlays the status bar area and states that this is not supported by the server. -
@Ekopalypse said in New (incomplete and x64 only) LSP client plugin:
That’s a valid response from the server if it can’t specify the location … but … why can’t it!
What version of Perl are you using?Strawberry Perl v5.38.0 – and it’s in my path, so PerlNavigator should be able to find it without options being passed from the client to the server.
Maybe it’s related to the unhandled “workspace/workspaceFolders” request that the NppLspClient plugin seems to ignore … again … why? … dooh - typo …
I must have been hungry to wait for a “workspace/wokspaceFolders” request …:-)
No, this is reserved for exclusively handle diagnostics.
Ah, that’s fine.
Perhaps a temporary (3-5 sec) pop-up window that overlays the status bar area and states that this is not supported by the server.
I think Console is fine, and probably less work for you than a popup.
-
Looks like it is caused by the unhandled request.
and now the server responded, for the goto definition request, with
{ "id": 33, "jsonrpc": "2.0", "result": [ { "range": { "end": { "character": 500, "line": 9 }, "start": { "character": 0, "line": 9 } }, "uri": "file:///D:/scripts/perl/tests/main.pl" } ] }
But the end character 500 is not correct.
The formatting does not seem to work either.
Renaming is not supported by the server.I will prepare another alpha version tomorrow and make it available.
-
@Ekopalypse said in New (incomplete and x64 only) LSP client plugin:
I will prepare another alpha version tomorrow and make it available.
Great! Looking forward to it.
-
I’ve opened an issue that I wanted to wait for before releasing a new version.
-
Hi Ekopalypse:
I’m in the midst of learning Rust, amongst a few other new languages.
I installed your latest version of NppLspClient.
Following your instructions, I tried to install a Language Server for Rust, they mentioned that the OLD version of RLS is no longer supported (deprecated I think) and recommended using rust-analyzer.
Here is the link: https://github.com/rust-lang/rls
I have rust-analyzer installed in Visual Studio Code w022 but was unsure how to install it for Notepad++.Any comments or advice would be appreciated.
Thanks
Murray -
Either download a pre-built binary or clone their repo and build it yourself, which is what I do to stay up to date.
My config for rust looks like this
[lspservers.rust] mode = "io" executable = 'D:\Repositories\rust\rust-analyzer\target\release\rust-analyzer.exe' auto_start_server = true # initialization_options = '{"completion":{"limit": 1000}}'
Since rust-analyzer can be quite chatty, you might want to comment out the
initialization_options
if you are having performance issues. My old i5 2nd edition processor seems to get along fine most of the time even with the commented line.For questions, suggestions etc… a discussion via github is also possible.
-
@Ekopalypse I downloaded this file: https://github.com/rust-lang/rust-analyzer/releases/download/2024-11-25/rust-analyzer-i686-pc-windows-msvc.zip and unzipped it.
You mention a “config for Rust”, how/ where do I place this??
BTW: my environment is Windows 11 64-bitProfessional edition. -
Is there a reason why you are using the 32bit version of rust analyzer?
Does that fit your rust toolchain?
For a 64 bit Windows I would have used this one I guess.You mention a “config for Rust”, how/ where do I place this??
Plugin->NppLspClient->Open Configuration File
-
@Ekopalypse
Thanks, I replaced rust-analyzer with the 64-bit version.
When I try to edit/modify a Rust program, i.e. main.rs I do not get the coloring of keywords or suggested completions.
Is there something else that i am missing in my setup??
Here’s my Notepad++ debug info:
Notepad++ v8.7.4 (64-bit)
Build time : Dec 4 2024 - 23:50:05
Path : C:\Program Files\Notepad++\notepad++.exe
Command Line :
Admin mode : OFF
Local Conf mode : OFF
Cloud Config : OFF
Periodic Backup : ON
Placeholders : OFF
DirectWrite : OFF
Multi-instance Mode : monoInst
File Status Auto-Detection : cdEnabledNew (for current file/tab only)
Dark Mode : OFF
OS Name : Windows 11 Pro (64-bit)
OS Version : 24H2
OS Build : 26100.2454
Current ANSI codepage : 1252
Plugins :
mimeTools (3.1)
NppConverter (4.6)
NppExport (0.4)
NppLspClient (0.0.31)
rustnpp (1.0.2) -
This sounds like Rust is not part of your Notepad++ setup because keyword coloring is done by Npp/Scintilla and is not part of the language server protocol and if that is the case, then the NppLspClient plugin will not work with Rust files.
So what does the NppLspClient plugin do?
When loading the plugin, it checks if the configuration file is available and if not, it creates the minimal version where no servers are available. Currently, users have to manually configure the servers they want to use.
When activating a buffer, the plugin checks whether the language of the current buffer is configured in the configuration file. If it finds a corresponding section, it checks whether the FolderAsWorkspace (FAW) dialog has entries, and if it finds something, it remembers its root node. If the server is to be started automatically, it checks whether the current file belongs to one of the root nodes of the FAW dialog. If this is the case, this root node path is used to initialize the configured server; if this is not the case, the current directory is used instead. An attempt is then made to start the process. That’s it, and the success or failure can be displayed in the console dialog.
If this does not solve your problem, you are welcome to open a request in the NppLspClient github repo and attach the log entries together with your configuration for further investigation.
-
May I ask that one of the moderators change the title of this post to
New (incomplete) LSP client plugin
Since version v.0.0.30 a 32bit plugin is also available.
Thank you very much.
-
Thank you for renaming the title.