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-2023, University of Amsterdam 7 VU University Amsterdam 8 CWI, Amsterdam 9 SWI-Prolog Solutions b.v. 10 All rights reserved. 11 12 Redistribution and use in source and binary forms, with or without 13 modification, are permitted provided that the following conditions 14 are met: 15 16 1. Redistributions of source code must retain the above copyright 17 notice, this list of conditions and the following disclaimer. 18 19 2. Redistributions in binary form must reproduce the above copyright 20 notice, this list of conditions and the following disclaimer in 21 the documentation and/or other materials provided with the 22 distribution. 23 24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 POSSIBILITY OF SUCH DAMAGE. 36*/ 37 38:- module(pldoc_html, 39 [ doc_for_file/2, % +FileSpec, +Options 40 doc_write_html/3, % +Stream, +Title, +Term 41 doc_for_wiki_file/2, % +FileSpec, +Options 42 % Support doc_index 43 doc_page_dom/3, % +Title, +Body, -DOM 44 print_html_head/1, % +Stream 45 predref//1, % +PI // 46 predref//2, % +PI, Options // 47 nopredref//1, % +PI // 48 module_info/3, % +File, +Options0, -Options 49 doc_hide_private/3, % +Doc0, -Doc, +Options 50 edit_button//2, % +File, +Options, // 51 source_button//2, % +File, +Options, // 52 zoom_button//2, % +File, +Options, // 53 pred_edit_button//2, % +PredInd, +Options, // 54 object_edit_button//2, % +Obj, +Options, // 55 object_source_button//2, % +Obj, +Options, // 56 doc_resources//1, % +Options 57 ensure_doc_objects/1, % +File 58 % Support other backends 59 doc_file_objects/5, % +FSpec, -File, -Objs, -FileOpts, +Opts 60 existing_linked_file/2, % +FileSpec, -Path 61 unquote_filespec/2, % +FileSpec, -Unquoted 62 doc_tag_title/2, % +Tag, -Title 63 mode_anchor_name/2, % +Mode, -Anchor 64 pred_anchor_name/3, % +Head, -PI, -Anchor 65 private/2, % +Obj, +Options 66 (multifile)/2, % +Obj, +Options 67 is_pi/1, % @Term 68 is_op_type/2, % +Atom, ?Type 69 % Output routines 70 file//1, % +File, // 71 file//2, % +File, +Options, // 72 include//3, % +File, +Type, +Options // 73 tags//1, % +Tags, // 74 term//3, % +Text, +Term, +Bindings, // 75 file_header//2, % +File, +Options, // 76 flagref//1, % +Flag 77 objects//2, % +Objects, +Options, // 78 object_ref//2, % +Object, +Options, // 79 object_name//2, % +Object, +Object 80 object_href/2, % +Object, -URL 81 object_tree//3, % +Tree, +Current, +Options 82 object_page//2, % +Object, +Options, // 83 object_page_header//2, % +File, +Options, // 84 object_synopsis//2, % +Object, +Options, // 85 object_footer//2, % +Object, +Options, // 86 object_page_footer//2, % +Object, +Options, // 87 cite//1 % +Citations 88 ]). 89% Get HTTP server infrastructure when available 90:- if(exists_source(library(http/http_dispatch))). 91:- use_module(library(http/http_dispatch)). 92:- use_module(library(http/http_wrapper)). 93:- use_module(library(http/jquery)). 94 95pldoc_server(true). 96:- else. 97 98:- multifile 99 http:location/3. 100 101httplocation(pldoc_resource, '/pldoc/res', []). 102 103pldoc_server(false). 104:- endif. 105 106:- use_module(library(lists)). 107:- use_module(library(option)). 108:- use_module(library(uri)). 109:- use_module(library(readutil)). 110:- use_module(library(http/html_write)). 111:- use_module(library(http/http_path)). 112:- use_module(library(http/html_head)). 113:- use_module(library(http/term_html)). 114:- use_module(library(debug)). 115:- use_module(library(apply)). 116:- use_module(library(pairs)). 117:- use_module(library(filesex)). 118:- use_module(doc_process). 119:- use_module(doc_man). 120:- use_module(doc_modes). 121:- use_module(doc_wiki). 122:- use_module(doc_search). 123:- use_module(doc_index). 124:- use_module(doc_util). 125:- use_module(library(solution_sequences)). 126:- use_module(library(error)). 127:- use_module(library(occurs)). 128:- use_module(library(prolog_source)). 129:- use_module(library(prolog_xref)). 130 131:- include(hooks).
143:- public 144 args//1, % Called from \Term output created 145 pred_dt//3, % by the wiki renderer 146 section//2, 147 tag//2. 148 149 150:- predicate_options(doc_for_wiki_file/2, 2, 151 [ edit(boolean) 152 ]). 153:- predicate_options(doc_hide_private/3, 3, 154 [module(atom), public(list), public_only(boolean)]). 155:- predicate_options(edit_button//2, 2, 156 [ edit(boolean) 157 ]). 158:- predicate_options(file//2, 2, 159 [ label(any), 160 absolute_path(atom), 161 href(atom), 162 map_extension(list), 163 files(list), 164 edit_handler(atom) 165 ]). 166:- predicate_options(file_header//2, 2, 167 [ edit(boolean), 168 files(list), 169 public_only(boolean) 170 ]). 171:- predicate_options(include//3, 3, 172 [ absolute_path(atom), 173 class(atom), 174 files(list), 175 href(atom), 176 label(any), 177 map_extension(list) 178 ]). 179:- predicate_options(object_edit_button//2, 2, 180 [ edit(boolean), 181 pass_to(pred_edit_button//2, 2) 182 ]). 183:- predicate_options(object_page//2, 2, 184 [ for(any), 185 header(boolean), 186 links(boolean), 187 no_manual(boolean), 188 try_manual(boolean), 189 search_in(oneof([all,app,man])), 190 search_match(oneof([name,summary])), 191 search_options(boolean) 192 ]). 193:- predicate_options(object_ref//2, 2, 194 [ files(list), 195 qualify(boolean), 196 style(oneof([number,title,number_title])), 197 secref_style(oneof([number,title,number_title])) 198 ]). 199:- predicate_options(object_synopsis//2, 2, 200 [ href(atom) 201 ]). 202:- predicate_options(pred_dt//3, 3, 203 [ edit(boolean) 204 ]). 205:- predicate_options(pred_edit_button//2, 2, 206 [ edit(boolean) 207 ]). 208:- predicate_options(predref//2, 2, 209 [ files(list), 210 prefer(oneof([manual,app])), 211 pass_to(object_ref/4, 2) 212 ]). 213:- predicate_options(private/2, 2, 214 [ module(atom), 215 public(list) 216 ]). 217:- predicate_options(source_button//2, 2, 218 [ files(list) 219 ]). 220 221 222 /******************************* 223 * RESOURCES * 224 *******************************/ 225 226:- if(pldoc_server(true)). 227:- html_resource(pldoc_css, 228 [ virtual(true), 229 requires([ pldoc_resource('pldoc.css') 230 ]) 231 ]). 232:- html_resource(pldoc_resource('pldoc.js'), 233 [ requires([ jquery 234 ]) 235 ]). 236:- html_resource(pldoc_js, 237 [ virtual(true), 238 requires([ pldoc_resource('pldoc.js') 239 ]) 240 ]). 241:- html_resource(pldoc, 242 [ virtual(true), 243 requires([ pldoc_css, 244 pldoc_js 245 ]) 246 ]). 247:- else. 248:- html_resource(pldoc_css, [virtual(true)]). 249:- html_resource(pldoc_resource('pldoc.js'), [virtual(true)]). 250:- html_resource(pldoc_js, [virtual(true)]). 251:- html_resource(pldoc, [virtual(true)]). 252:- endif. 253 254 255 /******************************* 256 * FILE PROCESSING * 257 *******************************/
true
(default), only emit documentation for
exported predicates.true
, provide edit buttons. Default, these buttons
are suppressed.278doc_for_file(FileSpec, Options) :- 279 doc_file_objects(FileSpec, File, Objects, FileOptions, Options), 280 doc_file_title(File, Title, FileOptions, Options), 281 doc_write_page( 282 pldoc(file(File, Title)), 283 title(Title), 284 \prolog_file(File, Objects, FileOptions, Options), 285 Options). 286 287doc_file_title(_, Title, _, Options) :- 288 option(title(Title), Options), 289 !. 290doc_file_title(File, Title, FileOptions, _) :- 291 memberchk(file(Title0, _Comment), FileOptions), 292 !, 293 file_base_name(File, Base), 294 atomic_list_concat([Base, ' -- ', Title0], Title). 295doc_file_title(File, Title, _, _) :- 296 file_base_name(File, Title). 297 298:- html_meta doc_write_page( , , , ). 299 300doc_write_page(Style, Head, Body, Options) :- 301 option(files(_), Options), 302 !, 303 phrase(page(Style, Head, Body), HTML), 304 print_html(HTML). 305doc_write_page(Style, Head, Body, _) :- 306 reply_html_page(Style, Head, Body). 307 308 309prolog_file(File, Objects, FileOptions, Options) --> 310 { b_setval(pldoc_file, File), % TBD: delete? 311 file_directory_name(File, Dir) 312 }, 313 html([ \doc_resources(Options), 314 \doc_links(Dir, FileOptions), 315 \file_header(File, FileOptions) 316 | \objects(Objects, FileOptions) 317 ]), 318 undocumented(File, Objects, FileOptions).
doc_files.pl
. A bit hacky ...325doc_resources(Options) --> 326 { option(resource_directory(ResDir), Options), 327 nb_current(pldoc_output, OutputFile), 328 !, 329 directory_file_path(ResDir, 'pldoc.css', Res), 330 relative_file_name(Res, OutputFile, Ref) 331 }, 332 html_requires(Ref). 333doc_resources(Options) --> 334 { option(html_resources(Resoures), Options, pldoc) 335 }, 336 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:
365doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 366 xref_current_source(FileSpec), 367 xref_option(FileSpec, comments(collect)), 368 !, 369 File = FileSpec, 370 findall(Object, xref_doc_object(File, Object), Objects0), 371 reply_file_objects(File, Objects0, Objects, FileOptions, Options). 372doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 373 absolute_file_name(FileSpec, File, 374 [ file_type(prolog), 375 access(read) 376 ]), 377 source_file(File), 378 !, 379 ensure_doc_objects(File), 380 Pos = File:Line, 381 findall(Line-doc(Obj,Pos,Comment), 382 doc_comment(Obj, Pos, _, Comment), Pairs), 383 sort(Pairs, Pairs1), % remove duplicates 384 keysort(Pairs1, ByLine), 385 pairs_values(ByLine, Objs0), 386 reply_file_objects(File, Objs0, Objects, FileOptions, Options). 387doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 388 absolute_file_name(FileSpec, File, 389 [ file_type(prolog), 390 access(read) 391 ]), 392 xref_source(File, [silent(true)]), 393 findall(Object, xref_doc_object(File, Object), Objects0), 394 reply_file_objects(File, Objects0, Objects, FileOptions, Options). 395 396 397reply_file_objects(File, Objs0, Objects, FileOptions, Options) :- 398 module_info(File, ModuleOptions, Options), 399 file_info(Objs0, Objs1, FileOptions, ModuleOptions), 400 doc_hide_private(Objs1, ObjectsSelf, ModuleOptions), 401 include_reexported(ObjectsSelf, Objects1, File, FileOptions), 402 remove_doc_duplicates(Objects1, Objects, []). 403 404remove_doc_duplicates([], [], _). 405remove_doc_duplicates([H|T0], [H|T], Seen) :- 406 H = doc(_, _, Comment), 407 \+ memberchk(Comment, Seen), 408 !, 409 remove_doc_duplicates(T0, T, [Comment|Seen]). 410remove_doc_duplicates([_|T0], T, Seen) :- 411 remove_doc_duplicates(T0, T, Seen). 412 413include_reexported(SelfObjects, Objects, File, Options) :- 414 option(include_reexported(true), Options), 415 option(module(Module), Options), 416 option(public(Exports), Options), 417 select_undocumented(Exports, Module, SelfObjects, Undoc), 418 re_exported_doc(Undoc, File, Module, REObjs, _), 419 REObjs \== [], 420 !, 421 append(SelfObjects, REObjs, Objects). 422include_reexported(Objects, Objects, _, _).
427xref_doc_object(File, doc(M:module(Title),File:0,Comment)) :- 428 xref_comment(File, Title, Comment), 429 xref_module(File, M). 430xref_doc_object(File, doc(M:Name/Arity,File:0,Comment)) :- 431 xref_comment(File, Head, _Summary, Comment), 432 xref_module(File, Module), 433 strip_module(Module:Head, M, Plain), 434 functor(Plain, Name, Arity).
445:- dynamic 446 no_comments/2. 447 448ensure_doc_objects(File) :- 449 source_file(File), 450 !, 451 ( doc_file_has_comments(File) 452 -> true 453 ; no_comments(File, TimeChecked), 454 time_file(File, TimeChecked) 455 -> true 456 ; xref_source(File, [silent(true), comments(store)]), 457 retractall(no_comments(File, _)), 458 ( doc_file_has_comments(File) 459 -> true 460 ; time_file(File, TimeChecked), 461 assertz(no_comments(File, TimeChecked)) 462 ) 463 ). 464ensure_doc_objects(File) :- 465 xref_source(File, [silent(true)]).
module(Name)
, public(Exports)
to OtherOptions if
File is a module file.472module_info(File, [module(Module), public(Exports)|Options], Options) :- 473 module_property(Module, file(File)), 474 !, 475 module_property(Module, exports(Exports)). 476module_info(File, [module(Module), public(Exports)|Options], Options) :- 477 xref_module(File, Module), 478 !, 479 findall(PI, xref_exported_pi(File, PI), Exports). 480module_info(_, Options, Options). 481 482xref_exported_pi(Src, Name/Arity) :- 483 xref_exported(Src, Head), 484 functor(Head, Name, Arity).
490doc_hide_private(Objs, Objs, Options) :- 491 option(public_only(false), Options, true), 492 !. 493doc_hide_private(Objs0, Objs, Options) :- 494 hide_private(Objs0, Objs, Options). 495 496hide_private([], [], _). 497hide_private([H|T0], T, Options) :- 498 obj(H, Obj), 499 private(Obj, Options), 500 !, 501 hide_private(T0, T, Options). 502hide_private([H|T0], [H|T], Options) :- 503 hide_private(T0, T, Options).
511obj(doc(Obj0, _Pos, _Summary), Obj) :- 512 !, 513 ( Obj0 = [Obj|_] 514 -> true 515 ; Obj = Obj0 516 ). 517obj(Obj0, Obj) :- 518 ( Obj0 = [Obj|_] 519 -> true 520 ; Obj = Obj0 521 ).
530:- multifile 531 prolog:doc_is_public_object/1. 532 533private(Object, _Options) :- 534 prolog:doc_is_public_object(Object), !, fail. 535private(Module:PI, Options) :- 536 multifile(Module:PI, Options), !, fail. 537private(Module:PI, Options) :- 538 public(Module:PI, Options), !, fail. 539private(Module:PI, Options) :- 540 option(module(Module), Options), 541 option(public(Public), Options), 542 !, 543 \+ ( member(PI2, Public), 544 eq_pi(PI, PI2) 545 ). 546private(Module:PI, _Options) :- 547 module_property(Module, file(_)), % A loaded module 548 !, 549 module_property(Module, exports(Exports)), 550 \+ ( member(PI2, Exports), 551 eq_pi(PI, PI2) 552 ). 553private(Module:PI, _Options) :- 554 \+ (pi_to_head(PI, Head), 555 xref_exported(Source, Head), 556 xref_module(Source, Module)).
567multifile(Obj, _Options) :-
568 strip_module(user:Obj, Module, PI),
569 pi_to_head(PI, Head),
570 ( predicate_property(Module:Head, multifile)
571 ; xref_module(Source, Module),
572 xref_defined(Source, Head, multifile(_Line))
573 ),
574 !.
580public(Obj, _Options) :- 581 strip_module(user:Obj, Module, PI), 582 pi_to_head(PI, Head), 583 ( predicate_property(Module:Head, public) 584 ; xref_module(Source, Module), 585 xref_defined(Source, Head, public(_Line)) 586 ), 587 !. 588 589pi_to_head(Var, _) :- 590 var(Var), !, fail. 591pi_to_head(Name/Arity, Term) :- 592 functor(Term, Name, Arity). 593pi_to_head(Name//DCGArity, Term) :- 594 Arity is DCGArity+2, 595 functor(Term, Name, Arity).
file(Title, Comment)
to OtherOptions if available.601file_info(Comments, RestComments, [file(Title, Comment)|Opts], Opts) :- 602 select(doc(_:module(Title),_,Comment), Comments, RestComments), 603 !. 604file_info(Comments, Comments, Opts, Opts).
611file_header(File, Options) --> 612 { memberchk(file(Title, Comment), Options), 613 !, 614 file_base_name(File, Base) 615 }, 616 file_title([Base, ' -- ', Title], File, Options), 617 { is_structured_comment(Comment, Prefixes), 618 string_codes(Comment, Codes), 619 indented_lines(Codes, Prefixes, Lines), 620 section_comment_header(Lines, _Header, Lines1), 621 wiki_lines_to_dom(Lines1, [], DOM) 622 }, 623 html(DOM). 624file_header(File, Options) --> 625 { file_base_name(File, Base) 626 }, 627 file_title([Base], File, Options).
634file_title(Title, File, Options) --> 635 prolog:doc_file_title(Title, File, Options), 636 !. 637file_title(Title, File, Options) --> 638 { file_base_name(File, Base) 639 }, 640 html(h1(class(file), 641 [ span(style('float:right'), 642 [ \reload_button(File, Base, Options), 643 \zoom_button(Base, Options), 644 \source_button(Base, Options), 645 \edit_button(File, Options) 646 ]) 647 | Title 648 ])).
658reload_button(File, _Base, Options) --> 659 { \+ source_file(File), 660 \+ option(files(_), Options) 661 }, 662 !, 663 html(span(class(file_anot), '[not loaded]')). 664reload_button(_File, Base, Options) --> 665 { option(edit(true), Options), 666 !, 667 option(public_only(Public), Options, true) 668 }, 669 html(a(href(Base+[reload(true), public_only(Public)]), 670 img([ class(action), 671 alt('Reload'), 672 title('Make & Reload'), 673 src(location_by_id(pldoc_resource)+'reload.png') 674 ]))). 675reload_button(_, _, _) --> [].
683edit_button(File, Options) --> 684 { option(edit(true), Options) 685 }, 686 !, 687 html(a([ onClick('HTTPrequest(\'' + 688 location_by_id(pldoc_edit) + [file(File)] + 689 '\')') 690 ], 691 img([ class(action), 692 alt(edit), 693 title('Edit file'), 694 src(location_by_id(pldoc_resource)+'edit.png') 695 ]))). 696edit_button(_, _) --> 697 [].
704zoom_button(_, Options) --> 705 { option(files(_Map), Options) }, 706 !. % generating files 707zoom_button(Base, Options) --> 708 { ( option(public_only(true), Options, true) 709 -> Zoom = 'public.png', 710 Alt = 'Public', 711 Title = 'Click to include private', 712 PublicOnly = false 713 ; Zoom = 'private.png', 714 Alt = 'All predicates', 715 Title = 'Click to show exports only', 716 PublicOnly = true 717 ) 718 }, 719 html(a(href(Base+[public_only(PublicOnly)]), 720 img([ class(action), 721 alt(Alt), 722 title(Title), 723 src(location_by_id(pldoc_resource)+Zoom) 724 ]))).
731source_button(_File, Options) --> 732 { option(files(_Map), Options) }, 733 !. % generating files 734source_button(File, _Options) --> 735 { ( is_absolute_file_name(File) 736 -> doc_file_href(File, HREF0) 737 ; HREF0 = File 738 ) 739 }, 740 html(a(href(HREF0+[show(src)]), 741 img([ class(action), 742 alt('Show source'), 743 title('Show source'), 744 src(location_by_id(pldoc_resource)+'source.png') 745 ]))).
true
, provide a navitation tree.755objects(Objects, Options) --> 756 { option(navtree(true), Options), 757 !, 758 objects_nav_tree(Objects, Tree) 759 }, 760 html([ div(class(navtree), 761 div(class(navwindow), 762 \nav_tree(Tree, Objects, Options))), 763 div(class(navcontent), 764 \objects_nt(Objects, Options)) 765 ]). 766objects(Objects, Options) --> 767 objects_nt(Objects, Options). 768 769objects_nt(Objects, Options) --> 770 objects(Objects, [body], Options). 771 772objects([], Mode, _) --> 773 pop_mode(body, Mode, _). 774objects([Obj|T], Mode, Options) --> 775 object(Obj, Mode, Mode1, Options), 776 objects(T, Mode1, Options).
787object(doc(Obj,Pos,Comment), Mode0, Mode, Options) --> 788 !, 789 object(Obj, [Pos-Comment], Mode0, Mode, [scope(file)|Options]). 790object(Obj, Mode0, Mode, Options) --> 791 { findall(Pos-Comment, 792 doc_comment(Obj, Pos, _Summary, Comment), 793 Pairs) 794 }, 795 !, 796 { b_setval(pldoc_object, Obj) }, 797 object(Obj, Pairs, Mode0, Mode, Options). 798 799object(Obj, Pairs, Mode0, Mode, Options) --> 800 { is_pi(Obj), 801 !, 802 maplist(pred_dom(Obj, Options), Pairs, DOMS), 803 append(DOMS, DOM) 804 }, 805 need_mode(dl, Mode0, Mode), 806 html(DOM). 807object([Obj|_Same], Pairs, Mode0, Mode, Options) --> 808 !, 809 object(Obj, Pairs, Mode0, Mode, Options). 810object(Obj, _Pairs, Mode, Mode, _Options) --> 811 { debug(pldoc, 'Skipped ~p', [Obj]) }, 812 []. 813 814pred_dom(Obj, Options, Pos-Comment, DOM) :- 815 is_structured_comment(Comment, Prefixes), 816 string_codes(Comment, Codes), 817 indented_lines(Codes, Prefixes, Lines), 818 strip_module(user:Obj, Module, _), 819 process_modes(Lines, Module, Pos, Modes, Args, Lines1), 820 ( private(Obj, Options) 821 -> Class = privdef % private definition 822 ; multifile(Obj, Options) 823 -> ( option(scope(file), Options) 824 -> ( more_doc(Obj, Pos) 825 -> Class = multidef(object(Obj)) 826 ; Class = multidef 827 ) 828 ; Class = multidef(file((Pos))) 829 ) 830 ; public(Obj, Options) 831 -> Class = publicdef % :- public definition 832 ; Class = pubdef % exported definition 833 ), 834 ( Obj = Module:_ 835 -> POptions = [module(Module)|Options] 836 ; POptions = Options 837 ), 838 Pos = File:Line, 839 DTOptions = [file(File),line(Line)|POptions], 840 DOM = [\pred_dt(Modes, Class, DTOptions), dd(class=defbody, DOM1)], 841 wiki_lines_to_dom(Lines1, Args, DOM0), 842 strip_leading_par(DOM0, DOM1). 843 844more_doc(Obj, File:_) :- 845 doc_comment(Obj, File2:_, _, _), 846 File2 \== File, 847 !.
856need_mode(Mode, Stack, Stack) --> 857 { Stack = [Mode|_] }, 858 !, 859 []. 860need_mode(Mode, Stack, Rest) --> 861 { memberchk(Mode, Stack) 862 }, 863 !, 864 pop_mode(Mode, Stack, Rest). 865need_mode(Mode, Stack, [Mode|Stack]) --> 866 !, 867 html_begin(Mode). 868 869pop_mode(Mode, Stack, Stack) --> 870 { Stack = [Mode|_] }, 871 !, 872 []. 873pop_mode(Mode, [H|Rest0], Rest) --> 874 html_end(H), 875 pop_mode(Mode, Rest0, Rest).
881undocumented(File, Objs, Options) --> 882 { memberchk(module(Module), Options), 883 memberchk(public(Exports), Options), 884 select_undocumented(Exports, Module, Objs, Undoc), 885 re_exported_doc(Undoc, File, Module, UREObjs, ReallyUnDoc), 886 sort(2, @=<, UREObjs, REObjs) % UREObjs = doc(PI,Pos,Comment) 887 % i.e., sort on Pos 888 }, 889 !, 890 re_exported_doc(REObjs, Options), 891 undocumented(ReallyUnDoc, Options). 892undocumented(_, _, _) --> 893 []. 894 895re_exported_doc([], _) --> !. 896re_exported_doc(Objs, Options) --> 897 reexport_header(Objs, Options), 898 objects(Objs, Options). 899 900reexport_header(_, Options) --> 901 { option(reexport_header(true), Options, true) 902 }, 903 !, 904 html([ h2(class(wiki), 'Re-exported predicates'), 905 p([ "The following predicates are exported from this file \c 906 while their implementation is defined in imported modules \c 907 or non-module files loaded by this module." 908 ]) 909 ]). 910reexport_header(_, _) --> 911 []. 912 913undocumented([], _) --> !. 914undocumented(UnDoc, Options) --> 915 html([ h2(class(undoc), 'Undocumented predicates'), 916 p(['The following predicates are exported, but not ', 917 'or incorrectly documented.' 918 ]), 919 dl(class(undoc), 920 \undocumented_predicates(UnDoc, Options)) 921 ]). 922 923 924undocumented_predicates([], _) --> 925 []. 926undocumented_predicates([H|T], Options) --> 927 undocumented_pred(H, Options), 928 undocumented_predicates(T, Options). 929 930undocumented_pred(Name/Arity, Options) --> 931 { functor(Head, Name, Arity) }, 932 html(dt(class=undoc, \pred_mode(Head, [], _, Options))). 933 934select_undocumented([], _, _, []). 935select_undocumented([PI|T0], M, Objs, [PI|T]) :- 936 is_pi(PI), 937 \+ in_doc(M:PI, Objs), 938 !, 939 select_undocumented(T0, M, Objs, T). 940select_undocumented([_|T0], M, Objs, T) :- 941 select_undocumented(T0, M, Objs, T). 942 943in_doc(PI, Objs) :- 944 member(doc(O,_,_), Objs), 945 ( is_list(O) 946 -> member(O2, O), 947 eq_pi(PI, O2) 948 ; eq_pi(PI, O) 949 ).
956eq_pi(PI, PI) :- !. 957eq_pi(M:PI1, M:PI2) :- 958 atom(M), 959 !, 960 eq_pi(PI1, PI2). 961eq_pi(Name/A, Name//DCGA) :- 962 A =:= DCGA+2, 963 !. 964eq_pi(Name//DCGA, Name/A) :- 965 A =:= DCGA+2.
971is_pi(Var) :- 972 var(Var), 973 !, 974 fail. 975is_pi(_:PI) :- 976 !, 977 is_pi(PI). 978is_pi(_/_). 979is_pi(_//_).
985re_exported_doc([], _, _, [], []). 986re_exported_doc([PI|T0], File, Module, [doc(Orig:PI,Pos,Comment)|ObjT], UnDoc) :- 987 pi_to_head(PI, Head), 988 ( predicate_property(Module:Head, imported_from(Orig)) 989 -> true 990 ; predicate_property(Module:Head, exported) 991 -> Orig = Module 992 ; xref_defined(File, Head, imported(File2)), 993 ensure_doc_objects(File2), 994 xref_module(File2, Orig) 995 ), 996 doc_comment(Orig:PI, Pos, _, Comment), 997 !, 998 re_exported_doc(T0, File, Module, ObjT, UnDoc). 999re_exported_doc([PI|T0], File, Module, REObj, [PI|UnDoc]) :- 1000 re_exported_doc(T0, File, Module, REObj, UnDoc). 1001 1002 1003 /******************************* 1004 * SINGLE OBJECT PAGE * 1005 *******************************/
1015object_page(Obj, Options) --> 1016 prolog:doc_object_page(Obj, Options), 1017 !, 1018 object_page_footer(Obj, Options). 1019object_page(Obj, Options) --> 1020 { doc_comment(Obj, File:_Line, _Summary, _Comment) 1021 }, 1022 !, 1023 ( { \+ ( doc_comment(Obj, File2:_, _, _), 1024 File2 \== File ) 1025 } 1026 -> html([ \html_requires(pldoc), 1027 \object_page_header(File, Options), 1028 \object_synopsis(Obj, []), 1029 \objects([Obj], Options) 1030 ]) 1031 ; html([ \html_requires(pldoc), 1032 \object_page_header(-, Options), 1033 \objects([Obj], [synopsis(true)|Options]) 1034 ]) 1035 ), 1036 object_page_footer(Obj, Options). 1037object_page(M:Name/Arity, Options) --> % specified module, but public 1038 { functor(Head, Name, Arity), 1039 ( predicate_property(M:Head, exported) 1040 -> module_property(M, class(library)) 1041 ; \+ predicate_property(M:Head, defined) 1042 ) 1043 }, 1044 prolog:doc_object_page(Name/Arity, Options), 1045 !, 1046 object_page_footer(Name/Arity, Options). 1047 1048object_page_header(File, Options) --> 1049 prolog:doc_page_header(file(File), Options), 1050 !. 1051object_page_header(File, Options) --> 1052 { option(header(true), Options, true) }, 1053 !, 1054 html(div(class(navhdr), 1055 [ div(class(jump), \file_link(File)), 1056 div(class(search), \search_form(Options)), 1057 br(clear(right)) 1058 ])). 1059object_page_header(_, _) --> []. 1060 1061file_link(-) --> 1062 !, 1063 places_menu(-). 1064file_link(File) --> 1065 { file_directory_name(File, Dir) 1066 }, 1067 places_menu(Dir), 1068 html([ div(a(href(location_by_id(pldoc_doc)+File), File)) 1069 ]).
1076object_footer(Obj, Options) --> 1077 prolog:doc_object_footer(Obj, Options), 1078 !. 1079object_footer(_, _) --> [].
1087object_page_footer(Obj, Options) --> 1088 prolog:doc_object_page_footer(Obj, Options), 1089 !. 1090object_page_footer(_, _) --> [].
1104object_synopsis(Name/Arity, _) --> 1105 { functor(Head, Name, Arity), 1106 predicate_property(system:Head, built_in) 1107 }, 1108 synopsis([span(class(builtin), 'built-in')]). 1109object_synopsis(Name/Arity, Options) --> 1110 !, 1111 object_synopsis(_:Name/Arity, Options). 1112object_synopsis(M:Name/Arity, Options) --> 1113 { functor(Head, Name, Arity), 1114 ( option(source(Spec), Options) 1115 -> absolute_file_name(Spec, File, 1116 [ access(read), 1117 file_type(prolog), 1118 file_errors(fail) 1119 ]) 1120 ; predicate_property(M:Head, exported), 1121 \+ predicate_property(M:Head, imported_from(_)), 1122 module_property(M, file(File)), 1123 file_name_on_path(File, Spec) 1124 ), 1125 !, 1126 unquote_filespec(Spec, Unquoted), 1127 ( predicate_property(Head, autoload(FileBase)), 1128 file_name_extension(FileBase, _Ext, File) 1129 -> Extra = [span(class(autoload), '(can be autoloaded)')] 1130 ; Extra = [] 1131 ) 1132 }, 1133 ( { option(href(HREF), Options) } 1134 -> synopsis([code([':- use_module(',a(href(HREF), '~q'-[Unquoted]),').'])|Extra]) 1135 ; synopsis([code(':- use_module(~q).'-[Unquoted])|Extra]) 1136 ). 1137object_synopsis(Name//Arity, Options) --> 1138 !, 1139 { DCGArity is Arity+2 }, 1140 object_synopsis(Name/DCGArity, Options). 1141object_synopsis(Module:Name//Arity, Options) --> 1142 !, 1143 { DCGArity is Arity+2 }, 1144 object_synopsis(Module:Name/DCGArity, Options). 1145object_synopsis(f(_/_), _) --> 1146 synopsis(span(class(function), 1147 [ 'Arithmetic function (see ', 1148 \object_ref(is/2, []), 1149 ')' 1150 ])). 1151object_synopsis(c(Func), _) --> 1152 { sub_atom(Func, 0, _, _, 'PL_') 1153 ; sub_atom(Func, 0, _, _, 'S') 1154 }, 1155 !, 1156 synopsis([span(class(cfunc), 'C-language interface function')]). 1157object_synopsis(_, _) --> []. 1158 1159synopsis(Text) --> 1160 html(div(class(synopsis), 1161 [ span(class('synopsis-hdr'), 'Availability:') 1162 | Text 1163 ])).
1170unquote_filespec(Spec, Unquoted) :- 1171 compound(Spec), 1172 Spec =.. [Alias,Path], 1173 atom(Path), 1174 atomic_list_concat(Parts, /, Path), 1175 maplist(need_no_quotes, Parts), 1176 !, 1177 parts_to_path(Parts, UnquotedPath), 1178 Unquoted =.. [Alias, UnquotedPath]. 1179unquote_filespec(Spec, Spec). 1180 1181need_no_quotes(Atom) :- 1182 format(atom(A), '~q', [Atom]), 1183 \+ sub_atom(A, 0, _, _, '\''). 1184 1185parts_to_path([One], One) :- !. 1186parts_to_path(List, More/T) :- 1187 ( append(H, [T], List) 1188 -> parts_to_path(H, More) 1189 ). 1190 1191 1192 /******************************* 1193 * PRINT * 1194 *******************************/
1200doc_write_html(Out, Title, Doc) :-
1201 doc_page_dom(Title, Doc, DOM),
1202 phrase(html(DOM), Tokens),
1203 print_html_head(Out),
1204 print_html(Out, Tokens).
1211doc_page_dom(Title, Body, DOM) :-
1212 DOM = html([ head([ title(Title),
1213 link([ rel(stylesheet),
1214 type('text/css'),
1215 href(location_by_id(pldoc_resource)+'pldoc.css')
1216 ]),
1217 script([ src(location_by_id(pldoc_resource)+'pldoc.js'),
1218 type('text/javascript')
1219 ], [])
1220 ]),
1221 body(Body)
1222 ]).
DOCTYPE
line.1228print_html_head(Out) :- 1229 format(Out, 1230 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" \c 1231 "http://www.w3.org/TR/html4/strict.dtd">~n', []). 1232 1233% Rendering rules 1234% 1235% These rules translate \-terms produced by wiki.pl
1243tags(Tags) -->
1244 html(dl(class=tags, Tags)).
tag(Name, Values)
terms produced by doc_wiki.pl
.1250tag(Tag, Values) --> 1251 { doc_tag_title(Tag, Title), 1252 atom_concat('keyword-', Tag, Class) 1253 }, 1254 html([ dt(class=Class, Title), 1255 \tag_values(Values, Class) 1256 ]). 1257 1258tag_values([], _) --> 1259 []. 1260tag_values([H|T], Class) --> 1261 html(dd(class=Class, ['- '|H])), 1262 tag_values(T, Class).
1269doc_tag_title(Tag, Title) :- 1270 tag_title(Tag, Title), 1271 !. 1272doc_tag_title(Tag, Tag). 1273 1274tag_title(compat, 'Compatibility'). 1275tag_title(tbd, 'To be done'). 1276tag_title(see, 'See also'). 1277tag_title(error, 'Errors'). 1278tag_title(since, 'Since').
args(List)
created by doc_wiki.pl
. Params is a
list of arg(Name, Descr)
.1285args(Params) --> 1286 html([ dt(class=tag, 'Arguments:'), 1287 dd(table(class=arglist, 1288 \arg_list(Params))) 1289 ]). 1290 1291arg_list([]) --> 1292 []. 1293arg_list([H|T]) --> 1294 argument(H), 1295 arg_list(T). 1296 1297argument(arg(Name,Descr)) --> 1298 html(tr([td(var(Name)), td(class=argdescr, ['- '|Descr])])). 1299 1300 1301 /******************************* 1302 * NAVIGATION TREE * 1303 *******************************/
node(Object, Children)
.1310objects_nav_tree(Objects, Tree) :- 1311 maplist(object_nav_tree, Objects, Trees), 1312 union_trees(Trees, Tree0), 1313 remove_unique_root(Tree0, Tree). 1314 Obj, Tree) (:- 1316 Node = node(directory(Dir), FileNodes), 1317 FileNode = node(file(File), Siblings), 1318 doc_comment(Obj, File:_Line, _Summary, _Comment), 1319 !, 1320 file_directory_name(File, Dir), 1321 sibling_file_nodes(Dir, FileNodes0), 1322 selectchk(node(file(File),[]), FileNodes0, FileNode, FileNodes), 1323 findall(Sibling, doc_comment(Sibling, File:_, _, _), Siblings0), 1324 delete(Siblings0, _:module(_), Siblings1), 1325 doc_hide_private(Siblings1, Siblings2, []), 1326 flatten(Siblings2, Siblings), % a comment may describe objects 1327 embed_directories(Node, Tree). 1328 1329sibling_file_nodes(Dir, Nodes) :- 1330 findall(node(file(File), []), 1331 ( source_file(File), 1332 file_directory_name(File, Dir) 1333 ), 1334 Nodes). 1335 1336embed_directories(Node, Tree) :- 1337 Node = node(file(File), _), 1338 !, 1339 file_directory_name(File, Dir), 1340 Super = node(directory(Dir), [Node]), 1341 embed_directories(Super, Tree). 1342embed_directories(Node, Tree) :- 1343 Node = node(directory(Dir), _), 1344 file_directory_name(Dir, SuperDir), 1345 SuperDir \== Dir, 1346 !, 1347 Super = node(directory(SuperDir), [Node]), 1348 embed_directories(Super, Tree). 1349embed_directories(Tree, Tree). 1350 1351 1352union_trees([Tree], Tree) :- !. 1353union_trees([T1,T2|Trees], Tree) :- 1354 merge_trees(T1, T2, M1), 1355 union_trees([M1|Trees], Tree). 1356 1357merge_trees(node(R, Ch1), node(R, Ch2), node(R, Ch)) :- 1358 merge_nodes(Ch1, Ch2, Ch). 1359 1360merge_nodes([], Ch, Ch) :- !. 1361merge_nodes(Ch, [], Ch) :- !. 1362merge_nodes([node(Root, Ch1)|T1], N1, [T1|Nodes]) :- 1363 selectchk(node(Root, Ch2), N1, N2), 1364 !, 1365 merge_trees(node(Root, Ch1), node(Root, Ch2), T1), 1366 merge_nodes(T1, N2, Nodes). 1367merge_nodes([Node|T1], N1, [Node|Nodes]) :- 1368 merge_nodes(T1, N1, Nodes).
1374remove_unique_root(node(_, [node(R1, [R2])]), Tree) :- 1375 !, 1376 remove_unique_root(node(R1, [R2]), Tree). 1377remove_unique_root(Tree, Tree).
1383nav_tree(Tree, Current, Options) -->
1384 html(ul(class(nav),
1385 \object_tree(Tree, Current, Options))).
1391object_tree(node(Id, []), Target, Options) --> 1392 !, 1393 { node_class(Id, Target, Class) }, 1394 html(li(class(Class), 1395 \node(Id, Options))). 1396object_tree(node(Id, Children), Target, Options) --> 1397 !, 1398 { node_class(Id, Target, Class) }, 1399 html(li(class(Class), 1400 [ \node(Id, Options), 1401 ul(class(nav), 1402 \object_trees(Children, Target, Options)) 1403 ])). 1404object_tree(Id, Target, Options) --> 1405 !, 1406 { node_class(Id, Target, Class) }, 1407 html(li(class([obj|Class]), \node(Id, Options))). 1408 1409object_trees([], _, _) --> []. 1410object_trees([H|T], Target, Options) --> 1411 object_tree(H, Target, Options), 1412 object_trees(T, Target, Options). 1413 1414node_class(Ids, Current, Class) :- 1415 is_list(Ids), 1416 !, 1417 ( member(Id, Ids), memberchk(Id, Current) 1418 -> Class = [nav,current] 1419 ; Class = [nav] 1420 ). 1421node_class(Id, Current, Class) :- 1422 ( memberchk(Id, Current) 1423 -> Class = [nav,current] 1424 ; Class = [nav] 1425 ). 1426 1427node(file(File), Options) --> 1428 !, 1429 object_ref(file(File), [style(title)|Options]). 1430node(Id, Options) --> 1431 object_ref(Id, Options). 1432 1433 1434 /******************************* 1435 * SECTIONS * 1436 *******************************/ 1437 1438section(Type, Title) --> 1439 { string_codes(Title, Codes), 1440 wiki_codes_to_dom(Codes, [], Content0), 1441 strip_leading_par(Content0, Content), 1442 make_section(Type, Content, HTML) 1443 }, 1444 html(HTML). 1445 1446make_section(module, Title, h1(class=module, Title)). 1447make_section(section, Title, h1(class=section, Title)). 1448 1449 1450 /******************************* 1451 * PRED MODE HEADER * 1452 *******************************/
1460pred_dt(Modes, Class, Options) --> 1461 pred_dt(Modes, Class, [], _Done, Options). 1462 1463pred_dt([], _, Done, Done, _) --> 1464 []. 1465pred_dt([H|T], Class, Done0, Done, Options) --> 1466 { functor(Class, CSSClass, _) }, 1467 html(dt(class=CSSClass, 1468 [ \pred_mode(H, Done0, Done1, Options), 1469 \mode_anot(Class) 1470 ])), 1471 pred_dt(T, Class, Done1, Done, Options). 1472 1473mode_anot(privdef) --> 1474 !, 1475 html(span([class(anot), style('float:right')], 1476 '[private]')). 1477mode_anot(multidef(object(Obj))) --> 1478 !, 1479 { object_href(Obj, HREF) }, 1480 html(span([class(anot), style('float:right')], 1481 ['[', a(href(HREF), multifile), ']' 1482 ])). 1483mode_anot(multidef(file(File:_))) --> 1484 !, 1485 { file_name_on_path(File, Spec), 1486 unquote_filespec(Spec, Unquoted), 1487 doc_file_href(File, HREF) 1488 }, 1489 html(span([class(anot), style('float:right')], 1490 ['[multifile, ', a(href(HREF), '~q'-[Unquoted]), ']' 1491 ])). 1492mode_anot(multidef) --> 1493 !, 1494 html(span([class(anot), style('float:right')], 1495 '[multifile]')). 1496mode_anot(_) --> 1497 []. 1498 1499pred_mode(mode(Head,Vars), Done0, Done, Options) --> 1500 !, 1501 { bind_vars(Head, Vars) }, 1502 pred_mode(Head, Done0, Done, Options). 1503pred_mode(Head is Det, Done0, Done, Options) --> 1504 !, 1505 anchored_pred_head(Head, Done0, Done, Options), 1506 pred_det(Det). 1507pred_mode(Head, Done0, Done, Options) --> 1508 anchored_pred_head(Head, Done0, Done, Options). 1509 1510bind_vars(Term, Bindings) :- 1511 bind_vars(Bindings), 1512 anon_vars(Term). 1513 1514bind_vars([]). 1515bind_vars([Name=Var|T]) :- 1516 Var = '$VAR'(Name), 1517 bind_vars(T).
1524anon_vars(Var) :- 1525 var(Var), 1526 !, 1527 Var = '$VAR'('_'). 1528anon_vars(Term) :- 1529 compound(Term), 1530 !, 1531 Term =.. [_|Args], 1532 maplist(anon_vars, Args). 1533anon_vars(_). 1534 1535 1536anchored_pred_head(Head, Done0, Done, Options) --> 1537 { pred_anchor_name(Head, PI, Name) }, 1538 ( { memberchk(PI, Done0) } 1539 -> { Done = Done0 }, 1540 pred_head(Head) 1541 ; html([ span(style('float:right'), 1542 [ \pred_edit_or_source_button(Head, Options), 1543 &(nbsp) 1544 ]), 1545 a(name=Name, \pred_head(Head)) 1546 ]), 1547 { Done = [PI|Done0] } 1548 ). 1549 1550 Head, Options) (--> 1552 { option(edit(true), Options) }, 1553 !, 1554 pred_edit_button(Head, Options). 1555pred_edit_or_source_button(Head, Options) --> 1556 { option(source_link(true), Options) }, 1557 !, 1558 pred_source_button(Head, Options). 1559pred_edit_or_source_button(_, _) --> [].
1573pred_edit_button(_, Options) --> 1574 { \+ option(edit(true), Options) }, 1575 !. 1576pred_edit_button(PI0, Options0) --> 1577 { canonicalise_predref(PI0, PI, Options0, Options) }, 1578 pred_edit_button2(PI, Options). 1579 Name/Arity, Options) (--> 1581 { \+ ( memberchk(file(_), Options), % always edit if file and line 1582 memberchk(line(_), Options) % are given. 1583 ), 1584 functor(Head, Name, Arity), 1585 option(module(M), Options, _), 1586 \+ ( current_module(M), 1587 source_file(M:Head, _File) 1588 ) 1589 }, 1590 !. 1591pred_edit_button2(Name/Arity, Options) --> 1592 { include(edit_param, Options, Extra), 1593 http_link_to_id(pldoc_edit, 1594 [name(Name),arity(Arity)|Extra], 1595 EditHREF) 1596 }, 1597 html(a(onClick('HTTPrequest(\'' + EditHREF + '\')'), 1598 img([ class(action), 1599 alt('Edit predicate'), 1600 title('Edit predicate'), 1601 src(location_by_id(pldoc_resource)+'editpred.png') 1602 ]))). 1603pred_edit_button2(_, _) --> 1604 !, 1605 []. 1606 1607edit_param(module(_)). 1608edit_param(file(_)). 1609edit_param(line(_)).
1616object_edit_button(_, Options) --> 1617 { \+ option(edit(true), Options) }, 1618 !. 1619object_edit_button(PI, Options) --> 1620 { is_pi(PI) }, 1621 !, 1622 pred_edit_button(PI, Options). 1623object_edit_button(_, _) --> 1624 [].
1631pred_source_button(PI0, Options0) --> 1632 { canonicalise_predref(PI0, PI, Options0, Options), 1633 option(module(M), Options, _), 1634 pred_source_href(PI, M, HREF), ! 1635 }, 1636 html(a([ href(HREF) 1637 ], 1638 img([ class(action), 1639 alt('Source'), 1640 title('Show source'), 1641 src(location_by_id(pldoc_resource)+'source.png') 1642 ]))). 1643pred_source_button(_, _) --> 1644 [].
1651object_source_button(PI, Options) --> 1652 { is_pi(PI), 1653 option(source_link(true), Options, true) 1654 }, 1655 !, 1656 pred_source_button(PI, Options). 1657object_source_button(_, _) --> 1658 [].
module(M)
to Options.1666canonicalise_predref(M:PI0, PI, Options0, [module(M)|Options]) :- 1667 !, 1668 canonicalise_predref(PI0, PI, Options0, Options). 1669canonicalise_predref(//(Head), PI, Options0, Options) :- 1670 !, 1671 functor(Head, Name, Arity), 1672 PredArity is Arity + 2, 1673 canonicalise_predref(Name/PredArity, PI, Options0, Options). 1674canonicalise_predref(Name//Arity, PI, Options0, Options) :- 1675 integer(Arity), Arity >= 0, 1676 !, 1677 PredArity is Arity + 2, 1678 canonicalise_predref(Name/PredArity, PI, Options0, Options). 1679canonicalise_predref(PI, PI, Options, Options) :- 1680 PI = Name/Arity, 1681 atom(Name), integer(Arity), Arity >= 0, 1682 !. 1683canonicalise_predref(Head, PI, Options0, Options) :- 1684 functor(Head, Name, Arity), 1685 canonicalise_predref(Name/Arity, PI, Options0, Options).
span
using
class pred
and the arguments and var
using class arglist
.1693pred_head(Var) --> 1694 { var(Var), 1695 !, 1696 instantiation_error(Var) 1697 }. 1698pred_head(//(Head)) --> 1699 !, 1700 pred_head(Head), 1701 html(//). 1702pred_head(M:Head) --> 1703 html([span(class=module, M), :]), 1704 pred_head(Head). 1705pred_head(Head) --> 1706 { atom(Head) }, 1707 !, 1708 html(b(class=pred, Head)). 1709pred_head(Head) --> % Infix operators 1710 { Head =.. [Functor,Left,Right], 1711 is_op_type(Functor, infix) 1712 }, 1713 !, 1714 html([ var(class=arglist, \pred_arg(Left, 1)), 1715 ' ', b(class=pred, Functor), ' ', 1716 var(class=arglist, \pred_arg(Right, 2)) 1717 ]). 1718pred_head(Head) --> % Prefix operators 1719 { Head =.. [Functor,Arg], 1720 is_op_type(Functor, prefix) 1721 }, 1722 !, 1723 html([ b(class=pred, Functor), ' ', 1724 var(class=arglist, \pred_arg(Arg, 1)) 1725 ]). 1726pred_head(Head) --> % Postfix operators 1727 { Head =.. [Functor,Arg], 1728 is_op_type(Functor, postfix) 1729 }, 1730 !, 1731 html([ var(class=arglist, \pred_arg(Arg, 1)), 1732 ' ', b(class=pred, Functor) 1733 ]). 1734pred_head({Head}) --> 1735 !, 1736 html([ b(class=pred, '{'), 1737 var(class=arglist, 1738 \pred_args([Head], 1)), 1739 b(class=pred, '}') 1740 ]). 1741pred_head(Head) --> % Plain terms 1742 { Head =.. [Functor|Args] }, 1743 html([ b(class=pred, Functor), 1744 var(class=arglist, 1745 [ '(', \pred_args(Args, 1), ')' ]) 1746 ]).
prefix
,
infix
or postfix
.1753is_op_type(Functor, Type) :- 1754 current_op(_Pri, F, Functor), 1755 op_type(F, Type). 1756 1757op_type(fx, prefix). 1758op_type(fy, prefix). 1759op_type(xf, postfix). 1760op_type(yf, postfix). 1761op_type(xfx, infix). 1762op_type(xfy, infix). 1763op_type(yfx, infix). 1764op_type(yfy, infix). 1765 1766 1767pred_args([], _) --> 1768 []. 1769pred_args([H|T], I) --> 1770 pred_arg(H, I), 1771 ( {T==[]} 1772 -> [] 1773 ; html(', '), 1774 { I2 is I + 1 }, 1775 pred_args(T, I2) 1776 ). 1777 1778pred_arg(Var, I) --> 1779 { var(Var) }, 1780 !, 1781 html(['Arg', I]). 1782pred_arg(...(Term), I) --> 1783 !, 1784 pred_arg(Term, I), 1785 html('...'). 1786pred_arg(Term, I) --> 1787 { Term =.. [Ind,Arg], 1788 mode_indicator(Ind) 1789 }, 1790 !, 1791 html([Ind, \pred_arg(Arg, I)]). 1792pred_arg(Arg:Type, _) --> 1793 !, 1794 html([\argname(Arg), :, \argtype(Type)]). 1795pred_arg(Arg, _) --> 1796 argname(Arg). 1797 1798argname('$VAR'(Name)) --> 1799 !, 1800 html(Name). 1801argname(Name) --> 1802 !, 1803 html(Name). 1804 1805argtype(Term) --> 1806 { format(string(S), '~W', 1807 [ Term, 1808 [ quoted(true), 1809 numbervars(true) 1810 ] 1811 ]) }, 1812 html(S). 1813 1814pred_det(unknown) --> 1815 []. 1816pred_det(Det) --> 1817 html([' is ', b(class=det, Det)]).
doc_wiki.pl
.
1826term(_, Atom, []) --> 1827 { atomic(Atom), 1828 !, 1829 format(string(S), '~W', [Atom,[quoted(true)]]) 1830 }, 1831 html(span(class=functor, S)). 1832term(_, Key:Type, [TypeName=Type]) --> 1833 { atomic(Key) 1834 }, 1835 !, 1836 html([span(class='pl-key', Key), :, span(class('pl-var'), TypeName)]). 1837term(_, Term, Bindings) --> 1838 { is_mode(Term is det), % HACK. Bit too strict? 1839 bind_vars(Bindings) 1840 }, 1841 !, 1842 pred_head(Term). 1843term(_, Term, Bindings) --> 1844 term(Term, 1845 [ variable_names(Bindings), 1846 quoued(true) 1847 ]). 1848 1849 1850 /******************************* 1851 * PREDREF * 1852 *******************************/
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.
1865predref(Term) --> 1866 { catch(nb_getval(pldoc_options, Options), _, Options = []) }, 1867 predref(Term, Options). 1868 1869predref(Obj, Options) --> 1870 { Obj = _:_, 1871 doc_comment(Obj, File:_Line, _, _), 1872 ( ( option(files(Map), Options) 1873 -> memberchk(file(File,_), Map) 1874 ; true 1875 ) 1876 -> object_href(Obj, HREF, Options) 1877 ; manref(Obj, HREF, Options) 1878 ) 1879 }, 1880 !, 1881 html(a(href(HREF), \object_name(Obj, [qualify(true)|Options]))). 1882predref(M:Term, Options) --> 1883 !, 1884 predref(Term, M, Options). 1885predref(Term, Options) --> 1886 predref(Term, _, Options). 1887 1888predref(Name/Arity, _, Options) --> % Builtin; cannot be overruled 1889 { prolog:doc_object_summary(Name/Arity, manual, _, _), 1890 !, 1891 manref(Name/Arity, HREF, Options) 1892 }, 1893 html(a([class=builtin, href=HREF], [Name, /, Arity])). 1894predref(Name/Arity, _, Options) --> % From packages 1895 { option(prefer(manual), Options), 1896 prolog:doc_object_summary(Name/Arity, Category, _, _), 1897 !, 1898 manref(Name/Arity, HREF, Options) 1899 }, 1900 html(a([class=Category, href=HREF], [Name, /, Arity])). 1901predref(Obj, Module, Options) --> % Local 1902 { doc_comment(Module:Obj, File:_Line, _, _), 1903 ( option(files(Map), Options) 1904 -> memberchk(file(File,_), Map) 1905 ; true 1906 ) 1907 }, 1908 !, 1909 object_ref(Module:Obj, Options). 1910predref(Name/Arity, Module, Options) --> 1911 { \+ option(files(_), Options), 1912 pred_href(Name/Arity, Module, HREF) 1913 }, 1914 !, 1915 html(a(href=HREF, [Name, /, Arity])). 1916predref(Name//Arity, Module, Options) --> 1917 { \+ option(files(_), Options), 1918 PredArity is Arity + 2, 1919 pred_href(Name/PredArity, Module, HREF) 1920 }, 1921 !, 1922 html(a(href=HREF, [Name, //, Arity])). 1923predref(PI, _, Options) --> % From packages 1924 { canonical_pi(PI, CPI, HTML), 1925 ( option(files(_), Options) 1926 -> Category = extmanual 1927 ; prolog:doc_object_summary(CPI, Category, _, _) 1928 ), 1929 manref(CPI, HREF, Options) 1930 }, 1931 html(a([class=Category, href=HREF], HTML)). 1932predref(PI, _, _Options) --> 1933 { canonical_pi(PI, _CPI, HTML) 1934 }, 1935 !, 1936 html(span(class=undef, HTML)). 1937predref(Callable, Module, Options) --> 1938 { callable(Callable), 1939 functor(Callable, Name, Arity) 1940 }, 1941 predref(Name/Arity, Module, Options). 1942 1943canonical_pi(Name/Arity, Name/Arity, [Name, /, Arity]) :- 1944 atom(Name), integer(Arity), 1945 !. 1946canonical_pi(Name//Arity, Name/Arity2, [Name, //, Arity]) :- 1947 atom(Name), integer(Arity), 1948 !, 1949 Arity2 is Arity+2.
name/arity
, non-linking predicate indicator.
1955nopredref(PI) -->
1956 { canonical_pi(PI, _CPI, HTML)
1957 },
1958 !,
1959 html(span(class=nopredref, HTML)).
1967flagref(Flag) -->
1968 html(code(Flag)).
1975cite(Citations) --> 1976 html('['), citations(Citations), html(']'). 1977 1978citations([]) --> []. 1979citations([H|T]) --> 1980 citation(H), 1981 ( {T==[]} 1982 -> [] 1983 ; [';'], 1984 citations(T) 1985 ). 1986 1987citation(H) --> 1988 html([@,H]).
man_server(+Server)
.1996manref(PI, HREF, Options) :- 1997 predname(PI, PredName), 1998 ( option(files(_Map), Options) 1999 -> option(man_server(Server), Options, 2000 'http://www.swi-prolog.org/pldoc'), 2001 uri_components(Server, Comp0), 2002 uri_data(path, Comp0, Path0), 2003 directory_file_path(Path0, man, Path), 2004 uri_data(path, Comp0, Path, Components), 2005 uri_query_components(Query, [predicate=PredName]), 2006 uri_data(search, Components, Query), 2007 uri_components(HREF, Components) 2008 ; http_link_to_id(pldoc_man, [predicate=PredName], HREF) 2009 ). 2010 2011predname(Name/Arity, PredName) :- 2012 !, 2013 format(atom(PredName), '~w/~d', [Name, Arity]). 2014predname(Module:Name/Arity, PredName) :- 2015 !, 2016 format(atom(PredName), '~w:~w/~d', [Module, Name, Arity]).
2030pred_href(Name/Arity, Module, HREF) :- 2031 format(string(FragmentId), '~w/~d', [Name, Arity]), 2032 uri_data(fragment, Components, FragmentId), 2033 functor(Head, Name, Arity), 2034 ( catch(relative_file(Module:Head, File), _, fail) 2035 -> uri_data(path, Components, File), 2036 uri_components(HREF, Components) 2037 ; in_file(Module:Head, File) 2038 -> ( current_prolog_flag(home, SWI), 2039 sub_atom(File, 0, _, _, SWI), 2040 prolog:doc_object_summary(Name/Arity, packages, _, _) 2041 -> http_link_to_id(pldoc_man, [predicate=FragmentId], HREF) 2042 ; http_location_by_id(pldoc_doc, DocHandler), 2043 atom_concat(DocHandler, File, Path), 2044 uri_data(path, Components, Path), 2045 uri_components(HREF, Components) 2046 ) 2047 ). 2048 2049relative_file(Head, '') :- 2050 b_getval(pldoc_file, CurrentFile), CurrentFile \== [], 2051 in_file(Head, CurrentFile), 2052 !. 2053relative_file(Head, RelFile) :- 2054 b_getval(pldoc_file, CurrentFile), CurrentFile \== [], 2055 in_file(Head, DefFile), 2056 relative_file_name(DefFile, CurrentFile, RelFile).
2062pred_source_href(Name/Arity, Module, HREF) :-
2063 format(string(FragmentId), '~w/~d', [Name, Arity]),
2064 uri_data(fragment, Components, FragmentId),
2065 uri_query_components(Query, [show=src]),
2066 uri_data(search, Components, Query),
2067 functor(Head, Name, Arity),
2068 ( catch(relative_file(Module:Head, File), _, fail)
2069 -> uri_data(path, Components, File),
2070 uri_components(HREF, Components)
2071 ; in_file(Module:Head, File0)
2072 -> insert_alias(File0, File),
2073 http_location_by_id(pldoc_doc, DocHandler),
2074 atom_concat(DocHandler, File, Path),
2075 uri_data(path, Components, Path),
2076 uri_components(HREF, Components)
2077 ).
2086object_ref([], _) --> 2087 !, 2088 []. 2089object_ref([H|T], Options) --> 2090 !, 2091 object_ref(H, Options), 2092 ( {T == []} 2093 -> html(', '), 2094 object_ref(T, Options) 2095 ; [] 2096 ). 2097object_ref(Obj, Options) --> 2098 { object_href(Obj, HREF, Options) 2099 }, 2100 html(a(href(HREF), \object_name(Obj, Options))).
2107object_href(Obj, HREF) :- 2108 object_href(Obj, HREF, []). 2109 2110object_href(M:PI0, HREF, Options) :- 2111 option(files(Map), Options), 2112 ( module_property(M, file(File)) 2113 -> true 2114 ; xref_module(File, M) 2115 ), 2116 memberchk(file(File, DocFile), Map), 2117 !, 2118 file_base_name(DocFile, LocalFile), % TBD: proper directory index 2119 expand_pi(PI0, PI), 2120 term_to_string(PI, PIS), 2121 uri_data(path, Components, LocalFile), 2122 uri_data(fragment, Components, PIS), 2123 uri_components(HREF, Components). 2124object_href(file(File), HREF, _Options) :- 2125 doc_file_href(File, HREF), 2126 !. 2127object_href(directory(Dir), HREF, _Options) :- 2128 directory_file_path(Dir, 'index.html', Index), 2129 doc_file_href(Index, HREF), 2130 !. 2131object_href(Obj, HREF, _Options) :- 2132 prolog:doc_object_href(Obj, HREF), 2133 !. 2134object_href(Obj0, HREF, _Options) :- 2135 localise_object(Obj0, Obj), 2136 term_to_string(Obj, String), 2137 http_link_to_id(pldoc_object, [object=String], HREF). 2138 2139expand_pi(Name//Arity0, Name/Arity) :- 2140 !, 2141 Arity is Arity0+2. 2142expand_pi(PI, PI).
2150localise_object(Obj0, Obj) :- 2151 prolog:doc_canonical_object(Obj0, Obj), 2152 !. 2153localise_object(Obj, Obj).
2161term_to_string(Term, String) :-
2162 State = state(-),
2163 ( numbervars(Term, 0, _, [singletons(true)]),
2164 with_output_to(string(String),
2165 write_term(Term,
2166 [ numbervars(true),
2167 quoted(true)
2168 ])),
2169 nb_setarg(1, State, String),
2170 fail
2171 ; arg(1, State, String)
2172 ).
inline
or title
number
, title
or number_title
2186object_name(Obj, Options) --> 2187 { option(style(Style), Options, inline) 2188 }, 2189 object_name(Style, Obj, Options). 2190 2191object_name(title, Obj, Options) --> 2192 { merge_options(Options, [secref_style(title)], Options1) }, 2193 prolog:doc_object_link(Obj, Options1), 2194 !. 2195object_name(inline, Obj, Options) --> 2196 prolog:doc_object_link(Obj, Options), 2197 !. 2198object_name(title, f(Name/Arity), _Options) --> 2199 !, 2200 html(['Function ', Name, /, Arity]). 2201object_name(inline, f(Name/Arity), _Options) --> 2202 !, 2203 html([Name, /, Arity]). 2204object_name(Style, PI, Options) --> 2205 { is_pi(PI) }, 2206 !, 2207 pi(Style, PI, Options). 2208object_name(inline, Module:module(_Title), _) --> 2209 !, 2210 { module_property(Module, file(File)), 2211 file_base_name(File, Base) 2212 }, 2213 !, 2214 html(Base). 2215object_name(title, Module:module(Title), _) --> 2216 { module_property(Module, file(File)), 2217 file_base_name(File, Base) 2218 }, 2219 !, 2220 html([Base, ' -- ', Title]). 2221object_name(title, file(File), _) --> 2222 { module_property(Module, file(File)), 2223 doc_comment(Module:module(Title), _, _, _), 2224 !, 2225 file_base_name(File, Base) 2226 }, 2227 html([Base, ' -- ', Title]). 2228object_name(_, file(File), _) --> 2229 { file_base_name(File, Base) }, 2230 html(Base). 2231object_name(_, directory(Dir), _) --> 2232 { file_base_name(Dir, Base) }, 2233 html(Base). 2234object_name(_, module(Title), _Options) --> 2235 { print_message(warning, 2236 pldoc(module_comment_outside_module(Title))) 2237 }. 2238 2239pi(title, PI, Options) --> 2240 pi_type(PI), 2241 pi(PI, Options). 2242pi(inline, PI, Options) --> 2243 pi(PI, Options). 2244 2245pi(M:PI, Options) --> 2246 !, 2247 ( { option(qualify(true), Options) } 2248 -> html([span(class(module), M), :]) 2249 ; [] 2250 ), 2251 pi(PI, Options). 2252pi(Name/Arity, _) --> 2253 !, 2254 html([Name, /, \arity(Arity)]). 2255pi(Name//Arity, _) --> 2256 html([Name, //, \arity(Arity)]). 2257 2258arity(Arity) --> 2259 { var(Arity) }, 2260 !, 2261 html('_'). 2262arity(Arity) --> 2263 html(Arity). 2264 2265pi_type(_:PI) --> 2266 !, 2267 pi_type(PI). 2268pi_type(_/_) --> 2269 html(['Predicate ']). 2270pi_type(_//_) --> 2271 html(['Grammar rule ']).
2283in_file(Module:Head, File) :- 2284 !, 2285 distinct(File, in_file(Module, Head, File)). 2286in_file(Head, File) :- 2287 distinct(File, in_file(_, Head, File)). 2288 2289in_file(Module, Head, File) :- 2290 var(Module), 2291 ( predicate_property(system:Head, foreign) 2292 -> !, 2293 fail 2294 ; predicate_property(system:Head, file(File)), 2295 \+ system_arithmetic_function(Head) 2296 -> ! 2297 ; predicate_property(Head, autoload(File0)) 2298 -> !, 2299 file_name_extension(File0, pl, File) 2300 ; exported_from(Module, Head, File), 2301 module_property(Module, class(library)) 2302 ). 2303in_file(Module, Head, File) :- 2304 nonvar(Module), 2305 predicate_property(Module:Head, file(File)), 2306 \+ predicate_property(Module:Head, imported_from(_)). 2307in_file(Module, Head, File) :- 2308 xref_defined(File, Head, How), 2309 xref_current_source(File), 2310 atom(File), % only plain files 2311 xref_module(File, Module), 2312 How \= imported(_From). 2313in_file(Module, Head, File) :- 2314 exported_from(Module, Head, File). 2315in_file(Module, Head, File) :- 2316 predicate_property(Module:Head, file(File)), 2317 \+ predicate_property(Module:Head, imported_from(_)). 2318in_file(Module, Head, File) :- 2319 current_module(Module), 2320 source_file(Module:Head, File). 2321 2322exported_from(Module, Head, File) :- 2323 distinct(Primary, 2324 ( predicate_property(Module:Head, exported), 2325 ( predicate_property(Module:Head, imported_from(Primary)) 2326 -> true 2327 ; Primary = Module 2328 ))), 2329 module_property(Primary, file(File)). 2330 2331:- multifile 2332 arithmetic:evaluable/2. 2333 2334system_arithmetic_function(Head) :- 2335 functor(Head, Name, Arity), 2336 FArith is Arity-1, 2337 FArith >= 0, 2338 functor(FHead, Name, FArith), 2339 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.2370file(File) --> 2371 file(File, []). 2372 2373file(File, Options) --> 2374 { catch(nb_getval(pldoc_options, GenOptions), _, GenOptions = []), 2375 merge_options(Options, GenOptions, FinalOptions) 2376 }, 2377 link_file(File, FinalOptions), 2378 !. 2379file(File, Options) --> 2380 { option(edit_handler(Handler), Options), 2381 http_current_request(Request), 2382 memberchk(path(Path), Request), 2383 absolute_file_name(File, Location, 2384 [ relative_to(Path) 2385 ]), 2386 http_link_to_id(Handler, [location(Location)], HREF), 2387 format(atom(Title), 'Click to create ~w', [File]) 2388 }, 2389 html(a([href(HREF), class(nofile), title(Title)], File)). 2390file(File, _) --> 2391 html(code(class(nofile), File)). 2392 2393link_file(File, Options) --> 2394 { file_href(File, HREF, Options), 2395 option(label(Label), Options, File), 2396 option(class(Class), Options, file) 2397 }, 2398 html(a([class(Class), href(HREF)], Label)).
2404file_href(_, HREF, Options) :- 2405 option(href(HREF), Options), 2406 !. 2407file_href(File, HREF, Options) :- 2408 file_href_real(File, HREF0, Options), 2409 map_extension(HREF0, HREF, Options).
map_extension(+Pairs)
2417map_extension(HREF0, HREF, Options) :- 2418 option(map_extension(Map), Options), 2419 file_name_extension(Base, Old, HREF0), 2420 memberchk(Old-New, Map), 2421 !, 2422 file_name_extension(Base, New, HREF). 2423map_extension(HREF, HREF, _). 2424 2425 2426file_href_real(File, HREF, Options) :- 2427 ( option(absolute_path(Path), Options) 2428 ; existing_linked_file(File, Path) 2429 ), 2430 !, 2431 ( option(files(Map), Options), 2432 memberchk(file(Path, LinkFile), Map) 2433 -> true 2434 ; LinkFile = Path 2435 ), 2436 file_href(LinkFile, HREF). 2437file_href_real(File, HREF, _) :- 2438 directory_alias(Alias), 2439 Term =.. [Alias,File], 2440 absolute_file_name(Term, _, 2441 [ access(read), 2442 file_errors(fail) 2443 ]), 2444 !, 2445 http_absolute_location(Term, HREF, []). 2446 2447directory_alias(icons). 2448directory_alias(css).
pldoc_file
.2458file_href(Path, HREF) :- % a loaded Prolog file 2459 source_file(Path), 2460 !, 2461 doc_file_href(Path, HREF). 2462file_href(Path, HREF) :- 2463 ( nb_current(pldoc_output, CFile) 2464 ; nb_current(pldoc_file, CFile) 2465 ), 2466 CFile \== [], 2467 !, 2468 relative_file_name(Path, CFile, HREF). 2469file_href(Path, Path).
2477existing_linked_file(File, Path) :-
2478 catch(b_getval(pldoc_file, CurrentFile), _, fail),
2479 CurrentFile \== [],
2480 absolute_file_name(File, Path,
2481 [ relative_to(CurrentFile),
2482 access(read),
2483 file_errors(fail)
2484 ]).
include(File,
Type)
terms in the DOM term generated by wiki.pl if it
encounters [[file.ext]].2494include(PI, predicate, _) --> 2495 !, 2496 ( html_tokens_for_predicates(PI, []) 2497 -> [] 2498 ; html(['[[', \predref(PI), ']]']) 2499 ). 2500include(File, image, Options) --> 2501 { file_name_extension(_, svg, File), 2502 file_href(File, HREF, Options), 2503 !, 2504 include(image_attribute, Options, Attrs0), 2505 merge_options(Attrs0, 2506 [ alt(File), 2507 data(HREF), 2508 type('image/svg+xml') 2509 ], Attrs) 2510 }, 2511 ( { option(caption(Caption), Options) } 2512 -> html(div(class(figure), 2513 [ div(class(image), object(Attrs, [])), 2514 div(class(caption), Caption) 2515 ])) 2516 ; html(object(Attrs, [])) 2517 ). 2518include(File, image, Options) --> 2519 { file_href(File, HREF, Options), 2520 !, 2521 include(image_attribute, Options, Attrs0), 2522 merge_options(Attrs0, 2523 [ alt(File), 2524 border(0), 2525 src(HREF) 2526 ], Attrs) 2527 }, 2528 ( { option(caption(Caption), Options) } 2529 -> html(div(class(figure), 2530 [ div(class(image), img(Attrs)), 2531 div(class(caption), Caption) 2532 ])) 2533 ; html(img(Attrs)) 2534 ). 2535include(File, wiki, _Options) --> % [[file.txt]] is included 2536 { access_file(File, read), 2537 !, 2538 read_file_to_codes(File, String, []), 2539 wiki_codes_to_dom(String, [], DOM) 2540 }, 2541 html(DOM). 2542include(File, _Type, Options) --> 2543 link_file(File, Options), 2544 !. 2545include(File, _, _) --> 2546 html(code(class(nofile), ['[[',File,']]'])). 2547 2548image_attribute(src(_)). 2549image_attribute(alt(_)). 2550image_attribute(title(_)). 2551image_attribute(align(_)). 2552image_attribute(width(_)). 2553image_attribute(height(_)). 2554image_attribute(border(_)). 2555image_attribute(class(_)). 2556image_attribute(style(_)).
* [[member/2]] * [[append/3]]
2569html_tokens_for_predicates([], _Options) --> 2570 []. 2571html_tokens_for_predicates([H|T], Options) --> 2572 !, 2573 html_tokens_for_predicates(H, Options), 2574 html_tokens_for_predicates(T, Options). 2575html_tokens_for_predicates(PI, Options) --> 2576 { PI = _:_/_, 2577 !, 2578 ( doc_comment(PI, Pos, _Summary, Comment) 2579 -> true 2580 ; Comment = '' 2581 ) 2582 }, 2583 object(PI, [Pos-Comment], [dl], _, Options). 2584html_tokens_for_predicates(Spec, Options) --> 2585 { findall(PI, documented_pi(Spec, PI), List), 2586 List \== [], ! 2587 }, 2588 html_tokens_for_predicates(List, Options). 2589html_tokens_for_predicates(Spec, Options) --> 2590 man_page(Spec, 2591 [ links(false), % no header 2592 navtree(false), % no navigation tree 2593 footer(false), % no footer 2594 synopsis(false) % no synopsis 2595 | Options 2596 ]). 2597 2598 2599documented_pi(Spec, PI) :- 2600 generalise_spec(Spec, PI), 2601 doc_comment(PI, _Pos, _Summary, _Comment). 2602 2603generalise_spec(Name/Arity, _M:Name/Arity). 2604generalise_spec(Name//Arity, _M:Name//Arity). 2605 2606 2607 /******************************* 2608 * WIKI FILES * 2609 *******************************/
2616doc_for_wiki_file(FileSpec, Options) :- 2617 absolute_file_name(FileSpec, File, 2618 [ access(read) 2619 ]), 2620 read_file_to_codes(File, String, []), 2621 b_setval(pldoc_file, File), 2622 call_cleanup(reply_wiki_page(File, String, Options), 2623 nb_delete(pldoc_file)). 2624 2625reply_wiki_page(File, String, Options) :- 2626 wiki_codes_to_dom(String, [], DOM0), 2627 title(DOM0, File, Title), 2628 insert_edit_button(DOM0, File, DOM, Options), 2629 reply_html_page(pldoc(wiki), 2630 title(Title), 2631 [ \html_requires(pldoc) 2632 | DOM 2633 ]). 2634 2635title(DOM, _, Title) :- 2636 sub_term(h1(_,Title), DOM), 2637 !. 2638title(_, File, Title) :- 2639 file_base_name(File, Title). 2640 DOM, _, DOM, Options) (:- 2642 option(edit(false), Options, false), 2643 !. 2644insert_edit_button([h1(Attrs,Title)|DOM], File, 2645 [h1(Attrs,[ span(style('float:right'), 2646 \edit_button(File, [edit(true)])) 2647 | Title 2648 ])|DOM], _) :- !. 2649insert_edit_button(DOM, File, 2650 [ h1(class(wiki), 2651 [ span(style('float:right'), 2652 \edit_button(File, [edit(true)])) 2653 ]) 2654 | DOM 2655 ], _). 2656 2657 2658 /******************************* 2659 * ANCHORS * 2660 *******************************/
2666mode_anchor_name(Var, _) :- 2667 var(Var), 2668 !, 2669 instantiation_error(Var). 2670mode_anchor_name(mode(Head, _), Anchor) :- 2671 !, 2672 mode_anchor_name(Head, Anchor). 2673mode_anchor_name(Head is _Det, Anchor) :- 2674 !, 2675 mode_anchor_name(Head, Anchor). 2676mode_anchor_name(Head, Anchor) :- 2677 pred_anchor_name(Head, _, Anchor).
2684pred_anchor_name(//(Head), Name/Arity, Anchor) :- 2685 !, 2686 functor(Head, Name, DCGArity), 2687 Arity is DCGArity+2, 2688 format(atom(Anchor), '~w/~d', [Name, Arity]). 2689pred_anchor_name(Head, Name/Arity, Anchor) :- 2690 functor(Head, Name, Arity), 2691 format(atom(Anchor), '~w/~d', [Name, Arity]). 2692 2693:- multifile prolog:message//1. 2694 2695prologmessage(pldoc(module_comment_outside_module(Title))) --> 2696 [ '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.