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) 2006-2020, University of Amsterdam 7 VU University Amsterdam 8 CWI, Amsterdam 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_html, 38 [ doc_for_file/2, % +FileSpec, +Options 39 doc_write_html/3, % +Stream, +Title, +Term 40 doc_for_wiki_file/2, % +FileSpec, +Options 41 % Support doc_index 42 doc_page_dom/3, % +Title, +Body, -DOM 43 print_html_head/1, % +Stream 44 predref//1, % +PI // 45 predref//2, % +PI, Options // 46 nopredref//1, % +PI // 47 module_info/3, % +File, +Options0, -Options 48 doc_hide_private/3, % +Doc0, -Doc, +Options 49 edit_button//2, % +File, +Options, // 50 source_button//2, % +File, +Options, // 51 zoom_button//2, % +File, +Options, // 52 pred_edit_button//2, % +PredInd, +Options, // 53 object_edit_button//2, % +Obj, +Options, // 54 object_source_button//2, % +Obj, +Options, // 55 doc_resources//1, % +Options 56 ensure_doc_objects/1, % +File 57 % Support other backends 58 doc_file_objects/5, % +FSpec, -File, -Objs, -FileOpts, +Opts 59 existing_linked_file/2, % +FileSpec, -Path 60 unquote_filespec/2, % +FileSpec, -Unquoted 61 doc_tag_title/2, % +Tag, -Title 62 mode_anchor_name/2, % +Mode, -Anchor 63 pred_anchor_name/3, % +Head, -PI, -Anchor 64 private/2, % +Obj, +Options 65 (multifile)/2, % +Obj, +Options 66 is_pi/1, % @Term 67 is_op_type/2, % +Atom, ?Type 68 % Output routines 69 file//1, % +File, // 70 file//2, % +File, +Options, // 71 include//3, % +File, +Type, +Options // 72 tags//1, % +Tags, // 73 term//3, % +Text, +Term, +Bindings, // 74 file_header//2, % +File, +Options, // 75 flagref//1, % +Flag 76 objects//2, % +Objects, +Options, // 77 object_ref//2, % +Object, +Options, // 78 object_name//2, % +Object, +Object 79 object_href/2, % +Object, -URL 80 object_tree//3, % +Tree, +Current, +Options 81 object_page//2, % +Object, +Options, // 82 object_page_header//2, % +File, +Options, // 83 object_synopsis//2, % +Object, +Options, // 84 object_footer//2, % +Object, +Options, // 85 object_page_footer//2, % +Object, +Options, // 86 cite//1 % +Citations 87 ]). 88:- use_module(library(lists)). 89:- use_module(library(option)). 90:- use_module(library(uri)). 91:- use_module(library(readutil)). 92:- use_module(library(http/html_write)). 93:- use_module(library(http/http_dispatch)). 94:- use_module(library(http/http_wrapper)). 95:- use_module(library(http/http_path)). 96:- use_module(library(http/html_head)). 97:- use_module(library(http/term_html)). 98:- use_module(library(http/jquery)). 99:- use_module(library(debug)). 100:- use_module(library(apply)). 101:- use_module(library(pairs)). 102:- use_module(library(filesex)). 103:- use_module(doc_process). 104:- use_module(doc_man). 105:- use_module(doc_modes). 106:- use_module(doc_wiki). 107:- use_module(doc_search). 108:- use_module(doc_index). 109:- use_module(doc_util). 110:- use_module(library(solution_sequences)). 111:- use_module(library(error)). 112:- use_module(library(occurs)). 113:- use_module(library(prolog_source)). 114:- use_module(library(prolog_xref)). 115 116:- include(hooks).
128:- public 129 args//1, % Called from \Term output created 130 pred_dt//3, % by the wiki renderer 131 section//2, 132 tag//2. 133 134 135:- predicate_options(doc_for_wiki_file/2, 2, 136 [ edit(boolean) 137 ]). 138:- predicate_options(doc_hide_private/3, 3, 139 [module(atom), public(list), public_only(boolean)]). 140:- predicate_options(edit_button//2, 2, 141 [ edit(boolean) 142 ]). 143:- predicate_options(file//2, 2, 144 [ label(any), 145 absolute_path(atom), 146 href(atom), 147 map_extension(list), 148 files(list), 149 edit_handler(atom) 150 ]). 151:- predicate_options(file_header//2, 2, 152 [ edit(boolean), 153 files(list), 154 public_only(boolean) 155 ]). 156:- predicate_options(include//3, 3, 157 [ absolute_path(atom), 158 class(atom), 159 files(list), 160 href(atom), 161 label(any), 162 map_extension(list) 163 ]). 164:- predicate_options(object_edit_button//2, 2, 165 [ edit(boolean), 166 pass_to(pred_edit_button//2, 2) 167 ]). 168:- predicate_options(object_page//2, 2, 169 [ for(any), 170 header(boolean), 171 links(boolean), 172 no_manual(boolean), 173 try_manual(boolean), 174 search_in(oneof([all,app,man])), 175 search_match(oneof([name,summary])), 176 search_options(boolean) 177 ]). 178:- predicate_options(object_ref//2, 2, 179 [ files(list), 180 qualify(boolean), 181 style(oneof([number,title,number_title])), 182 secref_style(oneof([number,title,number_title])) 183 ]). 184:- predicate_options(object_synopsis//2, 2, 185 [ href(atom) 186 ]). 187:- predicate_options(pred_dt//3, 3, 188 [ edit(boolean) 189 ]). 190:- predicate_options(pred_edit_button//2, 2, 191 [ edit(boolean) 192 ]). 193:- predicate_options(predref//2, 2, 194 [ files(list), 195 prefer(oneof([manual,app])), 196 pass_to(object_ref/4, 2) 197 ]). 198:- predicate_options(private/2, 2, 199 [ module(atom), 200 public(list) 201 ]). 202:- predicate_options(source_button//2, 2, 203 [ files(list) 204 ]). 205 206 207 /******************************* 208 * RESOURCES * 209 *******************************/ 210 211:- html_resource(pldoc_css, 212 [ virtual(true), 213 requires([ pldoc_resource('pldoc.css') 214 ]) 215 ]). 216:- html_resource(pldoc_resource('pldoc.js'), 217 [ requires([ jquery 218 ]) 219 ]). 220:- html_resource(pldoc_js, 221 [ virtual(true), 222 requires([ pldoc_resource('pldoc.js') 223 ]) 224 ]). 225:- html_resource(pldoc, 226 [ virtual(true), 227 requires([ pldoc_css, 228 pldoc_js 229 ]) 230 ]). 231 232 233 /******************************* 234 * FILE PROCESSING * 235 *******************************/
true
(default), only emit documentation for
exported predicates.true
, provide edit buttons. Default, these buttons
are suppressed.256doc_for_file(FileSpec, Options) :- 257 doc_file_objects(FileSpec, File, Objects, FileOptions, Options), 258 doc_file_title(File, Title, FileOptions, Options), 259 doc_write_page( 260 pldoc(file(File, Title)), 261 title(Title), 262 \prolog_file(File, Objects, FileOptions, Options), 263 Options). 264 265doc_file_title(_, Title, _, Options) :- 266 option(title(Title), Options), 267 !. 268doc_file_title(File, Title, FileOptions, _) :- 269 memberchk(file(Title0, _Comment), FileOptions), 270 !, 271 file_base_name(File, Base), 272 atomic_list_concat([Base, ' -- ', Title0], Title). 273doc_file_title(File, Title, _, _) :- 274 file_base_name(File, Title). 275 276:- html_meta doc_write_page( , , , ). 277 278doc_write_page(Style, Head, Body, Options) :- 279 option(files(_), Options), 280 !, 281 phrase(page(Style, Head, Body), HTML), 282 print_html(HTML). 283doc_write_page(Style, Head, Body, _) :- 284 reply_html_page(Style, Head, Body). 285 286 287prolog_file(File, Objects, FileOptions, Options) --> 288 { b_setval(pldoc_file, File), % TBD: delete? 289 file_directory_name(File, Dir) 290 }, 291 html([ \doc_resources(Options), 292 \doc_links(Dir, FileOptions), 293 \file_header(File, FileOptions) 294 | \objects(Objects, FileOptions) 295 ]), 296 undocumented(File, Objects, FileOptions).
doc_files.pl
. A bit hacky ...303doc_resources(Options) --> 304 { option(resource_directory(ResDir), Options), 305 nb_current(pldoc_output, OutputFile), 306 !, 307 directory_file_path(ResDir, 'pldoc.css', Res), 308 relative_file_name(Res, OutputFile, Ref) 309 }, 310 html_requires(Ref). 311doc_resources(Options) --> 312 { option(html_resources(Resoures), Options, pldoc) 313 }, 314 html_requires(Resoures).
file(Title:string, Comment:string)
module(Module:atom)
list(predicate_indicator)
Objects contains
doc(PI:predicate_indicator, File:Line, Comment)
We distinguish three different states for FileSpec:
343doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 344 xref_current_source(FileSpec), 345 xref_option(FileSpec, comments(collect)), 346 !, 347 File = FileSpec, 348 findall(Object, xref_doc_object(File, Object), Objects0), 349 reply_file_objects(File, Objects0, Objects, FileOptions, Options). 350doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 351 absolute_file_name(FileSpec, File, 352 [ file_type(prolog), 353 access(read) 354 ]), 355 source_file(File), 356 !, 357 ensure_doc_objects(File), 358 Pos = File:Line, 359 findall(Line-doc(Obj,Pos,Comment), 360 doc_comment(Obj, Pos, _, Comment), Pairs), 361 sort(Pairs, Pairs1), % remove duplicates 362 keysort(Pairs1, ByLine), 363 pairs_values(ByLine, Objs0), 364 reply_file_objects(File, Objs0, Objects, FileOptions, Options). 365doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 366 absolute_file_name(FileSpec, File, 367 [ file_type(prolog), 368 access(read) 369 ]), 370 xref_source(File, [silent(true)]), 371 findall(Object, xref_doc_object(File, Object), Objects0), 372 reply_file_objects(File, Objects0, Objects, FileOptions, Options). 373 374 375reply_file_objects(File, Objs0, Objects, FileOptions, Options) :- 376 module_info(File, ModuleOptions, Options), 377 file_info(Objs0, Objs1, FileOptions, ModuleOptions), 378 doc_hide_private(Objs1, ObjectsSelf, ModuleOptions), 379 include_reexported(ObjectsSelf, Objects1, File, FileOptions), 380 remove_doc_duplicates(Objects1, Objects, []). 381 382remove_doc_duplicates([], [], _). 383remove_doc_duplicates([H|T0], [H|T], Seen) :- 384 H = doc(_, _, Comment), 385 \+ memberchk(Comment, Seen), 386 !, 387 remove_doc_duplicates(T0, T, [Comment|Seen]). 388remove_doc_duplicates([_|T0], T, Seen) :- 389 remove_doc_duplicates(T0, T, Seen). 390 391include_reexported(SelfObjects, Objects, File, Options) :- 392 option(include_reexported(true), Options), 393 option(module(Module), Options), 394 option(public(Exports), Options), 395 select_undocumented(Exports, Module, SelfObjects, Undoc), 396 re_exported_doc(Undoc, File, Module, REObjs, _), 397 REObjs \== [], 398 !, 399 append(SelfObjects, REObjs, Objects). 400include_reexported(Objects, Objects, _, _).
405xref_doc_object(File, doc(M:module(Title),File:0,Comment)) :- 406 xref_comment(File, Title, Comment), 407 xref_module(File, M). 408xref_doc_object(File, doc(M:Name/Arity,File:0,Comment)) :- 409 xref_comment(File, Head, _Summary, Comment), 410 xref_module(File, Module), 411 strip_module(Module:Head, M, Plain), 412 functor(Plain, Name, Arity).
423:- dynamic 424 no_comments/2. 425 426ensure_doc_objects(File) :- 427 source_file(File), 428 !, 429 ( doc_file_has_comments(File) 430 -> true 431 ; no_comments(File, TimeChecked), 432 time_file(File, TimeChecked) 433 -> true 434 ; xref_source(File, [silent(true), comments(store)]), 435 retractall(no_comments(File, _)), 436 ( doc_file_has_comments(File) 437 -> true 438 ; time_file(File, TimeChecked), 439 assertz(no_comments(File, TimeChecked)) 440 ) 441 ). 442ensure_doc_objects(File) :- 443 xref_source(File, [silent(true)]).
module(Name)
, public(Exports)
to OtherOptions if
File is a module file.450module_info(File, [module(Module), public(Exports)|Options], Options) :- 451 module_property(Module, file(File)), 452 !, 453 module_property(Module, exports(Exports)). 454module_info(File, [module(Module), public(Exports)|Options], Options) :- 455 xref_module(File, Module), 456 !, 457 findall(PI, xref_exported_pi(File, PI), Exports). 458module_info(_, Options, Options). 459 460xref_exported_pi(Src, Name/Arity) :- 461 xref_exported(Src, Head), 462 functor(Head, Name, Arity).
468doc_hide_private(Objs, Objs, Options) :- 469 option(public_only(false), Options, true), 470 !. 471doc_hide_private(Objs0, Objs, Options) :- 472 hide_private(Objs0, Objs, Options). 473 474hide_private([], [], _). 475hide_private([H|T0], T, Options) :- 476 obj(H, Obj), 477 private(Obj, Options), 478 !, 479 hide_private(T0, T, Options). 480hide_private([H|T0], [H|T], Options) :- 481 hide_private(T0, T, Options).
489obj(doc(Obj0, _Pos, _Summary), Obj) :- 490 !, 491 ( Obj0 = [Obj|_] 492 -> true 493 ; Obj = Obj0 494 ). 495obj(Obj0, Obj) :- 496 ( Obj0 = [Obj|_] 497 -> true 498 ; Obj = Obj0 499 ).
508:- multifile 509 prolog:doc_is_public_object/1. 510 511private(Object, _Options):- 512 prolog:doc_is_public_object(Object), !, fail. 513private(Module:PI, Options) :- 514 multifile(Module:PI, Options), !, fail. 515private(Module:PI, Options) :- 516 option(module(Module), Options), 517 option(public(Public), Options), 518 !, 519 \+ ( member(PI2, Public), 520 eq_pi(PI, PI2) 521 ). 522private(Module:PI, _Options) :- 523 module_property(Module, file(_)), % A loaded module 524 !, 525 module_property(Module, exports(Exports)), 526 \+ ( member(PI2, Exports), 527 eq_pi(PI, PI2) 528 ). 529private(Module:PI, _Options) :- 530 \+ (pi_to_head(PI, Head), 531 xref_exported(Source, Head), 532 xref_module(Source, Module)).
543multifile(Obj, _Options) :- 544 strip_module(user:Obj, Module, PI), 545 pi_to_head(PI, Head), 546 ( predicate_property(Module:Head, multifile) 547 ; xref_module(Source, Module), 548 xref_defined(Source, Head, multifile(_)) 549 ), 550 !. 551 552pi_to_head(Var, _) :- 553 var(Var), !, fail. 554pi_to_head(Name/Arity, Term) :- 555 functor(Term, Name, Arity). 556pi_to_head(Name//DCGArity, Term) :- 557 Arity is DCGArity+2, 558 functor(Term, Name, Arity).
file(Title, Comment)
to OtherOptions if available.564file_info(Comments, RestComments, [file(Title, Comment)|Opts], Opts) :- 565 select(doc(_:module(Title),_,Comment), Comments, RestComments), 566 !. 567file_info(Comments, Comments, Opts, Opts).
574file_header(File, Options) --> 575 { memberchk(file(Title, Comment), Options), 576 !, 577 file_base_name(File, Base) 578 }, 579 file_title([Base, ' -- ', Title], File, Options), 580 { is_structured_comment(Comment, Prefixes), 581 string_codes(Comment, Codes), 582 indented_lines(Codes, Prefixes, Lines), 583 section_comment_header(Lines, _Header, Lines1), 584 wiki_lines_to_dom(Lines1, [], DOM) 585 }, 586 html(DOM). 587file_header(File, Options) --> 588 { file_base_name(File, Base) 589 }, 590 file_title([Base], File, Options).
597file_title(Title, File, Options) --> 598 prolog:doc_file_title(Title, File, Options), 599 !. 600file_title(Title, File, Options) --> 601 { file_base_name(File, Base) 602 }, 603 html(h1(class(file), 604 [ span(style('float:right'), 605 [ \reload_button(File, Base, Options), 606 \zoom_button(Base, Options), 607 \source_button(Base, Options), 608 \edit_button(File, Options) 609 ]) 610 | Title 611 ])).
621reload_button(File, _Base, Options) --> 622 { \+ source_file(File), 623 \+ option(files(_), Options) 624 }, 625 !, 626 html(span(class(file_anot), '[not loaded]')). 627reload_button(_File, Base, Options) --> 628 { option(edit(true), Options), 629 !, 630 option(public_only(Public), Options, true) 631 }, 632 html(a(href(Base+[reload(true), public_only(Public)]), 633 img([ class(action), 634 alt('Reload'), 635 title('Make & Reload'), 636 src(location_by_id(pldoc_resource)+'reload.png') 637 ]))). 638reload_button(_, _, _) --> [].
646edit_button(File, Options) --> 647 { option(edit(true), Options) 648 }, 649 !, 650 html(a([ onClick('HTTPrequest(\'' + 651 location_by_id(pldoc_edit) + [file(File)] + 652 '\')') 653 ], 654 img([ class(action), 655 alt(edit), 656 title('Edit file'), 657 src(location_by_id(pldoc_resource)+'edit.png') 658 ]))). 659edit_button(_, _) --> 660 [].
667zoom_button(_, Options) --> 668 { option(files(_Map), Options) }, 669 !. % generating files 670zoom_button(Base, Options) --> 671 { ( option(public_only(true), Options, true) 672 -> Zoom = 'public.png', 673 Alt = 'Public', 674 Title = 'Click to include private', 675 PublicOnly = false 676 ; Zoom = 'private.png', 677 Alt = 'All predicates', 678 Title = 'Click to show exports only', 679 PublicOnly = true 680 ) 681 }, 682 html(a(href(Base+[public_only(PublicOnly)]), 683 img([ class(action), 684 alt(Alt), 685 title(Title), 686 src(location_by_id(pldoc_resource)+Zoom) 687 ]))).
694source_button(_File, Options) --> 695 { option(files(_Map), Options) }, 696 !. % generating files 697source_button(File, _Options) --> 698 { ( is_absolute_file_name(File) 699 -> doc_file_href(File, HREF0) 700 ; HREF0 = File 701 ) 702 }, 703 html(a(href(HREF0+[show(src)]), 704 img([ class(action), 705 alt('Show source'), 706 title('Show source'), 707 src(location_by_id(pldoc_resource)+'source.png') 708 ]))).
true
, provide a navitation tree.718objects(Objects, Options) --> 719 { option(navtree(true), Options), 720 !, 721 objects_nav_tree(Objects, Tree) 722 }, 723 html([ div(class(navtree), 724 div(class(navwindow), 725 \nav_tree(Tree, Objects, Options))), 726 div(class(navcontent), 727 \objects_nt(Objects, Options)) 728 ]). 729objects(Objects, Options) --> 730 objects_nt(Objects, Options). 731 732objects_nt(Objects, Options) --> 733 objects(Objects, [body], Options). 734 735objects([], Mode, _) --> 736 pop_mode(body, Mode, _). 737objects([Obj|T], Mode, Options) --> 738 object(Obj, Mode, Mode1, Options), 739 objects(T, Mode1, Options).
750object(doc(Obj,Pos,Comment), Mode0, Mode, Options) --> 751 !, 752 object(Obj, [Pos-Comment], Mode0, Mode, [scope(file)|Options]). 753object(Obj, Mode0, Mode, Options) --> 754 { findall(Pos-Comment, 755 doc_comment(Obj, Pos, _Summary, Comment), 756 Pairs) 757 }, 758 !, 759 { b_setval(pldoc_object, Obj) }, 760 object(Obj, Pairs, Mode0, Mode, Options). 761 762object(Obj, Pairs, Mode0, Mode, Options) --> 763 { is_pi(Obj), 764 !, 765 maplist(pred_dom(Obj, Options), Pairs, DOMS), 766 append(DOMS, DOM) 767 }, 768 need_mode(dl, Mode0, Mode), 769 html(DOM). 770object([Obj|_Same], Pairs, Mode0, Mode, Options) --> 771 !, 772 object(Obj, Pairs, Mode0, Mode, Options). 773object(Obj, _Pairs, Mode, Mode, _Options) --> 774 { debug(pldoc, 'Skipped ~p', [Obj]) }, 775 []. 776 777pred_dom(Obj, Options, Pos-Comment, DOM) :- 778 is_structured_comment(Comment, Prefixes), 779 string_codes(Comment, Codes), 780 indented_lines(Codes, Prefixes, Lines), 781 strip_module(user:Obj, Module, _), 782 process_modes(Lines, Module, Pos, Modes, Args, Lines1), 783 ( private(Obj, Options) 784 -> Class = privdef % private definition 785 ; multifile(Obj, Options) 786 -> ( option(scope(file), Options) 787 -> ( more_doc(Obj, Pos) 788 -> Class = multidef(object(Obj)) 789 ; Class = multidef 790 ) 791 ; Class = multidef(file((Pos))) 792 ) 793 ; Class = pubdef % public definition 794 ), 795 ( Obj = Module:_ 796 -> POptions = [module(Module)|Options] 797 ; POptions = Options 798 ), 799 Pos = File:Line, 800 DTOptions = [file(File),line(Line)|POptions], 801 DOM = [\pred_dt(Modes, Class, DTOptions), dd(class=defbody, DOM1)], 802 wiki_lines_to_dom(Lines1, Args, DOM0), 803 strip_leading_par(DOM0, DOM1). 804 805more_doc(Obj, File:_) :- 806 doc_comment(Obj, File2:_, _, _), 807 File2 \== File, 808 !.
817need_mode(Mode, Stack, Stack) --> 818 { Stack = [Mode|_] }, 819 !, 820 []. 821need_mode(Mode, Stack, Rest) --> 822 { memberchk(Mode, Stack) 823 }, 824 !, 825 pop_mode(Mode, Stack, Rest). 826need_mode(Mode, Stack, [Mode|Stack]) --> 827 !, 828 html_begin(Mode). 829 830pop_mode(Mode, Stack, Stack) --> 831 { Stack = [Mode|_] }, 832 !, 833 []. 834pop_mode(Mode, [H|Rest0], Rest) --> 835 html_end(H), 836 pop_mode(Mode, Rest0, Rest).
842undocumented(File, Objs, Options) --> 843 { memberchk(module(Module), Options), 844 memberchk(public(Exports), Options), 845 select_undocumented(Exports, Module, Objs, Undoc), 846 re_exported_doc(Undoc, File, Module, REObjs, ReallyUnDoc) 847 }, 848 !, 849 re_exported_doc(REObjs, Options), 850 undocumented(ReallyUnDoc, Options). 851undocumented(_, _, _) --> 852 []. 853 854re_exported_doc([], _) --> !. 855re_exported_doc(Objs, Options) --> 856 reexport_header(Objs, Options), 857 objects(Objs, Options). 858 859reexport_header(_, Options) --> 860 { option(reexport_header(true), Options, true) 861 }, 862 !, 863 html([ h2(class(wiki), 'Re-exported predicates'), 864 p([ 'The following predicates are re-exported from other ', 865 'modules' 866 ]) 867 ]). 868reexport_header(_, _) --> 869 []. 870 871undocumented([], _) --> !. 872undocumented(UnDoc, Options) --> 873 html([ h2(class(undoc), 'Undocumented predicates'), 874 p(['The following predicates are exported, but not ', 875 'or incorrectly documented.' 876 ]), 877 dl(class(undoc), 878 \undocumented_predicates(UnDoc, Options)) 879 ]). 880 881 882undocumented_predicates([], _) --> 883 []. 884undocumented_predicates([H|T], Options) --> 885 undocumented_pred(H, Options), 886 undocumented_predicates(T, Options). 887 888undocumented_pred(Name/Arity, Options) --> 889 { functor(Head, Name, Arity) }, 890 html(dt(class=undoc, \pred_mode(Head, [], _, Options))). 891 892select_undocumented([], _, _, []). 893select_undocumented([PI|T0], M, Objs, [PI|T]) :- 894 is_pi(PI), 895 \+ in_doc(M:PI, Objs), 896 !, 897 select_undocumented(T0, M, Objs, T). 898select_undocumented([_|T0], M, Objs, T) :- 899 select_undocumented(T0, M, Objs, T). 900 901in_doc(PI, Objs) :- 902 member(doc(O,_,_), Objs), 903 ( is_list(O) 904 -> member(O2, O), 905 eq_pi(PI, O2) 906 ; eq_pi(PI, O) 907 ).
914eq_pi(PI, PI) :- !. 915eq_pi(M:PI1, M:PI2) :- 916 atom(M), 917 !, 918 eq_pi(PI1, PI2). 919eq_pi(Name/A, Name//DCGA) :- 920 A =:= DCGA+2, 921 !. 922eq_pi(Name//DCGA, Name/A) :- 923 A =:= DCGA+2.
929is_pi(Var) :- 930 var(Var), 931 !, 932 fail. 933is_pi(_:PI) :- 934 !, 935 is_pi(PI). 936is_pi(_/_). 937is_pi(_//_).
943re_exported_doc([], _, _, [], []). 944re_exported_doc([PI|T0], File, Module, [doc(Orig:PI,Pos,Comment)|ObjT], UnDoc) :- 945 pi_to_head(PI, Head), 946 ( predicate_property(Module:Head, imported_from(Orig)) 947 -> true 948 ; xref_defined(File, Head, imported(File2)), 949 ensure_doc_objects(File2), 950 xref_module(File2, Orig) 951 ), 952 doc_comment(Orig:PI, Pos, _, Comment), 953 !, 954 re_exported_doc(T0, File, Module, ObjT, UnDoc). 955re_exported_doc([PI|T0], File, Module, REObj, [PI|UnDoc]) :- 956 re_exported_doc(T0, File, Module, REObj, UnDoc). 957 958 959 /******************************* 960 * SINGLE OBJECT PAGE * 961 *******************************/
971object_page(Obj, Options) --> 972 prolog:doc_object_page(Obj, Options), 973 !, 974 object_page_footer(Obj, Options). 975object_page(Obj, Options) --> 976 { doc_comment(Obj, File:_Line, _Summary, _Comment) 977 }, 978 !, 979 ( { \+ ( doc_comment(Obj, File2:_, _, _), 980 File2 \== File ) 981 } 982 -> html([ \html_requires(pldoc), 983 \object_page_header(File, Options), 984 \object_synopsis(Obj, []), 985 \objects([Obj], Options) 986 ]) 987 ; html([ \html_requires(pldoc), 988 \object_page_header(-, Options), 989 \objects([Obj], [synopsis(true)|Options]) 990 ]) 991 ), 992 object_page_footer(Obj, Options). 993object_page(M:Name/Arity, Options) --> % specified module, but public 994 { functor(Head, Name, Arity), 995 ( predicate_property(M:Head, exported) 996 -> module_property(M, class(library)) 997 ; \+ predicate_property(M:Head, defined) 998 ) 999 }, 1000 prolog:doc_object_page(Name/Arity, Options), 1001 !, 1002 object_page_footer(Name/Arity, Options). 1003 1004object_page_header(File, Options) --> 1005 prolog:doc_page_header(file(File), Options), 1006 !. 1007object_page_header(File, Options) --> 1008 { option(header(true), Options, true) }, 1009 !, 1010 html(div(class(navhdr), 1011 [ div(class(jump), \file_link(File)), 1012 div(class(search), \search_form(Options)), 1013 br(clear(right)) 1014 ])). 1015object_page_header(_, _) --> []. 1016 1017file_link(-) --> 1018 !, 1019 places_menu(-). 1020file_link(File) --> 1021 { file_directory_name(File, Dir) 1022 }, 1023 places_menu(Dir), 1024 html([ div(a(href(location_by_id(pldoc_doc)+File), File)) 1025 ]).
1032object_footer(Obj, Options) --> 1033 prolog:doc_object_footer(Obj, Options), 1034 !. 1035object_footer(_, _) --> [].
1043object_page_footer(Obj, Options) --> 1044 prolog:doc_object_page_footer(Obj, Options), 1045 !. 1046object_page_footer(_, _) --> [].
1060object_synopsis(Name/Arity, _) --> 1061 { functor(Head, Name, Arity), 1062 predicate_property(system:Head, built_in) 1063 }, 1064 synopsis([span(class(builtin), 'built-in')]). 1065object_synopsis(Name/Arity, Options) --> 1066 !, 1067 object_synopsis(_:Name/Arity, Options). 1068object_synopsis(M:Name/Arity, Options) --> 1069 { functor(Head, Name, Arity), 1070 ( option(source(Spec), Options) 1071 -> absolute_file_name(Spec, File, 1072 [ access(read), 1073 file_type(prolog), 1074 file_errors(fail) 1075 ]) 1076 ; predicate_property(M:Head, exported), 1077 \+ predicate_property(M:Head, imported_from(_)), 1078 module_property(M, file(File)), 1079 file_name_on_path(File, Spec) 1080 ), 1081 !, 1082 unquote_filespec(Spec, Unquoted), 1083 ( predicate_property(Head, autoload(FileBase)), 1084 file_name_extension(FileBase, _Ext, File) 1085 -> Extra = [span(class(autoload), '(can be autoloaded)')] 1086 ; Extra = [] 1087 ) 1088 }, 1089 ( { option(href(HREF), Options) } 1090 -> synopsis([code([':- use_module(',a(href(HREF), '~q'-[Unquoted]),').'])|Extra]) 1091 ; synopsis([code(':- use_module(~q).'-[Unquoted])|Extra]) 1092 ). 1093object_synopsis(Name//Arity, Options) --> 1094 !, 1095 { DCGArity is Arity+2 }, 1096 object_synopsis(Name/DCGArity, Options). 1097object_synopsis(Module:Name//Arity, Options) --> 1098 !, 1099 { DCGArity is Arity+2 }, 1100 object_synopsis(Module:Name/DCGArity, Options). 1101object_synopsis(f(_/_), _) --> 1102 synopsis(span(class(function), 1103 [ 'Arithmetic function (see ', 1104 \object_ref(is/2, []), 1105 ')' 1106 ])). 1107object_synopsis(c(Func), _) --> 1108 { sub_atom(Func, 0, _, _, 'PL_') 1109 }, 1110 !, 1111 synopsis([span(class(cfunc), 'C-language interface function')]). 1112object_synopsis(_, _) --> []. 1113 1114synopsis(Text) --> 1115 html(div(class(synopsis), 1116 [ span(class('synopsis-hdr'), 'Availability:') 1117 | Text 1118 ])).
1125unquote_filespec(Spec, Unquoted) :- 1126 compound(Spec), 1127 Spec =.. [Alias,Path], 1128 atom(Path), 1129 atomic_list_concat(Parts, /, Path), 1130 maplist(need_no_quotes, Parts), 1131 !, 1132 parts_to_path(Parts, UnquotedPath), 1133 Unquoted =.. [Alias, UnquotedPath]. 1134unquote_filespec(Spec, Spec). 1135 1136need_no_quotes(Atom) :- 1137 format(atom(A), '~q', [Atom]), 1138 \+ sub_atom(A, 0, _, _, '\''). 1139 1140parts_to_path([One], One) :- !. 1141parts_to_path(List, More/T) :- 1142 ( append(H, [T], List) 1143 -> parts_to_path(H, More) 1144 ). 1145 1146 1147 /******************************* 1148 * PRINT * 1149 *******************************/
1155doc_write_html(Out, Title, Doc) :-
1156 doc_page_dom(Title, Doc, DOM),
1157 phrase(html(DOM), Tokens),
1158 print_html_head(Out),
1159 print_html(Out, Tokens).
1166doc_page_dom(Title, Body, DOM) :-
1167 DOM = html([ head([ title(Title),
1168 link([ rel(stylesheet),
1169 type('text/css'),
1170 href(location_by_id(pldoc_resource)+'pldoc.css')
1171 ]),
1172 script([ src(location_by_id(pldoc_resource)+'pldoc.js'),
1173 type('text/javascript')
1174 ], [])
1175 ]),
1176 body(Body)
1177 ]).
DOCTYPE
line.1183print_html_head(Out) :- 1184 format(Out, 1185 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" \c 1186 "http://www.w3.org/TR/html4/strict.dtd">~n', []). 1187 1188% Rendering rules 1189% 1190% These rules translate \-terms produced by wiki.pl
1198tags(Tags) -->
1199 html(dl(class=tags, Tags)).
tag(Name, Values)
terms produced by doc_wiki.pl
.1205tag(Tag, Values) --> 1206 { doc_tag_title(Tag, Title), 1207 atom_concat('keyword-', Tag, Class) 1208 }, 1209 html([ dt(class=Class, Title), 1210 \tag_values(Values, Class) 1211 ]). 1212 1213tag_values([], _) --> 1214 []. 1215tag_values([H|T], Class) --> 1216 html(dd(class=Class, ['- '|H])), 1217 tag_values(T, Class).
1224doc_tag_title(Tag, Title) :- 1225 tag_title(Tag, Title), 1226 !. 1227doc_tag_title(Tag, Tag). 1228 1229tag_title(compat, 'Compatibility'). 1230tag_title(tbd, 'To be done'). 1231tag_title(see, 'See also'). 1232tag_title(error, 'Errors').
args(List)
created by doc_wiki.pl
. Params is a
list of arg(Name, Descr)
.1239args(Params) --> 1240 html([ dt(class=tag, 'Arguments:'), 1241 dd(table(class=arglist, 1242 \arg_list(Params))) 1243 ]). 1244 1245arg_list([]) --> 1246 []. 1247arg_list([H|T]) --> 1248 argument(H), 1249 arg_list(T). 1250 1251argument(arg(Name,Descr)) --> 1252 html(tr([td(var(Name)), td(class=argdescr, ['- '|Descr])])). 1253 1254 1255 /******************************* 1256 * NAVIGATION TREE * 1257 *******************************/
node(Object, Children)
.1264objects_nav_tree(Objects, Tree) :- 1265 maplist(object_nav_tree, Objects, Trees), 1266 union_trees(Trees, Tree0), 1267 remove_unique_root(Tree0, Tree). 1268 Obj, Tree) (:- 1270 Node = node(directory(Dir), FileNodes), 1271 FileNode = node(file(File), Siblings), 1272 doc_comment(Obj, File:_Line, _Summary, _Comment), 1273 !, 1274 file_directory_name(File, Dir), 1275 sibling_file_nodes(Dir, FileNodes0), 1276 selectchk(node(file(File),[]), FileNodes0, FileNode, FileNodes), 1277 findall(Sibling, doc_comment(Sibling, File:_, _, _), Siblings0), 1278 delete(Siblings0, _:module(_), Siblings1), 1279 doc_hide_private(Siblings1, Siblings2, []), 1280 flatten(Siblings2, Siblings), % a comment may describe objects 1281 embed_directories(Node, Tree). 1282 1283sibling_file_nodes(Dir, Nodes) :- 1284 findall(node(file(File), []), 1285 ( source_file(File), 1286 file_directory_name(File, Dir) 1287 ), 1288 Nodes). 1289 1290embed_directories(Node, Tree) :- 1291 Node = node(file(File), _), 1292 !, 1293 file_directory_name(File, Dir), 1294 Super = node(directory(Dir), [Node]), 1295 embed_directories(Super, Tree). 1296embed_directories(Node, Tree) :- 1297 Node = node(directory(Dir), _), 1298 file_directory_name(Dir, SuperDir), 1299 SuperDir \== Dir, 1300 !, 1301 Super = node(directory(SuperDir), [Node]), 1302 embed_directories(Super, Tree). 1303embed_directories(Tree, Tree). 1304 1305 1306union_trees([Tree], Tree) :- !. 1307union_trees([T1,T2|Trees], Tree) :- 1308 merge_trees(T1, T2, M1), 1309 union_trees([M1|Trees], Tree). 1310 1311merge_trees(node(R, Ch1), node(R, Ch2), node(R, Ch)) :- 1312 merge_nodes(Ch1, Ch2, Ch). 1313 1314merge_nodes([], Ch, Ch) :- !. 1315merge_nodes(Ch, [], Ch) :- !. 1316merge_nodes([node(Root, Ch1)|T1], N1, [T1|Nodes]) :- 1317 selectchk(node(Root, Ch2), N1, N2), 1318 !, 1319 merge_trees(node(Root, Ch1), node(Root, Ch2), T1), 1320 merge_nodes(T1, N2, Nodes). 1321merge_nodes([Node|T1], N1, [Node|Nodes]) :- 1322 merge_nodes(T1, N1, Nodes).
1328remove_unique_root(node(_, [node(R1, [R2])]), Tree) :- 1329 !, 1330 remove_unique_root(node(R1, [R2]), Tree). 1331remove_unique_root(Tree, Tree).
1337nav_tree(Tree, Current, Options) -->
1338 html(ul(class(nav),
1339 \object_tree(Tree, Current, Options))).
1345object_tree(node(Id, []), Target, Options) --> 1346 !, 1347 { node_class(Id, Target, Class) }, 1348 html(li(class(Class), 1349 \node(Id, Options))). 1350object_tree(node(Id, Children), Target, Options) --> 1351 !, 1352 { node_class(Id, Target, Class) }, 1353 html(li(class(Class), 1354 [ \node(Id, Options), 1355 ul(class(nav), 1356 \object_trees(Children, Target, Options)) 1357 ])). 1358object_tree(Id, Target, Options) --> 1359 !, 1360 { node_class(Id, Target, Class) }, 1361 html(li(class([obj|Class]), \node(Id, Options))). 1362 1363object_trees([], _, _) --> []. 1364object_trees([H|T], Target, Options) --> 1365 object_tree(H, Target, Options), 1366 object_trees(T, Target, Options). 1367 1368node_class(Ids, Current, Class) :- 1369 is_list(Ids), 1370 !, 1371 ( member(Id, Ids), memberchk(Id, Current) 1372 -> Class = [nav,current] 1373 ; Class = [nav] 1374 ). 1375node_class(Id, Current, Class) :- 1376 ( memberchk(Id, Current) 1377 -> Class = [nav,current] 1378 ; Class = [nav] 1379 ). 1380 1381node(file(File), Options) --> 1382 !, 1383 object_ref(file(File), [style(title)|Options]). 1384node(Id, Options) --> 1385 object_ref(Id, Options). 1386 1387 1388 /******************************* 1389 * SECTIONS * 1390 *******************************/ 1391 1392section(Type, Title) --> 1393 { string_codes(Title, Codes), 1394 wiki_codes_to_dom(Codes, [], Content0), 1395 strip_leading_par(Content0, Content), 1396 make_section(Type, Content, HTML) 1397 }, 1398 html(HTML). 1399 1400make_section(module, Title, h1(class=module, Title)). 1401make_section(section, Title, h1(class=section, Title)). 1402 1403 1404 /******************************* 1405 * PRED MODE HEADER * 1406 *******************************/
1414pred_dt(Modes, Class, Options) --> 1415 pred_dt(Modes, Class, [], _Done, Options). 1416 1417pred_dt([], _, Done, Done, _) --> 1418 []. 1419pred_dt([H|T], Class, Done0, Done, Options) --> 1420 { functor(Class, CSSClass, _) }, 1421 html(dt(class=CSSClass, 1422 [ \pred_mode(H, Done0, Done1, Options), 1423 \mode_anot(Class) 1424 ])), 1425 pred_dt(T, Class, Done1, Done, Options). 1426 1427mode_anot(privdef) --> 1428 !, 1429 html(span([class(anot), style('float:right')], 1430 '[private]')). 1431mode_anot(multidef(object(Obj))) --> 1432 !, 1433 { object_href(Obj, HREF) }, 1434 html(span([class(anot), style('float:right')], 1435 ['[', a(href(HREF), multifile), ']' 1436 ])). 1437mode_anot(multidef(file(File:_))) --> 1438 !, 1439 { file_name_on_path(File, Spec), 1440 unquote_filespec(Spec, Unquoted), 1441 doc_file_href(File, HREF) 1442 }, 1443 html(span([class(anot), style('float:right')], 1444 ['[multifile, ', a(href(HREF), '~q'-[Unquoted]), ']' 1445 ])). 1446mode_anot(multidef) --> 1447 !, 1448 html(span([class(anot), style('float:right')], 1449 '[multifile]')). 1450mode_anot(_) --> 1451 []. 1452 1453pred_mode(mode(Head,Vars), Done0, Done, Options) --> 1454 !, 1455 { bind_vars(Head, Vars) }, 1456 pred_mode(Head, Done0, Done, Options). 1457pred_mode(Head is Det, Done0, Done, Options) --> 1458 !, 1459 anchored_pred_head(Head, Done0, Done, Options), 1460 pred_det(Det). 1461pred_mode(Head, Done0, Done, Options) --> 1462 anchored_pred_head(Head, Done0, Done, Options). 1463 1464bind_vars(Term, Bindings) :- 1465 bind_vars(Bindings), 1466 anon_vars(Term). 1467 1468bind_vars([]). 1469bind_vars([Name=Var|T]) :- 1470 Var = '$VAR'(Name), 1471 bind_vars(T).
1478anon_vars(Var) :- 1479 var(Var), 1480 !, 1481 Var = '$VAR'('_'). 1482anon_vars(Term) :- 1483 compound(Term), 1484 !, 1485 Term =.. [_|Args], 1486 maplist(anon_vars, Args). 1487anon_vars(_). 1488 1489 1490anchored_pred_head(Head, Done0, Done, Options) --> 1491 { pred_anchor_name(Head, PI, Name) }, 1492 ( { memberchk(PI, Done0) } 1493 -> { Done = Done0 }, 1494 pred_head(Head) 1495 ; html([ span(style('float:right'), 1496 [ \pred_edit_or_source_button(Head, Options), 1497 &(nbsp) 1498 ]), 1499 a(name=Name, \pred_head(Head)) 1500 ]), 1501 { Done = [PI|Done0] } 1502 ). 1503 1504 Head, Options) (--> 1506 { option(edit(true), Options) }, 1507 !, 1508 pred_edit_button(Head, Options). 1509pred_edit_or_source_button(Head, Options) --> 1510 { option(source_link(true), Options) }, 1511 !, 1512 pred_source_button(Head, Options). 1513pred_edit_or_source_button(_, _) --> [].
1527pred_edit_button(_, Options) --> 1528 { \+ option(edit(true), Options) }, 1529 !. 1530pred_edit_button(PI0, Options0) --> 1531 { canonicalise_predref(PI0, PI, Options0, Options) }, 1532 pred_edit_button2(PI, Options). 1533 Name/Arity, Options) (--> 1535 { \+ ( memberchk(file(_), Options), % always edit if file and line 1536 memberchk(line(_), Options) % are given. 1537 ), 1538 functor(Head, Name, Arity), 1539 option(module(M), Options, _), 1540 \+ ( current_module(M), 1541 source_file(M:Head, _File) 1542 ) 1543 }, 1544 !. 1545pred_edit_button2(Name/Arity, Options) --> 1546 { include(edit_param, Options, Extra), 1547 http_link_to_id(pldoc_edit, 1548 [name(Name),arity(Arity)|Extra], 1549 EditHREF) 1550 }, 1551 html(a(onClick('HTTPrequest(\'' + EditHREF + '\')'), 1552 img([ class(action), 1553 alt('Edit predicate'), 1554 title('Edit predicate'), 1555 src(location_by_id(pldoc_resource)+'editpred.png') 1556 ]))). 1557pred_edit_button2(_, _) --> 1558 !, 1559 []. 1560 1561edit_param(module(_)). 1562edit_param(file(_)). 1563edit_param(line(_)).
1570object_edit_button(_, Options) --> 1571 { \+ option(edit(true), Options) }, 1572 !. 1573object_edit_button(PI, Options) --> 1574 { is_pi(PI) }, 1575 !, 1576 pred_edit_button(PI, Options). 1577object_edit_button(_, _) --> 1578 [].
1585pred_source_button(PI0, Options0) --> 1586 { canonicalise_predref(PI0, PI, Options0, Options), 1587 option(module(M), Options, _), 1588 pred_source_href(PI, M, HREF), ! 1589 }, 1590 html(a([ href(HREF) 1591 ], 1592 img([ class(action), 1593 alt('Source'), 1594 title('Show source'), 1595 src(location_by_id(pldoc_resource)+'source.png') 1596 ]))). 1597pred_source_button(_, _) --> 1598 [].
1605object_source_button(PI, Options) --> 1606 { is_pi(PI), 1607 option(source_link(true), Options, true) 1608 }, 1609 !, 1610 pred_source_button(PI, Options). 1611object_source_button(_, _) --> 1612 [].
module(M)
to Options.1620canonicalise_predref(M:PI0, PI, Options0, [module(M)|Options]) :- 1621 !, 1622 canonicalise_predref(PI0, PI, Options0, Options). 1623canonicalise_predref(//(Head), PI, Options0, Options) :- 1624 !, 1625 functor(Head, Name, Arity), 1626 PredArity is Arity + 2, 1627 canonicalise_predref(Name/PredArity, PI, Options0, Options). 1628canonicalise_predref(Name//Arity, PI, Options0, Options) :- 1629 integer(Arity), Arity >= 0, 1630 !, 1631 PredArity is Arity + 2, 1632 canonicalise_predref(Name/PredArity, PI, Options0, Options). 1633canonicalise_predref(PI, PI, Options, Options) :- 1634 PI = Name/Arity, 1635 atom(Name), integer(Arity), Arity >= 0, 1636 !. 1637canonicalise_predref(Head, PI, Options0, Options) :- 1638 functor(Head, Name, Arity), 1639 canonicalise_predref(Name/Arity, PI, Options0, Options).
span
using
class pred
and the arguments and var
using class arglist
.1647pred_head(Var) --> 1648 { var(Var), 1649 !, 1650 instantiation_error(Var) 1651 }. 1652pred_head(//(Head)) --> 1653 !, 1654 pred_head(Head), 1655 html(//). 1656pred_head(M:Head) --> 1657 html([span(class=module, M), :]), 1658 pred_head(Head). 1659pred_head(Head) --> 1660 { atom(Head) }, 1661 !, 1662 html(b(class=pred, Head)). 1663pred_head(Head) --> % Infix operators 1664 { Head =.. [Functor,Left,Right], 1665 is_op_type(Functor, infix) 1666 }, 1667 !, 1668 html([ var(class=arglist, \pred_arg(Left, 1)), 1669 ' ', b(class=pred, Functor), ' ', 1670 var(class=arglist, \pred_arg(Right, 2)) 1671 ]). 1672pred_head(Head) --> % Prefix operators 1673 { Head =.. [Functor,Arg], 1674 is_op_type(Functor, prefix) 1675 }, 1676 !, 1677 html([ b(class=pred, Functor), ' ', 1678 var(class=arglist, \pred_arg(Arg, 1)) 1679 ]). 1680pred_head(Head) --> % Postfix operators 1681 { Head =.. [Functor,Arg], 1682 is_op_type(Functor, postfix) 1683 }, 1684 !, 1685 html([ var(class=arglist, \pred_arg(Arg, 1)), 1686 ' ', b(class=pred, Functor) 1687 ]). 1688pred_head({Head}) --> 1689 !, 1690 html([ b(class=pred, '{'), 1691 var(class=arglist, 1692 \pred_args([Head], 1)), 1693 b(class=pred, '}') 1694 ]). 1695pred_head(Head) --> % Plain terms 1696 { Head =.. [Functor|Args] }, 1697 html([ b(class=pred, Functor), 1698 var(class=arglist, 1699 [ '(', \pred_args(Args, 1), ')' ]) 1700 ]).
prefix
,
infix
or postfix
.1707is_op_type(Functor, Type) :- 1708 current_op(_Pri, F, Functor), 1709 op_type(F, Type). 1710 1711op_type(fx, prefix). 1712op_type(fy, prefix). 1713op_type(xf, postfix). 1714op_type(yf, postfix). 1715op_type(xfx, infix). 1716op_type(xfy, infix). 1717op_type(yfx, infix). 1718op_type(yfy, infix). 1719 1720 1721pred_args([], _) --> 1722 []. 1723pred_args([H|T], I) --> 1724 pred_arg(H, I), 1725 ( {T==[]} 1726 -> [] 1727 ; html(', '), 1728 { I2 is I + 1 }, 1729 pred_args(T, I2) 1730 ). 1731 1732pred_arg(Var, I) --> 1733 { var(Var) }, 1734 !, 1735 html(['Arg', I]). 1736pred_arg(...(Term), I) --> 1737 !, 1738 pred_arg(Term, I), 1739 html('...'). 1740pred_arg(Term, I) --> 1741 { Term =.. [Ind,Arg], 1742 mode_indicator(Ind) 1743 }, 1744 !, 1745 html([Ind, \pred_arg(Arg, I)]). 1746pred_arg(Arg:Type, _) --> 1747 !, 1748 html([\argname(Arg), :, \argtype(Type)]). 1749pred_arg(Arg, _) --> 1750 argname(Arg). 1751 1752argname('$VAR'(Name)) --> 1753 !, 1754 html(Name). 1755argname(Name) --> 1756 !, 1757 html(Name). 1758 1759argtype(Term) --> 1760 { format(string(S), '~W', 1761 [ Term, 1762 [ quoted(true), 1763 numbervars(true) 1764 ] 1765 ]) }, 1766 html(S). 1767 1768pred_det(unknown) --> 1769 []. 1770pred_det(Det) --> 1771 html([' is ', b(class=det, Det)]).
doc_wiki.pl
.
1780term(_, Atom, []) --> 1781 { atomic(Atom), 1782 !, 1783 format(string(S), '~W', [Atom,[quoted(true)]]) 1784 }, 1785 html(span(class=functor, S)). 1786term(_, Key:Type, [TypeName=Type]) --> 1787 { atomic(Key) 1788 }, 1789 !, 1790 html([span(class='pl-key', Key), :, span(class('pl-var'), TypeName)]). 1791term(_, Term, Bindings) --> 1792 { is_mode(Term is det), % HACK. Bit too strict? 1793 bind_vars(Bindings) 1794 }, 1795 !, 1796 pred_head(Term). 1797term(_, Term, Bindings) --> 1798 term(Term, 1799 [ variable_names(Bindings), 1800 quoued(true) 1801 ]). 1802 1803 1804 /******************************* 1805 * PREDREF * 1806 *******************************/
Current file must be available through the global variable
pldoc_file
. If this variable not set it creates a link to
/doc/<file>#anchor. Such links only work in the online browser.
1819predref(Term) --> 1820 { catch(nb_getval(pldoc_options, Options), _, Options = []) }, 1821 predref(Term, Options). 1822 1823predref(Obj, Options) --> 1824 { Obj = _:_, 1825 doc_comment(Obj, File:_Line, _, _), 1826 ( ( option(files(Map), Options) 1827 -> memberchk(file(File,_), Map) 1828 ; true 1829 ) 1830 -> object_href(Obj, HREF, Options) 1831 ; manref(Obj, HREF, Options) 1832 ) 1833 }, 1834 !, 1835 html(a(href(HREF), \object_name(Obj, [qualify(true)|Options]))). 1836predref(M:Term, Options) --> 1837 !, 1838 predref(Term, M, Options). 1839predref(Term, Options) --> 1840 predref(Term, _, Options). 1841 1842predref(Name/Arity, _, Options) --> % Builtin; cannot be overruled 1843 { prolog:doc_object_summary(Name/Arity, manual, _, _), 1844 !, 1845 manref(Name/Arity, HREF, Options) 1846 }, 1847 html(a([class=builtin, href=HREF], [Name, /, Arity])). 1848predref(Name/Arity, _, Options) --> % From packages 1849 { option(prefer(manual), Options), 1850 prolog:doc_object_summary(Name/Arity, Category, _, _), 1851 !, 1852 manref(Name/Arity, HREF, Options) 1853 }, 1854 html(a([class=Category, href=HREF], [Name, /, Arity])). 1855predref(Obj, Module, Options) --> % Local 1856 { doc_comment(Module:Obj, File:_Line, _, _), 1857 ( option(files(Map), Options) 1858 -> memberchk(file(File,_), Map) 1859 ; true 1860 ) 1861 }, 1862 !, 1863 object_ref(Module:Obj, Options). 1864predref(Name/Arity, Module, Options) --> 1865 { \+ option(files(_), Options), 1866 pred_href(Name/Arity, Module, HREF) 1867 }, 1868 !, 1869 html(a(href=HREF, [Name, /, Arity])). 1870predref(Name//Arity, Module, Options) --> 1871 { \+ option(files(_), Options), 1872 PredArity is Arity + 2, 1873 pred_href(Name/PredArity, Module, HREF) 1874 }, 1875 !, 1876 html(a(href=HREF, [Name, //, Arity])). 1877predref(PI, _, Options) --> % From packages 1878 { canonical_pi(PI, CPI, HTML), 1879 ( option(files(_), Options) 1880 -> Category = extmanual 1881 ; prolog:doc_object_summary(CPI, Category, _, _) 1882 ), 1883 manref(CPI, HREF, Options) 1884 }, 1885 html(a([class=Category, href=HREF], HTML)). 1886predref(PI, _, _Options) --> 1887 { canonical_pi(PI, _CPI, HTML) 1888 }, 1889 !, 1890 html(span(class=undef, HTML)). 1891predref(Callable, Module, Options) --> 1892 { callable(Callable), 1893 functor(Callable, Name, Arity) 1894 }, 1895 predref(Name/Arity, Module, Options). 1896 1897canonical_pi(Name/Arity, Name/Arity, [Name, /, Arity]) :- 1898 atom(Name), integer(Arity), 1899 !. 1900canonical_pi(Name//Arity, Name/Arity2, [Name, //, Arity]) :- 1901 atom(Name), integer(Arity), 1902 !, 1903 Arity2 is Arity+2.
name/arity
, non-linking predicate indicator.
1909nopredref(PI) -->
1910 { canonical_pi(PI, _CPI, HTML)
1911 },
1912 !,
1913 html(span(class=nopredref, HTML)).
1921flagref(Flag) -->
1922 html(code(Flag)).
1929cite(Citations) --> 1930 html('['), citations(Citations), html(']'). 1931 1932citations([]) --> []. 1933citations([H|T]) --> 1934 citation(H), 1935 ( {T==[]} 1936 -> [] 1937 ; [';'], 1938 citations(T) 1939 ). 1940 1941citation(H) --> 1942 html([@,H]).
man_server(+Server)
.1950manref(PI, HREF, Options) :- 1951 predname(PI, PredName), 1952 ( option(files(_Map), Options) 1953 -> option(man_server(Server), Options, 1954 'http://www.swi-prolog.org/pldoc'), 1955 uri_components(Server, Comp0), 1956 uri_data(path, Comp0, Path0), 1957 directory_file_path(Path0, man, Path), 1958 uri_data(path, Comp0, Path, Components), 1959 uri_query_components(Query, [predicate=PredName]), 1960 uri_data(search, Components, Query), 1961 uri_components(HREF, Components) 1962 ; http_link_to_id(pldoc_man, [predicate=PredName], HREF) 1963 ). 1964 1965predname(Name/Arity, PredName) :- 1966 !, 1967 format(atom(PredName), '~w/~d', [Name, Arity]). 1968predname(Module:Name/Arity, PredName) :- 1969 !, 1970 format(atom(PredName), '~w:~w/~d', [Module, Name, Arity]).
1984pred_href(Name/Arity, Module, HREF) :- 1985 format(string(FragmentId), '~w/~d', [Name, Arity]), 1986 uri_data(fragment, Components, FragmentId), 1987 functor(Head, Name, Arity), 1988 ( catch(relative_file(Module:Head, File), _, fail) 1989 -> uri_data(path, Components, File), 1990 uri_components(HREF, Components) 1991 ; in_file(Module:Head, File) 1992 -> ( current_prolog_flag(home, SWI), 1993 sub_atom(File, 0, _, _, SWI), 1994 prolog:doc_object_summary(Name/Arity, packages, _, _) 1995 -> http_link_to_id(pldoc_man, [predicate=FragmentId], HREF) 1996 ; http_location_by_id(pldoc_doc, DocHandler), 1997 atom_concat(DocHandler, File, Path), 1998 uri_data(path, Components, Path), 1999 uri_components(HREF, Components) 2000 ) 2001 ). 2002 2003relative_file(Head, '') :- 2004 b_getval(pldoc_file, CurrentFile), CurrentFile \== [], 2005 in_file(Head, CurrentFile), 2006 !. 2007relative_file(Head, RelFile) :- 2008 b_getval(pldoc_file, CurrentFile), CurrentFile \== [], 2009 in_file(Head, DefFile), 2010 relative_file_name(DefFile, CurrentFile, RelFile).
2016pred_source_href(Name/Arity, Module, HREF) :-
2017 format(string(FragmentId), '~w/~d', [Name, Arity]),
2018 uri_data(fragment, Components, FragmentId),
2019 uri_query_components(Query, [show=src]),
2020 uri_data(search, Components, Query),
2021 functor(Head, Name, Arity),
2022 ( catch(relative_file(Module:Head, File), _, fail)
2023 -> uri_data(path, Components, File),
2024 uri_components(HREF, Components)
2025 ; in_file(Module:Head, File0)
2026 -> insert_alias(File0, File),
2027 http_location_by_id(pldoc_doc, DocHandler),
2028 atom_concat(DocHandler, File, Path),
2029 uri_data(path, Components, Path),
2030 uri_components(HREF, Components)
2031 ).
2040object_ref([], _) --> 2041 !, 2042 []. 2043object_ref([H|T], Options) --> 2044 !, 2045 object_ref(H, Options), 2046 ( {T == []} 2047 -> html(', '), 2048 object_ref(T, Options) 2049 ; [] 2050 ). 2051object_ref(Obj, Options) --> 2052 { object_href(Obj, HREF, Options) 2053 }, 2054 html(a(href(HREF), \object_name(Obj, Options))).
2061object_href(Obj, HREF) :- 2062 object_href(Obj, HREF, []). 2063 2064object_href(M:PI0, HREF, Options) :- 2065 option(files(Map), Options), 2066 ( module_property(M, file(File)) 2067 -> true 2068 ; xref_module(File, M) 2069 ), 2070 memberchk(file(File, DocFile), Map), 2071 !, 2072 file_base_name(DocFile, LocalFile), % TBD: proper directory index 2073 expand_pi(PI0, PI), 2074 term_to_string(PI, PIS), 2075 uri_data(path, Components, LocalFile), 2076 uri_data(fragment, Components, PIS), 2077 uri_components(HREF, Components). 2078object_href(file(File), HREF, _Options) :- 2079 doc_file_href(File, HREF), 2080 !. 2081object_href(directory(Dir), HREF, _Options) :- 2082 directory_file_path(Dir, 'index.html', Index), 2083 doc_file_href(Index, HREF), 2084 !. 2085object_href(Obj, HREF, _Options) :- 2086 prolog:doc_object_href(Obj, HREF), 2087 !. 2088object_href(Obj0, HREF, _Options) :- 2089 localise_object(Obj0, Obj), 2090 term_to_string(Obj, String), 2091 http_link_to_id(pldoc_object, [object=String], HREF). 2092 2093expand_pi(Name//Arity0, Name/Arity) :- 2094 !, 2095 Arity is Arity0+2. 2096expand_pi(PI, PI).
2104localise_object(Obj0, Obj) :- 2105 prolog:doc_canonical_object(Obj0, Obj), 2106 !. 2107localise_object(Obj, Obj).
2115term_to_string(Term, String) :-
2116 State = state(-),
2117 ( numbervars(Term, 0, _, [singletons(true)]),
2118 with_output_to(string(String),
2119 write_term(Term,
2120 [ numbervars(true),
2121 quoted(true)
2122 ])),
2123 nb_setarg(1, State, String),
2124 fail
2125 ; arg(1, State, String)
2126 ).
inline
or title
number
, title
or number_title
2140object_name(Obj, Options) --> 2141 { option(style(Style), Options, inline) 2142 }, 2143 object_name(Style, Obj, Options). 2144 2145object_name(title, Obj, Options) --> 2146 { merge_options(Options, [secref_style(title)], Options1) }, 2147 prolog:doc_object_link(Obj, Options1), 2148 !. 2149object_name(inline, Obj, Options) --> 2150 prolog:doc_object_link(Obj, Options), 2151 !. 2152object_name(title, f(Name/Arity), _Options) --> 2153 !, 2154 html(['Function ', Name, /, Arity]). 2155object_name(inline, f(Name/Arity), _Options) --> 2156 !, 2157 html([Name, /, Arity]). 2158object_name(Style, PI, Options) --> 2159 { is_pi(PI) }, 2160 !, 2161 pi(Style, PI, Options). 2162object_name(inline, Module:module(_Title), _) --> 2163 !, 2164 { module_property(Module, file(File)), 2165 file_base_name(File, Base) 2166 }, 2167 !, 2168 html(Base). 2169object_name(title, Module:module(Title), _) --> 2170 { module_property(Module, file(File)), 2171 file_base_name(File, Base) 2172 }, 2173 !, 2174 html([Base, ' -- ', Title]). 2175object_name(title, file(File), _) --> 2176 { module_property(Module, file(File)), 2177 doc_comment(Module:module(Title), _, _, _), 2178 !, 2179 file_base_name(File, Base) 2180 }, 2181 html([Base, ' -- ', Title]). 2182object_name(_, file(File), _) --> 2183 { file_base_name(File, Base) }, 2184 html(Base). 2185object_name(_, directory(Dir), _) --> 2186 { file_base_name(Dir, Base) }, 2187 html(Base). 2188object_name(_, module(Title), _Options) --> 2189 { print_message(warning, 2190 pldoc(module_comment_outside_module(Title))) 2191 }. 2192 2193pi(title, PI, Options) --> 2194 pi_type(PI), 2195 pi(PI, Options). 2196pi(inline, PI, Options) --> 2197 pi(PI, Options). 2198 2199pi(M:PI, Options) --> 2200 !, 2201 ( { option(qualify(true), Options) } 2202 -> html([span(class(module), M), :]) 2203 ; [] 2204 ), 2205 pi(PI, Options). 2206pi(Name/Arity, _) --> 2207 !, 2208 html([Name, /, Arity]). 2209pi(Name//Arity, _) --> 2210 html([Name, //, Arity]). 2211 2212pi_type(_:PI) --> 2213 !, 2214 pi_type(PI). 2215pi_type(_/_) --> 2216 html(['Predicate ']). 2217pi_type(_//_) --> 2218 html(['Grammar rule ']).
2230in_file(Module:Head, File) :- 2231 !, 2232 distinct(File, in_file(Module, Head, File)). 2233in_file(Head, File) :- 2234 distinct(File, in_file(_, Head, File)). 2235 2236in_file(Module, Head, File) :- 2237 var(Module), 2238 ( predicate_property(system:Head, foreign) 2239 -> !, 2240 fail 2241 ; predicate_property(system:Head, file(File)), 2242 \+ system_arithmetic_function(Head) 2243 -> ! 2244 ; predicate_property(Head, autoload(File0)) 2245 -> !, 2246 file_name_extension(File0, pl, File) 2247 ; exported_from(Module, Head, File), 2248 module_property(Module, class(library)) 2249 ). 2250in_file(Module, Head, File) :- 2251 xref_defined(File, Head, How), 2252 xref_current_source(File), 2253 atom(File), % only plain files 2254 xref_module(File, Module), 2255 How \= imported(_From). 2256in_file(Module, Head, File) :- 2257 exported_from(Module, Head, File). 2258in_file(Module, Head, File) :- 2259 predicate_property(Module:Head, file(File)), 2260 \+ predicate_property(Module:Head, imported_from(_)). 2261in_file(Module, Head, File) :- 2262 current_module(Module), 2263 source_file(Module:Head, File). 2264 2265exported_from(Module, Head, File) :- 2266 distinct(Primary, 2267 ( predicate_property(Module:Head, exported), 2268 ( predicate_property(Module:Head, imported_from(Primary)) 2269 -> true 2270 ; Primary = Module 2271 ))), 2272 module_property(Primary, file(File)). 2273 2274:- multifile 2275 arithmetic:evaluable/2. 2276 2277system_arithmetic_function(Head) :- 2278 functor(Head, Name, Arity), 2279 FArith is Arity-1, 2280 FArith >= 0, 2281 functor(FHead, Name, FArith), 2282 arithmetic:evaluable(FHead, system).
file(File)
terms in the DOM term generated by wiki.pl
. Supported
options are:
file(Name, Link)
that specifies that we must
user Link for the given physical file Name.2313file(File) --> 2314 file(File, []). 2315 2316file(File, Options) --> 2317 { catch(nb_getval(pldoc_options, GenOptions), _, GenOptions = []), 2318 merge_options(Options, GenOptions, FinalOptions) 2319 }, 2320 link_file(File, FinalOptions), 2321 !. 2322file(File, Options) --> 2323 { option(edit_handler(Handler), Options), 2324 http_current_request(Request), 2325 memberchk(path(Path), Request), 2326 absolute_file_name(File, Location, 2327 [ relative_to(Path) 2328 ]), 2329 http_link_to_id(Handler, [location(Location)], HREF), 2330 format(atom(Title), 'Click to create ~w', [File]) 2331 }, 2332 html(a([href(HREF), class(nofile), title(Title)], File)). 2333file(File, _) --> 2334 html(code(class(nofile), File)). 2335 2336link_file(File, Options) --> 2337 { file_href(File, HREF, Options), 2338 option(label(Label), Options, File), 2339 option(class(Class), Options, file) 2340 }, 2341 html(a([class(Class), href(HREF)], Label)).
2347file_href(_, HREF, Options) :- 2348 option(href(HREF), Options), 2349 !. 2350file_href(File, HREF, Options) :- 2351 file_href_real(File, HREF0, Options), 2352 map_extension(HREF0, HREF, Options).
map_extension(+Pairs)
2360map_extension(HREF0, HREF, Options) :- 2361 option(map_extension(Map), Options), 2362 file_name_extension(Base, Old, HREF0), 2363 memberchk(Old-New, Map), 2364 !, 2365 file_name_extension(Base, New, HREF). 2366map_extension(HREF, HREF, _). 2367 2368 2369file_href_real(File, HREF, Options) :- 2370 ( option(absolute_path(Path), Options) 2371 ; existing_linked_file(File, Path) 2372 ), 2373 !, 2374 ( option(files(Map), Options), 2375 memberchk(file(Path, LinkFile), Map) 2376 -> true 2377 ; LinkFile = Path 2378 ), 2379 file_href(LinkFile, HREF). 2380file_href_real(File, HREF, _) :- 2381 directory_alias(Alias), 2382 Term =.. [Alias,File], 2383 absolute_file_name(Term, _, 2384 [ access(read), 2385 file_errors(fail) 2386 ]), 2387 !, 2388 http_absolute_location(Term, HREF, []). 2389 2390directory_alias(icons). 2391directory_alias(css).
pldoc_file
.2401file_href(Path, HREF) :- % a loaded Prolog file 2402 source_file(Path), 2403 !, 2404 doc_file_href(Path, HREF). 2405file_href(Path, HREF) :- 2406 ( nb_current(pldoc_output, CFile) 2407 ; nb_current(pldoc_file, CFile) 2408 ), 2409 CFile \== [], 2410 !, 2411 relative_file_name(Path, CFile, HREF). 2412file_href(Path, Path).
2420existing_linked_file(File, Path) :-
2421 catch(b_getval(pldoc_file, CurrentFile), _, fail),
2422 CurrentFile \== [],
2423 absolute_file_name(File, Path,
2424 [ relative_to(CurrentFile),
2425 access(read),
2426 file_errors(fail)
2427 ]).
include(File,
Type)
terms in the DOM term generated by wiki.pl
if it
encounters [[file.ext]].2437include(PI, predicate, _) --> 2438 !, 2439 ( html_tokens_for_predicates(PI, []) 2440 -> [] 2441 ; html(['[[', \predref(PI), ']]']) 2442 ). 2443include(File, image, Options) --> 2444 { file_name_extension(_, svg, File), 2445 file_href(File, HREF, Options), 2446 !, 2447 include(image_attribute, Options, Attrs0), 2448 merge_options(Attrs0, 2449 [ alt(File), 2450 data(HREF), 2451 type('image/svg+xml') 2452 ], Attrs) 2453 }, 2454 ( { option(caption(Caption), Options) } 2455 -> html(div(class(figure), 2456 [ div(class(image), object(Attrs, [])), 2457 div(class(caption), Caption) 2458 ])) 2459 ; html(object(Attrs, [])) 2460 ). 2461include(File, image, Options) --> 2462 { file_href(File, HREF, Options), 2463 !, 2464 include(image_attribute, Options, Attrs0), 2465 merge_options(Attrs0, 2466 [ alt(File), 2467 border(0), 2468 src(HREF) 2469 ], Attrs) 2470 }, 2471 ( { option(caption(Caption), Options) } 2472 -> html(div(class(figure), 2473 [ div(class(image), img(Attrs)), 2474 div(class(caption), Caption) 2475 ])) 2476 ; html(img(Attrs)) 2477 ). 2478include(File, wiki, _Options) --> % [[file.txt]] is included 2479 { access_file(File, read), 2480 !, 2481 read_file_to_codes(File, String, []), 2482 wiki_codes_to_dom(String, [], DOM) 2483 }, 2484 html(DOM). 2485include(File, _Type, Options) --> 2486 link_file(File, Options), 2487 !. 2488include(File, _, _) --> 2489 html(code(class(nofile), ['[[',File,']]'])). 2490 2491image_attribute(src(_)). 2492image_attribute(alt(_)). 2493image_attribute(title(_)). 2494image_attribute(align(_)). 2495image_attribute(width(_)). 2496image_attribute(height(_)). 2497image_attribute(border(_)). 2498image_attribute(class(_)). 2499image_attribute(style(_)).
* [[member/2]] * [[append/3]]
2512html_tokens_for_predicates([], _Options) --> 2513 []. 2514html_tokens_for_predicates([H|T], Options) --> 2515 !, 2516 html_tokens_for_predicates(H, Options), 2517 html_tokens_for_predicates(T, Options). 2518html_tokens_for_predicates(PI, Options) --> 2519 { PI = _:_/_, 2520 !, 2521 ( doc_comment(PI, Pos, _Summary, Comment) 2522 -> true 2523 ; Comment = '' 2524 ) 2525 }, 2526 object(PI, [Pos-Comment], [dl], _, Options). 2527html_tokens_for_predicates(Spec, Options) --> 2528 { findall(PI, documented_pi(Spec, PI), List), 2529 List \== [], ! 2530 }, 2531 html_tokens_for_predicates(List, Options). 2532html_tokens_for_predicates(Spec, Options) --> 2533 man_page(Spec, 2534 [ links(false), % no header 2535 navtree(false), % no navigation tree 2536 footer(false), % no footer 2537 synopsis(false) % no synopsis 2538 | Options 2539 ]). 2540 2541 2542documented_pi(Spec, PI) :- 2543 generalise_spec(Spec, PI), 2544 doc_comment(PI, _Pos, _Summary, _Comment). 2545 2546generalise_spec(Name/Arity, _M:Name/Arity). 2547generalise_spec(Name//Arity, _M:Name//Arity). 2548 2549 2550 /******************************* 2551 * WIKI FILES * 2552 *******************************/
2559doc_for_wiki_file(FileSpec, Options) :- 2560 absolute_file_name(FileSpec, File, 2561 [ access(read) 2562 ]), 2563 read_file_to_codes(File, String, []), 2564 b_setval(pldoc_file, File), 2565 call_cleanup(reply_wiki_page(File, String, Options), 2566 nb_delete(pldoc_file)). 2567 2568reply_wiki_page(File, String, Options) :- 2569 wiki_codes_to_dom(String, [], DOM0), 2570 title(DOM0, File, Title), 2571 insert_edit_button(DOM0, File, DOM, Options), 2572 reply_html_page(pldoc(wiki), 2573 title(Title), 2574 [ \html_requires(pldoc) 2575 | DOM 2576 ]). 2577 2578title(DOM, _, Title) :- 2579 sub_term(h1(_,Title), DOM), 2580 !. 2581title(_, File, Title) :- 2582 file_base_name(File, Title). 2583 DOM, _, DOM, Options) (:- 2585 option(edit(false), Options, false), 2586 !. 2587insert_edit_button([h1(Attrs,Title)|DOM], File, 2588 [h1(Attrs,[ span(style('float:right'), 2589 \edit_button(File, [edit(true)])) 2590 | Title 2591 ])|DOM], _) :- !. 2592insert_edit_button(DOM, File, 2593 [ h1(class(wiki), 2594 [ span(style('float:right'), 2595 \edit_button(File, [edit(true)])) 2596 ]) 2597 | DOM 2598 ], _). 2599 2600 2601 /******************************* 2602 * ANCHORS * 2603 *******************************/
2609mode_anchor_name(Var, _) :- 2610 var(Var), 2611 !, 2612 instantiation_error(Var). 2613mode_anchor_name(mode(Head, _), Anchor) :- 2614 !, 2615 mode_anchor_name(Head, Anchor). 2616mode_anchor_name(Head is _Det, Anchor) :- 2617 !, 2618 mode_anchor_name(Head, Anchor). 2619mode_anchor_name(Head, Anchor) :- 2620 pred_anchor_name(Head, _, Anchor).
2627pred_anchor_name(//(Head), Name/Arity, Anchor) :- 2628 !, 2629 functor(Head, Name, DCGArity), 2630 Arity is DCGArity+2, 2631 format(atom(Anchor), '~w/~d', [Name, Arity]). 2632pred_anchor_name(Head, Name/Arity, Anchor) :- 2633 functor(Head, Name, Arity), 2634 format(atom(Anchor), '~w/~d', [Name, Arity]). 2635 2636:- multifile prolog:message//1. 2637 2638prologmessage(pldoc(module_comment_outside_module(Title))) --> 2639 [ 'PlDoc comment <module> ~w does not appear in a module'-[Title] ]
PlDoc HTML backend
This module translates the Herbrand term from the documentation extracting module
doc_wiki.pl
into HTML+CSS.