34
35:- module(prolog_predicate, []). 36:- use_module(library(pce)). 37:- use_module(pce_arm). 38:- use_module(library(persistent_frame)). 39:- use_module(library(tabbed_window)). 40:- use_module(library(tabular)). 41:- require([ atomic_list_concat/2
42 , term_to_atom/2
43 ]). 44
45:- if(exists_source(library(helpidx))). 46:- use_module(library(helpidx), [predicate/5]). 47:- endif. 48
54
55:- pce_begin_class(prolog_predicate, object,
56 ).
57
58variable(module, name*, get, ).
59variable(name, name, get, ).
60variable(arity, ['0..'], get, ).
61
62initialise(P, Term:prolog) :->
63 ::
64 ( Term = Module:Name/Arity
65 -> true
66 ; Term = Name/Arity
67 -> Module = @nil
68 ; Term = Module:Head,
69 callable(Head)
70 -> functor(Head, Name, Arity)
71 ; callable(Term)
72 -> functor(Term, Name, Arity),
73 Module = @nil
74 ),
75 ( var(Arity)
76 -> Arity = @default
77 ; true
78 ),
79 ( var(Module)
80 -> Module = @nil
81 ; true
82 ),
83 send(P, slot, module, Module),
84 send(P, slot, name, Name),
85 send(P, slot, arity, Arity).
86
87convert(_, From:name, P:prolog_predicate) :<-
88 ::
89 catch(term_to_atom(From, Term), _, fail),
90 ( ( Term = _:_/_
91 ; Term = _/_
92 )
93 -> new(P, prolog_predicate(Term))
94 ; Term = Module:Head,
95 callable(Head)
96 -> functor(Head, Name, Arity),
97 new(P, prolog_predicate(Module:Name/Arity))
98 ; callable(Term)
99 -> functor(Term, Name, Arity),
100 new(P, prolog_predicate(Name/Arity))
101 ).
102
103print_name(P, PN:name) :<-
104 ::
105 get(P, name, Name),
106 get(P, arity, Arity),
107 get(P, module, Module),
108 ( Module \== @nil,
109 Arity \== @default
110 -> functor(Head, Name, Arity), 111 ( user:prolog_predicate_name(Module:Head, PN)
112 -> true
113 ; \+ hidden_module(Module, Head)
114 -> atomic_list_concat([Module, :, Name, /, Arity], PN)
115 ; atomic_list_concat([Name, /, Arity], PN)
116 )
117 ; ( Arity == @default
118 -> End = ['/_']
119 ; End = [/, Arity]
120 )
121 -> ( Module == @nil
122 -> atomic_list_concat([Name|End], PN)
123 ; atomic_list_concat([Module, :, Name|End], PN)
124 )
125 ).
126
127hidden_module(system, _).
128hidden_module(user, _).
129hidden_module(M, H) :-
130 predicate_property(system:H, imported_from(M)).
131
132head(P, Qualify:[bool], Head:prolog) :<-
133 ::
134 get(P, module, Module),
135 get(P, name, Name),
136 get(P, arity, Arity),
137 Arity \== @default,
138 functor(Head0, Name, Arity),
139 qualify(Qualify, Module, Head0, Head).
140
141qualify(Qualify, Module, Head0, Head) :-
142 ( ( Qualify == @off
143 ; Qualify == @default,
144 Module == @nil
145 )
146 -> Head = Head0
147 ; Module \== @nil
148 -> Head = Module:Head0
149 ; Head = user:Head0
150 ).
151
152pi(P, Qualify:[bool], PI:prolog) :<-
153 ::
154 get(P, module, Module),
155 get(P, name, Name),
156 get(P, arity, Arity),
157 ( Arity == @default
158 -> PI0 = Name/_
159 ; PI0 = Name/Arity
160 ),
161 qualify(Qualify, Module, PI0, PI).
162
163
171
172source(P, Autoload:[bool], Loc:source_location) :<-
173 ::
174 get(P, head, Head0),
175 ( Head0 = _:_
176 -> Head = Head0
177 ; Head = _:Head0
178 ),
179 ( predicate_property(Head, file(File))
180 -> true
181 ; Autoload \== @off,
182 send(P, autoload),
183 predicate_property(Head, file(File))
184 ),
185 ( predicate_property(Head, line_count(Line))
186 -> new(Loc, source_location(File, Line))
187 ; new(Loc, source_location(File))
188 ).
189
190
191edit(P) :->
192 ::
193 get(P, head, @on, Head),
194 edit(Head).
195
196
197autoload(P, Module:[name]) :->
198 ::
199 get(P, head, @off, Term),
200 ( Module == @default
201 -> '$define_predicate'(Term)
202 ; '$define_predicate'(Module:Term)
203 ).
204
205has_property(P, Prop:prolog) :->
206 ::
207 get(P, head, Head),
208 predicate_property(Head, Prop).
209
210help(P) :->
211 ::
212 get(P, head, @off, Head),
213 functor(Head, Name, Arity),
214 ( help(Name/Arity)
215 -> true
216 ; send(P, report, warning, 'Cannot find help for %s/%d', Name, Arity)
217 ).
218
219has_help(P) :->
220 ::
221 get(P, summary, _).
222
223summary(P, Summary:string) :<-
224 get(P, name, Name),
225 get(P, arity, Arity),
226 ( catch(predicate(Name, Arity, Summary0, _, _), _, fail),
227 new(Summary, string('%s', Summary0))
228 -> true
229 ; ( get(P, module, M),
230 M \== @nil
231 -> true
232 ; M = _
233 ),
234 summary(M:Name/Arity, Summary)
235 ).
236
237:- multifile
238 prolog:predicate_summary/2. 239
240summary(PI, Summary) :-
241 prolog:predicate_summary(PI, Summary).
242
243info(P) :->
244 ::
245 ( get(P, head, Head),
246 predicate_property(Head, imported_from(M2))
247 -> get(P, pi, @off, PI),
248 send(prolog_predicate_frame(prolog_predicate(M2:PI)), open)
249 ; send(prolog_predicate_frame(P), open)
250 ).
251
252:- pce_end_class(prolog_predicate).
253
254
255:- pce_begin_class(prolog_predicate_frame, persistent_frame,
256 ).
257
258variable(predicate, prolog_predicate, get, ).
259
260initialise(F, P:prolog_predicate) :->
261 ::
262 send_super(F, initialise, string('Info for %s', P?print_name)),
263 send(F, slot, predicate, P),
264 send(F, append, new(tabbed_window)),
265 send(F, add_general_info),
266 send(F, add_documentation),
267 send(F, add_callers).
268
269add_general_info(F) :->
270 ::
271 get(F, predicate, P),
272 get(F, member, tabbed_window, TW),
273 send(TW, append, prolog_predicate_info_window(P)).
274
275add_documentation(_F) :->
276 ::
277 true.
278
279add_callers(_F) :->
280 ::
281 true.
282
283:- pce_end_class(prolog_predicate_frame).
284
285
286:- pce_begin_class(prolog_predicate_info_window, window,
287 ).
288:- use_class_template(arm).
289
290variable(tabular, tabular, get, ).
291variable(predicate, prolog_predicate, get, ).
292
293initialise(W, P:prolog_predicate) :->
294 ::
295 send_super(W, initialise),
296 send(W, name, properties),
297 send(W, pen, 0),
298 send(W, scrollbars, vertical),
299 send(W, display, new(T, tabular)),
300 send(T, rules, all),
301 send(T, cell_spacing, -1),
302 send(W, slot, tabular, T),
303 send(W, predicate, P).
304
305resize(W) :->
306 send_super(W, resize),
307 get(W?visible, width, Width),
308 send(W?tabular, table_width, Width-3).
309
310clear(W) :->
311 send(W?tabular, clear).
312
313predicate(W, P:prolog_predicate) :->
314 send(W, slot, predicate, P),
315 send(W, update).
316
317update(W) :->
318 get(W, predicate, P),
319 send(W, clear),
320 get(P, pi, PI),
321 ( PI = _:_
322 -> QPI = PI
323 ; QPI = _:PI
324 ),
325 forall(setof(Prop, pi_property(QPI, Prop), Props),
326 send(W, properties, QPI, Props)).
327
328pi_property(M:Name/Arity, Prop) :-
329 integer(Arity),
330 functor(Head, Name, Arity),
331 current_predicate(M:Name/Arity),
332 \+ predicate_property(M:Head, imported_from(_)),
333 predicate_property(M:Head, Prop).
334pi_property(M:Name/_, Prop) :-
335 current_predicate(M:Name, Head),
336 \+ predicate_property(M:Head, imported_from(_)),
337 predicate_property(M:Head, Prop).
338
339properties(W, QPI:prolog, Props:prolog) :->
340 ::
341 get(W, tabular, T),
342 format(atom(AQPI), '~q', [QPI]),
343 BG = (background := khaki1),
344 send(T, append, AQPI, halign := center, colspan := 2, BG),
345 send(T, next_row),
346 partition(atom, Props, Atomic, Valued),
347 ( select(file(File), Valued, Valued1),
348 select(line_count(Line), Valued1, Valued2)
349 -> send(T, append, 'Source:', bold, right),
350 send(T, append, source_location_text(source_location(File,Line))),
351 send(T, next_row)
352 ; Valued2 = Valued
353 ),
354 delete(Atomic, visible, Atomic1),
355 ( memberchk(meta_predicate(_), Valued2)
356 -> delete(Atomic1, transparent, Atomic2)
357 ; Atomic2 = Atomic1
358 ),
359 forall(member(P, Valued2), send(W, property, P)),
360 atomic_list_concat(Atomic2, ', ', AtomicText),
361 send(T, append, 'Flags:', bold, right),
362 send(T, append, AtomicText),
363 send(T, next_row).
364
365property(W, Prop:prolog) :->
366 ::
367 get(W, tabular, T),
368 ( Prop =.. [Name,Value]
369 -> send(T, append, string('%s:', Name?label_name), bold, right),
370 format(atom(AValue), '~q', [Value]),
371 send(T, append, AValue)
372 ; send(T, append, Prop?label_name, colspan := 2)
373 ),
374 send(T, next_row).
375
376:- pce_end_class(prolog_predicate_info_window).
377
378
379:- pce_begin_class(source_location_text, text,
380 ).
381
382variable(location, source_location, get, ).
383
384initialise(T, Loc:source_location) :->
385 ::
386 send_super(T, initialise, Loc?print_name),
387 send(T, slot, location, Loc).
388
389:- pce_global(@source_location_text_recogniser,
390 new(handler_group(@arm_recogniser,
391 click_gesture(left, '', single,
392 message(@receiver, edit))))).
393
394event(T, Ev:event) :->
395 ( send_super(T, event, Ev)
396 -> true
397 ; send(@source_location_text_recogniser, event, Ev)
398 ).
399
400
401arm(TF, Val:bool) :->
402 ::
403 ( Val == @on
404 -> send(TF, underline, @on)
405 ; send(TF, underline, @off)
406 ).
407
408edit(T) :->
409 get(T, location, Loc),
410 send(@emacs, goto_source_location, Loc, tab).
411
412:- pce_end_class(source_location_text)