I’m using the prolog lsp server by @jamesnvc, and I find it works perfectly for going to definition, references, and quickly seeing documentation of builtin predicates. However, I can’t get it to display the documentation for my own predicates. Perusing the source of the lsp_server, I think they should be written as pldoc, so here’s an example module:
:- module(foo, [bar/2]).
%! foo(-X:atom) is nondet.
%
% Beautiful predicate.
foo(a).
foo(b).
foo(c).
foo(d).
%! bar(-X:atom) is nondet.
%
% Another predicate.
bar(X, X) :- foo(X), member(X, [a,b,c,d,e,f,g]).
however, if I try to get the documentation of foo, I get LSP :: no content at point. Does any of you have this feature working?
I tried this on one of my modules … interactively entering help(transform_kythe_fact) produced warning messages “Invalid mode declaration in PlDoc comment”, “PlDoc: failed to process structured comment”, and this:
ERROR: Failed to translate to HTML: \man_pages([transform_kythe_fact/2],[no_manual(fail),links(false),link_source(false),navtree(false),server(false)])
I had autoload set to true, if that makes a difference.
That’s the same error I get too, when I try to use help directly. However I think the lsp server should be able to take the pldoc documentation, based on this line in the source code. But you raise a good question: how can we have help see the pldoc documentation, without invoking the documentation server?
I assume you have invalid PlDoc comments. There is not a lot of syntax that is validated. Notably the mode lines have to satisfy the mode syntax though.
Without autoloading many of the development tools do not work.
I understand that the flag autoload is true by default, so should help work on a predicate in the example module I shared above? The pldocs seem in the right format to me (edit: I tried using a wrong pldoc format, and I get an error saying I’m wrong, which I don’t get in the module above).
Yeas, that should not be a problem. I don’t know whether the lsp server supports user defined predicates. @jamesnvc was quite enthusiastic about the new Emacs sweep mode by @oskardrums. If Emacs is your target, I’d try that.
But the predicate whose help I was trying to output didn’t generate any warnings about invalid PlDoc syntax. So, I presume that there’s a problem with man_page//2 (possibly related to Text help fails in some cases ?)
Looks like there is an issue with this predicate. Possibly it fails if some of the predicates it tries to generate documentation for has wrong comments? Should be possible to debug with a spy point and a bit of tracing (although it isn’t the most beautiful piece of code )
Correction: with the removal of private(Full,Options) from packages/pldoc/doc_man.pl, I get documentation on exported predicates (without this change, I get the “No help” message).
I edited the source files (I routinely build and install from the github sources).
If you install in a user-writeable director, you can edit the source files. For example, my executable is ~/.local/bin/swipl and the file that I edited is ~/.local/lib/swipl/library/pldoc/doc_man.pl (if you install in the standard place, presumably you could edit /usr/lib/swipl/library/pldoc/doc_man.pl or something like that).
Back to the original, the file defines bar/2, but documents bar/1. You easily see this when using
swipl --pldoc foo.pl
For me, as is, help(bar) results in telling me there is no help for bar and showing the close match var/1 as alternative. After fixing the comment it works as expected.
Does anyone has a reproducible example of main_page//2 failing when called from help/1?
This is my test file (it’s longer than it needs to be). It succeeds with the exported predicate and fails with the non-exported one. (I earlier reported that it failed with an exported predicate, but that was incorrect):
test file
:- module(pykythe, [pykythe_main/0]).
:- det(pykythe_main/0).
%! pykythe_main is det.
% By default, this is called as part of initialization. It sets up
% an error handler and some appropriate global limits, then calls
% pykythe_main2/0 to process the files according to the command line
% arguments.
pykythe_main =>
set_prolog_flag(stack_limit, 1_610_612_736), % TODO: 1.5GB - default of 1GB might suffice
% TODO: catch_with_backtrace/3 wrap might not be needed when the
% initialization/2 directive is enabled.
catch_with_backtrace(pykythe_main2,
Error,
( print_message(error, Error),
halt(1) )),
log_if(true, 'End'), % TODO: delete
halt(0).
:- det(transform_kythe_fact/2).
%! transform_kythe_fact(+Fact0, -Fact1) is det.
% TODO: Note that this also changes fact_value to base64 and has special
% cases for symtab, text, colors
transform_kythe_fact(json{source:Source0, fact_name:FactName, fact_value:FactValue}, Fact1) =>
Fact1 = json{source:Source1, fact_name:FactName, fact_value:FactValueBase64},
% text is alread in base64 (from Meta.contents_base64)
( FactName == '/kythe/text'
-> FactValueBase64 = FactValue
; FactName == '/pykythe/color_all'
-> FactValueBase64 = FactValue
; base64_utf8(FactValue, FactValueBase64)
),
transform_kythe_vname(Source0, Source1).
with output:
failure in man_page//2
$ ~/src/swipl-devel/build/src/swipl -O -l /tmp/mm.pl
Welcome to SWI-Prolog (threaded, 64 bits, version 9.1.17-2-g95852849b-DIRTY)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
CMake built from "/home/peter/src/swipl-devel/build"
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- help(transform_kythe_fact).
ERROR: Failed to translate to HTML: \man_pages([transform_kythe_fact/2],[no_manual(fail),links(false),link_source(false),navtree(false),server(false)])
true.
and when I remove the \\+ private(Full, Options) in man_page//2, I get:
success (after changing doc_man.pl)
?- help(transform_kythe_fact).
/tmp/mm.pl
transform_kythe_fact(+Fact0, -Fact1) is det[private]
TODO: Note that this also changes fact_value to base64 and has special
cases for symtab, text, colors
true.