It's been a few weeks since I last wrote about the progress I've been making on the Psion OPL language server front. This is, at least in part, because I've been spending my free time getting to grips with Pascal - my chosen programming language for this particular endeavour. To help me on this journey, I got hold of a copy of Marco Cantù's splendid “Object Pascal Handbook”, which while written specifically for a Delphi audience is nevertheless a very good primer on all things Pascal, especially the second half of the book which does a great job of introducing the OOP elements of the language. To that end, I headed down a rabbithole of writing what started out as some simple example programs that very quickly ballooned into a “let's see if I can create animated 3D maze-style graphics inside a console window.” Long story short, that's quite a challenge to set for oneself, and while I did make some progress with it (see here, if you're interested) I had to remind myself that what I was really aiming at was a good enough grasp of Pascal to get stuck into working on the language server itself.
Well, this weekend it struck me that I hadn't got my head fully around exactly what a language server is. Don't get me wrong, I am pretty au fait with what they do, and indeed most search engine results delivered in answer to the question “what is a language server” will, in fact, simply recapitulate what the functions of a language server are, and why they're such a good idea. Having already been sold on that idea some time ago, I was more interested in getting to grips with what they are comprised of and how they operate. Initial reading (faulty, as it transpires, thank you Reddit…) suggested they were some kind of “mini web server”, so I decided to investigate what kind of native support might already exist within Free Pascal (FPC) for setting up a web server.
The good news is, there is plenty of such support, in the form of the fcl-web package and its associated units. Indeed, you can spin up a rudimentary HTTP server using a handful of these units with just a few lines of code:
program OPLServer; uses fphttpapp, httpdefs, httproute, fpjsonrpc; procedure DoHello(ARequest:TRequest; AResponse: TResponse); begin AResponse.Content := '<html><head><title>Psion OPL Language Server</title></head>'+ '<body><h1>Hello, World!</h1></body></html>' end; begin HTTPRouter.RegisterRoute('*', @DoHello); Application.Port := 9000; Application.Initialize; Application.Run; end. |
Compiling this simple program and running it creates a very basic HTTP server running on port 9000 which you can then access locally from your browser at localhost:9000 to be greeted by a ‘Hello, World!’ message. So far, so pointless… but it did prove that creating an HTTP server in Pascal was easy enough to achieve. Unfortunately, it was also not actually what I needed, because that's not what the ‘server’ in 'language server' means.
Rather than HTTP, the language server is designed to run using JSON-RPC (JSON remote procedure protocol, a means of exchanging messages via JSON). The code IDE (client) shares a document URI with the language server, and subsequent edits made in the IDE are sent as update messages; the server, in turn, responds as applicable with its own suggestions, for things like code completion, lookups and other helpful features.
But if that isn't happening via HTTP, how does it work? The answer, at least if you adhere to Microsoft's Language Server Protocol, is more than one - but the easiest to code for is stdio, which means exchanging messages via stdin and stdout. If you define a language server this way, not only will it work as a language server, but you can also more readily unit test it by passing messages to it at the command line and seeing what it gives you back in response.
I'll be honest, I'm still not a lot closer to standing up a language server, still less one that actually does anything useful; but my thinking has at least advanced sufficiently to understand what it is I need to aim for. Small steps, and all that, but I believe I am that little bit closer to knowing what the ‘server’ bit of a language server means!