1:- module(lsp_colours, [file_colours/2,
2 file_range_colours/4,
3 token_types/1,
4 token_modifiers/1]).
12:- use_module(library(apply), [maplist/4]). 13:- use_module(library(apply_macros)). 14:- use_module(library(debug), [debug/3]). 15:- use_module(library(lists), [numlist/3, nth0/3]). 16:- use_module(library(prolog_colour), [prolog_colourise_stream/3,
17 prolog_colourise_term/4]). 18:- use_module(library(prolog_source), [read_source_term_at_location/3]). 19:- use_module(library(yall)). 20
21:- include('_lsp_path_add.pl'). 22:- use_module(lsp(lsp_changes), [doc_text/2]). 23:- use_module(lsp(lsp_utils), [seek_to_line/2,
24 linechar_offset/3]). 25
26token_types([namespace,
27 type,
28 class,
29 enum,
30 interface,
31 struct,
32 typeParameter,
33 parameter,
34 variable,
35 property,
36 enumMember,
37 event,
38 function,
39 member,
40 macro,
41 keyword,
42 modifier,
43 comment,
44 string,
45 number,
46 regexp,
47 operator
48 ]).
49token_modifiers([declaration,
50 definition,
51 readonly,
52 static,
53 deprecated,
54 abstract,
55 async,
56 modification,
57 documentation,
58 defaultLibrary
59 ]).
60
61token_types_dict(Dict) :-
62 token_types(Types),
63 length(Types, Len),
64 Len0 is Len - 1,
65 numlist(0, Len0, Ns),
66 maplist([Type, Idx, Type-Idx]>>true, Types, Ns,
67 Pairs),
68 dict_create(Dict, _, Pairs).
74file_colours(File, Tuples) :-
75 file_colours_helper(File, Colours0),
76 sort(2, @=<, Colours0, Colours),
77 flatten_colour_terms(File, Colours, Tuples).
84file_range_colours(File, Start, End, Tuples) :-
85 file_term_colours_helper(File, Start, End, Colours0),
86 sort(2, @=<, Colours0, Colours),
87 flatten_colour_terms(File, Colours, Tuples).
88
89file_stream(File, S) :-
90 ( doc_text(File, Changes)
91 -> open_string(Changes, S)
92 ; open(File, read, S) ),
93 set_stream(S, newline(posix)).
101flatten_colour_terms(File, ColourTerms, Nums) :-
102 token_types_dict(TokenDict),
103 setup_call_cleanup(
104 file_stream(File, S),
105 ( seek(S, 0, bof, _),
106 phrase(colour_term_to_tuple(S, TokenDict, 0, 1, 0),
107 ColourTerms,
108 Nums)
109 ),
110 close(S)
111 ).
112
113colour_term_to_tuple(Stream, Dict, LastOffset, LastLine, LastChar), R -->
114 [colour(Type, NewOffset, Len)], !,
115 { ( colour_type(Type, TypeCategory, Mods),
116 get_dict(TypeCategory, Dict, TypeCode),
117 mods_mask(Mods, ModMask) )
118 -> Seek is NewOffset - LastOffset,
119 Offset = NewOffset,
120 stream_seek_line_position(Stream, Seek, Line, Char),
121 ( Line == LastLine
122 -> DeltaLine = 0,
123 DeltaStart is Char - LastChar
124 ; DeltaLine is Line - LastLine,
125 DeltaStart = Char ),
126 R = [DeltaLine, DeltaStart, Len, TypeCode, ModMask]
127 ; R = [],
128 Offset = LastOffset, Line = LastLine, Char = LastChar
129 },
130 colour_term_to_tuple(Stream, Dict, Offset, Line, Char).
131colour_term_to_tuple(_, _, _, _, _) --> [].
138stream_seek_line_position(Stream, Seek, Line, LineChar) :-
139 setup_call_cleanup(open_null_stream(NullStream),
140 ( set_stream(NullStream, newline(posix)),
141 copy_stream_data(Stream, NullStream, Seek) ),
142 close(NullStream)),
143 stream_property(Stream, position(Pos)),
144 stream_position_data(line_count, Pos, Line),
145 146 147 line_position_characters(Stream, Pos, LineChar).
148
149line_position_characters(Stream, Pos, Char) :-
150 stream_position_data(char_count, Pos, StartChar),
151 stream_position_data(line_count, Pos, StartLine),
152 ( StartLine > 1
153 -> ( repeat,
154 seek(Stream, -1, current, _),
155 peek_code(Stream, 0'\n), !,
156 get_code(Stream, _) )
157 ; seek(Stream, 0, bof, _) ),
158 character_count(Stream, StartOfLine),
159 ( repeat,
160 character_count(Stream, CharHere),
161 get_code(Stream, _),
162 CharHere >= StartChar, !
163 ),
164 Char is max(0, CharHere - StartOfLine),
165 set_stream_position(Stream, Pos).
166
167colour_type(directive, namespace, []).
168
169colour_type(head(_, _), function, [declaration]).
171colour_type(neck(directive), operator, [declaration]).
172colour_type(neck(':-'), operator, [declaration]).
173colour_type(neck(clause), operator, [definition]).
174colour_type(neck(grammar_rule), operator, [definition]).
175colour_type(goal(built_in, A), macro, []) :- atom(A), !.
176colour_type(goal(built_in, _), function, [defaultLibrary]).
177colour_type(goal(undefined, _), function, []).
178colour_type(goal(imported(_), _), function, []).
179colour_type(goal(local(_), _), function, []).
180colour_type(goal(extern(_,_), _), function, []).
181colour_type(goal(recursion, _), member, []).
182colour_type(goal(('dynamic'(_)), _), member, []).
191colour_type(atom, string, []).
192colour_type(var, variable, []).
193colour_type(singleton, variable, [readonly]).
194colour_type(fullstop, operator, []).
195colour_type(control, operator, []).
196colour_type(dict_key, property, []).
197colour_type(dict_sep, operator, []).
198colour_type(string, string, []).
199colour_type(int, number, []).
200colour_type(comment(line), comment, []).
201colour_type(comment(structured), comment, [documentation]).
202colour_type(arity, parameter, []).
203colour_type(functor, struct, []).
204colour_type(option_name, struct, []).
205colour_type(predicate_indicator, interface, []).
206colour_type(predicate_indicator(_, _), interface, []).
207colour_type(unused_import, macro, [deprecated]).
208colour_type(undefined_import, macro, [deprecated]).
209colour_type(dcg, regexp, []).
210colour_type(dcg(terminal), regexp, []).
211colour_type(dcg(plain), function, []).
212colour_type(dcg_right_hand_ctx, regexp, []).
213colour_type(grammar_rule, regexp, []).
214colour_type(identifier, namespace, []).
215colour_type(file(_), namespace, []).
216colour_type(file_no_depend(_), namespace, [abstract]).
217colour_type(module(_), namespace, []).
218
219mods_mask(Mods, Mask) :-
220 mods_mask(Mods, 0, Mask).
221
222mods_mask([], Mask, Mask).
223mods_mask([Mod|Mods], Mask0, Mask) :-
224 token_modifiers(ModsList),
225 nth0(N, ModsList, Mod),
226 Mask1 is Mask0 \/ (1 << N),
227 mods_mask(Mods, Mask1, Mask).
228
235file_colours_helper(File, Info) :-
236 Acc = acc([]),
237 setup_call_cleanup(
238 file_stream(File, S),
239 prolog_colourise_stream(
240 S, File,
241 {Acc}/[Cat, Start, Len]>>(
242 arg(1, Acc, Data),
243 nb_setarg(1, Acc, [colour(Cat, Start, Len)|Data])
244 )
245 ),
246 close(S)
247 ),
248 arg(1, Acc, Info).
249
250nearest_term_start(Stream, StartL, TermStart) :-
251 read_source_term_at_location(Stream, _, [line(StartL), error(Error)]),
252 ( nonvar(Error)
253 -> ( LineBack is StartL - 1,
254 nearest_term_start(Stream, LineBack, TermStart) )
255 ; TermStart = StartL
256 ).
257
258file_term_colours_helper(File, line_char(StartL, _StartC), End, Info) :-
259 Acc = acc([]),
260 setup_call_cleanup(
261 file_stream(File, S),
262 ( nearest_term_start(S, StartL, TermLine),
263 seek(S, 0, bof, _),
264 set_stream_position(S, '$stream_position'(0,0,0,0)),
265 seek_to_line(S, TermLine),
266 colourise_terms_to_position(Acc, File, S, 0-0, End)
267 ),
268 close(S)
269 ),
270 arg(1, Acc, Info).
271
272colourise_terms_to_position(Acc, File, Stream, Prev, End) :-
273 once(prolog_colourise_term(
274 Stream, File,
275 {Acc}/[Cat, Start, Len]>>(
276 arg(1, Acc, Tail),
277 nb_setarg(1, Acc, [colour(Cat, Start, Len)|Tail])),
278 [])),
279 stream_property(Stream, position(Pos)),
280 stream_position_data(line_count, Pos, Line),
281 stream_position_data(line_position, Pos, Char),
282 End = line_char(EndL, EndC),
283 ( Line-Char == Prev
284 -> true
285 ; EndL =< Line
286 -> true
287 ; ( EndL == Line, EndC =< Char )
288 -> true
289 ; colourise_terms_to_position(Acc, File, Stream, Line-Char, End)
290 )
LSP Colours
Module with predicates for colourizing Prolog code, via library(prolog_colour).