1:- module(lsp_completion, [completions_at/3]).
14:- use_module(library(apply), [maplist/3]). 15:- use_module(library(lists), [numlist/3]). 16:- use_module(library(prolog_xref), [xref_defined/3, xref_source/2]). 17:- use_module(library(yall)). 18:- use_module(lsp_utils, [linechar_offset/3]). 19:- use_module(lsp_changes, [doc_text_fallback/2]). 20
21part_of_prefix(Code) :- code_type(Code, prolog_var_start).
22part_of_prefix(Code) :- code_type(Code, prolog_atom_start).
23part_of_prefix(Code) :- code_type(Code, prolog_identifier_continue).
24
25get_prefix_codes(Stream, Offset, Codes) :-
26 get_prefix_codes(Stream, Offset, [], Codes).
27
28get_prefix_codes(Stream, Offset0, Codes0, Codes) :-
29 peek_code(Stream, Code),
30 part_of_prefix(Code), !,
31 succ(Offset1, Offset0),
32 seek(Stream, Offset1, bof, Offset),
33 get_prefix_codes(Stream, Offset, [Code|Codes0], Codes).
34get_prefix_codes(_, _, Codes, Codes).
35
36prefix_at(File, Position, Prefix) :-
37 doc_text_fallback(File, DocCodes),
38 setup_call_cleanup(
39 open_string(DocCodes, Stream),
40 ( linechar_offset(Stream, Position, _),
41 seek(Stream, -1, current, Offset),
42 get_prefix_codes(Stream, Offset, PrefixCodes),
43 string_codes(Prefix, PrefixCodes) ),
44 close(Stream)
45 ).
46
47completions_at(File, Position, Completions) :-
48 prefix_at(File, Position, Prefix),
49 xref_source(File, [silent(true)]),
50 findall(
51 Result,
52 ( xref_defined(File, Goal, _),
53 functor(Goal, Name, Arity),
54 atom_concat(Prefix, _, Name),
55 args_str(Arity, Args),
56 format(string(Func), "~w(~w)$0", [Name, Args]),
57 format(string(Label), "~w/~w", [Name, Arity]),
58 Result = _{label: Label,
59 insertText: Func,
60 insertTextFormat: 2}),
61 Completions
62 ).
63
64args_str(Arity, Str) :-
65 numlist(1, Arity, Args),
66 maplist([A, S]>>format(string(S), "${~w:_}", [A]),
67 Args, ArgStrs),
68 atomic_list_concat(ArgStrs, ', ', Str)
LSP Completion
This module implements code completion, based on defined predicates in the file & imports.
Uses
lsp_changes
in order to see the state of the buffer being edited.