35
36:- module(pldoc_latex,
37 [ doc_latex/3, 38 latex_for_file/3, 39 latex_for_wiki_file/3, 40 latex_for_predicates/3 41 ]). 42:- use_module(library(pldoc)). 43:- use_module(library(readutil)). 44:- use_module(library(error)). 45:- use_module(library(apply)). 46:- use_module(library(option)). 47:- use_module(library(lists)). 48:- use_module(library(debug)). 49:- use_module(pldoc(doc_wiki)). 50:- use_module(pldoc(doc_process)). 51:- use_module(pldoc(doc_modes)). 52:- use_module(library(pairs), [pairs_values/2]). 53:- use_module(library(prolog_source), [file_name_on_path/2]). 54:- use_module(library(prolog_xref), [xref_hook/1]). 55:- use_module(pldoc(doc_html), 56 [ doc_file_objects/5, 57 unquote_filespec/2,
58 doc_tag_title/2,
59 existing_linked_file/2,
60 pred_anchor_name/3,
61 private/2,
62 (multifile)/2,
63 is_pi/1,
64 is_op_type/2
65 ]). 66
87
88:- predicate_options(doc_latex/3, 3,
89 [ stand_alone(boolean),
90 public_only(boolean),
91 section_level(oneof([section,subsection,subsubsection])),
92 summary(atom)
93 ]). 94:- predicate_options(latex_for_file/3, 3,
95 [ stand_alone(boolean),
96 public_only(boolean),
97 section_level(oneof([section,subsection,subsubsection]))
98 ]). 99:- predicate_options(latex_for_predicates/3, 3,
100 [ 101 ]). 102:- predicate_options(latex_for_wiki_file/3, 3,
103 [ stand_alone(boolean),
104 public_only(boolean),
105 section_level(oneof([section,subsection,subsubsection]))
106 ]). 107
108
109:- thread_local
110 options/1,
111 documented/1. 112
113current_options(Options) :-
114 options(Current),
115 !,
116 Options = Current.
117current_options([]).
118
154
155doc_latex(Spec, OutFile, Options) :-
156 load_urldefs,
157 merge_options(Options,
158 [ include_reexported(true)
159 ],
160 Options1),
161 retractall(documented(_)),
162 setup_call_cleanup(
163 asserta(options(Options), Ref),
164 phrase(process_items(Spec, [body], Options1), Tokens),
165 erase(Ref)),
166 setup_call_cleanup(
167 open(OutFile, write, Out),
168 print_latex(Out, Tokens, Options1),
169 close(Out)),
170 latex_summary(Options).
171
172process_items([], Mode, _) -->
173 !,
174 pop_mode(body, Mode, _).
175process_items([H|T], Mode, Options) -->
176 process_items(H, Mode, Mode1, Options),
177 process_items(T, Mode1, Options).
178process_items(Spec, Mode, Options) -->
179 {Mode = [Mode0|_]},
180 process_items(Spec, Mode, Mode1, Options),
181 pop_mode(Mode0, Mode1, _).
182
183process_items(PI, Mode0, Mode, Options) -->
184 { is_pi(PI) },
185 !,
186 need_mode(description, Mode0, Mode),
187 latex_tokens_for_predicates(PI, Options).
188process_items(FileSpec, Mode0, Mode, Options) -->
189 { ( absolute_file_name(FileSpec,
190 [ file_type(source),
191 access(read),
192 file_errors(fail)
193 ],
194 File)
195 -> true
196 ; absolute_file_name(FileSpec,
197 [ access(read)
198 ],
199 File)
200 ),
201 file_name_extension(_Base, Ext, File)
202 },
203 need_mode(body, Mode0, Mode),
204 ( { user:prolog_file_type(Ext, prolog) }
205 -> latex_tokens_for_file(File, Options)
206 ; latex_tokens_for_wiki_file(File, Options)
207 ).
208
209
216
217latex_for_file(FileSpec, Out, Options) :-
218 load_urldefs,
219 phrase(latex_tokens_for_file(FileSpec, Options), Tokens),
220 print_latex(Out, Tokens, Options).
221
222
224
225latex_tokens_for_file(FileSpec, Options, Tokens, Tail) :-
226 absolute_file_name(FileSpec,
227 [ file_type(prolog),
228 access(read)
229 ],
230 File),
231 doc_file_objects(FileSpec, File, Objects, FileOptions, Options),
232 asserta(options(Options), Ref),
233 call_cleanup(phrase(latex([ \file_header(File, FileOptions)
234 | \objects(Objects, FileOptions)
235 ]),
236 Tokens, Tail),
237 erase(Ref)).
238
239
246
247latex_for_wiki_file(FileSpec, Out, Options) :-
248 load_urldefs,
249 phrase(latex_tokens_for_wiki_file(FileSpec, Options), Tokens),
250 print_latex(Out, Tokens, Options).
251
252latex_tokens_for_wiki_file(FileSpec, Options, Tokens, Tail) :-
253 absolute_file_name(FileSpec, File,
254 [ access(read)
255 ]),
256 read_file_to_codes(File, String, []),
257 b_setval(pldoc_file, File),
258 asserta(options(Options), Ref),
259 call_cleanup((wiki_codes_to_dom(String, [], DOM),
260 phrase(latex(DOM), Tokens, Tail)
261 ),
262 (nb_delete(pldoc_file),
263 erase(Ref))).
264
265
272
273latex_for_predicates(Spec, Out, Options) :-
274 load_urldefs,
275 phrase(latex_tokens_for_predicates(Spec, Options), Tokens),
276 print_latex(Out, [nl_exact(0)|Tokens], Options).
277
278latex_tokens_for_predicates([], _Options) --> !.
279latex_tokens_for_predicates([H|T], Options) -->
280 !,
281 latex_tokens_for_predicates(H, Options),
282 latex_tokens_for_predicates(T, Options).
283latex_tokens_for_predicates(PI, Options) -->
284 { generic_pi(PI),
285 !,
286 ( doc_comment(PI, Pos, _Summary, Comment)
287 -> true
288 ; Comment = ''
289 )
290 },
291 object(PI, Pos, Comment, [description], _, Options).
292latex_tokens_for_predicates(Spec, Options) -->
293 { findall(PI, documented_pi(Spec, PI, Options), List),
294 ( List == []
295 -> print_message(warning, pldoc(no_predicates_from(Spec)))
296 ; true
297 )
298 },
299 latex_tokens_for_predicates(List, Options).
300
301documented_pi(Spec, PI, Options) :-
302 option(modules(List), Options),
303 member(M, List),
304 generalise_spec(Spec, PI, M),
305 doc_comment(PI, _Pos, _Summary, _Comment),
306 !.
307documented_pi(Spec, PI, Options) :-
308 option(module(M), Options),
309 generalise_spec(Spec, PI, M),
310 doc_comment(PI, _Pos, _Summary, _Comment),
311 !.
312documented_pi(Spec, PI, _Options) :-
313 generalise_spec(Spec, PI, _),
314 doc_comment(PI, _Pos, _Summary, _Comment).
315
316generic_pi(Module:Name/Arity) :-
317 atom(Module), atom(Name), integer(Arity),
318 !.
319generic_pi(Module:Name//Arity) :-
320 atom(Module), atom(Name), integer(Arity).
321
322generalise_spec(Name/Arity, M:Name/Arity, M).
323generalise_spec(Name//Arity, M:Name//Arity, M).
324
325
326 329
330:- thread_local
331 fragile/0. 332
333latex([]) -->
334 !,
335 [].
336latex(Atomic) -->
337 { string(Atomic),
338 atom_string(Atom, Atomic),
339 sub_atom(Atom, 0, _, 0, 'LaTeX')
340 },
341 !,
342 [ latex('\\LaTeX{}') ].
343latex(Atomic) --> 344 { atomic(Atomic),
345 !,
346 atom_string(Atom, Atomic),
347 findall(x, sub_atom(Atom, _, _, _, '\n'), Xs),
348 length(Xs, Lines)
349 },
350 ( {Lines == 0}
351 -> [ Atomic ]
352 ; [ nl(Lines) ]
353 ).
354latex(List) -->
355 latex_special(List, Rest),
356 !,
357 latex(Rest).
358latex(w(Word)) -->
359 [ Word ].
360latex([H|T]) -->
361 !,
362 ( latex(H)
363 -> latex(T)
364 ; { print_message(error, latex(failed(H))) },
365 latex(T)
366 ).
367
369latex(h1(Attrs, Content)) -->
370 latex_section(0, Attrs, Content).
371latex(h2(Attrs, Content)) -->
372 latex_section(1, Attrs, Content).
373latex(h3(Attrs, Content)) -->
374 latex_section(2, Attrs, Content).
375latex(h4(Attrs, Content)) -->
376 latex_section(3, Attrs, Content).
377latex(p(Content)) -->
378 [ nl_exact(2) ],
379 latex(Content).
380latex(blockquote(Content)) -->
381 latex(cmd(begin(quote))),
382 latex(Content),
383 latex(cmd(end(quote))).
384latex(center(Content)) -->
385 latex(cmd(begin(center))),
386 latex(Content),
387 latex(cmd(end(center))).
388latex(a(Attrs, Content)) -->
389 { attribute(href(HREF), Attrs) },
390 ( {HREF == Content}
391 -> latex(cmd(url(url_escape(HREF))))
392 ; { atom_concat(#,Sec,HREF) }
393 -> latex([Content, ' (', cmd(secref(Sec)), ')'])
394 ; latex(cmd(href(url_escape(HREF), Content)))
395 ).
396latex(br(_)) -->
397 latex(latex(\\)).
398latex(hr(_)) -->
399 latex(cmd(hrule)).
400latex(code(CodeList)) -->
401 { is_list(CodeList),
402 !,
403 atomic_list_concat(CodeList, Atom)
404 },
405 ( {fragile}
406 -> latex(cmd(const(Atom)))
407 ; [ verb(Atom) ]
408 ).
409latex(code(Code)) -->
410 { identifier(Code) },
411 !,
412 latex(cmd(const(Code))).
413latex(code(Code)) -->
414 ( {fragile}
415 -> latex(cmd(const(Code)))
416 ; [ verb(Code) ]
417 ).
418latex(b(Code)) -->
419 latex(cmd(textbf(Code))).
420latex(strong(Code)) -->
421 latex(cmd(textbf(Code))).
422latex(i(Code)) -->
423 latex(cmd(textit(Code))).
424latex(var(Var)) -->
425 latex(cmd(arg(Var))).
426latex(pre(_Class, Code)) -->
427 [ nl_exact(2), code(Code), nl_exact(2) ].
428latex(ul(Content)) -->
429 { if_short_list(Content, shortlist, itemize, Env) },
430 latex(cmd(begin(Env))),
431 latex(Content),
432 latex(cmd(end(Env))).
433latex(ol(Content)) -->
434 latex(cmd(begin(enumerate))),
435 latex(Content),
436 latex(cmd(end(enumerate))).
437latex(li(Content)) -->
438 latex(cmd(item)),
439 latex(Content).
440latex(dl(_, Content)) -->
441 latex(cmd(begin(description))),
442 latex(Content),
443 latex(cmd(end(description))).
444latex(dd(_, Content)) -->
445 latex(Content).
446latex(dd(Content)) -->
447 latex(Content).
448latex(dt(class=term, \term(Text, Term, Bindings))) -->
449 termitem(Text, Term, Bindings).
450latex(dt(Content)) -->
451 latex(cmd(item(opt(Content)))).
452latex(table(Attrs, Content)) -->
453 latex_table(Attrs, Content).
454latex(\Cmd, List, Tail) :-
455 call(Cmd, List, Tail).
456
458latex(latex(Text)) -->
459 [ latex(Text) ].
460latex(cmd(Term)) -->
461 { Term =.. [Cmd|Args] },
462 indent(Cmd),
463 [ cmd(Cmd) ],
464 latex_arguments(Args),
465 outdent(Cmd).
466
467indent(begin) --> !, [ nl(2) ].
468indent(end) --> !, [ nl_exact(1) ].
469indent(section) --> !, [ nl(2) ].
470indent(subsection) --> !, [ nl(2) ].
471indent(subsubsection) --> !, [ nl(2) ].
472indent(item) --> !, [ nl(1), indent(4) ].
473indent(definition) --> !, [ nl(1), indent(4) ].
474indent(tag) --> !, [ nl(1), indent(4) ].
475indent(termitem) --> !, [ nl(1), indent(4) ].
476indent(prefixtermitem) --> !, [ nl(1), indent(4) ].
477indent(infixtermitem) --> !, [ nl(1), indent(4) ].
478indent(postfixtermitem) --> !, [ nl(1), indent(4) ].
479indent(predicate) --> !, [ nl(1), indent(4) ].
480indent(dcg) --> !, [ nl(1), indent(4) ].
481indent(infixop) --> !, [ nl(1), indent(4) ].
482indent(prefixop) --> !, [ nl(1), indent(4) ].
483indent(postfixop) --> !, [ nl(1), indent(4) ].
484indent(predicatesummary) --> !,[ nl(1) ].
485indent(dcgsummary) --> !, [ nl(1) ].
486indent(oppredsummary) --> !, [ nl(1) ].
487indent(hline) --> !, [ nl(1) ].
488indent(_) --> [].
489
490outdent(begin) --> !, [ nl_exact(1) ].
491outdent(end) --> !, [ nl(2) ].
492outdent(item) --> !, [ ' ' ].
493outdent(tag) --> !, [ nl(1) ].
494outdent(termitem) --> !, [ nl(1) ].
495outdent(prefixtermitem) --> !, [ nl(1) ].
496outdent(infixtermitem) --> !, [ nl(1) ].
497outdent(postfixtermitem) --> !, [ nl(1) ].
498outdent(definition) --> !, [ nl(1) ].
499outdent(section) --> !, [ nl(2) ].
500outdent(subsection) --> !, [ nl(2) ].
501outdent(subsubsection) --> !, [ nl(2) ].
502outdent(predicate) --> !, [ nl(1) ].
503outdent(dcg) --> !, [ nl(1) ].
504outdent(infixop) --> !, [ nl(1) ].
505outdent(prefixop) --> !, [ nl(1) ].
506outdent(postfixop) --> !, [ nl(1) ].
507outdent(predicatesummary) --> !,[ nl(1) ].
508outdent(dcgsummary) --> !, [ nl(1) ].
509outdent(oppredsummary) --> !, [ nl(1) ].
510outdent(hline) --> !, [ nl(1) ].
511outdent(_) --> [].
512
513fragile_latex(Content, In, Out) :-
514 setup_call_cleanup(
515 asserta(fragile, Ref),
516 phrase(latex(Content), In, Out),
517 erase(Ref)).
518
522
523latex_special(In, Rest) -->
524 { url_chars(In, Chars, Rest),
525 special(Chars),
526 atom_chars(Atom, Chars),
527 urldef_name(Atom, Name)
528 },
529 !,
530 latex([cmd(Name), latex('{}')]).
531
532special(Chars) :-
533 memberchk(\, Chars),
534 !.
535special(Chars) :-
536 length(Chars, Len),
537 Len > 1.
538
539url_chars([H|T0], [H|T], Rest) :-
540 urlchar(H),
541 !,
542 url_chars(T0, T, Rest).
543url_chars(L, [], L).
544
545
556
557latex_arguments(List, Out, Tail) :-
558 asserta(fragile, Ref),
559 call_cleanup(fragile_list(List, Out, Tail),
560 erase(Ref)).
561
562fragile_list([]) --> [].
563fragile_list([opt([])|T]) -->
564 !,
565 fragile_list(T).
566fragile_list([opt(H)|T]) -->
567 !,
568 [ '[' ],
569 latex_arg(H),
570 [ ']' ],
571 fragile_list(T).
572fragile_list([H|T]) -->
573 [ curl(open) ],
574 latex_arg(H),
575 [ curl(close) ],
576 fragile_list(T).
577
582
583latex_arg(H) -->
584 { atomic(H),
585 atom_string(Atom, H),
586 urldef_name(Atom, Name)
587 },
588 !,
589 latex(cmd(Name)).
590latex_arg(H) -->
591 { maplist(atom, H),
592 atomic_list_concat(H, Atom),
593 urldef_name(Atom, Name)
594 },
595 !,
596 latex(cmd(Name)).
597latex_arg(no_escape(Text)) -->
598 !,
599 [no_escape(Text)].
600latex_arg(url_escape(Text)) -->
601 !,
602 [url_escape(Text)].
603latex_arg(H) -->
604 latex(H).
605
606attribute(Att, Attrs) :-
607 is_list(Attrs),
608 !,
609 option(Att, Attrs).
610attribute(Att, One) :-
611 option(Att, [One]).
612
613if_short_list(Content, If, Else, Env) :-
614 ( short_list(Content)
615 -> Env = If
616 ; Env = Else
617 ).
618
623
624short_list([]).
625short_list([_,dd(Content)|T]) :-
626 !,
627 short_content(Content),
628 short_list(T).
629short_list([_,dd(_, Content)|T]) :-
630 !,
631 short_content(Content),
632 short_list(T).
633short_list([li(Content)|T]) :-
634 short_content(Content),
635 short_list(T).
636
637short_content(Content) :-
638 phrase(latex(Content), Tokens),
639 summed_string_len(Tokens, 0, Len),
640 Len < 50.
641
642summed_string_len([], Len, Len).
643summed_string_len([H|T], L0, L) :-
644 atomic(H),
645 !,
646 atom_length(H, AL),
647 L1 is L0 + AL,
648 summed_string_len(T, L1, L).
649summed_string_len([_|T], L0, L) :-
650 summed_string_len(T, L0, L).
651
652
660
661latex_section(Level, Attrs, Content) -->
662 { current_options(Options),
663 option(section_level(LaTexSection), Options, section),
664 latex_section_level(LaTexSection, BaseLevel),
665 FinalLevel is BaseLevel+Level,
666 ( latex_section_level(SectionCommand, FinalLevel)
667 -> Term =.. [SectionCommand, Content]
668 ; domain_error(latex_section_level, FinalLevel)
669 )
670 },
671 latex(cmd(Term)),
672 section_label(Attrs).
673
674section_label(Attrs) -->
675 { is_list(Attrs),
676 memberchk(id(Name), Attrs),
677 !,
678 delete_unsafe_label_chars(Name, SafeName),
679 atom_concat('sec:', SafeName, Label)
680 },
681 latex(cmd(label(Label))).
682section_label(_) -->
683 [].
684
685latex_section_level(chapter, 0).
686latex_section_level(section, 1).
687latex_section_level(subsection, 2).
688latex_section_level(subsubsection, 3).
689latex_section_level(paragraph, 4).
690
691deepen_section_level(Level0, Level1) :-
692 latex_section_level(Level0, N),
693 N1 is N + 1,
694 latex_section_level(Level1, N1).
695
701
702delete_unsafe_label_chars(LabelIn, LabelOut) :-
703 atom_chars(LabelIn, Chars),
704 delete(Chars, '_', CharsOut),
705 atom_chars(LabelOut, CharsOut).
706
707
708 711
715
716include(PI, predicate, _) -->
717 !,
718 ( { options(Options)
719 -> true
720 ; Options = []
721 },
722 latex_tokens_for_predicates(PI, Options)
723 -> []
724 ; latex(cmd(item(['[[', \predref(PI), ']]'])))
725 ).
726include(File, Type, Options) -->
727 { existing_linked_file(File, Path) },
728 !,
729 include_file(Path, Type, Options).
730include(File, _, _) -->
731 latex(code(['[[', File, ']]'])).
732
733include_file(Path, image, Options) -->
734 { option(caption(Caption), Options) },
735 !,
736 latex(cmd(begin(figure, [no_escape(htbp)]))),
737 latex(cmd(begin(center))),
738 latex(cmd(includegraphics(Path))),
739 latex(cmd(end(center))),
740 latex(cmd(caption(Caption))),
741 latex(cmd(end(figure))).
742include_file(Path, image, _) -->
743 !,
744 latex(cmd(includegraphics(Path))).
745include_file(Path, Type, _) -->
746 { assertion(memberchk(Type, [prolog,wiki])),
747 current_options(Options0),
748 select_option(stand_alone(_), Options0, Options1, _),
749 select_option(section_level(Level0), Options1, Options2, section),
750 deepen_section_level(Level0, Level),
751 Options = [stand_alone(false), section_level(Level)|Options2]
752 },
753 ( {Type == prolog}
754 -> latex_tokens_for_file(Path, Options)
755 ; latex_tokens_for_wiki_file(Path, Options)
756 ).
757
762
763file(File, _Options) -->
764 { fragile },
765 !,
766 latex(cmd(texttt(File))).
767file(File, _Options) -->
768 latex(cmd(file(File))).
769
774
775predref(Module:Name/Arity) -->
776 !,
777 latex(cmd(qpredref(Module, Name, Arity))).
778predref(Module:Name//Arity) -->
779 latex(cmd(qdcgref(Module, Name, Arity))).
780predref(Name/Arity) -->
781 latex(cmd(predref(Name, Arity))).
782predref(Name//Arity) -->
783 latex(cmd(dcgref(Name, Arity))).
784
788
789nopredref(Name/Arity) -->
790 latex(cmd(nopredref(Name, Arity))).
791
795
796flagref(Flag) -->
797 latex(cmd(prologflag(Flag))).
798
802
803cite(Citations) -->
804 { atomic_list_concat(Citations, ',', Atom) },
805 latex(cmd(cite(Atom))).
806
811
812tags([\args(Params)|Rest]) -->
813 !,
814 args(Params),
815 tags_list(Rest).
816tags(List) -->
817 tags_list(List).
818
819tags_list([]) -->
820 [].
821tags_list(List) -->
822 [ nl(2) ],
823 latex(cmd(begin(tags))),
824 latex(List),
825 latex(cmd(end(tags))),
826 [ nl(2) ].
827
831
832tag(Tag, [One]) -->
833 !,
834 { doc_tag_title(Tag, Title) },
835 latex([ cmd(tag(Title))
836 | One
837 ]).
838tag(Tag, More) -->
839 { doc_tag_title(Tag, Title) },
840 latex([ cmd(mtag(Title)),
841 \tag_value_list(More)
842 ]).
843
844tag_value_list([H|T]) -->
845 latex(['- '|H]),
846 ( { T \== [] }
847 -> [latex(' \\\\')],
848 tag_value_list(T)
849 ; []
850 ).
851
856
857args(Params) -->
858 latex([ cmd(begin(arguments)),
859 \arg_list(Params),
860 cmd(end(arguments))
861 ]).
862
863arg_list([]) -->
864 [].
865arg_list([H|T]) -->
866 argument(H),
867 arg_list(T).
868
869argument(arg(Name,Descr)) -->
870 [ nl(1) ],
871 latex(cmd(arg(Name))), [ latex(' & ') ],
872 latex(Descr), [latex(' \\\\')].
873
877
(File, Options) -->
879 { memberchk(file(Title, Comment), Options),
880 !,
881 file_synopsis(File, Synopsis, Options)
882 },
883 file_title([Synopsis, ': ', Title], File, Options),
884 { is_structured_comment(Comment, Prefixes),
885 string_codes(Comment, Codes),
886 indented_lines(Codes, Prefixes, Lines),
887 section_comment_header(Lines, _Header, Lines1),
888 wiki_lines_to_dom(Lines1, [], DOM0),
889 tags_to_front(DOM0, DOM)
890 },
891 latex(DOM),
892 latex(cmd(vspace('0.7cm'))).
893file_header(File, Options) -->
894 { file_synopsis(File, Synopsis, Options)
895 },
896 file_title([Synopsis], File, Options).
897
898tags_to_front(DOM0, DOM) :-
899 append(Content, [\tags(Tags)], DOM0),
900 !,
901 DOM = [\tags(Tags)|Content].
902tags_to_front(DOM, DOM).
903
904file_synopsis(_File, Synopsis, Options) :-
905 option(file_synopsis(Synopsis), Options),
906 !.
907file_synopsis(File, Synopsis, _) :-
908 file_name_on_path(File, Term),
909 unquote_filespec(Term, Unquoted),
910 format(atom(Synopsis), '~w', [Unquoted]).
911
912
916
917file_title(Title, File, Options) -->
918 { option(section_level(Level), Options, section),
919 Section =.. [Level,Title],
920 file_base_name(File, BaseExt),
921 file_name_extension(Base, _, BaseExt),
922 ( option(label(Seclabel), Options)
923 -> true
924 ; delete_unsafe_label_chars(Base, Seclabel)
925 ),
926 atom_concat('sec:', Seclabel, Label)
927 },
928 latex(cmd(Section)),
929 latex(cmd(label(Label))).
930
931
935
936objects(Objects, Options) -->
937 objects(Objects, [body], Options).
938
939objects([], Mode, _) -->
940 pop_mode(body, Mode, _).
941objects([Obj|T], Mode, Options) -->
942 object(Obj, Mode, Mode1, Options),
943 objects(T, Mode1, Options).
944
945object(doc(Obj,Pos,Comment), Mode0, Mode, Options) -->
946 !,
947 object(Obj, Pos, Comment, Mode0, Mode, Options).
948object(Obj, Mode0, Mode, Options) -->
949 { doc_comment(Obj, Pos, _Summary, Comment)
950 },
951 !,
952 object(Obj, Pos, Comment, Mode0, Mode, Options).
953
954object(Obj, Pos, Comment, Mode0, Mode, Options) -->
955 { is_pi(Obj),
956 !,
957 is_structured_comment(Comment, Prefixes),
958 string_codes(Comment, Codes),
959 indented_lines(Codes, Prefixes, Lines),
960 strip_module(user:Obj, Module, _),
961 process_modes(Lines, Module, Pos, Modes, Args, Lines1),
962 ( private(Obj, Options)
963 -> Class = privdef 964 ; multifile(Obj, Options)
965 -> Class = multidef
966 ; Class = pubdef 967 ),
968 ( Obj = Module:_
969 -> POptions = [module(Module)|Options]
970 ; POptions = Options
971 ),
972 DOM = [\pred_dt(Modes, Class, POptions), dd(class=defbody, DOM1)],
973 wiki_lines_to_dom(Lines1, Args, DOM0),
974 strip_leading_par(DOM0, DOM1),
975 assert_documented(Obj)
976 },
977 need_mode(description, Mode0, Mode),
978 latex(DOM).
979object([Obj|Same], Pos, Comment, Mode0, Mode, Options) -->
980 !,
981 object(Obj, Pos, Comment, Mode0, Mode, Options),
982 { maplist(assert_documented, Same) }.
983object(Obj, _Pos, _Comment, Mode, Mode, _Options) -->
984 { debug(pldoc, 'Skipped ~p', [Obj]) },
985 [].
986
987assert_documented(Obj) :-
988 assert(documented(Obj)).
989
990
997
998need_mode(Mode, Stack, Stack) -->
999 { Stack = [Mode|_] },
1000 !,
1001 [].
1002need_mode(Mode, Stack, Rest) -->
1003 { memberchk(Mode, Stack)
1004 },
1005 !,
1006 pop_mode(Mode, Stack, Rest).
1007need_mode(Mode, Stack, [Mode|Stack]) -->
1008 !,
1009 latex(cmd(begin(Mode))).
1010
1011pop_mode(Mode, Stack, Stack) -->
1012 { Stack = [Mode|_] },
1013 !,
1014 [].
1015pop_mode(Mode, [H|Rest0], Rest) -->
1016 latex(cmd(end(H))),
1017 pop_mode(Mode, Rest0, Rest).
1018
1019
1028
1029pred_dt(Modes, Class, Options) -->
1030 [nl(2)],
1031 pred_dt(Modes, [], _Done, [class(Class)|Options]).
1032
1033pred_dt([], Done, Done, _) -->
1034 [].
1035pred_dt([H|T], Done0, Done, Options) -->
1036 pred_mode(H, Done0, Done1, Options),
1037 ( {T == []}
1038 -> []
1039 ; latex(cmd(nodescription)),
1040 pred_dt(T, Done1, Done, Options)
1041 ).
1042
1043pred_mode(mode(Head,Vars), Done0, Done, Options) -->
1044 !,
1045 { bind_vars(Head, Vars) },
1046 pred_mode(Head, Done0, Done, Options).
1047pred_mode(Head is Det, Done0, Done, Options) -->
1048 !,
1049 anchored_pred_head(Head, Done0, Done, [det(Det)|Options]).
1050pred_mode(Head, Done0, Done, Options) -->
1051 anchored_pred_head(Head, Done0, Done, Options).
1052
1053bind_vars(Term, Bindings) :-
1054 bind_vars(Bindings),
1055 anon_vars(Term).
1056
1057bind_vars([]).
1058bind_vars([Name=Var|T]) :-
1059 Var = '$VAR'(Name),
1060 bind_vars(T).
1061
1066
1067anon_vars(Var) :-
1068 var(Var),
1069 !,
1070 Var = '$VAR'('_').
1071anon_vars(Term) :-
1072 compound(Term),
1073 !,
1074 Term =.. [_|Args],
1075 maplist(anon_vars, Args).
1076anon_vars(_).
1077
1078
1079anchored_pred_head(Head, Done0, Done, Options) -->
1080 { pred_anchor_name(Head, PI, _Name) },
1081 ( { memberchk(PI, Done0) }
1082 -> { Done = Done0 }
1083 ; { Done = [PI|Done0] }
1084 ),
1085 pred_head(Head, Options).
1086
1087
1094
1095pred_head(//(Head), Options) -->
1096 !,
1097 { pred_attributes(Options, Atts),
1098 Head =.. [Functor|Args],
1099 length(Args, Arity)
1100 },
1101 latex(cmd(dcg(opt(Atts), Functor, Arity, \pred_args(Args, 1)))).
1102pred_head(Head, _Options) --> 1103 { Head =.. [Functor,Left,Right],
1104 Functor \== (:),
1105 is_op_type(Functor, infix), !
1106 },
1107 latex(cmd(infixop(Functor, \pred_arg(Left, 1), \pred_arg(Right, 2)))).
1108pred_head(Head, _Options) --> 1109 { Head =.. [Functor,Arg],
1110 is_op_type(Functor, prefix), !
1111 },
1112 latex(cmd(prefixop(Functor, \pred_arg(Arg, 1)))).
1113pred_head(Head, _Options) --> 1114 { Head =.. [Functor,Arg],
1115 is_op_type(Functor, postfix), !
1116 },
1117 latex(cmd(postfixop(Functor, \pred_arg(Arg, 1)))).
1118pred_head(M:Head, Options) --> 1119 !,
1120 { pred_attributes(Options, Atts),
1121 Head =.. [Functor|Args],
1122 length(Args, Arity)
1123 },
1124 latex(cmd(qpredicate(opt(Atts),
1125 M,
1126 Functor, Arity, \pred_args(Args, 1)))).
1127pred_head(Head, Options) --> 1128 { pred_attributes(Options, Atts),
1129 Head =.. [Functor|Args],
1130 length(Args, Arity)
1131 },
1132 latex(cmd(predicate(opt(Atts),
1133 Functor, Arity, \pred_args(Args, 1)))).
1134
1139
1140pred_attributes(Options, Attrs) :-
1141 findall(A, pred_att(Options, A), As),
1142 insert_comma(As, Attrs).
1143
1144pred_att(Options, Det) :-
1145 option(det(Det), Options).
1146pred_att(Options, private) :-
1147 option(class(privdef), Options).
1148pred_att(Options, multifile) :-
1149 option(class(multidef), Options).
1150
1151insert_comma([H1,H2|T0], [H1, ','|T]) :-
1152 !,
1153 insert_comma([H2|T0], T).
1154insert_comma(L, L).
1155
1156
1157:- if(current_predicate(is_dict/1)). 1158dict_kv_pairs([]) --> [].
1159dict_kv_pairs([H|T]) -->
1160 dict_kv(H),
1161 ( { T == [] }
1162 -> []
1163 ; latex(', '),
1164 dict_kv_pairs(T)
1165 ).
1166
1167dict_kv(Key-Value) -->
1168 latex(cmd(key(Key))),
1169 latex(':'),
1170 term(Value).
1171:- endif. 1172
1173pred_args([], _) -->
1174 [].
1175pred_args([H|T], I) -->
1176 pred_arg(H, I),
1177 ( {T==[]}
1178 -> []
1179 ; latex(', '),
1180 { I2 is I + 1 },
1181 pred_args(T, I2)
1182 ).
1183
1184pred_arg(Var, I) -->
1185 { var(Var) },
1186 !,
1187 latex(['Arg', I]).
1188pred_arg(...(Term), I) -->
1189 !,
1190 pred_arg(Term, I),
1191 latex(cmd(ldots)).
1192pred_arg(Term, I) -->
1193 { Term =.. [Ind,Arg],
1194 mode_indicator(Ind)
1195 },
1196 !,
1197 latex([Ind, \pred_arg(Arg, I)]).
1198pred_arg(Arg:Type, _) -->
1199 !,
1200 latex([\argname(Arg), :, \argtype(Type)]).
1201pred_arg(Arg, _) -->
1202 { atom(Arg) },
1203 !,
1204 argname(Arg).
1205pred_arg(Arg, _) -->
1206 argtype(Arg). 1207
1208argname('$VAR'(Name)) -->
1209 !,
1210 latex(Name).
1211argname(Name) -->
1212 !,
1213 latex(Name).
1214
1215argtype(Term) -->
1216 { format(string(S), '~W',
1217 [ Term,
1218 [ quoted(true),
1219 numbervars(true)
1220 ]
1221 ]) },
1222 latex(S).
1223
1229
1230term(_, Term, Bindings) -->
1231 { bind_vars(Bindings) },
1232 term(Term).
1233
1234term('$VAR'(Name)) -->
1235 !,
1236 latex(cmd(arg(Name))).
1237term(Compound) -->
1238 { callable(Compound),
1239 !,
1240 Compound =.. [Functor|Args]
1241 },
1242 !,
1243 term_with_args(Functor, Args).
1244term(Rest) -->
1245 latex(Rest).
1246
1247term_with_args(Functor, [Left, Right]) -->
1248 { is_op_type(Functor, infix) },
1249 !,
1250 latex(cmd(infixterm(Functor, \term(Left), \term(Right)))).
1251term_with_args(Functor, [Arg]) -->
1252 { is_op_type(Functor, prefix) },
1253 !,
1254 latex(cmd(prefixterm(Functor, \term(Arg)))).
1255term_with_args(Functor, [Arg]) -->
1256 { is_op_type(Functor, postfix) },
1257 !,
1258 latex(cmd(postfixterm(Functor, \term(Arg)))).
1259term_with_args(Functor, Args) -->
1260 latex(cmd(term(Functor, \pred_args(Args, 1)))).
1261
1262
1266
1267termitem(_Text, Term, Bindings) -->
1268 { bind_vars(Bindings) },
1269 termitem(Term).
1270
1271termitem('$VAR'(Name)) -->
1272 !,
1273 latex(cmd(termitem(var(Name), ''))).
1274:- if(current_predicate(is_dict/1)). 1275termitem(Dict) -->
1276 { is_dict(Dict),
1277 !,
1278 dict_pairs(Dict, Tag, Pairs)
1279 },
1280 latex(cmd(dictitem(Tag, \dict_kv_pairs(Pairs)))).
1281:- endif. 1282termitem(Compound) -->
1283 { callable(Compound),
1284 !,
1285 Compound =.. [Functor|Args]
1286 },
1287 !,
1288 termitem_with_args(Functor, Args).
1289termitem(Rest) -->
1290 latex(cmd(termitem(Rest, ''))).
1291
1292termitem_with_args(Functor, [Left, Right]) -->
1293 { is_op_type(Functor, infix) },
1294 !,
1295 latex(cmd(infixtermitem(Functor, \term(Left), \term(Right)))).
1296termitem_with_args(Functor, [Arg]) -->
1297 { is_op_type(Functor, prefix) },
1298 !,
1299 latex(cmd(prefixtermitem(Functor, \term(Arg)))).
1300termitem_with_args(Functor, [Arg]) -->
1301 { is_op_type(Functor, postfix) },
1302 !,
1303 latex(cmd(postfixtermitem(Functor, \term(Arg)))).
1304termitem_with_args({}, [Arg]) -->
1305 !,
1306 latex(cmd(curltermitem(\argtype(Arg)))).
1307termitem_with_args(Functor, Args) -->
1308 latex(cmd(termitem(Functor, \pred_args(Args, 1)))).
1309
1310
1314
1315latex_table(_Attrs, Content) -->
1316 { max_columns(Content, 0, _, -, Wittness),
1317 col_align(Wittness, 1, Content, Align),
1318 atomics_to_string(Align, '|', S0),
1319 atomic_list_concat(['|',S0,'|'], Format)
1320 },
1321 latex(cmd(begin(quote))),
1322 latex(cmd(begin(tabulary,
1323 no_escape('0.9\\textwidth'),
1324 no_escape(Format)))),
1325 latex(cmd(hline)),
1326 rows(Content),
1327 latex(cmd(hline)),
1328 latex(cmd(end(tabulary))),
1329 latex(cmd(end(quote))).
1330
1331max_columns([], C, C, W, W).
1332max_columns([tr(List)|T], C0, C, _, W) :-
1333 length(List, C1),
1334 C1 >= C0, 1335 !,
1336 max_columns(T, C1, C, List, W).
1337max_columns([_|T], C0, C, W0, W) :-
1338 max_columns(T, C0, C, W0, W).
1339
1340col_align([], _, _, []).
1341col_align([CH|CT], Col, Rows, [AH|AT]) :-
1342 ( member(tr(Cells), Rows),
1343 nth1(Col, Cells, Cell),
1344 auto_par(Cell)
1345 -> Wrap = auto
1346 ; Wrap = false
1347 ),
1348 col_align(CH, Wrap, AH),
1349 Col1 is Col+1,
1350 col_align(CT, Col1, Rows, AT).
1351
1352col_align(td(class=Class,_), Wrap, Align) :-
1353 align_class(Class, Wrap, Align),
1354 !.
1355col_align(_, auto, 'L') :- !.
1356col_align(_, false, 'l').
1357
1358align_class(left, auto, 'L').
1359align_class(center, auto, 'C').
1360align_class(right, auto, 'R').
1361align_class(left, false, 'l').
1362align_class(center, false, 'c').
1363align_class(right, false, 'r').
1364
1365rows([]) -->
1366 [].
1367rows([tr(Content)|T]) -->
1368 row(Content),
1369 rows(T).
1370
1371row([]) -->
1372 [ latex(' \\\\'), nl(1) ].
1373row([td(_Attrs, Content)|T]) -->
1374 !,
1375 row([td(Content)|T]).
1376row([td(Content)|T]) -->
1377 fragile_latex(Content),
1378 ( {T == []}
1379 -> []
1380 ; [ latex(' & ') ]
1381 ),
1382 row(T).
1383row([th(Content)|T]) -->
1384 fragile_latex(cmd(textbf(Content))),
1385 ( {T == []}
1386 -> []
1387 ; [ latex(' & ') ]
1388 ),
1389 row(T).
1390
1394
1395auto_par(Content) :-
1396 phrase(html_text(Content), Words),
1397 length(Words, WC),
1398 WC > 1,
1399 atomics_to_string(Words, Text),
1400 string_length(Text, Width),
1401 Width > 15.
1402
1403html_text([]) -->
1404 !.
1405html_text([H|T]) -->
1406 !,
1407 html_text(H),
1408 html_text(T).
1409html_text(\predref(Name/Arity)) -->
1410 !,
1411 { format(string(S), '~q/~q', [Name, Arity]) },
1412 [S].
1413html_text(Compound) -->
1414 { compound(Compound),
1415 !,
1416 functor(Compound, _Name, Arity),
1417 arg(Arity, Compound, Content)
1418 },
1419 html_text(Content).
1420html_text(Word) -->
1421 [Word].
1422
1423
1424
1425
1426 1429
1434
1435latex_summary(Options) :-
1436 option(summary(File), Options),
1437 !,
1438 findall(Obj, summary_obj(Obj), Objs),
1439 maplist(pi_sort_key, Objs, Keyed),
1440 keysort(Keyed, KSorted),
1441 pairs_values(KSorted, SortedObj),
1442 phrase(summarylist(SortedObj, Options), Tokens),
1443 open(File, write, Out),
1444 call_cleanup(print_latex(Out, Tokens, Options),
1445 close(Out)).
1446latex_summary(_) :-
1447 retractall(documented(_)).
1448
1449summary_obj(Obj) :-
1450 documented(Obj),
1451 pi_head(Obj, Head),
1452 \+ xref_hook(Head).
1453
1454pi_head(M:PI, M:Head) :-
1455 !,
1456 pi_head(PI, Head).
1457pi_head(Name/Arity, Head) :-
1458 functor(Head, Name, Arity).
1459pi_head(Name//DCGArity, Head) :-
1460 Arity is DCGArity+2,
1461 functor(Head, Name, Arity).
1462
1463
1464pi_sort_key(M:PI, PI-(M:PI)) :- !.
1465pi_sort_key(PI, PI-PI).
1466
1467object_name_arity(_:Term, Type, Name, Arity) :-
1468 nonvar(Term),
1469 !,
1470 object_name_arity(Term, Type, Name, Arity).
1471object_name_arity(Name/Arity, pred, Name, Arity).
1472object_name_arity(Name//Arity, dcg, Name, Arity).
1473
1474summarylist(Objs, Options) -->
1475 latex(cmd(begin(summarylist, ll))),
1476 summary(Objs, Options),
1477 latex(cmd(end(summarylist))).
1478
1479summary([], _) -->
1480 [].
1481summary([H|T], Options) -->
1482 summary_line(H, Options),
1483 summary(T, Options).
1484
1485summary_line(Obj, _Options) -->
1486 { doc_comment(Obj, _Pos, Summary, _Comment),
1487 !,
1488 atom_codes(Summary, Codes),
1489 phrase(pldoc_wiki:line_tokens(Tokens), Codes), 1490 object_name_arity(Obj, Type, Name, Arity)
1491 },
1492 ( {Type == dcg}
1493 -> latex(cmd(dcgsummary(Name, Arity, Tokens)))
1494 ; { strip_module(Obj, M, _),
1495 current_op(Pri, Ass, M:Name)
1496 }
1497 -> latex(cmd(oppredsummary(Name, Arity, Ass, Pri, Tokens)))
1498 ; latex(cmd(predicatesummary(Name, Arity, Tokens)))
1499 ).
1500summary_line(Obj, _Options) -->
1501 { print_message(warning, pldoc(no_summary_for(Obj)))
1502 }.
1503
1504 1507
1508print_latex(Out, Tokens, Options) :-
1509 latex_header(Out, Options),
1510 print_latex_tokens(Tokens, Out),
1511 latex_footer(Out, Options).
1512
1513
1517
1518print_latex_tokens([], _).
1519print_latex_tokens([nl(N)|T0], Out) :-
1520 !,
1521 max_nl(T0, T, N, NL),
1522 nl(Out, NL),
1523 print_latex_tokens(T, Out).
1524print_latex_tokens([nl_exact(N)|T0], Out) :-
1525 !,
1526 nl_exact(T0, T,N, NL),
1527 nl(Out, NL),
1528 print_latex_tokens(T, Out).
1529print_latex_tokens([H|T], Out) :-
1530 print_latex_token(H, Out),
1531 print_latex_tokens(T, Out).
1532
1533print_latex_token(cmd(Cmd), Out) :-
1534 !,
1535 format(Out, '\\~w', [Cmd]).
1536print_latex_token(curl(open), Out) :-
1537 !,
1538 format(Out, '{', []).
1539print_latex_token(curl(close), Out) :-
1540 !,
1541 format(Out, '}', []).
1542print_latex_token(indent(N), Out) :-
1543 !,
1544 format(Out, '~t~*|', [N]).
1545print_latex_token(nl(N), Out) :-
1546 !,
1547 format(Out, '~N', []),
1548 forall(between(2,N,_), nl(Out)).
1549print_latex_token(verb(Verb), Out) :-
1550 is_list(Verb), Verb \== [],
1551 !,
1552 atomic_list_concat(Verb, Atom),
1553 print_latex_token(verb(Atom), Out).
1554print_latex_token(verb(Verb), Out) :-
1555 !,
1556 ( member(C, [$,'|',@,=,'"',^,!]),
1557 \+ sub_atom(Verb, _, _, _, C)
1558 -> atom_replace_char(Verb, '\n', ' ', Verb2),
1559 format(Out, '\\verb~w~w~w', [C,Verb2,C])
1560 ; assertion(fail)
1561 ).
1562print_latex_token(code(Code), Out) :-
1563 !,
1564 format(Out, '~N\\begin{code}~n', []),
1565 format(Out, '~w', [Code]),
1566 format(Out, '~N\\end{code}', []).
1567print_latex_token(latex(Code), Out) :-
1568 !,
1569 write(Out, Code).
1570print_latex_token(w(Word), Out) :-
1571 !,
1572 print_latex(Out, Word).
1573print_latex_token(no_escape(Text), Out) :-
1574 !,
1575 write(Out, Text).
1576print_latex_token(url_escape(Text), Out) :-
1577 !,
1578 print_url(Out, Text).
1579print_latex_token(Rest, Out) :-
1580 ( atomic(Rest)
1581 -> print_latex(Out, Rest)
1582 ; 1583 write(Out, Rest)
1584 ).
1585
1586atom_replace_char(In, From, To, Out) :-
1587 sub_atom(In, _, _, _, From),
1588 !,
1589 atom_chars(In, CharsIn),
1590 replace(CharsIn, From, To, CharsOut),
1591 atom_chars(Out, CharsOut).
1592atom_replace_char(In, _, _, In).
1593
1594replace([], _, _, []).
1595replace([H|T0], H, N, [N|T]) :-
1596 !,
1597 replace(T0, H, N, T).
1598replace([H|T0], F, N, [H|T]) :-
1599 replace(T0, F, N, T).
1600
1601
1605
1606print_latex(Out, String) :-
1607 atom_string(Atom, String),
1608 atom_chars(Atom, Chars),
1609 print_chars(Chars, Out).
1610
1611print_chars([], _).
1612print_chars([H|T], Out) :-
1613 print_char(H, Out),
1614 print_chars(T, Out).
1615
1616
1617print_url(Out, String) :-
1618 string_chars(String, Chars),
1619 print_url_chars(Chars, Out).
1620
1621print_url_chars([], _).
1622print_url_chars([H|T], Out) :-
1623 print_url_char(H, Out),
1624 print_url_chars(T, Out).
1625
1626print_url_char('#', Out) :- !, write(Out, '\\#').
1627print_url_char(C, Out) :- put_char(Out, C).
1628
1629
1633
1634max_nl([nl(M1)|T0], T, M0, M) :-
1635 !,
1636 M2 is max(M1, M0),
1637 max_nl(T0, T, M2, M).
1638max_nl([nl_exact(M1)|T0], T, _, M) :-
1639 !,
1640 nl_exact(T0, T, M1, M).
1641max_nl(T, T, M, M).
1642
1643nl_exact([nl(_)|T0], T, M0, M) :-
1644 !,
1645 max_nl(T0, T, M0, M).
1646nl_exact([nl_exact(M1)|T0], T, M0, M) :-
1647 !,
1648 M2 is max(M1, M0),
1649 max_nl(T0, T, M2, M).
1650nl_exact(T, T, M, M).
1651
1652
1653nl(Out, N) :-
1654 forall(between(1, N, _), nl(Out)).
1655
1656
1661
1662print_char('<', Out) :- !, write(Out, '$<$').
1663print_char('>', Out) :- !, write(Out, '$>$').
1664print_char('{', Out) :- !, write(Out, '\\{').
1665print_char('}', Out) :- !, write(Out, '\\}').
1666print_char('$', Out) :- !, write(Out, '\\$').
1667print_char('&', Out) :- !, write(Out, '\\&').
1668print_char('#', Out) :- !, write(Out, '\\#').
1669print_char('%', Out) :- !, write(Out, '\\%').
1670print_char('~', Out) :- !, write(Out, '\\Stilde{}').
1671print_char('\\',Out) :- !, write(Out, '\\bsl{}').
1672print_char('^', Out) :- !, write(Out, '\\Shat{}').
1673print_char('|', Out) :- !, write(Out, '\\Sbar{}').
1674print_char(C, Out) :- decompose_char(C, Out), !.
1675print_char(C, Out) :- put_char(Out, C).
1676
1682
1683:- if(exists_source(library(unicode))). 1684:- use_module(library(unicode)). 1685decompose_char(Char, Out) :-
1686 char_code(Char, Code),
1687 Code > 128,
1688 unicode_map(Char, Decomposed, [decompose]),
1689 atom_codes(Decomposed, [C,D]),
1690 diacritic_cmd(D, Cmd),
1691 format(Out, '\\~w~c', [Cmd, C]).
1692:- else. 1693decompose_char(_,_) :-
1694 fail.
1695:- endif. 1696
1697diacritic_cmd(768, '`').
1698diacritic_cmd(769, '\'').
1699diacritic_cmd(770, '~').
1700diacritic_cmd(771, '=').
1701diacritic_cmd(774, 'v').
1702diacritic_cmd(775, '.').
1703diacritic_cmd(776, '"').
1704diacritic_cmd(785, 'u').
1705diacritic_cmd(807, 'c').
1706diacritic_cmd(808, 'k').
1707
1711
1712identifier(Atom) :-
1713 atom_chars(Atom, [C0|Chars]),
1714 char_type(C0, lower),
1715 all_chartype(Chars, alnum).
1716
1717all_chartype([], _).
1718all_chartype([H|T], Type) :-
1719 char_type(H, Type),
1720 all_chartype(T, Type).
1721
1722
1723 1726
1734
1735:- dynamic
1736 urldef_name/2,
1737 urlchar/1, 1738 urldefs_loaded/1. 1739
1745
1746load_urldefs :-
1747 urldefs_loaded(_),
1748 !.
1749load_urldefs :-
1750 absolute_file_name(library('pldoc/pldoc.sty'), File,
1751 [ access(read) ]),
1752 load_urldefs(File).
1753
1754load_urldefs(File) :-
1755 urldefs_loaded(File),
1756 !.
1757load_urldefs(File) :-
1758 open(File, read, In),
1759 call_cleanup(( read_line_to_codes(In, L0),
1760 process_urldefs(L0, In)),
1761 close(In)),
1762 assert(urldefs_loaded(File)).
1763
1764process_urldefs(end_of_file, _) :- !.
1765process_urldefs(Line, In) :-
1766 ( phrase(urldef(Name, String), Line)
1767 -> assert(urldef_name(String, Name)),
1768 assert_chars(String)
1769 ; true
1770 ),
1771 read_line_to_codes(In, L2),
1772 process_urldefs(L2, In).
1773
1774assert_chars(String) :-
1775 atom_chars(String, Chars),
1776 ( member(C, Chars),
1777 \+ urlchar(C),
1778 assert(urlchar(C)),
1779 fail
1780 ; true
1781 ).
1782
1783urldef(Name, String) -->
1784 "\\urldef{\\", string(NameS), "}\\satom{", string(StringS), "}",
1785 ws,
1786 ( "%"
1787 -> string(_)
1788 ; []
1789 ),
1790 eol,
1791 !,
1792 { atom_codes(Name, NameS),
1793 atom_codes(String, StringS)
1794 }.
1795
1796ws --> [C], { C =< 32 }, !, ws.
1797ws --> [].
1798
1799string([]) --> [].
1800string([H|T]) --> [H], string(T).
1801
1802eol([],[]).
1803
1804
1805 1808
(Out, Options) :-
1810 ( option(stand_alone(true), Options, true)
1811 -> forall(header(Line), format(Out, '~w~n', [Line]))
1812 ; true
1813 ),
1814 forall(generated(Line), format(Out, '~w~n', [Line])).
1815
(Out, Options) :-
1817 ( option(stand_alone(true), Options, true)
1818 -> forall(footer(Line), format(Out, '~w~n', [Line]))
1819 ; true
1820 ).
1821
('\\documentclass[11pt]{article}').
1823header('\\usepackage{times}').
1824header('\\usepackage{pldoc}').
1825header('\\sloppy').
1826header('\\makeindex').
1827header('').
1828header('\\begin{document}').
1829
('').
1831footer('\\printindex').
1832footer('\\end{document}').
1833
1834generated('% This LaTeX document was generated using the LaTeX backend of PlDoc,').
1835generated('% The SWI-Prolog documentation system').
1836generated('').
1837
1838
1839 1842
1843:- multifile
1844 prolog:message//1. 1845
1846prolog:message(pldoc(no_summary_for(Obj))) -->
1847 [ 'No summary documentation for ~p'-[Obj] ]