1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2007-2015, University of Amsterdam 7 VU University Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(pldoc_latex, 37 [ doc_latex/3, % +Items, +OutFile, +Options 38 latex_for_file/3, % +FileSpec, +Out, +Options 39 latex_for_wiki_file/3, % +FileSpec, +Out, +Options 40 latex_for_predicates/3 % +PI, +Out, +Options 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), % we cannot import all as the 56 [ doc_file_objects/5, % \commands have the same name 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 ]).
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 [ % no options 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([]).
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]).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 ).
stand_alone, public_only and section_level.
See doc_latex/3 for a description of the options.
217latex_for_file(FileSpec, Out, Options) :-
218 load_urldefs,
219 phrase(latex_tokens_for_file(FileSpec, Options), Tokens),
220 print_latex(Out, Tokens, Options).
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)).stand_alone, public_only and
section_level. See doc_latex/3 for a description of the
options.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))).
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 /******************************* 327 * LATEX PRODUCTION * 328 *******************************/ 329 330:- thread_local 331 fragile/0. % provided when in fragile mode 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) --> % can this actually happen? 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 368% high level commands 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 457% low level commands 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)).
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).
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 {...}).
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).
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 ).
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).
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).
702delete_unsafe_label_chars(LabelIn, LabelOut) :- 703 atom_chars(LabelIn, Chars), 704 delete(Chars, '_', CharsOut), 705 atom_chars(LabelOut, CharsOut). 706 707 708 /******************************* 709 * \ COMMANDS * 710 *******************************/
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 ).
763file(File, _Options) --> 764 { fragile }, 765 !, 766 latex(cmd(texttt(File))). 767file(File, _Options) --> 768 latex(cmd(file(File))).
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))).
name/arity.
789nopredref(Name/Arity) -->
790 latex(cmd(nopredref(Name, Arity))).
796flagref(Flag) -->
797 latex(cmd(prologflag(Flag))).\cite{Citations} command
803cite(Citations) -->
804 { atomic_list_concat(Citations, ',', Atom) },
805 latex(cmd(cite(Atom))).([\args(Params)|Rest]) --> 813 !, 814 args(Params), 815 tags_list(Rest). 816tags(List) --> 817 tags_list(List). 818 ([]) --> 820 []. 821tags_list(List) --> 822 [ nl(2) ], 823 latex(cmd(begin(tags))), 824 latex(List), 825 latex(cmd(end(tags))), 826 [ nl(2) ].
tag(Name, Values) terms produced by doc_wiki.pl.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 ).
args(List) created by doc_wiki.pl. Params is a
list of arg(Name, Descr).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(' \\\\')].
878file_header(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 (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]).
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))).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 % private definition 964 ; multifile(Obj, Options) 965 -> Class = multidef 966 ; Class = pubdef % public definition 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)).
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).
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).
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).
span using
class pred and the arguments and var using class arglist.
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) --> % Infix operators 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) --> % Prefix operators 1109 { Head =.. [Functor,Arg], 1110 is_op_type(Functor, prefix), ! 1111 }, 1112 latex(cmd(prefixop(Functor, \pred_arg(Arg, 1)))). 1113pred_head(Head, _Options) --> % Postfix operators 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) --> % Qualified predicates 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) --> % Plain terms 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)))).
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). % arbitrary term 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).
doc_wiki.pl.
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)))).
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)))).
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, % take last as wittness to avoid getting the header 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).
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 /******************************* 1427 * SUMMARY PROCESSING * 1428 *******************************/
summary(+File), write a summary of all
documented predicates to File.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), % TBD: proper export 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 /******************************* 1505 * PRINT TOKENS * 1506 *******************************/ 1507 1508print_latex(Out, Tokens, Options) :- 1509 latex_header(Out, Options), 1510 print_latex_tokens(Tokens, Out), 1511 latex_footer(Out, Options).
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 ; %type_error(latex_token, Rest) 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).
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).
nl(N) and return the maximum of it.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)).
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).
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').
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 /******************************* 1724 * LATEX SPECIAL SEQUENCES * 1725 *******************************/
1735:- dynamic
1736 urldef_name/2,
1737 urlchar/1, % true if C appears in ine of them
1738 urldefs_loaded/1.\urldef definitions from File and populate
urldef_name/2. See pldoc.sty for details.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 /******************************* 1806 * HEADER/FOOTER * 1807 *******************************/ 1808 1809latex_header(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 1822header('\\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 /******************************* 1840 * MESSAGES * 1841 *******************************/ 1842 1843:- multifile 1844 prolog:message//1. 1845 1846prologmessage(pldoc(no_summary_for(Obj))) --> 1847 [ '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