Skip to content

Instantly share code, notes, and snippets.

@thacuber2a03
Last active July 17, 2024 03:12
Show Gist options
  • Save thacuber2a03/7285effd7ad6cec17e24a70fd30be467 to your computer and use it in GitHub Desktop.
Save thacuber2a03/7285effd7ad6cec17e24a70fd30be467 to your computer and use it in GitHub Desktop.
the nothing language server
-- NOTE: to TC of the future
-- if you attempt to make an actual language server, *please* read the specification
-- https://microsoft.github.io/language-server-protocol/specifications/specification-current
-- here's a sample server so you can read along too, in case you ever forget how it's done
--
-- NOTE: for everyone else
-- the nothing language server: a (really buggy) language server that does nothing
-- this thing is public domain (we're talking https://unlicense.org/)
--
-- NOTE: for both
-- it doesn't use sockets, it uses standard I/O
-- go look up sockets somewhere else fool
-- (I don't know sockets either)
-- you'll have to use https://github.com/rxi/json.lua for this one,
-- but any json library with a "decode" and "encode" methods will suffice
local json = require 'json'
-- shorthand for sending a table back
local function send(t)
t.jsonrpc = '2.0'
local out = json.encode(t)
-- output the header, and then the content
-- https://microsoft.github.io/language-server-protocol/specifications/specification-current#headerPart
io.stdout:write('Content-Length: ', #out)
io.stdout:write('\r\n\r\n', out, '\n')
end
-- these are the most important streams in this program
-- so it just makes sense to disable buffering on them
io.stdin:setvbuf 'no'
io.stdout:setvbuf 'no'
local intialized = false
-- all requests sent by the client that runs this server
-- will be logged in this file, might be helpful for actual lsp development
local requestsSent = assert(io.open('requests.txt', 'w+b'))
while true do
local input = io.read()
if input then
-- this is *not* a good way to parse the header.
-- please just parse it properly.
local len = tonumber(assert(input:match 'Content%-Length: (%d+)'))
if input:match 'Content%-Type: .-' then input = io.read() end
input = io.read() -- obligatory empty line
input = io.read(len)
requestsSent:write(input, '\n')
local request = json.decode(input)
if not intialized then
-- https://microsoft.github.io/language-server-protocol/specifications/specification-current#initialize
if request.method == 'exit' then
requestsSent:close()
os.exit(-1)
elseif request.method == 'initialize' then
send { id = request.id, method = 'initialized' }
else
-- spoiler: -32002 means uninitalized server
send { id = request.id, code = -32002 }
end
else
-- do nothing
-- yeah, mindblowing
end
end
-- do *not* yield using this.
-- I'm pretty sure it will either completely
-- freeze both the server and the client, or
-- cause something else to happen, but it's
-- probably not good, I have not tried it
-- and nor will I
os.execute 'sleep 1'
end
-- now you'll have to go on from here, good luck and hope you arrive at your destination sane :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment