1:- module(pls_index_completions, [
2 completions_for_position/3,
3 suggestions_for_position/3,
4 identifier_for_position/3
5]). 6
7:- use_module(docs). 8:- use_module(documents). 9
10:- use_module(library(log4p)). 11
12completions_for_position(URI, Position, Completions) :-
13 14 15 prev_position(Position, Previous),
16 ( suggestions_for_position(URI, Previous, Suggestions)
17 -> (
18 findall(
19 _{
20 label: Label,
21 kind: 3,
22 documentation: Docs,
23 insertText: Signature,
24 insertMode: 2
25 },
26 (
27 member(Suggestion, Suggestions),
28 Suggestion = Name/Arity,
29 term_string(Suggestion, Label),
30 get_document_item(_DefURI, _DefRange, signature(Name/Arity, Signature)),
31 get_docs(Suggestion, Docs)
32 ),
33 Completions
34 )
35 )
36 ; Completions = []
37 ).
38
39suggestions_for_position(URI, Position, Suggestions) :-
40 identifier_for_position(URI, Position, Identifier),
41 atom_length(Identifier, Length),
42 (Length >= 3
43 -> findall(
44 Name/Arity,
45 (
46 get_document_item(_DefURI, _DefRange, defines(Name/Arity)),
47 sub_atom(Name, _Before, Length, _After, Identifier)
48 ),
49 Suggestions
50 )
51 ; fail
52 ).
53
54identifier_for_position(URI, Position, Identifier) :-
55 find_identifier_start(URI, Position, Start),
56 find_identifier_end(URI, Position, End),
57 Length is End.character - Start.character + 1,
58 content_at_position(URI, Start, Length, Text),
59 atom_string(Identifier, Text).
60
61find_identifier_start(URI, Position, Start) :-
62 Position.character = 0,
63 character_at_position(URI, Position, Character),
64 identifier_character(Character),
65 Start = Position,
66 !.
67
68find_identifier_start(URI, Position, Start) :-
69 character_at_position(URI, Position, Character),
70 identifier_character(Character),
71 prev_position(Position, Previous),
72 character_at_position(URI, Previous, PreviousCharacter),
73 \+identifier_character(PreviousCharacter),
74 Start = Position,
75 !.
76
77find_identifier_start(URI, Position, Start) :-
78 character_at_position(URI, Position, Character),
79 identifier_character(Character),
80 prev_position(Position, Previous),
81 find_identifier_start(URI, Previous, Start),
82 !.
83
84find_identifier_end(URI, Position, End) :-
85 character_at_position(URI, Position, Character),
86 identifier_character(Character),
87 next_position(Position, NextPosition),
88 character_at_position(URI, NextPosition, NextCharacter),
89 \+identifier_character(NextCharacter),
90 End = Position,
91 !.
92
93find_identifier_end(URI, Position, End) :-
94 character_at_position(URI, Position, Character),
95 identifier_character(Character),
96 next_position(Position, NextPosition),
97 find_identifier_end(URI, NextPosition, End),
98 !.
99
100prev_position(Position, _Previous) :-
101 Position.character = 0, fail.
102
103prev_position(Position, Previous) :-
104 PreviousCharacter is Position.character - 1,
105 Previous = _{
106 line: Position.line,
107 character: PreviousCharacter
108 }.
109
110next_position(Position, Next) :-
111 NextCharacter is Position.character + 1,
112 Next = _{
113 line: Position.line,
114 character: NextCharacter
115 }.
116
117character_at_position(URI, Position, Character) :-
118 content_at_position(URI, Position, 1, Character).
119
120content_at_position(URI, Position, Length, Text) :-
121 Line = Position.line,
122 CharacterPos = Position.character,
123 get_document_line_position(URI, Line, LineStart),
124 Offset is LineStart + CharacterPos,
125 with_content(URI, In,
126 (
127 seek(In, Offset, bof, _),
128 read_string(In, Length, Text),
129 (Text \= [])
130 )
131 ).
132
133identifier_character(Character) :-
134 letter(Character).
135
136identifier_character(Character) :-
137 digit(Character).
138
139identifier_character("_").
140
141digit(Character) :-
142 Character >= "0", Character =< "9".
143
144letter(Character) :-
145 Character >= "a", Character =< "z".
146
147letter(Character) :-
148 Character >= "A", Character =< "Z"