Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

README.md

Goal

Trying to get Pascal intelligent completion in Emacs (and VS Code) using LSP.

LSP is cross-editor protocol, known from VS Code but useful in other editors alike, see https://microsoft.github.io/language-server-protocol/ .

Short version

(require 'lsp-pascal)

;; choose LSP server binary
(setq lsp-pascal-command "/home/michalis/cge/bin/pasls")

;; pass basic info to LSP server, all LSP Pascal servers above support these:
(setq lsp-pascal-fpcdir "/home/michalis/cge/tools/contrib/fpc/src")
(setq lsp-pascal-lazarusdir "/home/michalis/lazarus")
(setq lsp-pascal-pp "/home/michalis/cge/tools/contrib/fpc/bin/fpc-cge")
(setq lsp-pascal-fpctarget "linux")
(setq lsp-pascal-fpctargetcpu "x86_64")

Various LSP Pascal servers

Arjan Adriaanse repo (original, unmaintained)

https://github.com/arjanadriaanse/pascal-language-server started it all, but after 4 commits in 2020 it seems unmaintained.

I found 2 maintained forks of it that I got to work. (I did create 2 forks of them in turn, through I also contributed back some commits to original authors.)

Ryan Joseph (genericptr) LSP server

https://github.com/genericptr/pascal-language-server

Michalis fork: https://github.com/michaliskambi/pascal-language-server-genericptr

Installation:

sudo apt install libsqlite3-dev
git clone https://github.com/michaliskambi/pascal-language-server-genericptr
cd pascal-language-server-genericptr
lazbuild pasls.lpi
create $HOME/.config/pasls/castle-pasls.ini following https://github.com/michaliskambi/pascal-language-server-genericptr docs

Notes:

  • Tested in both VS Code and Emacs.

  • DONE: initially failed to work, VS Code reports (when opening any Pascal file):

    [Error - 02:25:51] Server initialization failed.
      Message: TFPCUnitToSrcCache.GetConfigCache missing CompilerFilename
      Code: -32603
    [Error - 02:25:51] Starting client failed
      Message: TFPCUnitToSrcCache.GetConfigCache missing CompilerFilename
      Code: -32603
    

    From Emacs lsp-pascal, failed with the same message.

    Fixed by https://github.com/michaliskambi/pascal-language-server-genericptr/commit/210f131f9cd32a9441f90d4613938c503fa1ec03

  • (NICE): It exposes extra FPC options as LSP initialization options, which allows me to add CGE paths from VS Code.

    This also means I could, in principle, use it with CGE without my mods to add ~/.config/pasls/castle-pasls.ini. Though ~/.config/pasls/castle-pasls.ini still makes it easier by allowing me to provide just single CGE path.

  • (SOLVED IN MY FORK, BUT WITH A HACK): On really invalid syntax (e.g. open LFM and try to use kambi-pascal-mode) it can send invalid JSON to LSP ({"result":,"id":85,"jsonrpc":"2.0"}), and Emacs will spam console with errors.

    Warning (lsp-mode): Failed to parse the following chunk:
    ’’’
    Content-Type: application/vscode-jsonrpc; charset=utf-8
    Content-Length: 35
    
    {"result":,"id":85,"jsonrpc":"2.0"}Content-Type: application/vscode-jsonrpc; charset=utf-8
    Content-Length: 39
    
    {"result":null,"id":86,"jsonrpc":"2.0"}Content-Type: application/vscode-jsonrpc; charset=utf-8
    Content-Length: 39
    
    {"result":null,"id":87,"jsonrpc":"2.0"}
    ’’’
    with message (json-parse-error unexpected token near ',' <callback> 1 11 11)
    
  • It does error message (like on missing unit) using LSP window/showMessage method. To activate this you need to pass LSP initialization options with showSyntaxErrors=true (all LSP clients should enable to pass LSP initialization options somehow).

    This works great in VS Code.

    It works in Emacs, but poorly: The message is there but it is immediately covered by "No completion found". You have to switch to Emacs *Messages* buffer to see it. Note: see kambi-pascal-lsp.el for :initialization-options example how to activate it using Lisp.

  • It is not efficient at finding LCL units, it seems. It does not read LPI / LPK, unlike Philip Zander's LSP server.

    Testcase:

Philip Zander (Isopod) LSP server

https://github.com/Isopod/pascal-language-server

Notes specific to this fork:

Kagamma

https://github.com/Kagamma/pascal-language-server

Fork of Isopod version ( https://github.com/Isopod/pascal-language-server ).

Adds Windows compatibility (but since then it was addressed by Michalis, in CGE and Isopod versions) and more.

Castle Game Engine (Michalis Kamburelis, Andrzej Kilijanski, other CGE developers)

https://github.com/castle-engine/pascal-language-server

Fork of Isopod version ( https://github.com/Isopod/pascal-language-server ). We added various enhancements, contributing back to upstream.

We also added some CGE-specific options, and work now on tighter CGE integration in cge_vscode_extension branch.

Installation:

git clone https://github.com/castle-engine/pascal-language-server cge-pascal-language-server
cd cge-pascal-language-server/
git submodule update --init --recursive
cd server
lazbuild pasls.lpi
create $HOME/.config/pasls/castle-pasls.ini following https://github.com/castle-engine/pascal-language-server docs

Notes about both Ryan Joseph (genericptr) and Philip Zander (Isopod) versions

Delphi LSP

To be complete, I should mention Embarcadero also makes their proprietary LSP server.

Docs: https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Using_DelphiLSP_Code_Insight_with_Other_Editors

To use it, make sure to generate .delphilsp.json in the project folder, following https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Code_Insight_Reference#Creating_.delphilsp.json_Files :

  • Go to Tools > Options > User Interface > Editor > Language > Code Insight and turn on Generate LSP Config
  • Save and close your project in the IDE.

TODO: I didn't manage to make it actually work. When trying to complete, it fails with DelphiLSP Agent1 terminated and will be respawned..

Other editors than Emacs (mentioning it here for completeness)

VS Code Extension

https://github.com/genericptr/pasls-vscode

git clone https://github.com/genericptr/pasls-vscode
install vsix in VS Code
config:
- FPC sources:
- Laz sources:
- FPC exe:
- pasls exe: the one you got from above

Tested, works nicely, with both pasls forks.

Neovim

Available in https://github.com/Isopod/pascal-language-server repo in client/nvim ( https://github.com/Isopod/pascal-language-server/tree/master/client/nvim ).

Installing necessary packages in Emacs

Basic config

This is the basic configuration you need:

(require 'lsp-pascal)

;; choose LSP server binary
(setq lsp-pascal-command "/home/michalis/sources/pascal-language-server/server/lib/x86_64-linux/pasls")

;; pass basic info to LSP server, all LSP Pascal servers above support these:
(setq lsp-pascal-fpcdir "/home/michalis/installed/fpclazarus/current/fpcsrc/")
(setq lsp-pascal-lazarusdir "/home/michalis/installed/fpclazarus/current/lazarus")
(setq lsp-pascal-pp "/home/michalis/installed/fpclazarus/current/fpc/bin/x86_64-linux/fpc.sh")
(setq lsp-pascal-fpctarget "linux")
(setq lsp-pascal-fpctargetcpu "x86_64")

Complicated configuration, specific to Michalis preferences

Add this to ~/.emacs

(add-to-list 'load-path (concat kambi-elisp-path "lsp/"))
(require 'kambi-pascal-lsp)

Read and customize kambi-pascal-lsp.el.

What works

  • Completion aware of methods/properties in each namespace.

    Demo:

    • Open a new Pascal file.
    • Declare instance of some known class from used unit, e.g. TList.
    • Type MyInstance. and then M-x company-complete.
    • This should be intelligent completion, listing TList properties/methods now.
  • Ctrll+clicking on identifier jumps to declaration (works in VS Code and Emacs alike).

  • When you start (, you see parameters of method/routine.

    TODO: How to show them all in Emacs? Currently I only see 1st parameters (in case of overloads) in Emacs, with prefix like "1/2", I still don't know how to view them all. And/or how to see all possible parameters using a tooltop, like in VS Code. So functionality works in Emacs, but presentation is poor.

  • "Go to Definition" / "Go to Declaration"

    In VS Code: context menu (right click), ctrl + click, F12.

    In Emacs: context menu (right click), ctrl + click, shortcuts mentioned there. lsp-find-declaration lsp-find-definition

TODO (in general, for both VS Code and Emacs)

  • Is there anything like "Code complete" (Ctrl+Shift+C in Lazarus) available in any fork?

    So that e.g. writing "MyButton.OnClick := @Foo", pressing Ctrl+Shift+C would automatically create empty Foo implementation.

    Note: GitHub Copilot in practice can often perform this job.

TODO (specifically for Emacs)

  • How to see CGE docs in company mode?

    company-mode in Emacs can show docs in F1. How to configure it to show docs of CGE routine? It is useful from VS Code too?

  • How to make company-show-location work?

    company docs say:

    """ C-w ¶ Display a buffer with the definition of the selected candidate (company-show-location). """

    but it does nothing for me.

  • In Emacs: make completion not case sensitive, e.g. Event.is should complete IsKey.