1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: jan@swi-prolog.org 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2007-2026, University of Amsterdam 7 VU University Amsterdam 8 SWI-Prolog Solutions b.v. 9 All rights reserved. 10 11 Redistribution and use in source and binary forms, with or without 12 modification, are permitted provided that the following conditions 13 are met: 14 15 1. Redistributions of source code must retain the above copyright 16 notice, this list of conditions and the following disclaimer. 17 18 2. Redistributions in binary form must reproduce the above copyright 19 notice, this list of conditions and the following disclaimer in 20 the documentation and/or other materials provided with the 21 distribution. 22 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 POSSIBILITY OF SUCH DAMAGE. 35*/ 36 37:- module(pldoc_latex, 38 [ doc_latex/3, % +Items, +OutFile, +Options 39 latex_for_file/3, % +FileSpec, +Out, +Options 40 latex_for_wiki_file/3, % +FileSpec, +Out, +Options 41 latex_for_predicates/3 % +PI, +Out, +Options 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), % we cannot import all as the 57 [ doc_file_objects/5, % \commands have the same name 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 ]).
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 [ % no options 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([]).
Typically Spec is either a list of filenames or a list of predicate indicators. Defined options are:
true (default), create a document that can be run
through LaTeX. If false, produce a document to be
included in another LaTeX document.true (default), only emit documentation for
exported predicates.section.modules([Module]).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 ).
stand_alone, public_only and section_level.
See doc_latex/3 for a description of the options.
218latex_for_file(FileSpec, Out, Options) :-
219 load_urldefs,
220 phrase(latex_tokens_for_file(FileSpec, Options), Tokens),
221 print_latex(Out, Tokens, Options).
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)).stand_alone, public_only and
section_level. See doc_latex/3 for a description of the
options.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))).
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 /******************************* 328 * LATEX PRODUCTION * 329 *******************************/ 330 331:- thread_local 332 fragile/0. % provided when in fragile mode 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) --> % can this actually happen? 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 369% high level commands 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 458% low level commands 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)).
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).
opt(Arg) it is written as [Arg], Otherwise it is written as
{Arg}. Note that opt([]) is omitted. I think no LaTeX command is
designed to handle an empty optional argument special.
During processing the arguments it asserts fragile/0 to allow is taking care of LaTeX fragile constructs (i.e. constructs that are not allows inside {...}).
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).
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 ).
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).
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).
703delete_unsafe_label_chars(LabelIn, LabelOut) :- 704 atom_chars(LabelIn, Chars), 705 delete(Chars, '_', CharsOut), 706 atom_chars(LabelOut, CharsOut). 707 708 709 /******************************* 710 * \ COMMANDS * 711 *******************************/
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 ).
764file(File, _Options) --> 765 { fragile }, 766 !, 767 latex(cmd(texttt(File))). 768file(File, _Options) --> 769 latex(cmd(file(File))).
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))).
name/arity.
790nopredref(Name/Arity) -->
791 latex(cmd(nopredref(Name, Arity))).
797flagref(Flag) -->
798 latex(cmd(prologflag(Flag))).\cite{Citations} command
804cite(Citations) -->
805 { atomic_list_concat(Citations, ',', Atom) },
806 latex(cmd(cite(Atom))).([\args(Params)|Rest]) --> 814 !, 815 args(Params), 816 tags_list(Rest). 817tags(List) --> 818 tags_list(List). 819 ([]) --> 821 []. 822tags_list(List) --> 823 [ nl(2) ], 824 latex(cmd(begin(tags))), 825 latex(List), 826 latex(cmd(end(tags))), 827 [ nl(2) ].
tag(Name, Values) terms produced by doc_wiki.pl.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 ).
args(List) created by doc_wiki.pl. Params is a
list of arg(Name, Descr).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(' \\\\')].
879file_header(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 (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]).
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))).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 % private definition 965 ; multifile(Obj, Options) 966 -> Class = multidef 967 ; Class = pubdef % public definition 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)).
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).
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).
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).
span using
class pred and the arguments and var using class arglist.
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) --> % Infix operators 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) --> % Prefix operators 1110 { Head =.. [Functor,Arg], 1111 is_op_type(Functor, prefix), ! 1112 }, 1113 latex(cmd(prefixop(Functor, \pred_arg(Arg, 1)))). 1114pred_head(Head, _Options) --> % Postfix operators 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) --> % Qualified predicates 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) --> % Plain terms 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)))).
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). % arbitrary term 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).
doc_wiki.pl.
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)))).
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)))).
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, % take last as wittness to avoid getting the header 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).
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 /******************************* 1428 * SUMMARY PROCESSING * 1429 *******************************/
summary(+File), write a summary of all
documented predicates to File.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), % TBD: proper export 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 /******************************* 1506 * PRINT TOKENS * 1507 *******************************/ 1508 1509print_latex(Out, Tokens, Options) :- 1510 latex_header(Out, Options), 1511 print_latex_tokens(Tokens, Out), 1512 latex_footer(Out, Options).
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 ; %type_error(latex_token, Rest) 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).
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).
nl(N) and return the maximum of it.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)).
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).
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 /******************************* 1693 * LATEX SPECIAL SEQUENCES * 1694 *******************************/
1704:- dynamic
1705 urldef_name/2,
1706 urlchar/1, % true if C appears in ine of them
1707 urldefs_loaded/1.\urldef definitions from File and populate
urldef_name/2. See pldoc.sty for details.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 /******************************* 1775 * HEADER/FOOTER * 1776 *******************************/ 1777 1778latex_header(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 1791header('\\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 /******************************* 1809 * MESSAGES * 1810 *******************************/ 1811 1812:- multifile 1813 prolog:message//1. 1814 1815prologmessage(pldoc(no_summary_for(Obj))) --> 1816 [ 'No summary documentation for ~p'-[Obj] ]
PlDoc LaTeX backend
This module translates the Herbrand term from the documentation extracting module
doc_wiki.plinto a LaTeX document for us with the pl.sty LaTeX style file. The function of this module is very similar todoc_html.pl, providing the HTML backend, and the implementation follows the same paradigm. The module canTODO