Recent development has been sponsored by LogicMoo - Thank you!
Still a work-in-progress – please open an issue if you have any issues or feature requests!.
Currently supports:
- diagnostics (singleton variables, syntax errors) via xref
- find references/definitions
- documentation of predicates on hover
- auto-completion of predicates
- code formatting (✨new!✨)
- symbol highlighting (✨new!✨)
- variable renaming (✨new!✨)
The code formatter can also be run stand-alone. After installing the lsp_server pack, you can run swipl formatter <file> at the command line.
Only tested with SWI-Prolog, as it heavily uses its introspection facilities to do its stuff.
It should work with any relatively-recent version of SWI-Prolog, but for best results (for “find references” in particular), use a version with xref_called/5 (8.1.5 or newer; past commit 303f6430de5c).
Installable as a pack with swipl pack install lsp_server or ?- pack_install(lsp_server). from a repl.
As of version 2.5.0, running the server over a socket is now supported by passing in the commandline arguments port <port number> (instead of stdio).
If running on Windows directly (i.e. not via WSL) running the server via stdio will NOT work and you will need to run the server over a socket, so please consult that section of the documention for your editor..
(lsp-register-client
(make-lsp-client
:new-connection
(lsp-tcp-connection (lambda (port) (list "swipl"
"-g" "use_module(library(lsp_server))."
"-g" "lsp_server:main"
"-t" "halt"
"--" "port" port)))
:major-modes '(prolog-mode)
:priority 1
:multi-root t
:server-id 'prolog-ls))(lsp-register-client
(make-lsp-client
:new-connection
(lsp-stdio-connection (list "swipl"
"-g" "use_module(library(lsp_server))."
"-g" "lsp_server:main"
"-t" "halt"
"--" "stdio"))
:major-modes '(prolog-mode)
:priority 1
:multi-root t
:server-id 'prolog-ls))(setopt eglot-server-programs (cons
(cons 'prolog-mode
(list "swipl"
"-O"
"-g" "use_module(library(lsp_server))."
"-g" "lsp_server:main"
"-t" "halt"
"--" "port" :autoport))
eglot-server-programs))(setopt eglot-server-programs (cons
(cons 'prolog-mode
(list "swipl"
"-O"
"-g" "use_module(library(lsp_server))."
"-g" "lsp_server:main"
"-t" "halt"
"--" "stdio"))
eglot-server-programs))Put the following in coc-settings.json (which you can access by using the command :CocConfig).
{"languageserver": {
"prolog-lsp": {
"command": "swipl",
"args": ["-g", "use_module(library(lsp_server)).",
"-g", "lsp_server:main",
"-t", "halt",
"--", "stdio"
],
"filetypes": ["prolog"]
}}
}CoC does not support automatically starting a socket server. If you are on Windows and using CoC and hence need a socket server, you’ll have to manually start the LSP process by running the following command:
swipl -g 'use_module(library(lsp_server))' -g 'lsp_server:main' -t halt -- port 12345Where “12345” is an arbitrary, free port number.
Then, with that started, add the following to coc-settings.json (accessed via :CocConfig).
{"languageserver": {
"prolog-lsp": {
"host": "127.0.0.1",
"port": 12345,
"filetypes": ["prolog"]
}}
}Ensuring the port entered in the config is the same one used when starting the server process
Put the following in $XDG_CONFIG_DIR/nvim/lsp/prolog.lua:
return {
cmd = { 'swipl',
'-g', 'use_module(library(lsp_server))',
'-g', 'lsp_server:main',
'-t', 'halt',
'--', 'stdio' },
root_markers = { '.git', },
filetypes = { 'prolog' },
}And add vim.lsp.enable({'prolog'}) to $XDG_CONFIG_DIR/nvim/init.lua.
Put the following in $XDG_CONFIG_DIR/nvim/lsp/prolog.lua:
local find_port = function()
local uv = vim.uv
local tcp = uv.new_tcp()
tcp:bind("127.0.0.1", 0)
local port = tcp:getsockname().port
tcp:close_reset()
return port
end
return {
cmd = function(...)
local server_port = find_port()
vim.system({'swipl',
'-g', 'use_module(library(lsp_server))',
'-g', 'lsp_server:main',
'-t', 'halt',
'--', 'port', server_port},
{},
function(...)
print("LSP PROCESS EXITED", ...)
end)
vim.uv.sleep(500)
return vim.lsp.rpc.connect('127.0.0.1', server_port)(...)
end,
root_markers = { '.git', },
filetypes = { 'prolog' },
}And add vim.lsp.enable({'prolog'}) to $XDG_CONFIG_DIR/nvim/init.lua.
Install the neovim/nvim-lspconfig package
Put the following in $XDG_CONFIG_DIR/nvim/lua/lspconfig/prolog_lsp.lua:
local configs = require 'lspconfig/configs'
local util = require 'lspconfig/util'
configs.prolog_lsp = {
default_config = {
cmd = {"swipl",
"-g", "use_module(library(lsp_server)).",
"-g", "lsp_server:main",
"-t", "halt",
"--", "stdio"};
filetypes = {"prolog"};
root_dir = util.root_pattern("pack.pl");
};
docs = {
description = [[
https://github.com/jamesnvc/prolog_lsp
Prolog Language Server
]];
}
}
-- vim:et ts=2 sw=2Then add the following to init.vim:
lua << EOF
require('lspconfig/prolog_lsp')
require('lspconfig').prolog_lsp.setup{}
EOFCreate the following file in $XDG_CONFIG_DIR/nvim/lua/plugins/lsp.lua
return {
{
"neovim/nvim-lspconfig",
opts = {
servers = {
prolog = {},
},
setup = {
prolog = function(_, opts)
local lspconfig = require("lspconfig")
local configs = require("lspconfig.configs")
local util = require("lspconfig.util")
local root_files = { ".git", "pack.pl" }
if not configs.prolog then
configs.prolog = {
default_config = {
cmd = {
"swipl",
"-g",
"use_module(library(lsp_server)).",
"-g",
"lsp_server:main",
"-t",
"halt",
"--",
"stdio",
},
filetypes = { "prolog" },
single_file_support = true,
root_dir = util.root_pattern(unpack(root_files)),
settings = {},
},
commands = {},
docs = {
description = [[
Prolog LSP server
]],
},
}
end
lspconfig.prolog.setup(opts)
end,
},
},
},
}Choose one from the list below:
- download the latest
.vsixfile from the releases page - clone this repo and copy/symlink the
vscode/directory to ~~/.vscode/extensions/~ - clone and build the
.vsixfile yourself by the follwing steps:cd /path/to/clone/vscodenpm installnpx vsce package- add the resulting
.vsixto VSCode by clicking the...at the top right of the “Extensions” panel then selectingInstall from VSIX...
Helix already includes configuration for this Prolog LSP server, so it should mostly Just Work.
However, the default configuration gives the ‘.pl’ extension to perl, so to avoid having to manually do :set-language prolog each time, you can add the following to $XDG_CONFIG/helix/languages.toml to remove Perl’s association with that extension:
[[language]]
name = "perl"
file-types = ["perl"]