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-2017, University of Amsterdam 7 VU University Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(pldoc_html, 37 [ doc_for_file/2, % +FileSpec, +Options 38 doc_write_html/3, % +Stream, +Title, +Term 39 doc_for_wiki_file/2, % +FileSpec, +Options 40 % Support doc_index 41 doc_page_dom/3, % +Title, +Body, -DOM 42 print_html_head/1, % +Stream 43 predref//1, % +PI // 44 predref//2, % +PI, Options // 45 module_info/3, % +File, +Options0, -Options 46 doc_hide_private/3, % +Doc0, -Doc, +Options 47 edit_button//2, % +File, +Options, // 48 source_button//2, % +File, +Options, // 49 zoom_button//2, % +File, +Options, // 50 pred_edit_button//2, % +PredInd, +Options, // 51 object_edit_button//2, % +Obj, +Options, // 52 object_source_button//2, % +Obj, +Options, // 53 doc_resources//1, % +Options 54 ensure_doc_objects/1, % +File 55 % Support other backends 56 doc_file_objects/5, % +FSpec, -File, -Objs, -FileOpts, +Opts 57 existing_linked_file/2, % +FileSpec, -Path 58 unquote_filespec/2, % +FileSpec, -Unquoted 59 doc_tag_title/2, % +Tag, -Title 60 mode_anchor_name/2, % +Mode, -Anchor 61 pred_anchor_name/3, % +Head, -PI, -Anchor 62 private/2, % +Obj, +Options 63 (multifile)/2, % +Obj, +Options 64 is_pi/1, % @Term 65 is_op_type/2, % +Atom, ?Type 66 % Output routines 67 file//1, % +File, // 68 file//2, % +File, +Options, // 69 include//3, % +File, +Type, +Options // 70 tags//1, % +Tags, // 71 term//3, % +Text, +Term, +Bindings, // 72 file_header//2, % +File, +Options, // 73 objects//2, % +Objects, +Options, // 74 object_ref//2, % +Object, +Options, // 75 object_name//2, % +Object, +Object 76 object_href/2, % +Object, -URL 77 object_tree//3, % +Tree, +Current, +Options 78 object_page//2, % +Object, +Options, // 79 object_page_header//2, % +File, +Options, // 80 object_synopsis//2, % +Object, +Options, // 81 object_page_footer//2 % +Object, +Options, // 82 ]). 83:- use_module(library(lists)). 84:- use_module(library(option)). 85:- use_module(library(uri)). 86:- use_module(library(readutil)). 87:- use_module(library(http/html_write)). 88:- use_module(library(http/http_dispatch)). 89:- use_module(library(http/http_wrapper)). 90:- use_module(library(http/http_path)). 91:- use_module(library(http/html_head)). 92:- use_module(library(http/term_html)). 93:- use_module(library(http/jquery)). 94:- use_module(library(debug)). 95:- use_module(library(apply)). 96:- use_module(library(pairs)). 97:- use_module(library(filesex)). 98:- use_module(doc_process). 99:- use_module(doc_man). 100:- use_module(doc_modes). 101:- use_module(doc_wiki). 102:- use_module(doc_search). 103:- use_module(doc_index). 104:- use_module(doc_util). 105:- include(hooks).
116:- public 117 args//1, % Called from \Term output created 118 pred_dt//3, % by the wiki renderer 119 section//2, 120 tag//2. 121 122 123:- predicate_options(doc_for_wiki_file/2, 2, 124 [ edit(boolean) 125 ]). 126:- predicate_options(doc_hide_private/3, 3, 127 [module(atom), public(list), public_only(boolean)]). 128:- predicate_options(edit_button//2, 2, 129 [ edit(boolean) 130 ]). 131:- predicate_options(file//2, 2, 132 [ label(any), 133 absolute_path(atom), 134 href(atom), 135 map_extension(list), 136 files(list), 137 edit_handler(atom) 138 ]). 139:- predicate_options(file_header//2, 2, 140 [ edit(boolean), 141 files(list), 142 public_only(boolean) 143 ]). 144:- predicate_options(include//3, 3, 145 [ absolute_path(atom), 146 class(atom), 147 files(list), 148 href(atom), 149 label(any), 150 map_extension(list) 151 ]). 152:- predicate_options(object_edit_button//2, 2, 153 [ edit(boolean), 154 pass_to(pred_edit_button//2, 2) 155 ]). 156:- predicate_options(object_page//2, 2, 157 [ for(any), 158 header(boolean), 159 links(boolean), 160 no_manual(boolean), 161 try_manual(boolean), 162 search_in(oneof([all,app,man])), 163 search_match(oneof([name,summary])), 164 search_options(boolean) 165 ]). 166:- predicate_options(object_ref//2, 2, 167 [ files(list), 168 qualify(boolean), 169 style(oneof([number,title,number_title])), 170 secref_style(oneof([number,title,number_title])) 171 ]). 172:- predicate_options(object_synopsis//2, 2, 173 [ href(atom) 174 ]). 175:- predicate_options(pred_dt//3, 3, 176 [ edit(boolean) 177 ]). 178:- predicate_options(pred_edit_button//2, 2, 179 [ edit(boolean) 180 ]). 181:- predicate_options(predref//2, 2, 182 [ files(list), 183 prefer(oneof([manual,app])), 184 pass_to(object_ref/4, 2) 185 ]). 186:- predicate_options(private/2, 2, 187 [ module(atom), 188 public(list) 189 ]). 190:- predicate_options(source_button//2, 2, 191 [ files(list) 192 ]). 193 194 195 /******************************* 196 * RESOURCES * 197 *******************************/ 198 199:- html_resource(pldoc_css, 200 [ virtual(true), 201 requires([ pldoc_resource('pldoc.css') 202 ]) 203 ]). 204:- html_resource(pldoc_resource('pldoc.js'), 205 [ requires([ jquery 206 ]) 207 ]). 208:- html_resource(pldoc_js, 209 [ virtual(true), 210 requires([ pldoc_resource('pldoc.js') 211 ]) 212 ]). 213:- html_resource(pldoc, 214 [ virtual(true), 215 requires([ pldoc_css, 216 pldoc_js 217 ]) 218 ]). 219 220 221 /******************************* 222 * FILE PROCESSING * 223 *******************************/
true
(default), only emit documentation for
exported predicates.true
, provide edit buttons. Default, these buttons
are suppressed.244doc_for_file(FileSpec, Options) :- 245 doc_file_objects(FileSpec, File, Objects, FileOptions, Options), 246 doc_file_title(File, Title, FileOptions, Options), 247 doc_write_page( 248 pldoc(file(File, Title)), 249 title(Title), 250 \prolog_file(File, Objects, FileOptions, Options), 251 Options). 252 253doc_file_title(_, Title, _, Options) :- 254 option(title(Title), Options), 255 !. 256doc_file_title(File, Title, FileOptions, _) :- 257 memberchk(file(Title0, _Comment), FileOptions), 258 !, 259 file_base_name(File, Base), 260 atomic_list_concat([Base, ' -- ', Title0], Title). 261doc_file_title(File, Title, _, _) :- 262 file_base_name(File, Title). 263 264:- html_meta doc_write_page( , , , ). 265 266doc_write_page(Style, Head, Body, Options) :- 267 option(files(_), Options), 268 !, 269 phrase(page(Style, Head, Body), HTML), 270 print_html(HTML). 271doc_write_page(Style, Head, Body, _) :- 272 reply_html_page(Style, Head, Body). 273 274 275prolog_file(File, Objects, FileOptions, Options) --> 276 { b_setval(pldoc_file, File), % TBD: delete? 277 file_directory_name(File, Dir) 278 }, 279 html([ \doc_resources(Options), 280 \doc_links(Dir, FileOptions), 281 \file_header(File, FileOptions) 282 | \objects(Objects, FileOptions) 283 ]), 284 undocumented(File, Objects, FileOptions).
doc_files.pl
. A bit hacky ...291doc_resources(Options) --> 292 { option(resource_directory(ResDir), Options), 293 nb_current(pldoc_output, OutputFile), 294 !, 295 directory_file_path(ResDir, 'pldoc.css', Res), 296 relative_file_name(Res, OutputFile, Ref) 297 }, 298 html_requires(Ref). 299doc_resources(Options) --> 300 { option(html_resources(Resoures), Options, pldoc) 301 }, 302 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:
331doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 332 xref_current_source(FileSpec), 333 xref_option(FileSpec, comments(collect)), 334 !, 335 File = FileSpec, 336 findall(Object, xref_doc_object(File, Object), Objects0), 337 reply_file_objects(File, Objects0, Objects, FileOptions, Options). 338doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 339 absolute_file_name(FileSpec, File, 340 [ file_type(prolog), 341 access(read) 342 ]), 343 source_file(File), 344 !, 345 ensure_doc_objects(File), 346 Pos = File:Line, 347 findall(Line-doc(Obj,Pos,Comment), 348 doc_comment(Obj, Pos, _, Comment), Pairs), 349 sort(Pairs, Pairs1), % remove duplicates 350 keysort(Pairs1, ByLine), 351 pairs_values(ByLine, Objs0), 352 reply_file_objects(File, Objs0, Objects, FileOptions, Options). 353doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 354 absolute_file_name(FileSpec, File, 355 [ file_type(prolog), 356 access(read) 357 ]), 358 xref_source(File, [silent(true)]), 359 findall(Object, xref_doc_object(File, Object), Objects0), 360 reply_file_objects(File, Objects0, Objects, FileOptions, Options). 361 362 363reply_file_objects(File, Objs0, Objects, FileOptions, Options) :- 364 module_info(File, ModuleOptions, Options), 365 file_info(Objs0, Objs1, FileOptions, ModuleOptions), 366 doc_hide_private(Objs1, ObjectsSelf, ModuleOptions), 367 include_reexported(ObjectsSelf, Objects, File, FileOptions). 368 369include_reexported(SelfObjects, Objects, File, Options) :- 370 option(include_reexported(true), Options), 371 option(module(Module), Options), 372 option(public(Exports), Options), 373 select_undocumented(Exports, Module, SelfObjects, Undoc), 374 re_exported_doc(Undoc, File, Module, REObjs, _), 375 REObjs \== [], 376 !, 377 append(SelfObjects, REObjs, Objects). 378include_reexported(Objects, Objects, _, _).
383xref_doc_object(File, doc(M:module(Title),File:0,Comment)) :- 384 xref_comment(File, Title, Comment), 385 xref_module(File, M). 386xref_doc_object(File, doc(M:Name/Arity,File:0,Comment)) :- 387 xref_comment(File, Head, _Summary, Comment), 388 xref_module(File, Module), 389 strip_module(Module:Head, M, Plain), 390 functor(Plain, Name, Arity).
401:- dynamic 402 no_comments/2. 403 404ensure_doc_objects(File) :- 405 source_file(File), 406 !, 407 ( doc_file_has_comments(File) 408 -> true 409 ; no_comments(File, TimeChecked), 410 time_file(File, TimeChecked) 411 -> true 412 ; xref_source(File, [silent(true), comments(store)]), 413 retractall(no_comments(File, _)), 414 ( doc_file_has_comments(File) 415 -> true 416 ; time_file(File, TimeChecked), 417 assertz(no_comments(File, TimeChecked)) 418 ) 419 ). 420ensure_doc_objects(File) :- 421 xref_source(File, [silent(true)]).
module(Name)
, public(Exports)
to OtherOptions if
File is a module file.428module_info(File, [module(Module), public(Exports)|Options], Options) :- 429 module_property(Module, file(File)), 430 !, 431 module_property(Module, exports(Exports)). 432module_info(File, [module(Module), public(Exports)|Options], Options) :- 433 xref_module(File, Module), 434 !, 435 findall(PI, xref_exported_pi(File, PI), Exports). 436module_info(_, Options, Options). 437 438xref_exported_pi(Src, Name/Arity) :- 439 xref_exported(Src, Head), 440 functor(Head, Name, Arity).
446doc_hide_private(Objs, Objs, Options) :- 447 option(public_only(false), Options, true), 448 !. 449doc_hide_private(Objs0, Objs, Options) :- 450 hide_private(Objs0, Objs, Options). 451 452hide_private([], [], _). 453hide_private([H|T0], T, Options) :- 454 obj(H, Obj), 455 private(Obj, Options), 456 !, 457 hide_private(T0, T, Options). 458hide_private([H|T0], [H|T], Options) :- 459 hide_private(T0, T, Options).
467obj(doc(Obj0, _Pos, _Summary), Obj) :- 468 !, 469 ( Obj0 = [Obj|_] 470 -> true 471 ; Obj = Obj0 472 ). 473obj(Obj0, Obj) :- 474 ( Obj0 = [Obj|_] 475 -> true 476 ; Obj = Obj0 477 ).
486:- multifile 487 prolog:doc_is_public_object/1. 488 489private(Object, _Options):- 490 prolog:doc_is_public_object(Object), !, fail. 491private(Module:PI, Options) :- 492 multifile(Module:PI, Options), !, fail. 493private(Module:PI, Options) :- 494 option(module(Module), Options), 495 option(public(Public), Options), 496 !, 497 \+ ( member(PI2, Public), 498 eq_pi(PI, PI2) 499 ). 500private(Module:PI, _Options) :- 501 module_property(Module, file(_)), % A loaded module 502 !, 503 export_list(Module, Exports), 504 \+ ( member(PI2, Exports), 505 eq_pi(PI, PI2) 506 ). 507private(Module:PI, _Options) :- 508 \+ (pi_to_head(PI, Head), 509 xref_exported(Source, Head), 510 xref_module(Source, Module)).
521multifile(Obj, _Options) :- 522 strip_module(user:Obj, Module, PI), 523 pi_to_head(PI, Head), 524 ( predicate_property(Module:Head, multifile) 525 ; xref_module(Source, Module), 526 xref_defined(Source, Head, multifile(_)) 527 ), 528 !. 529 530pi_to_head(Var, _) :- 531 var(Var), !, fail. 532pi_to_head(Name/Arity, Term) :- 533 functor(Term, Name, Arity). 534pi_to_head(Name//DCGArity, Term) :- 535 Arity is DCGArity+2, 536 functor(Term, Name, Arity).
file(Title, Comment)
to OtherOptions if available.542file_info(Comments, RestComments, [file(Title, Comment)|Opts], Opts) :- 543 select(doc(_:module(Title),_,Comment), Comments, RestComments), 544 !. 545file_info(Comments, Comments, Opts, Opts).
552file_header(File, Options) --> 553 { memberchk(file(Title, Comment), Options), 554 !, 555 file_base_name(File, Base) 556 }, 557 file_title([Base, ' -- ', Title], File, Options), 558 { is_structured_comment(Comment, Prefixes), 559 string_codes(Comment, Codes), 560 indented_lines(Codes, Prefixes, Lines), 561 section_comment_header(Lines, _Header, Lines1), 562 wiki_lines_to_dom(Lines1, [], DOM) 563 }, 564 html(DOM). 565file_header(File, Options) --> 566 { file_base_name(File, Base) 567 }, 568 file_title([Base], File, Options).
575file_title(Title, File, Options) --> 576 prolog:doc_file_title(Title, File, Options), 577 !. 578file_title(Title, File, Options) --> 579 { file_base_name(File, Base) 580 }, 581 html(h1(class(file), 582 [ span(style('float:right'), 583 [ \reload_button(File, Base, Options), 584 \zoom_button(Base, Options), 585 \source_button(Base, Options), 586 \edit_button(File, Options) 587 ]) 588 | Title 589 ])).
599reload_button(File, _Base, Options) --> 600 { \+ source_file(File), 601 \+ option(files(_), Options) 602 }, 603 !, 604 html(span(class(file_anot), '[not loaded]')). 605reload_button(_File, Base, Options) --> 606 { option(edit(true), Options), 607 !, 608 option(public_only(Public), Options, true) 609 }, 610 html(a(href(Base+[reload(true), public_only(Public)]), 611 img([ class(action), 612 alt('Reload'), 613 title('Make & Reload'), 614 src(location_by_id(pldoc_resource)+'reload.png') 615 ]))). 616reload_button(_, _, _) --> [].
624edit_button(File, Options) --> 625 { option(edit(true), Options) 626 }, 627 !, 628 html(a([ onClick('HTTPrequest(\'' + 629 location_by_id(pldoc_edit) + [file(File)] + 630 '\')') 631 ], 632 img([ class(action), 633 alt(edit), 634 title('Edit file'), 635 src(location_by_id(pldoc_resource)+'edit.png') 636 ]))). 637edit_button(_, _) --> 638 [].
645zoom_button(_, Options) --> 646 { option(files(_Map), Options) }, 647 !. % generating files 648zoom_button(Base, Options) --> 649 { ( option(public_only(true), Options, true) 650 -> Zoom = 'public.png', 651 Alt = 'Public', 652 Title = 'Click to include private', 653 PublicOnly = false 654 ; Zoom = 'private.png', 655 Alt = 'All predicates', 656 Title = 'Click to show exports only', 657 PublicOnly = true 658 ) 659 }, 660 html(a(href(Base+[public_only(PublicOnly)]), 661 img([ class(action), 662 alt(Alt), 663 title(Title), 664 src(location_by_id(pldoc_resource)+Zoom) 665 ]))).
672source_button(_File, Options) --> 673 { option(files(_Map), Options) }, 674 !. % generating files 675source_button(File, _Options) --> 676 { ( is_absolute_file_name(File) 677 -> doc_file_href(File, HREF0) 678 ; HREF0 = File 679 ) 680 }, 681 html(a(href(HREF0+[show(src)]), 682 img([ class(action), 683 alt('Show source'), 684 title('Show source'), 685 src(location_by_id(pldoc_resource)+'source.png') 686 ]))).
true
, provide a navitation tree.696objects(Objects, Options) --> 697 { option(navtree(true), Options), 698 !, 699 objects_nav_tree(Objects, Tree) 700 }, 701 html([ div(class(navtree), 702 div(class(navwindow), 703 \nav_tree(Tree, Objects, Options))), 704 div(class(navcontent), 705 \objects_nt(Objects, Options)) 706 ]). 707objects(Objects, Options) --> 708 objects_nt(Objects, Options). 709 710objects_nt(Objects, Options) --> 711 objects(Objects, [body], Options). 712 713objects([], Mode, _) --> 714 pop_mode(body, Mode, _). 715objects([Obj|T], Mode, Options) --> 716 object(Obj, Mode, Mode1, Options), 717 objects(T, Mode1, Options).
728object(doc(Obj,Pos,Comment), Mode0, Mode, Options) --> 729 !, 730 object(Obj, [Pos-Comment], Mode0, Mode, [scope(file)|Options]). 731object(Obj, Mode0, Mode, Options) --> 732 { findall(Pos-Comment, 733 doc_comment(Obj, Pos, _Summary, Comment), 734 Pairs) 735 }, 736 !, 737 { b_setval(pldoc_object, Obj) }, 738 object(Obj, Pairs, Mode0, Mode, Options). 739 740object(Obj, Pairs, Mode0, Mode, Options) --> 741 { is_pi(Obj), 742 !, 743 maplist(pred_dom(Obj, Options), Pairs, DOMS), 744 append(DOMS, DOM) 745 }, 746 need_mode(dl, Mode0, Mode), 747 html(DOM). 748object([Obj|_Same], Pairs, Mode0, Mode, Options) --> 749 !, 750 object(Obj, Pairs, Mode0, Mode, Options). 751object(Obj, _Pairs, Mode, Mode, _Options) --> 752 { debug(pldoc, 'Skipped ~p', [Obj]) }, 753 []. 754 755pred_dom(Obj, Options, Pos-Comment, DOM) :- 756 is_structured_comment(Comment, Prefixes), 757 string_codes(Comment, Codes), 758 indented_lines(Codes, Prefixes, Lines), 759 strip_module(user:Obj, Module, _), 760 process_modes(Lines, Module, Pos, Modes, Args, Lines1), 761 ( private(Obj, Options) 762 -> Class = privdef % private definition 763 ; multifile(Obj, Options) 764 -> ( option(scope(file), Options) 765 -> ( more_doc(Obj, Pos) 766 -> Class = multidef(object(Obj)) 767 ; Class = multidef 768 ) 769 ; Class = multidef(file((Pos))) 770 ) 771 ; Class = pubdef % public definition 772 ), 773 ( Obj = Module:_ 774 -> POptions = [module(Module)|Options] 775 ; POptions = Options 776 ), 777 Pos = File:Line, 778 DTOptions = [file(File),line(Line)|POptions], 779 DOM = [\pred_dt(Modes, Class, DTOptions), dd(class=defbody, DOM1)], 780 wiki_lines_to_dom(Lines1, Args, DOM0), 781 strip_leading_par(DOM0, DOM1). 782 783more_doc(Obj, File:_) :- 784 doc_comment(Obj, File2:_, _, _), 785 File2 \== File, 786 !.
795need_mode(Mode, Stack, Stack) --> 796 { Stack = [Mode|_] }, 797 !, 798 []. 799need_mode(Mode, Stack, Rest) --> 800 { memberchk(Mode, Stack) 801 }, 802 !, 803 pop_mode(Mode, Stack, Rest). 804need_mode(Mode, Stack, [Mode|Stack]) --> 805 !, 806 html_begin(Mode). 807 808pop_mode(Mode, Stack, Stack) --> 809 { Stack = [Mode|_] }, 810 !, 811 []. 812pop_mode(Mode, [H|Rest0], Rest) --> 813 html_end(H), 814 pop_mode(Mode, Rest0, Rest).
820undocumented(File, Objs, Options) --> 821 { memberchk(module(Module), Options), 822 memberchk(public(Exports), Options), 823 select_undocumented(Exports, Module, Objs, Undoc), 824 re_exported_doc(Undoc, File, Module, REObjs, ReallyUnDoc) 825 }, 826 !, 827 re_exported_doc(REObjs, Options), 828 undocumented(ReallyUnDoc, Options). 829undocumented(_, _, _) --> 830 []. 831 832re_exported_doc([], _) --> !. 833re_exported_doc(Objs, Options) --> 834 reexport_header(Objs, Options), 835 objects(Objs, Options). 836 837reexport_header(_, Options) --> 838 { option(reexport_header(true), Options, true) 839 }, 840 !, 841 html([ h2(class(wiki), 'Re-exported predicates'), 842 p([ 'The following predicates are re-exported from other ', 843 'modules' 844 ]) 845 ]). 846reexport_header(_, _) --> 847 []. 848 849undocumented([], _) --> !. 850undocumented(UnDoc, Options) --> 851 html([ h2(class(undoc), 'Undocumented predicates'), 852 p(['The following predicates are exported, but not ', 853 'or incorrectly documented.' 854 ]), 855 dl(class(undoc), 856 \undocumented_predicates(UnDoc, Options)) 857 ]). 858 859 860undocumented_predicates([], _) --> 861 []. 862undocumented_predicates([H|T], Options) --> 863 undocumented_pred(H, Options), 864 undocumented_predicates(T, Options). 865 866undocumented_pred(Name/Arity, Options) --> 867 { functor(Head, Name, Arity) }, 868 html(dt(class=undoc, \pred_mode(Head, [], _, Options))). 869 870select_undocumented([], _, _, []). 871select_undocumented([PI|T0], M, Objs, [PI|T]) :- 872 is_pi(PI), 873 \+ in_doc(M:PI, Objs), 874 !, 875 select_undocumented(T0, M, Objs, T). 876select_undocumented([_|T0], M, Objs, T) :- 877 select_undocumented(T0, M, Objs, T). 878 879in_doc(PI, Objs) :- 880 member(doc(O,_,_), Objs), 881 ( is_list(O) 882 -> member(O2, O), 883 eq_pi(PI, O2) 884 ; eq_pi(PI, O) 885 ).
892eq_pi(PI, PI) :- !. 893eq_pi(M:PI1, M:PI2) :- 894 atom(M), 895 !, 896 eq_pi(PI1, PI2). 897eq_pi(Name/A, Name//DCGA) :- 898 A =:= DCGA+2, 899 !. 900eq_pi(Name//DCGA, Name/A) :- 901 A =:= DCGA+2.
907is_pi(Var) :- 908 var(Var), 909 !, 910 fail. 911is_pi(_:PI) :- 912 !, 913 is_pi(PI). 914is_pi(_/_). 915is_pi(_//_).
921re_exported_doc([], _, _, [], []). 922re_exported_doc([PI|T0], File, Module, [doc(Orig:PI,Pos,Comment)|ObjT], UnDoc) :- 923 pi_to_head(PI, Head), 924 ( predicate_property(Module:Head, imported_from(Orig)) 925 -> true 926 ; xref_defined(File, Head, imported(File2)), 927 ensure_doc_objects(File2), 928 xref_module(File2, Orig) 929 ), 930 doc_comment(Orig:PI, Pos, _, Comment), 931 !, 932 re_exported_doc(T0, File, Module, ObjT, UnDoc). 933re_exported_doc([PI|T0], File, Module, REObj, [PI|UnDoc]) :- 934 re_exported_doc(T0, File, Module, REObj, UnDoc). 935 936 937 /******************************* 938 * SINGLE OBJECT PAGE * 939 *******************************/
949object_page(Obj, Options) --> 950 prolog:doc_object_page(Obj, Options), 951 !, 952 object_page_footer(Obj, Options). 953object_page(Obj, Options) --> 954 { doc_comment(Obj, File:_Line, _Summary, _Comment) 955 }, 956 !, 957 ( { \+ ( doc_comment(Obj, File2:_, _, _), 958 File2 \== File ) 959 } 960 -> html([ \html_requires(pldoc), 961 \object_page_header(File, Options), 962 \object_synopsis(Obj, []), 963 \objects([Obj], Options) 964 ]) 965 ; html([ \html_requires(pldoc), 966 \object_page_header(-, Options), 967 \objects([Obj], [synopsis(true)|Options]) 968 ]) 969 ), 970 object_page_footer(Obj, Options). 971object_page(M:Name/Arity, Options) --> % specified module, but public 972 { functor(Head, Name, Arity), 973 ( predicate_property(M:Head, exported) 974 -> module_property(M, class(library)) 975 ; \+ predicate_property(M:Head, defined) 976 ) 977 }, 978 prolog:doc_object_page(Name/Arity, Options), 979 !, 980 object_page_footer(Name/Arity, Options). 981 982object_page_header(File, Options) --> 983 prolog:doc_page_header(file(File), Options), 984 !. 985object_page_header(File, Options) --> 986 { option(header(true), Options, true) }, 987 !, 988 html(div(class(navhdr), 989 [ div(class(jump), \file_link(File)), 990 div(class(search), \search_form(Options)), 991 br(clear(right)) 992 ])). 993object_page_header(_, _) --> []. 994 995file_link(-) --> 996 !, 997 places_menu(-). 998file_link(File) --> 999 { file_directory_name(File, Dir) 1000 }, 1001 places_menu(Dir), 1002 html([ div(a(href(location_by_id(pldoc_doc)+File), File)) 1003 ]).
1010object_page_footer(Obj, Options) --> 1011 prolog:doc_object_page_footer(Obj, Options). 1012object_page_footer(_, _) --> [].
1026object_synopsis(Name/Arity, _) --> 1027 { functor(Head, Name, Arity), 1028 predicate_property(system:Head, built_in) 1029 }, 1030 synopsis([span(class(builtin), 'built-in')]). 1031object_synopsis(Name/Arity, Options) --> 1032 !, 1033 object_synopsis(_:Name/Arity, Options). 1034object_synopsis(M:Name/Arity, Options) --> 1035 { functor(Head, Name, Arity), 1036 predicate_property(M:Head, exported), 1037 \+ predicate_property(M:Head, imported_from(_)), 1038 module_property(M, file(File)), 1039 file_name_on_path(File, Spec), 1040 !, 1041 unquote_filespec(Spec, Unquoted), 1042 ( predicate_property(Head, autoload(FileBase)), 1043 file_name_extension(FileBase, _Ext, File) 1044 -> Extra = [span(class(autoload), '(can be autoloaded)')] 1045 ; Extra = [] 1046 ) 1047 }, 1048 ( { option(href(HREF), Options) } 1049 -> synopsis([code([':- use_module(',a(href(HREF), '~q'-[Unquoted]),').'])|Extra]) 1050 ; synopsis([code(':- use_module(~q).'-[Unquoted])|Extra]) 1051 ). 1052object_synopsis(f(_/_), _) --> 1053 synopsis(span(class(function), 1054 [ 'Arithmetic function (see ', 1055 \object_ref(is/2, []), 1056 ')' 1057 ])). 1058object_synopsis(c(Func), _) --> 1059 { sub_atom(Func, 0, _, _, 'PL_') 1060 }, 1061 !, 1062 synopsis([span(class(cfunc), 'C-language interface function')]). 1063object_synopsis(_, _) --> []. 1064 1065synopsis(Text) --> 1066 html(div(class(synopsis), 1067 [ span(class('synopsis-hdr'), 'Availability:') 1068 | Text 1069 ])).
library('semweb/rdf_db')
into
library(semweb/rdf_db)
.1076unquote_filespec(Spec, Unquoted) :- 1077 compound(Spec), 1078 Spec =.. [Alias,Path], 1079 atomic_list_concat(Parts, /, Path), 1080 maplist(need_no_quotes, Parts), 1081 !, 1082 parts_to_path(Parts, UnquotedPath), 1083 Unquoted =.. [Alias, UnquotedPath]. 1084unquote_filespec(Spec, Spec). 1085 1086need_no_quotes(Atom) :- 1087 format(atom(A), '~q', [Atom]), 1088 \+ sub_atom(A, 0, _, _, '\''). 1089 1090parts_to_path([One], One) :- !. 1091parts_to_path(List, More/T) :- 1092 ( append(H, [T], List) 1093 -> parts_to_path(H, More) 1094 ). 1095 1096 1097 /******************************* 1098 * PRINT * 1099 *******************************/
1105doc_write_html(Out, Title, Doc) :-
1106 doc_page_dom(Title, Doc, DOM),
1107 phrase(html(DOM), Tokens),
1108 print_html_head(Out),
1109 print_html(Out, Tokens).
1116doc_page_dom(Title, Body, DOM) :-
1117 DOM = html([ head([ title(Title),
1118 link([ rel(stylesheet),
1119 type('text/css'),
1120 href(location_by_id(pldoc_resource)+'pldoc.css')
1121 ]),
1122 script([ src(location_by_id(pldoc_resource)+'pldoc.js'),
1123 type('text/javascript')
1124 ], [])
1125 ]),
1126 body(Body)
1127 ]).
DOCTYPE
line.1133print_html_head(Out) :- 1134 format(Out, 1135 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" \c 1136 "http://www.w3.org/TR/html4/strict.dtd">~n', []). 1137 1138% Rendering rules 1139% 1140% These rules translate \-terms produced by wiki.pl
1148tags(Tags) -->
1149 html(dl(class=tags, Tags)).
tag(Name, Values)
terms produced by doc_wiki.pl
.1155tag(Tag, Values) --> 1156 { doc_tag_title(Tag, Title), 1157 atom_concat('keyword-', Tag, Class) 1158 }, 1159 html([ dt(class=Class, Title), 1160 \tag_values(Values, Class) 1161 ]). 1162 1163tag_values([], _) --> 1164 []. 1165tag_values([H|T], Class) --> 1166 html(dd(class=Class, ['- '|H])), 1167 tag_values(T, Class).
1174doc_tag_title(Tag, Title) :- 1175 tag_title(Tag, Title), 1176 !. 1177doc_tag_title(Tag, Tag). 1178 1179tag_title(compat, 'Compatibility'). 1180tag_title(tbd, 'To be done'). 1181tag_title(see, 'See also'). 1182tag_title(error, 'Errors').
args(List)
created by doc_wiki.pl
. Params is a
list of arg(Name, Descr)
.1189args(Params) --> 1190 html([ dt(class=tag, 'Arguments:'), 1191 dd(table(class=arglist, 1192 \arg_list(Params))) 1193 ]). 1194 1195arg_list([]) --> 1196 []. 1197arg_list([H|T]) --> 1198 argument(H), 1199 arg_list(T). 1200 1201argument(arg(Name,Descr)) --> 1202 html(tr([td(var(Name)), td(class=argdescr, ['- '|Descr])])). 1203 1204 1205 /******************************* 1206 * NAVIGATION TREE * 1207 *******************************/
node(Object, Children)
.1214objects_nav_tree(Objects, Tree) :- 1215 maplist(object_nav_tree, Objects, Trees), 1216 union_trees(Trees, Tree0), 1217 remove_unique_root(Tree0, Tree). 1218 Obj, Tree) (:- 1220 Node = node(directory(Dir), FileNodes), 1221 FileNode = node(file(File), Siblings), 1222 doc_comment(Obj, File:_Line, _Summary, _Comment), 1223 !, 1224 file_directory_name(File, Dir), 1225 sibling_file_nodes(Dir, FileNodes0), 1226 selectchk(node(file(File),[]), FileNodes0, FileNode, FileNodes), 1227 findall(Sibling, doc_comment(Sibling, File:_, _, _), Siblings0), 1228 delete(Siblings0, _:module(_), Siblings1), 1229 doc_hide_private(Siblings1, Siblings2, []), 1230 flatten(Siblings2, Siblings), % a comment may describe objects 1231 embed_directories(Node, Tree). 1232 1233sibling_file_nodes(Dir, Nodes) :- 1234 findall(node(file(File), []), 1235 ( source_file(File), 1236 file_directory_name(File, Dir) 1237 ), 1238 Nodes). 1239 1240embed_directories(Node, Tree) :- 1241 Node = node(file(File), _), 1242 !, 1243 file_directory_name(File, Dir), 1244 Super = node(directory(Dir), [Node]), 1245 embed_directories(Super, Tree). 1246embed_directories(Node, Tree) :- 1247 Node = node(directory(Dir), _), 1248 file_directory_name(Dir, SuperDir), 1249 SuperDir \== Dir, 1250 !, 1251 Super = node(directory(SuperDir), [Node]), 1252 embed_directories(Super, Tree). 1253embed_directories(Tree, Tree). 1254 1255 1256union_trees([Tree], Tree) :- !. 1257union_trees([T1,T2|Trees], Tree) :- 1258 merge_trees(T1, T2, M1), 1259 union_trees([M1|Trees], Tree). 1260 1261merge_trees(node(R, Ch1), node(R, Ch2), node(R, Ch)) :- 1262 merge_nodes(Ch1, Ch2, Ch). 1263 1264merge_nodes([], Ch, Ch) :- !. 1265merge_nodes(Ch, [], Ch) :- !. 1266merge_nodes([node(Root, Ch1)|T1], N1, [T1|Nodes]) :- 1267 selectchk(node(Root, Ch2), N1, N2), 1268 !, 1269 merge_trees(node(Root, Ch1), node(Root, Ch2), T1), 1270 merge_nodes(T1, N2, Nodes). 1271merge_nodes([Node|T1], N1, [Node|Nodes]) :- 1272 merge_nodes(T1, N1, Nodes).
1278remove_unique_root(node(_, [node(R1, [R2])]), Tree) :- 1279 !, 1280 remove_unique_root(node(R1, [R2]), Tree). 1281remove_unique_root(Tree, Tree).
1287nav_tree(Tree, Current, Options) -->
1288 html(ul(class(nav),
1289 \object_tree(Tree, Current, Options))).
1295object_tree(node(Id, []), Target, Options) --> 1296 !, 1297 { node_class(Id, Target, Class) }, 1298 html(li(class(Class), 1299 \node(Id, Options))). 1300object_tree(node(Id, Children), Target, Options) --> 1301 !, 1302 { node_class(Id, Target, Class) }, 1303 html(li(class(Class), 1304 [ \node(Id, Options), 1305 ul(class(nav), 1306 \object_trees(Children, Target, Options)) 1307 ])). 1308object_tree(Id, Target, Options) --> 1309 !, 1310 { node_class(Id, Target, Class) }, 1311 html(li(class([obj|Class]), \node(Id, Options))). 1312 1313object_trees([], _, _) --> []. 1314object_trees([H|T], Target, Options) --> 1315 object_tree(H, Target, Options), 1316 object_trees(T, Target, Options). 1317 1318node_class(Ids, Current, Class) :- 1319 is_list(Ids), 1320 !, 1321 ( member(Id, Ids), memberchk(Id, Current) 1322 -> Class = [nav,current] 1323 ; Class = [nav] 1324 ). 1325node_class(Id, Current, Class) :- 1326 ( memberchk(Id, Current) 1327 -> Class = [nav,current] 1328 ; Class = [nav] 1329 ). 1330 1331node(file(File), Options) --> 1332 !, 1333 object_ref(file(File), [style(title)|Options]). 1334node(Id, Options) --> 1335 object_ref(Id, Options). 1336 1337 1338 /******************************* 1339 * SECTIONS * 1340 *******************************/ 1341 1342section(Type, Title) --> 1343 { string_codes(Title, Codes), 1344 wiki_codes_to_dom(Codes, [], Content0), 1345 strip_leading_par(Content0, Content), 1346 make_section(Type, Content, HTML) 1347 }, 1348 html(HTML). 1349 1350make_section(module, Title, h1(class=module, Title)). 1351make_section(section, Title, h1(class=section, Title)). 1352 1353 1354 /******************************* 1355 * PRED MODE HEADER * 1356 *******************************/
1364pred_dt(Modes, Class, Options) --> 1365 pred_dt(Modes, Class, [], _Done, Options). 1366 1367pred_dt([], _, Done, Done, _) --> 1368 []. 1369pred_dt([H|T], Class, Done0, Done, Options) --> 1370 { functor(Class, CSSClass, _) }, 1371 html(dt(class=CSSClass, 1372 [ \pred_mode(H, Done0, Done1, Options), 1373 \mode_anot(Class) 1374 ])), 1375 pred_dt(T, Class, Done1, Done, Options). 1376 1377mode_anot(privdef) --> 1378 !, 1379 html(span([class(anot), style('float:right')], 1380 '[private]')). 1381mode_anot(multidef(object(Obj))) --> 1382 !, 1383 { object_href(Obj, HREF) }, 1384 html(span([class(anot), style('float:right')], 1385 ['[', a(href(HREF), multifile), ']' 1386 ])). 1387mode_anot(multidef(file(File:_))) --> 1388 !, 1389 { file_name_on_path(File, Spec), 1390 unquote_filespec(Spec, Unquoted), 1391 doc_file_href(File, HREF) 1392 }, 1393 html(span([class(anot), style('float:right')], 1394 ['[multifile, ', a(href(HREF), '~q'-[Unquoted]), ']' 1395 ])). 1396mode_anot(multidef) --> 1397 !, 1398 html(span([class(anot), style('float:right')], 1399 '[multifile]')). 1400mode_anot(_) --> 1401 []. 1402 1403pred_mode(mode(Head,Vars), Done0, Done, Options) --> 1404 !, 1405 { bind_vars(Head, Vars) }, 1406 pred_mode(Head, Done0, Done, Options). 1407pred_mode(Head is Det, Done0, Done, Options) --> 1408 !, 1409 anchored_pred_head(Head, Done0, Done, Options), 1410 pred_det(Det). 1411pred_mode(Head, Done0, Done, Options) --> 1412 anchored_pred_head(Head, Done0, Done, Options). 1413 1414bind_vars(Term, Bindings) :- 1415 bind_vars(Bindings), 1416 anon_vars(Term). 1417 1418bind_vars([]). 1419bind_vars([Name=Var|T]) :- 1420 Var = '$VAR'(Name), 1421 bind_vars(T).
1428anon_vars(Var) :- 1429 var(Var), 1430 !, 1431 Var = '$VAR'('_'). 1432anon_vars(Term) :- 1433 compound(Term), 1434 !, 1435 Term =.. [_|Args], 1436 maplist(anon_vars, Args). 1437anon_vars(_). 1438 1439 1440anchored_pred_head(Head, Done0, Done, Options) --> 1441 { pred_anchor_name(Head, PI, Name) }, 1442 ( { memberchk(PI, Done0) } 1443 -> { Done = Done0 }, 1444 pred_head(Head) 1445 ; html([ span(style('float:right'), 1446 [ \pred_edit_or_source_button(Head, Options), 1447 &(nbsp) 1448 ]), 1449 a(name=Name, \pred_head(Head)) 1450 ]), 1451 { Done = [PI|Done0] } 1452 ). 1453 1454 Head, Options) (--> 1456 { option(edit(true), Options) }, 1457 !, 1458 pred_edit_button(Head, Options). 1459pred_edit_or_source_button(Head, Options) --> 1460 { option(source_link(true), Options) }, 1461 !, 1462 pred_source_button(Head, Options). 1463pred_edit_or_source_button(_, _) --> [].
1477pred_edit_button(_, Options) --> 1478 { \+ option(edit(true), Options) }, 1479 !. 1480pred_edit_button(PI0, Options0) --> 1481 { canonicalise_predref(PI0, PI, Options0, Options) }, 1482 pred_edit_button2(PI, Options). 1483 Name/Arity, Options) (--> 1485 { \+ ( memberchk(file(_), Options), % always edit if file and line 1486 memberchk(line(_), Options) % are given. 1487 ), 1488 functor(Head, Name, Arity), 1489 option(module(M), Options, _), 1490 \+ ( current_module(M), 1491 source_file(M:Head, _File) 1492 ) 1493 }, 1494 !. 1495pred_edit_button2(Name/Arity, Options) --> 1496 { include(edit_param, Options, Extra), 1497 http_link_to_id(pldoc_edit, 1498 [name(Name),arity(Arity)|Extra], 1499 EditHREF) 1500 }, 1501 html(a(onClick('HTTPrequest(\'' + EditHREF + '\')'), 1502 img([ class(action), 1503 alt('Edit predicate'), 1504 title('Edit predicate'), 1505 src(location_by_id(pldoc_resource)+'editpred.png') 1506 ]))). 1507pred_edit_button2(_, _) --> 1508 !, 1509 []. 1510 1511edit_param(module(_)). 1512edit_param(file(_)). 1513edit_param(line(_)).
1520object_edit_button(_, Options) --> 1521 { \+ option(edit(true), Options) }, 1522 !. 1523object_edit_button(PI, Options) --> 1524 { is_pi(PI) }, 1525 !, 1526 pred_edit_button(PI, Options). 1527object_edit_button(_, _) --> 1528 [].
1535pred_source_button(PI0, Options0) --> 1536 { canonicalise_predref(PI0, PI, Options0, Options), 1537 option(module(M), Options, _), 1538 pred_source_href(PI, M, HREF), ! 1539 }, 1540 html(a([ href(HREF) 1541 ], 1542 img([ class(action), 1543 alt('Source'), 1544 title('Show source'), 1545 src(location_by_id(pldoc_resource)+'source.png') 1546 ]))). 1547pred_source_button(_, _) --> 1548 [].
1555object_source_button(PI, Options) --> 1556 { is_pi(PI), 1557 option(source_link(true), Options, true) 1558 }, 1559 !, 1560 pred_source_button(PI, Options). 1561object_source_button(_, _) --> 1562 [].
module(M)
to Options.1570canonicalise_predref(M:PI0, PI, Options0, [module(M)|Options]) :- 1571 !, 1572 canonicalise_predref(PI0, PI, Options0, Options). 1573canonicalise_predref(//(Head), PI, Options0, Options) :- 1574 !, 1575 functor(Head, Name, Arity), 1576 PredArity is Arity + 2, 1577 canonicalise_predref(Name/PredArity, PI, Options0, Options). 1578canonicalise_predref(Name//Arity, PI, Options0, Options) :- 1579 integer(Arity), Arity >= 0, 1580 !, 1581 PredArity is Arity + 2, 1582 canonicalise_predref(Name/PredArity, PI, Options0, Options). 1583canonicalise_predref(PI, PI, Options, Options) :- 1584 PI = Name/Arity, 1585 atom(Name), integer(Arity), Arity >= 0, 1586 !. 1587canonicalise_predref(Head, PI, Options0, Options) :- 1588 functor(Head, Name, Arity), 1589 canonicalise_predref(Name/Arity, PI, Options0, Options).
span
using
class pred
and the arguments and var
using class arglist
.1597pred_head(Var) --> 1598 { var(Var), 1599 !, 1600 instantiation_error(Var) 1601 }. 1602pred_head(//(Head)) --> 1603 !, 1604 pred_head(Head), 1605 html(//). 1606pred_head(M:Head) --> 1607 html([span(class=module, M), :]), 1608 pred_head(Head). 1609pred_head(Head) --> 1610 { atom(Head) }, 1611 !, 1612 html(b(class=pred, Head)). 1613pred_head(Head) --> % Infix operators 1614 { Head =.. [Functor,Left,Right], 1615 is_op_type(Functor, infix) 1616 }, 1617 !, 1618 html([ var(class=arglist, \pred_arg(Left, 1)), 1619 ' ', b(class=pred, Functor), ' ', 1620 var(class=arglist, \pred_arg(Right, 2)) 1621 ]). 1622pred_head(Head) --> % Prefix operators 1623 { Head =.. [Functor,Arg], 1624 is_op_type(Functor, prefix) 1625 }, 1626 !, 1627 html([ b(class=pred, Functor), ' ', 1628 var(class=arglist, \pred_arg(Arg, 1)) 1629 ]). 1630pred_head(Head) --> % Postfix operators 1631 { Head =.. [Functor,Arg], 1632 is_op_type(Functor, postfix) 1633 }, 1634 !, 1635 html([ var(class=arglist, \pred_arg(Arg, 1)), 1636 ' ', b(class=pred, Functor) 1637 ]). 1638pred_head(Head) --> % Plain terms 1639 { Head =.. [Functor|Args] }, 1640 html([ b(class=pred, Functor), 1641 var(class=arglist, 1642 [ '(', \pred_args(Args, 1), ')' ]) 1643 ]).
prefix
,
infix
or postfix
.1650is_op_type(Functor, Type) :- 1651 current_op(_Pri, F, Functor), 1652 op_type(F, Type). 1653 1654op_type(fx, prefix). 1655op_type(fy, prefix). 1656op_type(xf, postfix). 1657op_type(yf, postfix). 1658op_type(xfx, infix). 1659op_type(xfy, infix). 1660op_type(yfx, infix). 1661op_type(yfy, infix). 1662 1663 1664pred_args([], _) --> 1665 []. 1666pred_args([H|T], I) --> 1667 pred_arg(H, I), 1668 ( {T==[]} 1669 -> [] 1670 ; html(', '), 1671 { I2 is I + 1 }, 1672 pred_args(T, I2) 1673 ). 1674 1675pred_arg(Var, I) --> 1676 { var(Var) }, 1677 !, 1678 html(['Arg', I]). 1679pred_arg(...(Term), I) --> 1680 !, 1681 pred_arg(Term, I), 1682 html('...'). 1683pred_arg(Term, I) --> 1684 { Term =.. [Ind,Arg], 1685 mode_indicator(Ind) 1686 }, 1687 !, 1688 html([Ind, \pred_arg(Arg, I)]). 1689pred_arg(Arg:Type, _) --> 1690 !, 1691 html([\argname(Arg), :, \argtype(Type)]). 1692pred_arg(Arg, _) --> 1693 argname(Arg). 1694 1695argname('$VAR'(Name)) --> 1696 !, 1697 html(Name). 1698argname(Name) --> 1699 !, 1700 html(Name). 1701 1702argtype(Term) --> 1703 { format(string(S), '~W', 1704 [ Term, 1705 [ quoted(true), 1706 numbervars(true) 1707 ] 1708 ]) }, 1709 html(S). 1710 1711pred_det(unknown) --> 1712 []. 1713pred_det(Det) --> 1714 html([' is ', b(class=det, Det)]).
doc_wiki.pl
.
1723term(_, Atom, []) --> 1724 { atomic(Atom), 1725 !, 1726 format(string(S), '~W', [Atom,[quoted(true)]]) 1727 }, 1728 html(span(class=functor, S)). 1729term(_, Key:Type, [TypeName=Type]) --> 1730 { atomic(Key) 1731 }, 1732 !, 1733 html([span(class='pl-key', Key), :, span(class('pl-var'), TypeName)]). 1734term(_, Term, Bindings) --> 1735 { is_mode(Term is det), % HACK. Bit too strict? 1736 bind_vars(Bindings) 1737 }, 1738 !, 1739 pred_head(Term). 1740term(_, Term, Bindings) --> 1741 term(Term, 1742 [ variable_names(Bindings), 1743 quoued(true) 1744 ]). 1745 1746 1747 /******************************* 1748 * PREDREF * 1749 *******************************/
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.
1762predref(Term) --> 1763 { catch(nb_getval(pldoc_options, Options), _, Options = []) }, 1764 predref(Term, Options). 1765 1766predref(Obj, Options) --> 1767 { Obj = _:_, 1768 doc_comment(Obj, File:_Line, _, _), 1769 ( ( option(files(Map), Options) 1770 -> memberchk(file(File,_), Map) 1771 ; true 1772 ) 1773 -> object_href(Obj, HREF, Options) 1774 ; manref(Obj, HREF, Options) 1775 ) 1776 }, 1777 !, 1778 html(a(href(HREF), \object_name(Obj, [qualify(true)|Options]))). 1779predref(M:Term, Options) --> 1780 !, 1781 predref(Term, M, Options). 1782predref(Term, Options) --> 1783 predref(Term, _, Options). 1784 1785predref(Name/Arity, _, Options) --> % Builtin; cannot be overruled 1786 { prolog:doc_object_summary(Name/Arity, manual, _, _), 1787 !, 1788 manref(Name/Arity, HREF, Options) 1789 }, 1790 html(a([class=builtin, href=HREF], [Name, /, Arity])). 1791predref(Name/Arity, _, Options) --> % From packages 1792 { option(prefer(manual), Options), 1793 prolog:doc_object_summary(Name/Arity, Category, _, _), 1794 !, 1795 manref(Name/Arity, HREF, Options) 1796 }, 1797 html(a([class=Category, href=HREF], [Name, /, Arity])). 1798predref(Obj, Module, Options) --> % Local 1799 { doc_comment(Module:Obj, File:_Line, _, _), 1800 ( option(files(Map), Options) 1801 -> memberchk(file(File,_), Map) 1802 ; true 1803 ) 1804 }, 1805 !, 1806 object_ref(Module:Obj, Options). 1807predref(Name/Arity, Module, Options) --> 1808 { \+ option(files(_), Options), 1809 pred_href(Name/Arity, Module, HREF) 1810 }, 1811 !, 1812 html(a(href=HREF, [Name, /, Arity])). 1813predref(Name//Arity, Module, Options) --> 1814 { \+ option(files(_), Options), 1815 PredArity is Arity + 2, 1816 pred_href(Name/PredArity, Module, HREF) 1817 }, 1818 !, 1819 html(a(href=HREF, [Name, //, Arity])). 1820predref(PI, _, Options) --> % From packages 1821 { canonical_pi(PI, CPI, HTML), 1822 ( option(files(_), Options) 1823 -> Category = extmanual 1824 ; prolog:doc_object_summary(CPI, Category, _, _) 1825 ), 1826 manref(CPI, HREF, Options) 1827 }, 1828 html(a([class=Category, href=HREF], HTML)). 1829predref(PI, _, _Options) --> 1830 { canonical_pi(PI, _CPI, HTML) 1831 }, 1832 !, 1833 html(span(class=undef, HTML)). 1834predref(Callable, Module, Options) --> 1835 { callable(Callable), 1836 functor(Callable, Name, Arity) 1837 }, 1838 predref(Name/Arity, Module, Options). 1839 1840canonical_pi(Name/Arity, Name/Arity, [Name, /, Arity]) :- 1841 atom(Name), integer(Arity), 1842 !. 1843canonical_pi(Name//Arity, Name/Arity2, [Name, //, Arity]) :- 1844 atom(Name), integer(Arity), 1845 !, 1846 Arity2 is Arity+2.
man_server(+Server)
.1854manref(PI, HREF, Options) :- 1855 predname(PI, PredName), 1856 ( option(files(_Map), Options) 1857 -> option(man_server(Server), Options, 1858 'http://www.swi-prolog.org/pldoc'), 1859 uri_components(Server, Comp0), 1860 uri_data(path, Comp0, Path0), 1861 directory_file_path(Path0, man, Path), 1862 uri_data(path, Comp0, Path, Components), 1863 uri_query_components(Query, [predicate=PredName]), 1864 uri_data(search, Components, Query), 1865 uri_components(HREF, Components) 1866 ; http_link_to_id(pldoc_man, [predicate=PredName], HREF) 1867 ). 1868 1869predname(Name/Arity, PredName) :- 1870 !, 1871 format(atom(PredName), '~w/~d', [Name, Arity]). 1872predname(Module:Name/Arity, PredName) :- 1873 !, 1874 format(atom(PredName), '~w:~w/~d', [Module, Name, Arity]).
1888pred_href(Name/Arity, Module, HREF) :- 1889 format(string(FragmentId), '~w/~d', [Name, Arity]), 1890 uri_data(fragment, Components, FragmentId), 1891 functor(Head, Name, Arity), 1892 ( catch(relative_file(Module:Head, File), _, fail) 1893 -> uri_data(path, Components, File), 1894 uri_components(HREF, Components) 1895 ; in_file(Module:Head, File) 1896 -> ( current_prolog_flag(home, SWI), 1897 sub_atom(File, 0, _, _, SWI), 1898 prolog:doc_object_summary(Name/Arity, packages, _, _) 1899 -> http_link_to_id(pldoc_man, [predicate=FragmentId], HREF) 1900 ; http_location_by_id(pldoc_doc, DocHandler), 1901 atom_concat(DocHandler, File, Path), 1902 uri_data(path, Components, Path), 1903 uri_components(HREF, Components) 1904 ) 1905 ). 1906 1907relative_file(Head, '') :- 1908 b_getval(pldoc_file, CurrentFile), CurrentFile \== [], 1909 in_file(Head, CurrentFile), 1910 !. 1911relative_file(Head, RelFile) :- 1912 b_getval(pldoc_file, CurrentFile), CurrentFile \== [], 1913 in_file(Head, DefFile), 1914 relative_file_name(DefFile, CurrentFile, RelFile).
1920pred_source_href(Name/Arity, Module, HREF) :-
1921 format(string(FragmentId), '~w/~d', [Name, Arity]),
1922 uri_data(fragment, Components, FragmentId),
1923 uri_query_components(Query, [show=src]),
1924 uri_data(search, Components, Query),
1925 functor(Head, Name, Arity),
1926 ( catch(relative_file(Module:Head, File), _, fail)
1927 -> uri_data(path, Components, File),
1928 uri_components(HREF, Components)
1929 ; in_file(Module:Head, File0),
1930 insert_alias(File0, File),
1931 http_location_by_id(pldoc_doc, DocHandler),
1932 atom_concat(DocHandler, File, Path),
1933 uri_data(path, Components, Path),
1934 uri_components(HREF, Components)
1935 ).
1944object_ref([], _) --> 1945 !, 1946 []. 1947object_ref([H|T], Options) --> 1948 !, 1949 object_ref(H, Options), 1950 ( {T == []} 1951 -> html(', '), 1952 object_ref(T, Options) 1953 ; [] 1954 ). 1955object_ref(Obj, Options) --> 1956 { object_href(Obj, HREF, Options) 1957 }, 1958 html(a(href(HREF), \object_name(Obj, Options))).
1965object_href(Obj, HREF) :- 1966 object_href(Obj, HREF, []). 1967 1968object_href(M:PI0, HREF, Options) :- 1969 option(files(Map), Options), 1970 ( module_property(M, file(File)) 1971 -> true 1972 ; xref_module(File, M) 1973 ), 1974 memberchk(file(File, DocFile), Map), 1975 !, 1976 file_base_name(DocFile, LocalFile), % TBD: proper directory index 1977 expand_pi(PI0, PI), 1978 term_to_string(PI, PIS), 1979 uri_data(path, Components, LocalFile), 1980 uri_data(fragment, Components, PIS), 1981 uri_components(HREF, Components). 1982object_href(file(File), HREF, _Options) :- 1983 doc_file_href(File, HREF), 1984 !. 1985object_href(directory(Dir), HREF, _Options) :- 1986 directory_file_path(Dir, 'index.html', Index), 1987 doc_file_href(Index, HREF), 1988 !. 1989object_href(Obj, HREF, _Options) :- 1990 prolog:doc_object_href(Obj, HREF), 1991 !. 1992object_href(Obj0, HREF, _Options) :- 1993 localise_object(Obj0, Obj), 1994 term_to_string(Obj, String), 1995 http_link_to_id(pldoc_object, [object=String], HREF). 1996 1997expand_pi(Name//Arity0, Name/Arity) :- 1998 !, 1999 Arity is Arity0+2. 2000expand_pi(PI, PI).
2008localise_object(Obj0, Obj) :- 2009 prolog:doc_canonical_object(Obj0, Obj), 2010 !. 2011localise_object(Obj, Obj).
2019term_to_string(Term, String) :-
2020 State = state(-),
2021 ( numbervars(Term, 0, _, [singletons(true)]),
2022 with_output_to(string(String),
2023 write_term(Term,
2024 [ numbervars(true),
2025 quoted(true)
2026 ])),
2027 nb_setarg(1, State, String),
2028 fail
2029 ; arg(1, State, String)
2030 ).
inline
or title
number
, title
or number_title
2044object_name(Obj, Options) --> 2045 { option(style(Style), Options, inline) 2046 }, 2047 object_name(Style, Obj, Options). 2048 2049object_name(title, Obj, Options) --> 2050 { merge_options(Options, [secref_style(title)], Options1) }, 2051 prolog:doc_object_link(Obj, Options1), 2052 !. 2053object_name(inline, Obj, Options) --> 2054 prolog:doc_object_link(Obj, Options), 2055 !. 2056object_name(title, f(Name/Arity), _Options) --> 2057 !, 2058 html(['Function ', Name, /, Arity]). 2059object_name(inline, f(Name/Arity), _Options) --> 2060 !, 2061 html([Name, /, Arity]). 2062object_name(Style, PI, Options) --> 2063 { is_pi(PI) }, 2064 !, 2065 pi(Style, PI, Options). 2066object_name(inline, Module:module(_Title), _) --> 2067 !, 2068 { module_property(Module, file(File)), 2069 file_base_name(File, Base) 2070 }, 2071 !, 2072 html(Base). 2073object_name(title, Module:module(Title), _) --> 2074 { module_property(Module, file(File)), 2075 file_base_name(File, Base) 2076 }, 2077 !, 2078 html([Base, ' -- ', Title]). 2079object_name(title, file(File), _) --> 2080 { module_property(Module, file(File)), 2081 doc_comment(Module:module(Title), _, _, _), 2082 !, 2083 file_base_name(File, Base) 2084 }, 2085 html([Base, ' -- ', Title]). 2086object_name(_, file(File), _) --> 2087 { file_base_name(File, Base) }, 2088 html(Base). 2089object_name(_, directory(Dir), _) --> 2090 { file_base_name(Dir, Base) }, 2091 html(Base). 2092 2093pi(title, PI, Options) --> 2094 pi_type(PI), 2095 pi(PI, Options). 2096pi(inline, PI, Options) --> 2097 pi(PI, Options). 2098 2099pi(M:PI, Options) --> 2100 !, 2101 ( { option(qualify(true), Options) } 2102 -> html([span(class(module), M), :]) 2103 ; [] 2104 ), 2105 pi(PI, Options). 2106pi(Name/Arity, _) --> 2107 !, 2108 html([Name, /, Arity]). 2109pi(Name//Arity, _) --> 2110 html([Name, //, Arity]). 2111 2112pi_type(_:PI) --> 2113 !, 2114 pi_type(PI). 2115pi_type(_/_) --> 2116 html(['Predicate ']). 2117pi_type(_//_) --> 2118 html(['Grammer rule ']).
2130in_file(Module:Head, File) :- 2131 !, 2132 in_file(Module, Head, File). 2133in_file(Head, File) :- 2134 in_file(_, Head, File). 2135 2136in_file(_, Head, File) :- 2137 xref_current_source(File), 2138 atom(File), % only plain files 2139 xref_defined(File, Head, How), 2140 How \= imported(_From). 2141in_file(Module, Head, File) :- 2142 predicate_property(Module:Head, exported), 2143 ( predicate_property(Module:Head, imported_from(Primary)) 2144 -> true 2145 ; Primary = Module 2146 ), 2147 module_property(Primary, file(File)). 2148in_file(Module, Head, File) :- 2149 predicate_property(Module:Head, file(File)). 2150in_file(Module, Head, File) :- 2151 current_module(Module), 2152 source_file(Module:Head, File).
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.2183file(File) --> 2184 file(File, []). 2185 2186file(File, Options) --> 2187 { catch(nb_getval(pldoc_options, GenOptions), _, GenOptions = []), 2188 merge_options(Options, GenOptions, FinalOptions) 2189 }, 2190 link_file(File, FinalOptions), 2191 !. 2192file(File, Options) --> 2193 { option(edit_handler(Handler), Options), 2194 http_current_request(Request), 2195 memberchk(path(Path), Request), 2196 absolute_file_name(File, Location, 2197 [ relative_to(Path) 2198 ]), 2199 http_link_to_id(Handler, [location(Location)], HREF), 2200 format(atom(Title), 'Click to create ~w', [File]) 2201 }, 2202 html(a([href(HREF), class(nofile), title(Title)], File)). 2203file(File, _) --> 2204 html(code(class(nofile), File)). 2205 2206link_file(File, Options) --> 2207 { file_href(File, HREF, Options), 2208 option(label(Label), Options, File), 2209 option(class(Class), Options, file) 2210 }, 2211 html(a([class(Class), href(HREF)], Label)).
2217file_href(_, HREF, Options) :- 2218 option(href(HREF), Options), 2219 !. 2220file_href(File, HREF, Options) :- 2221 file_href_real(File, HREF0, Options), 2222 map_extension(HREF0, HREF, Options).
map_extension(+Pairs)
2230map_extension(HREF0, HREF, Options) :- 2231 option(map_extension(Map), Options), 2232 file_name_extension(Base, Old, HREF0), 2233 memberchk(Old-New, Map), 2234 !, 2235 file_name_extension(Base, New, HREF). 2236map_extension(HREF, HREF, _). 2237 2238 2239file_href_real(File, HREF, Options) :- 2240 ( option(absolute_path(Path), Options) 2241 ; existing_linked_file(File, Path) 2242 ), 2243 !, 2244 ( option(files(Map), Options), 2245 memberchk(file(Path, LinkFile), Map) 2246 -> true 2247 ; LinkFile = Path 2248 ), 2249 file_href(LinkFile, HREF). 2250file_href_real(File, HREF, _) :- 2251 directory_alias(Alias), 2252 Term =.. [Alias,File], 2253 absolute_file_name(Term, _, 2254 [ access(read), 2255 file_errors(fail) 2256 ]), 2257 !, 2258 http_absolute_location(Term, HREF, []). 2259 2260directory_alias(icons). 2261directory_alias(css).
pldoc_file
.2271file_href(Path, HREF) :- % a loaded Prolog file 2272 source_file(Path), 2273 !, 2274 doc_file_href(Path, HREF). 2275file_href(Path, HREF) :- 2276 ( nb_current(pldoc_output, CFile) 2277 ; nb_current(pldoc_file, CFile) 2278 ), 2279 CFile \== [], 2280 !, 2281 relative_file_name(Path, CFile, HREF). 2282file_href(Path, Path).
2290existing_linked_file(File, Path) :-
2291 catch(b_getval(pldoc_file, CurrentFile), _, fail),
2292 CurrentFile \== [],
2293 absolute_file_name(File, Path,
2294 [ relative_to(CurrentFile),
2295 access(read),
2296 file_errors(fail)
2297 ]).
include(File,
Type)
terms in the DOM term generated by wiki.pl
if it
encounters [[file.ext]].2307include(PI, predicate, _) --> 2308 !, 2309 ( html_tokens_for_predicates(PI, []) 2310 -> [] 2311 ; html(['[[', \predref(PI), ']]']) 2312 ). 2313include(File, image, Options) --> 2314 { file_name_extension(_, svg, File), 2315 file_href(File, HREF, Options), 2316 !, 2317 include(image_attribute, Options, Attrs0), 2318 merge_options(Attrs0, 2319 [ alt(File), 2320 data(HREF), 2321 type('image/svg+xml') 2322 ], Attrs) 2323 }, 2324 ( { option(caption(Caption), Options) } 2325 -> html(div(class(figure), 2326 [ div(class(image), object(Attrs, [])), 2327 div(class(caption), Caption) 2328 ])) 2329 ; html(object(Attrs, [])) 2330 ). 2331include(File, image, Options) --> 2332 { file_href(File, HREF, Options), 2333 !, 2334 include(image_attribute, Options, Attrs0), 2335 merge_options(Attrs0, 2336 [ alt(File), 2337 border(0), 2338 src(HREF) 2339 ], Attrs) 2340 }, 2341 ( { option(caption(Caption), Options) } 2342 -> html(div(class(figure), 2343 [ div(class(image), img(Attrs)), 2344 div(class(caption), Caption) 2345 ])) 2346 ; html(img(Attrs)) 2347 ). 2348include(File, wiki, _Options) --> % [[file.txt]] is included 2349 { access_file(File, read), 2350 !, 2351 read_file_to_codes(File, String, []), 2352 wiki_codes_to_dom(String, [], DOM) 2353 }, 2354 html(DOM). 2355include(File, _Type, Options) --> 2356 link_file(File, Options), 2357 !. 2358include(File, _, _) --> 2359 html(code(class(nofile), ['[[',File,']]'])). 2360 2361image_attribute(src(_)). 2362image_attribute(alt(_)). 2363image_attribute(title(_)). 2364image_attribute(align(_)). 2365image_attribute(width(_)). 2366image_attribute(height(_)). 2367image_attribute(border(_)). 2368image_attribute(class(_)).
* [[member/2]] * [[append/3]]
2381html_tokens_for_predicates([], _Options) --> 2382 []. 2383html_tokens_for_predicates([H|T], Options) --> 2384 !, 2385 html_tokens_for_predicates(H, Options), 2386 html_tokens_for_predicates(T, Options). 2387html_tokens_for_predicates(PI, Options) --> 2388 { PI = _:_/_, 2389 !, 2390 ( doc_comment(PI, Pos, _Summary, Comment) 2391 -> true 2392 ; Comment = '' 2393 ) 2394 }, 2395 object(PI, [Pos-Comment], [dl], _, Options). 2396html_tokens_for_predicates(Spec, Options) --> 2397 { findall(PI, documented_pi(Spec, PI), List), 2398 List \== [], ! 2399 }, 2400 html_tokens_for_predicates(List, Options). 2401html_tokens_for_predicates(Spec, Options) --> 2402 man_page(Spec, 2403 [ links(false), % no header 2404 navtree(false), % no navigation tree 2405 footer(false) % no footer 2406 | Options 2407 ]). 2408 2409 2410documented_pi(Spec, PI) :- 2411 generalise_spec(Spec, PI), 2412 doc_comment(PI, _Pos, _Summary, _Comment). 2413 2414generalise_spec(Name/Arity, _M:Name/Arity). 2415generalise_spec(Name//Arity, _M:Name//Arity). 2416 2417 2418 /******************************* 2419 * WIKI FILES * 2420 *******************************/
2427doc_for_wiki_file(FileSpec, Options) :- 2428 absolute_file_name(FileSpec, File, 2429 [ access(read) 2430 ]), 2431 read_file_to_codes(File, String, []), 2432 b_setval(pldoc_file, File), 2433 call_cleanup(reply_wiki_page(File, String, Options), 2434 nb_delete(pldoc_file)). 2435 2436reply_wiki_page(File, String, Options) :- 2437 wiki_codes_to_dom(String, [], DOM0), 2438 title(DOM0, File, Title), 2439 insert_edit_button(DOM0, File, DOM, Options), 2440 reply_html_page(pldoc(wiki), 2441 title(Title), 2442 [ \html_requires(pldoc) 2443 | DOM 2444 ]). 2445 2446title(DOM, _, Title) :- 2447 sub_term(h1(_,Title), DOM), 2448 !. 2449title(_, File, Title) :- 2450 file_base_name(File, Title). 2451 DOM, _, DOM, Options) (:- 2453 option(edit(false), Options, false), 2454 !. 2455insert_edit_button([h1(Attrs,Title)|DOM], File, 2456 [h1(Attrs,[ span(style('float:right'), 2457 \edit_button(File, [edit(true)])) 2458 | Title 2459 ])|DOM], _) :- !. 2460insert_edit_button(DOM, File, 2461 [ h1(class(wiki), 2462 [ span(style('float:right'), 2463 \edit_button(File, [edit(true)])) 2464 ]) 2465 | DOM 2466 ], _). 2467 2468 2469 /******************************* 2470 * ANCHORS * 2471 *******************************/
2477mode_anchor_name(Var, _) :- 2478 var(Var), 2479 !, 2480 instantiation_error(Var). 2481mode_anchor_name(mode(Head, _), Anchor) :- 2482 !, 2483 mode_anchor_name(Head, Anchor). 2484mode_anchor_name(Head is _Det, Anchor) :- 2485 !, 2486 mode_anchor_name(Head, Anchor). 2487mode_anchor_name(Head, Anchor) :- 2488 pred_anchor_name(Head, _, Anchor).
2495pred_anchor_name(//(Head), Name/Arity, Anchor) :- 2496 !, 2497 functor(Head, Name, DCGArity), 2498 Arity is DCGArity+2, 2499 format(atom(Anchor), '~w/~d', [Name, Arity]). 2500pred_anchor_name(Head, Name/Arity, Anchor) :- 2501 functor(Head, Name, Arity), 2502 format(atom(Anchor), '~w/~d', [Name, Arity])
PlDoc HTML backend
This module translates the Herbrand term from the documentation extracting module
doc_wiki.pl
into HTML+CSS.