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