1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: jan@swi-prolog.org 5 WWW: https://www.swi-prolog.org 6 Copyright (c) 2006-2026, 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:- use_module(library(apply)). 95:- use_module(library(debug)). 96:- use_module(library(error)). 97:- use_module(library(filesex)). 98:- use_module(library(lists)). 99:- use_module(library(occurs)). 100:- use_module(library(option)). 101:- use_module(library(pairs)). 102:- use_module(library(prolog_source)). 103:- use_module(library(prolog_xref)). 104:- use_module(library(readutil)). 105:- use_module(library(solution_sequences)). 106:- use_module(library(uri)). 107:- use_module(library(http/html_head)). 108:- use_module(library(http/html_write)). 109:- use_module(library(http/http_path)). 110:- use_module(library(http/term_html)). 111:- use_module(pldoc(doc_index)). 112:- use_module(pldoc(doc_man)). 113:- use_module(pldoc(doc_modes)). 114:- use_module(pldoc(doc_process)). 115:- use_module(pldoc(doc_search)). 116:- use_module(pldoc(doc_util)). 117:- use_module(pldoc(doc_wiki)). 118:- use_module(library(dcg/high_order)). 119:- use_module(library(dcg/basics)). 120 121pldoc_server(true). 122:- else. 123 124:- multifile 125 http:location/3. 126 127httplocation(pldoc_resource, '/pldoc/res', []). 128 129pldoc_server(false). 130:- endif. 131 132:- use_module(library(lists)). 133:- use_module(library(option)). 134:- use_module(library(uri)). 135:- use_module(library(readutil)). 136:- use_module(library(http/html_write)). 137:- use_module(library(http/http_path)). 138:- use_module(library(http/html_head)). 139:- use_module(library(http/term_html)). 140:- use_module(library(debug)). 141:- use_module(library(apply)). 142:- use_module(library(pairs)). 143:- use_module(library(filesex)). 144:- use_module(doc_process). 145:- use_module(doc_man). 146:- use_module(doc_modes). 147:- use_module(doc_wiki). 148:- use_module(doc_search). 149:- use_module(doc_index). 150:- use_module(doc_util). 151:- use_module(library(solution_sequences)). 152:- use_module(library(error)). 153:- use_module(library(occurs)). 154:- use_module(library(prolog_source)). 155:- use_module(library(prolog_xref)). 156 157:- include(hooks).
169:- public 170 args//1, % Called from \Term output created 171 pred_dt//3, % by the wiki renderer 172 section//2, 173 tag//2. 174 175 176:- predicate_options(doc_for_wiki_file/2, 2, 177 [ edit(boolean) 178 ]). 179:- predicate_options(doc_hide_private/3, 3, 180 [module(atom), public(list), public_only(boolean)]). 181:- predicate_options(edit_button//2, 2, 182 [ edit(boolean) 183 ]). 184:- predicate_options(file//2, 2, 185 [ label(any), 186 absolute_path(atom), 187 href(atom), 188 map_extension(list), 189 files(list), 190 edit_handler(atom) 191 ]). 192:- predicate_options(file_header//2, 2, 193 [ edit(boolean), 194 files(list), 195 public_only(boolean) 196 ]). 197:- predicate_options(include//3, 3, 198 [ absolute_path(atom), 199 class(atom), 200 files(list), 201 href(atom), 202 label(any), 203 map_extension(list) 204 ]). 205:- predicate_options(object_edit_button//2, 2, 206 [ edit(boolean), 207 pass_to(pred_edit_button//2, 2) 208 ]). 209:- predicate_options(object_page//2, 2, 210 [ for(any), 211 header(boolean), 212 links(boolean), 213 no_manual(boolean), 214 try_manual(boolean), 215 search_in(oneof([all,app,man])), 216 search_match(oneof([name,summary])), 217 search_options(boolean) 218 ]). 219:- predicate_options(object_ref//2, 2, 220 [ files(list), 221 qualify(boolean), 222 style(oneof([number,title,number_title])), 223 secref_style(oneof([number,title,number_title])) 224 ]). 225:- predicate_options(object_synopsis//2, 2, 226 [ href(atom) 227 ]). 228:- predicate_options(pred_dt//3, 3, 229 [ edit(boolean) 230 ]). 231:- predicate_options(pred_edit_button//2, 2, 232 [ edit(boolean) 233 ]). 234:- predicate_options(predref//2, 2, 235 [ files(list), 236 prefer(oneof([manual,app])), 237 pass_to(object_ref/4, 2) 238 ]). 239:- predicate_options(private/2, 2, 240 [ module(atom), 241 public(list) 242 ]). 243:- predicate_options(source_button//2, 2, 244 [ files(list) 245 ]). 246 247 248 /******************************* 249 * RESOURCES * 250 *******************************/ 251 252:- if(pldoc_server(true)). 253:- html_resource(pldoc_css, 254 [ virtual(true), 255 requires([ pldoc_resource('pldoc.css') 256 ]) 257 ]). 258:- html_resource(pldoc_resource('pldoc.js'), 259 [ requires([ jquery 260 ]) 261 ]). 262:- html_resource(pldoc_js, 263 [ virtual(true), 264 requires([ pldoc_resource('pldoc.js') 265 ]) 266 ]). 267:- html_resource(pldoc, 268 [ virtual(true), 269 requires([ pldoc_css, 270 pldoc_js 271 ]) 272 ]). 273:- else. 274:- html_resource(pldoc_css, [virtual(true)]). 275:- html_resource(pldoc_resource('pldoc.js'), [virtual(true)]). 276:- html_resource(pldoc_js, [virtual(true)]). 277:- html_resource(pldoc, [virtual(true)]). 278:- endif. 279 280 281 /******************************* 282 * FILE PROCESSING * 283 *******************************/
true (default), only emit documentation for
exported predicates.true, provide edit buttons. Default, these buttons
are suppressed.304doc_for_file(FileSpec, Options) :- 305 doc_file_objects(FileSpec, File, Objects, FileOptions, Options), 306 doc_file_title(File, Title, FileOptions, Options), 307 doc_write_page( 308 pldoc(file(File, Title)), 309 title(Title), 310 \prolog_file(File, Objects, FileOptions, Options), 311 Options). 312 313doc_file_title(_, Title, _, Options) :- 314 option(title(Title), Options), 315 !. 316doc_file_title(File, Title, FileOptions, _) :- 317 memberchk(file(Title0, _Comment), FileOptions), 318 !, 319 file_base_name(File, Base), 320 atomic_list_concat([Base, ' -- ', Title0], Title). 321doc_file_title(File, Title, _, _) :- 322 file_base_name(File, Title). 323 324:- html_meta doc_write_page(+, html, html, +). 325 326doc_write_page(Style, Head, Body, Options) :- 327 option(files(_), Options), 328 !, 329 phrase(page(Style, Head, Body), HTML), 330 print_html(HTML). 331doc_write_page(Style, Head, Body, _) :- 332 reply_html_page(Style, Head, Body). 333 334 335prolog_file(File, Objects, FileOptions, Options) --> 336 { b_setval(pldoc_file, File), % TBD: delete? 337 file_directory_name(File, Dir) 338 }, 339 html([ \doc_resources(Options), 340 \doc_links(Dir, FileOptions), 341 \file_header(File, FileOptions) 342 | \objects(Objects, FileOptions) 343 ]), 344 undocumented(File, Objects, FileOptions).
doc_files.pl. A bit hacky ...351doc_resources(Options) --> 352 { option(resource_directory(ResDir), Options), 353 nb_current(pldoc_output, OutputFile), 354 !, 355 directory_file_path(ResDir, 'pldoc.css', Res), 356 relative_file_name(Res, OutputFile, Ref) 357 }, 358 html_requires(Ref). 359doc_resources(Options) --> 360 { option(html_resources(Resoures), Options, pldoc) 361 }, 362 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:
391doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 392 xref_current_source(FileSpec), 393 xref_option(FileSpec, comments(collect)), 394 !, 395 File = FileSpec, 396 findall(Object, xref_doc_object(File, Object), Objects0), 397 reply_file_objects(File, Objects0, Objects, FileOptions, Options). 398doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 399 absolute_file_name(FileSpec, File, 400 [ file_type(prolog), 401 access(read) 402 ]), 403 source_file(File), 404 !, 405 ensure_doc_objects(File), 406 Pos = File:Line, 407 findall(Line-doc(Obj,Pos,Comment), 408 doc_comment(Obj, Pos, _, Comment), Pairs), 409 sort(Pairs, Pairs1), % remove duplicates 410 keysort(Pairs1, ByLine), 411 pairs_values(ByLine, Objs0), 412 reply_file_objects(File, Objs0, Objects, FileOptions, Options). 413doc_file_objects(FileSpec, File, Objects, FileOptions, Options) :- 414 absolute_file_name(FileSpec, File, 415 [ file_type(prolog), 416 access(read) 417 ]), 418 xref_source(File, [silent(true)]), 419 findall(Object, xref_doc_object(File, Object), Objects0), 420 reply_file_objects(File, Objects0, Objects, FileOptions, Options). 421 422 423reply_file_objects(File, Objs0, Objects, FileOptions, Options) :- 424 module_info(File, ModuleOptions, Options), 425 file_info(Objs0, Objs1, FileOptions, ModuleOptions), 426 doc_hide_private(Objs1, ObjectsSelf, ModuleOptions), 427 include_reexported(ObjectsSelf, Objects1, File, FileOptions), 428 remove_doc_duplicates(Objects1, Objects, []). 429 430remove_doc_duplicates([], [], _). 431remove_doc_duplicates([H|T0], [H|T], Seen) :- 432 H = doc(_, _, Comment), 433 \+ memberchk(Comment, Seen), 434 !, 435 remove_doc_duplicates(T0, T, [Comment|Seen]). 436remove_doc_duplicates([_|T0], T, Seen) :- 437 remove_doc_duplicates(T0, T, Seen). 438 439include_reexported(SelfObjects, Objects, File, Options) :- 440 option(include_reexported(true), Options), 441 option(module(Module), Options), 442 option(public(Exports), Options), 443 select_undocumented(Exports, Module, SelfObjects, Undoc), 444 re_exported_doc(Undoc, File, Module, REObjs, _), 445 REObjs \== [], 446 !, 447 append(SelfObjects, REObjs, Objects). 448include_reexported(Objects, Objects, _, _).
453xref_doc_object(File, doc(M:module(Title),File:0,Comment)) :- 454 xref_comment(File, Title, Comment), 455 xref_module(File, M). 456xref_doc_object(File, doc(M:Name/Arity,File:0,Comment)) :- 457 xref_comment(File, Head, _Summary, Comment), 458 xref_module(File, Module), 459 strip_module(Module:Head, M, Plain), 460 functor(Plain, Name, Arity).
471:- dynamic 472 no_comments/2. 473 474ensure_doc_objects(File) :- 475 source_file(File), 476 !, 477 ( doc_file_has_comments(File) 478 -> true 479 ; no_comments(File, TimeChecked), 480 time_file(File, TimeChecked) 481 -> true 482 ; xref_source(File, [silent(true), comments(store)]), 483 retractall(no_comments(File, _)), 484 ( doc_file_has_comments(File) 485 -> true 486 ; time_file(File, TimeChecked), 487 assertz(no_comments(File, TimeChecked)) 488 ) 489 ). 490ensure_doc_objects(File) :- 491 xref_source(File, [silent(true)]).
module(Name), public(Exports) to OtherOptions if
File is a module file.498module_info(File, [module(Module), public(Exports)|Options], Options) :- 499 module_property(Module, file(File)), 500 !, 501 module_property(Module, exports(Exports)). 502module_info(File, [module(Module), public(Exports)|Options], Options) :- 503 xref_module(File, Module), 504 !, 505 findall(PI, xref_exported_pi(File, PI), Exports). 506module_info(_, Options, Options). 507 508xref_exported_pi(Src, Name/Arity) :- 509 xref_exported(Src, Head), 510 functor(Head, Name, Arity).
516doc_hide_private(Objs, Objs, Options) :- 517 option(public_only(false), Options, true), 518 !. 519doc_hide_private(Objs0, Objs, Options) :- 520 hide_private(Objs0, Objs, Options). 521 522hide_private([], [], _). 523hide_private([H|T0], T, Options) :- 524 obj(H, Obj), 525 private(Obj, Options), 526 !, 527 hide_private(T0, T, Options). 528hide_private([H|T0], [H|T], Options) :- 529 hide_private(T0, T, Options).
537obj(doc(Obj0, _Pos, _Summary), Obj) :- 538 !, 539 ( Obj0 = [Obj|_] 540 -> true 541 ; Obj = Obj0 542 ). 543obj(Obj0, Obj) :- 544 ( Obj0 = [Obj|_] 545 -> true 546 ; Obj = Obj0 547 ).
556:- multifile 557 prolog:doc_is_public_object/1. 558 559private(Object, _Options) :- 560 prolog:doc_is_public_object(Object), !, fail. 561private(Module:PI, Options) :- 562 multifile(Module:PI, Options), !, fail. 563private(Module:PI, Options) :- 564 public(Module:PI, Options), !, fail. 565private(Module:PI, Options) :- 566 option(module(Module), Options), 567 option(public(Public), Options), 568 !, 569 \+ ( member(PI2, Public), 570 eq_pi(PI, PI2) 571 ). 572private(Module:PI, _Options) :- 573 module_property(Module, file(_)), % A loaded module 574 !, 575 module_property(Module, exports(Exports)), 576 \+ ( member(PI2, Exports), 577 eq_pi(PI, PI2) 578 ). 579private(Module:PI, _Options) :- 580 \+ (pi_to_head(PI, Head), 581 xref_exported(Source, Head), 582 xref_module(Source, Module)).
593multifile(Obj, _Options) :-
594 strip_module(user:Obj, Module, PI),
595 pi_to_head(PI, Head),
596 ( predicate_property(Module:Head, multifile)
597 ; xref_module(Source, Module),
598 xref_defined(Source, Head, multifile(_Line))
599 ),
600 !.606public(Obj, _Options) :- 607 strip_module(user:Obj, Module, PI), 608 pi_to_head(PI, Head), 609 ( predicate_property(Module:Head, public) 610 ; xref_module(Source, Module), 611 xref_defined(Source, Head, public(_Line)) 612 ), 613 !. 614 615pi_to_head(Var, _) :- 616 var(Var), !, fail. 617pi_to_head(Name/Arity, Term) :- 618 functor(Term, Name, Arity). 619pi_to_head(Name//DCGArity, Term) :- 620 Arity is DCGArity+2, 621 functor(Term, Name, Arity).
file(Title, Comment) to OtherOptions if available.627file_info(Comments, RestComments, [file(Title, Comment)|Opts], Opts) :- 628 select(doc(_:module(Title),_,Comment), Comments, RestComments), 629 !. 630file_info(Comments, Comments, Opts, Opts).
637file_header(File, Options) --> 638 { memberchk(file(Title, Comment), Options), 639 !, 640 file_base_name(File, Base) 641 }, 642 file_title([Base, ' -- ', Title], File, Options), 643 { is_structured_comment(Comment, Prefixes), 644 string_codes(Comment, Codes), 645 indented_lines(Codes, Prefixes, Lines), 646 section_comment_header(Lines, _Header, Lines1), 647 wiki_lines_to_dom(Lines1, [], DOM) 648 }, 649 html(DOM). 650file_header(File, Options) --> 651 { file_base_name(File, Base) 652 }, 653 file_title([Base], File, Options).
660file_title(Title, File, Options) --> 661 prolog:doc_file_title(Title, File, Options), 662 !. 663file_title(Title, File, Options) --> 664 { file_base_name(File, Base) 665 }, 666 html(h1(class(file), 667 [ span(style('float:right'), 668 [ \reload_button(File, Base, Options), 669 \zoom_button(Base, Options), 670 \source_button(Base, Options), 671 \edit_button(File, Options) 672 ]) 673 | Title 674 ])).
684reload_button(File, _Base, Options) --> 685 { \+ source_file(File), 686 \+ option(files(_), Options) 687 }, 688 !, 689 html(span(class(file_anot), '[not loaded]')). 690reload_button(_File, Base, Options) --> 691 { option(edit(true), Options), 692 !, 693 option(public_only(Public), Options, true) 694 }, 695 html(a(href(Base+[reload(true), public_only(Public)]), 696 img([ class(action), 697 alt('Reload'), 698 title('Make & Reload'), 699 src(location_by_id(pldoc_resource)+'reload.png') 700 ]))). 701reload_button(_, _, _) --> [].
709edit_button(File, Options) --> 710 { option(edit(true), Options) 711 }, 712 !, 713 html(a([ onClick('HTTPrequest(\'' + 714 location_by_id(pldoc_edit) + [file(File)] + 715 '\')') 716 ], 717 img([ class(action), 718 alt(edit), 719 title('Edit file'), 720 src(location_by_id(pldoc_resource)+'edit.png') 721 ]))). 722edit_button(_, _) --> 723 [].
730zoom_button(_, Options) --> 731 { option(files(_Map), Options) }, 732 !. % generating files 733zoom_button(Base, Options) --> 734 { ( option(public_only(true), Options, true) 735 -> Zoom = 'public.png', 736 Alt = 'Public', 737 Title = 'Click to include private', 738 PublicOnly = false 739 ; Zoom = 'private.png', 740 Alt = 'All predicates', 741 Title = 'Click to show exports only', 742 PublicOnly = true 743 ) 744 }, 745 html(a(href(Base+[public_only(PublicOnly)]), 746 img([ class(action), 747 alt(Alt), 748 title(Title), 749 src(location_by_id(pldoc_resource)+Zoom) 750 ]))).
757source_button(_File, Options) --> 758 { option(files(_Map), Options) }, 759 !. % generating files 760source_button(File, _Options) --> 761 { ( is_absolute_file_name(File) 762 -> doc_file_href(File, HREF0) 763 ; HREF0 = File 764 ) 765 }, 766 html(a(href(HREF0+[show(src)]), 767 img([ class(action), 768 alt('Show source'), 769 title('Show source'), 770 src(location_by_id(pldoc_resource)+'source.png') 771 ]))).
true, provide a navitation tree.781objects(Objects, Options) --> 782 { option(navtree(true), Options), 783 !, 784 objects_nav_tree(Objects, Tree) 785 }, 786 html([ div(class(navtree), 787 div(class(navwindow), 788 \nav_tree(Tree, Objects, Options))), 789 div(class(navcontent), 790 \objects_nt(Objects, Options)) 791 ]). 792objects(Objects, Options) --> 793 objects_nt(Objects, Options). 794 795objects_nt(Objects, Options) --> 796 objects(Objects, [body], Options). 797 798objects([], Mode, _) --> 799 pop_mode(body, Mode, _). 800objects([Obj|T], Mode, Options) --> 801 object(Obj, Mode, Mode1, Options), 802 objects(T, Mode1, Options).
813object(doc(Obj,Pos,Comment), Mode0, Mode, Options) --> 814 !, 815 object(Obj, [Pos-Comment], Mode0, Mode, [scope(file)|Options]). 816object(Obj, Mode0, Mode, Options) --> 817 { findall(Pos-Comment, 818 doc_comment(Obj, Pos, _Summary, Comment), 819 Pairs) 820 }, 821 !, 822 { b_setval(pldoc_object, Obj) }, 823 object(Obj, Pairs, Mode0, Mode, Options). 824 825object(Obj, Pairs, Mode0, Mode, Options) --> 826 { is_pi(Obj), 827 !, 828 maplist(pred_dom(Obj, Options), Pairs, DOMS), 829 append(DOMS, DOM) 830 }, 831 need_mode(dl, Mode0, Mode), 832 html(DOM). 833object([Obj|_Same], Pairs, Mode0, Mode, Options) --> 834 !, 835 object(Obj, Pairs, Mode0, Mode, Options). 836object(Obj, _Pairs, Mode, Mode, _Options) --> 837 { debug(pldoc, 'Skipped ~p', [Obj]) }, 838 []. 839 840pred_dom(Obj, Options, Pos-Comment, DOM) :- 841 is_structured_comment(Comment, Prefixes), 842 string_codes(Comment, Codes), 843 indented_lines(Codes, Prefixes, Lines), 844 strip_module(user:Obj, Module, _), 845 process_modes(Lines, Module, Pos, Modes, Args, Lines1), 846 ( private(Obj, Options) 847 -> Class = privdef % private definition 848 ; multifile(Obj, Options) 849 -> ( option(scope(file), Options) 850 -> ( more_doc(Obj, Pos) 851 -> Class = multidef(object(Obj)) 852 ; Class = multidef 853 ) 854 ; Class = multidef(file((Pos))) 855 ) 856 ; public(Obj, Options) 857 -> Class = publicdef % :- public definition 858 ; Class = pubdef % exported definition 859 ), 860 ( Obj = Module:_ 861 -> POptions = [module(Module)|Options] 862 ; POptions = Options 863 ), 864 Pos = File:Line, 865 DTOptions = [file(File),line(Line)|POptions], 866 DOM = [\pred_dt(Modes, Class, DTOptions), dd(class=defbody, DOM1)], 867 wiki_lines_to_dom(Lines1, Args, DOM0), 868 strip_leading_par(DOM0, DOM1). 869 870more_doc(Obj, File:_) :- 871 doc_comment(Obj, File2:_, _, _), 872 File2 \== File, 873 !.
882need_mode(Mode, Stack, Stack) --> 883 { Stack = [Mode|_] }, 884 !, 885 []. 886need_mode(Mode, Stack, Rest) --> 887 { memberchk(Mode, Stack) 888 }, 889 !, 890 pop_mode(Mode, Stack, Rest). 891need_mode(Mode, Stack, [Mode|Stack]) --> 892 !, 893 html_begin(Mode). 894 895pop_mode(Mode, Stack, Stack) --> 896 { Stack = [Mode|_] }, 897 !, 898 []. 899pop_mode(Mode, [H|Rest0], Rest) --> 900 html_end(H), 901 pop_mode(Mode, Rest0, Rest).
907undocumented(File, Objs, Options) --> 908 { option(module(Module), Options), 909 option(public(Exports), Options), 910 select_undocumented(Exports, Module, Objs, Undoc), 911 re_exported_doc(Undoc, File, Module, UREObjs, ReallyUnDoc), 912 sort(2, @=<, UREObjs, REObjs) % UREObjs = doc(PI,Pos,Comment) 913 % i.e., sort on Pos 914 }, 915 !, 916 re_exported_doc(REObjs, Options), 917 undocumented(ReallyUnDoc, Options). 918undocumented(_, _, _) --> 919 []. 920 921re_exported_doc([], _) --> !. 922re_exported_doc(Objs, Options) --> 923 reexport_header(Objs, Options), 924 objects(Objs, Options). 925 926reexport_header(_, Options) --> 927 { option(reexport_header(true), Options, true) 928 }, 929 !, 930 html([ h2(class(wiki), 'Re-exported predicates'), 931 p([ "The following predicates are exported from this file \c 932 while their implementation is defined in imported modules \c 933 or non-module files loaded by this module." 934 ]) 935 ]). 936reexport_header(_, _) --> 937 []. 938 939undocumented([], _) --> !. 940undocumented(UnDoc, Options) --> 941 html([ h2(class(undoc), 'Undocumented predicates'), 942 p(['The following predicates are exported, but not ', 943 'or incorrectly documented.' 944 ]), 945 dl(class(undoc), 946 \undocumented_predicates(UnDoc, Options)) 947 ]). 948 949 950undocumented_predicates([], _) --> 951 []. 952undocumented_predicates([H|T], Options) --> 953 undocumented_pred(H, Options), 954 undocumented_predicates(T, Options). 955 956undocumented_pred(Name/Arity, Options) --> 957 { functor(Head, Name, Arity) }, 958 html(dt(class=undoc, \pred_mode(Head, [], _, Options))). 959 960select_undocumented([], _, _, []). 961select_undocumented([PI|T0], M, Objs, [PI|T]) :- 962 is_pi(PI), 963 \+ in_doc(M:PI, Objs), 964 !, 965 select_undocumented(T0, M, Objs, T). 966select_undocumented([_|T0], M, Objs, T) :- 967 select_undocumented(T0, M, Objs, T). 968 969in_doc(PI, Objs) :- 970 member(doc(O,_,_), Objs), 971 ( is_list(O) 972 -> member(O2, O), 973 eq_pi(PI, O2) 974 ; eq_pi(PI, O) 975 ).
982eq_pi(PI, PI) :- !. 983eq_pi(M:PI1, M:PI2) :- 984 atom(M), 985 !, 986 eq_pi(PI1, PI2). 987eq_pi(Name/A, Name//DCGA) :- 988 A =:= DCGA+2, 989 !. 990eq_pi(Name//DCGA, Name/A) :- 991 A =:= DCGA+2.
997is_pi(Var) :- 998 var(Var), 999 !, 1000 fail. 1001is_pi(_:PI) :- 1002 !, 1003 is_pi(PI). 1004is_pi(_/_). 1005is_pi(_//_).
1011re_exported_doc([], _, _, [], []). 1012re_exported_doc([PI|T0], File, Module, [doc(Orig:PI,Pos,Comment)|ObjT], UnDoc) :- 1013 pi_to_head(PI, Head), 1014 ( predicate_property(Module:Head, imported_from(Orig)) 1015 -> true 1016 ; predicate_property(Module:Head, exported) 1017 -> Orig = Module 1018 ; xref_defined(File, Head, imported(File2)), 1019 ensure_doc_objects(File2), 1020 xref_module(File2, Orig) 1021 ), 1022 doc_comment(Orig:PI, Pos, _, Comment), 1023 !, 1024 re_exported_doc(T0, File, Module, ObjT, UnDoc). 1025re_exported_doc([PI|T0], File, Module, REObj, [PI|UnDoc]) :- 1026 re_exported_doc(T0, File, Module, REObj, UnDoc). 1027 1028 1029 /******************************* 1030 * SINGLE OBJECT PAGE * 1031 *******************************/
1041object_page(Obj, Options) --> 1042 prolog:doc_object_page(Obj, Options), 1043 !, 1044 object_page_footer(Obj, Options). 1045object_page(Obj, Options) --> 1046 { doc_comment(Obj, File:_Line, _Summary, _Comment) 1047 }, 1048 !, 1049 ( { \+ ( doc_comment(Obj, File2:_, _, _), 1050 File2 \== File ) 1051 } 1052 -> html([ \html_requires(pldoc), 1053 \object_page_header(File, Options), 1054 \object_synopsis(Obj, []), 1055 \objects([Obj], Options) 1056 ]) 1057 ; html([ \html_requires(pldoc), 1058 \object_page_header(-, Options), 1059 \objects([Obj], [synopsis(true)|Options]) 1060 ]) 1061 ), 1062 object_page_footer(Obj, Options). 1063object_page(M:Name/Arity, Options) --> % specified module, but public 1064 { functor(Head, Name, Arity), 1065 ( predicate_property(M:Head, exported) 1066 -> module_property(M, class(library)) 1067 ; \+ predicate_property(M:Head, defined) 1068 ) 1069 }, 1070 prolog:doc_object_page(Name/Arity, Options), 1071 !, 1072 object_page_footer(Name/Arity, Options). 1073 1074object_page_header(File, Options) --> 1075 prolog:doc_page_header(file(File), Options), 1076 !. 1077object_page_header(File, Options) --> 1078 { option(header(true), Options, true) }, 1079 !, 1080 html(div(class(navhdr), 1081 [ div(class(jump), \file_link(File)), 1082 div(class(search), \search_form(Options)), 1083 br(clear(right)) 1084 ])). 1085object_page_header(_, _) --> []. 1086 1087file_link(-) --> 1088 !, 1089 places_menu(-). 1090file_link(File) --> 1091 { file_directory_name(File, Dir) 1092 }, 1093 places_menu(Dir), 1094 html([ div(a(href(location_by_id(pldoc_doc)+File), File)) 1095 ]).
1105object_footer(Obj, Options) -->
1106 object_changelog(Obj, Options),
1107 ( prolog:doc_object_footer(Obj, Options)
1108 -> []
1109 ; []
1110 ).f(...)) was introduced
and when it was last changed. Empty when no events are known or
when the changelog support was not built (CHANGELOG cmake option
off). Each version is rendered as Maj.Min.Patch and linked to
the underlying commit on GitHub.1121:- if(exists_source(library(pldoc/doc_changes))). 1122:- use_module(library(pldoc/doc_changes), 1123 [doc_introduced/3, doc_last_changed/4]). 1124 1125object_changelog(Objs, Options) --> 1126 { is_list(Objs), !, 1127 objs_pis(Objs, PIs) 1128 }, 1129 object_changelog_pis(PIs, Options). 1130object_changelog(Obj, Options) --> 1131 { objs_pis([Obj], PIs) 1132 }, 1133 object_changelog_pis(PIs, Options). 1134 1135object_changelog_pis(PIs, _Options) --> 1136 { changelog_union(PIs, Events), 1137 Events \== [] 1138 }, 1139 !, 1140 html(div(class('pldoc-changes'), 1141 [ div(class('pldoc-changes-header'), "History"), 1142 ul(\changelog_events(Events)), 1143 div(class('pldoc-changes-footer'), 1144 "Disclaimer: heuristically mined from GIT") 1145 ])). 1146object_changelog_pis(_, _) --> [].
// events separately). Other object
shapes (xpce(...), c(...), f(...), library(...), section(...)) are
dropped so the footer is suppressed for them.1157objs_pis(Objs, PIs) :- 1158 convlist(obj_pi, Objs, PIs). 1159 1160obj_pi(_:O, PI) :- !, obj_pi(O, PI). 1161obj_pi(Name/Arity, Name/Arity) :- atom(Name), integer(Arity). 1162obj_pi(Name//Arity, Name/PArity) :- 1163 atom(Name), integer(Arity), 1164 PArity is Arity + 2. 1165 1166changelog_events(Events) --> 1167 sequence(changelog_event, Events). 1168 1169changelog_event(Event) --> 1170 html(li(\changelog_event_(Event))). 1171 1172changelog_event_(event(Type, Version, Hash, Subject, Repo)) --> 1173 { clean_subject(Subject, Subject1) 1174 }, 1175 html([ \event_type(Type), " in ", 1176 \version_commit_link(Version, Hash, Repo), 1177 " ", em(Subject1) 1178 ]). 1179 1180clean_subject(Subject0, Subject) :- 1181 string_codes(Subject0, Codes), 1182 phrase((tag, string(Msg)), Codes), 1183 !, 1184 string_codes(Subject, Msg). 1185clean_subject(Subject, Subject). 1186 1187tag --> 1188 capitals, ":", whites. 1189 1190capitals --> 1191 [C], { between(0'A, 0'Z, C) }, !, 1192 capitals. 1193capitals --> 1194 []. 1195 1196event_type(introduced) ==> html(b(title("The predicate was added"), 1197 "Introduced")). 1198event_type(added) ==> html(b(title("New functinality was added"), 1199 "Extended")). 1200event_type(enhanced) ==> html(b(title("Implementation has been improved"), 1201 "Enhanced")). 1202event_type(fixed) ==> html(b(title("A bug was fixed"), 1203 "Fixed")). 1204event_type(modified) ==> html(b(title("The modification may break compatibility"), 1205 "Modified")). 1206event_type(Id) ==> html(b(title("Unknow tag"), 1207 Id)).
1217changelog_union(PIs, [Event]) :- 1218 all_introduced(PIs, Event). 1219changelog_union(PIs, Events) :- 1220 union_last_changed(PIs, Events).
1230all_introduced(PIs, Event) :- 1231 maplist(any_introduction, PIs, Events), 1232 E0 = event(introduced, V0, _, _, _), 1233 aggregate_all(max(V0, E0), 1234 member(E0, Events), 1235 max(_, Event)). 1236 1237any_introduction(PI, Event) :- 1238 doc_introduced(PI, _, Event), !.
1245union_last_changed(PIs, Events) :- 1246 Ev = event(T0, V0, _H0, _S0, _R0), 1247 findall(Ev, 1248 ( member(PI, PIs), 1249 doc_last_changed(PI, V0, T0, Ev) 1250 ), 1251 Events0), 1252 sort(2, >=, Events0, Events). 1253 1254version_commit_link(V, Hash, Repo) --> 1255 { version_string(V, VStr), 1256 short_hash(Hash, Short), 1257 commit_url(Repo, Hash, URL) 1258 }, 1259 html([ b(VStr), ' (👉', 1260 a([href(URL), target('_blank')], Short), 1261 ')' 1262 ]). 1263 1264version_string(N, VStr) :- 1265 Major is N // 10000, 1266 Minor is (N // 100) mod 100, 1267 Patch is N mod 100, 1268 format(string(VStr), "~d.~d.~d", [Major, Minor, Patch]). 1269 1270short_hash(Hash, Short) :- 1271 string(Hash), 1272 !, 1273 sub_string(Hash, 0, 7, _, Short). 1274short_hash(Hash, Short) :- 1275 sub_atom(Hash, 0, 7, _, Short), 1276 !. 1277short_hash(Hash, Hash). 1278 1279commit_url(Repo, Hash, URL) :- 1280 atom(Repo), Repo \== unknown, 1281 !, 1282 format(atom(URL), "https://github.com/~w/commit/~w", [Repo, Hash]). 1283commit_url(_, Hash, URL) :- 1284 format(atom(URL), "#~w", [Hash]). 1285:- else. % library(pldoc/doc_changes) is missing 1286object_changelog(_, _) --> []. 1287:- endif.
1295object_page_footer(Obj, Options) --> 1296 prolog:doc_object_page_footer(Obj, Options), 1297 !. 1298object_page_footer(_, _) --> [].
1312object_synopsis(Name/Arity, _) --> 1313 { functor(Head, Name, Arity), 1314 predicate_property(system:Head, built_in) 1315 }, 1316 synopsis([span(class(builtin), 'built-in')]). 1317object_synopsis(Name/Arity, Options) --> 1318 !, 1319 object_synopsis(_:Name/Arity, Options). 1320object_synopsis(M:Name/Arity, Options) --> 1321 { functor(Head, Name, Arity), 1322 ( option(source(Spec), Options) 1323 -> absolute_file_name(Spec, File, 1324 [ access(read), 1325 file_type(prolog), 1326 file_errors(fail) 1327 ]) 1328 ; predicate_property(M:Head, exported), 1329 \+ predicate_property(M:Head, imported_from(_)), 1330 module_property(M, file(File)), 1331 file_name_on_path(File, Spec) 1332 ), 1333 !, 1334 unquote_filespec(Spec, Unquoted0), 1335 ( prolog:pldoc_synopsis_spec(Unquoted0, Unquoted) 1336 -> true 1337 ; Unquoted = Unquoted0 1338 ) 1339 }, 1340 use_module_synopsis(Head, File, Unquoted, Options). 1341object_synopsis(Name//Arity, Options) --> 1342 !, 1343 { DCGArity is Arity+2 }, 1344 object_synopsis(Name/DCGArity, Options). 1345object_synopsis(Module:Name//Arity, Options) --> 1346 !, 1347 { DCGArity is Arity+2 }, 1348 object_synopsis(Module:Name/DCGArity, Options). 1349object_synopsis(f(_/_), _) --> 1350 synopsis(span(class(function), 1351 [ 'Arithmetic function (see ', 1352 \object_ref(is/2, []), 1353 ')' 1354 ])). 1355object_synopsis(c(Func), _) --> 1356 { sub_atom(Func, 0, _, _, 'PL_') 1357 ; sub_atom(Func, 0, _, _, 'S') 1358 }, 1359 !, 1360 synopsis([span(class(cfunc), 'C-language interface function')]). 1361object_synopsis(_, _) --> []. 1362 1363:- html_meta(synopsis(html,?,?)). 1364 1365use_module_synopsis(Head, File, Unquoted, Options) --> 1366 { Args = [class(copy), title('Click to copy')] }, 1367 ( { option(href(HREF), Options) } 1368 -> synopsis([ code(Args, [':- use_module(',a(href(HREF), '~q'-[Unquoted]),').']) 1369 | \can_autoload(Head, File) 1370 ]) 1371 ; synopsis([ code(Args, ':- use_module(~q).'-[Unquoted]) 1372 | \can_autoload(Head, File) 1373 ]) 1374 ). 1375 1376synopsis(HTML) --> 1377 html(div(class(synopsis), 1378 [ span(class('synopsis-hdr'), 'Availability:') 1379 | HTML 1380 ])). 1381 1382can_autoload(Head, File) --> 1383 { predicate_property(Head, autoload(FileBase)), 1384 file_name_extension(FileBase, _Ext, File) 1385 }, 1386 !, 1387 html(span(class(autoload), \can_be_autoloaded)). 1388can_autoload(_, _) --> 1389 []. 1390 1391can_be_autoloaded --> 1392 { catch(http_link_to_id(pldoc_man, [section(autoload)], HREF), 1393 error(_,_), fail) 1394 }, 1395 html(['(can be ', a(href(HREF), autoloaded), ')']). 1396can_be_autoloaded --> 1397 html('(can be autoloaded)').
1405unquote_filespec(Spec, Unquoted) :- 1406 compound(Spec), 1407 Spec =.. [Alias,Path], 1408 atom(Path), 1409 atomic_list_concat(Parts, /, Path), 1410 maplist(need_no_quotes, Parts), 1411 !, 1412 parts_to_path(Parts, UnquotedPath), 1413 Unquoted =.. [Alias, UnquotedPath]. 1414unquote_filespec(Spec, Spec). 1415 1416need_no_quotes(Atom) :- 1417 format(atom(A), '~q', [Atom]), 1418 \+ sub_atom(A, 0, _, _, '\''). 1419 1420parts_to_path([One], One) :- !. 1421parts_to_path(List, More/T) :- 1422 ( append(H, [T], List) 1423 -> parts_to_path(H, More) 1424 ). 1425 1426 1427 /******************************* 1428 * PRINT * 1429 *******************************/
1435doc_write_html(Out, Title, Doc) :-
1436 doc_page_dom(Title, Doc, DOM),
1437 phrase(html(DOM), Tokens),
1438 print_html_head(Out),
1439 print_html(Out, Tokens).
1446doc_page_dom(Title, Body, DOM) :-
1447 DOM = html([ head([ title(Title),
1448 link([ rel(stylesheet),
1449 type('text/css'),
1450 href(location_by_id(pldoc_resource)+'pldoc.css')
1451 ]),
1452 script([ src(location_by_id(pldoc_resource)+'pldoc.js'),
1453 type('text/javascript')
1454 ], [])
1455 ]),
1456 body(Body)
1457 ]).DOCTYPE line.1463print_html_head(Out) :- 1464 format(Out, 1465 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" \c 1466 "http://www.w3.org/TR/html4/strict.dtd">~n', []). 1467 1468% Rendering rules 1469% 1470% These rules translate \-terms produced by wiki.pl
1478tags(Tags) -->
1479 html(dl(class=tags, Tags)).tag(Name, Values) terms produced by doc_wiki.pl.1485tag(Tag, Values) --> 1486 { doc_tag_title(Tag, Title), 1487 atom_concat('keyword-', Tag, Class) 1488 }, 1489 html([ dt(class=Class, Title), 1490 \tag_values(Values, Class) 1491 ]). 1492 1493tag_values([], _) --> 1494 []. 1495tag_values([H|T], Class) --> 1496 html(dd(class=Class, ['- '|H])), 1497 tag_values(T, Class).
1504doc_tag_title(Tag, Title) :- 1505 tag_title(Tag, Title), 1506 !. 1507doc_tag_title(Tag, Tag). 1508 1509tag_title(compat, 'Compatibility'). 1510tag_title(tbd, 'To be done'). 1511tag_title(see, 'See also'). 1512tag_title(error, 'Errors'). 1513tag_title(since, 'Since').
args(List) created by doc_wiki.pl. Params is a
list of arg(Name, Descr).1520args(Params) --> 1521 html([ dt(class=tag, 'Arguments:'), 1522 dd(table(class=arglist, 1523 \arg_list(Params))) 1524 ]). 1525 1526arg_list([]) --> 1527 []. 1528arg_list([H|T]) --> 1529 argument(H), 1530 arg_list(T). 1531 1532argument(arg(Name,Descr)) --> 1533 html(tr([td(var(Name)), td(class=argdescr, ['- '|Descr])])). 1534 1535 1536 /******************************* 1537 * NAVIGATION TREE * 1538 *******************************/
node(Object, Children).1545objects_nav_tree(Objects, Tree) :- 1546 maplist(object_nav_tree, Objects, Trees), 1547 union_trees(Trees, Tree0), 1548 remove_unique_root(Tree0, Tree). 1549 (Obj, Tree) :- 1551 Node = node(directory(Dir), FileNodes), 1552 FileNode = node(file(File), Siblings), 1553 doc_comment(Obj, File:_Line, _Summary, _Comment), 1554 !, 1555 file_directory_name(File, Dir), 1556 sibling_file_nodes(Dir, FileNodes0), 1557 selectchk(node(file(File),[]), FileNodes0, FileNode, FileNodes), 1558 findall(Sibling, doc_comment(Sibling, File:_, _, _), Siblings0), 1559 delete(Siblings0, _:module(_), Siblings1), 1560 doc_hide_private(Siblings1, Siblings2, []), 1561 flatten(Siblings2, Siblings), % a comment may describe objects 1562 embed_directories(Node, Tree). 1563 1564sibling_file_nodes(Dir, Nodes) :- 1565 findall(node(file(File), []), 1566 ( source_file(File), 1567 file_directory_name(File, Dir) 1568 ), 1569 Nodes). 1570 1571embed_directories(Node, Tree) :- 1572 Node = node(file(File), _), 1573 !, 1574 file_directory_name(File, Dir), 1575 Super = node(directory(Dir), [Node]), 1576 embed_directories(Super, Tree). 1577embed_directories(Node, Tree) :- 1578 Node = node(directory(Dir), _), 1579 file_directory_name(Dir, SuperDir), 1580 SuperDir \== Dir, 1581 !, 1582 Super = node(directory(SuperDir), [Node]), 1583 embed_directories(Super, Tree). 1584embed_directories(Tree, Tree). 1585 1586 1587union_trees([Tree], Tree) :- !. 1588union_trees([T1,T2|Trees], Tree) :- 1589 merge_trees(T1, T2, M1), 1590 union_trees([M1|Trees], Tree). 1591 1592merge_trees(node(R, Ch1), node(R, Ch2), node(R, Ch)) :- 1593 merge_nodes(Ch1, Ch2, Ch). 1594 1595merge_nodes([], Ch, Ch) :- !. 1596merge_nodes(Ch, [], Ch) :- !. 1597merge_nodes([node(Root, Ch1)|T1], N1, [T1|Nodes]) :- 1598 selectchk(node(Root, Ch2), N1, N2), 1599 !, 1600 merge_trees(node(Root, Ch1), node(Root, Ch2), T1), 1601 merge_nodes(T1, N2, Nodes). 1602merge_nodes([Node|T1], N1, [Node|Nodes]) :- 1603 merge_nodes(T1, N1, Nodes).
1609remove_unique_root(node(_, [node(R1, [R2])]), Tree) :- 1610 !, 1611 remove_unique_root(node(R1, [R2]), Tree). 1612remove_unique_root(Tree, Tree).
1618nav_tree(Tree, Current, Options) -->
1619 html(ul(class(nav),
1620 \object_tree(Tree, Current, Options))).1626object_tree(node(Id, []), Target, Options) --> 1627 !, 1628 { node_class(Id, Target, Class) }, 1629 html(li(class(Class), 1630 \node(Id, Options))). 1631object_tree(node(Id, Children), Target, Options) --> 1632 !, 1633 { node_class(Id, Target, Class) }, 1634 html(li(class(Class), 1635 [ \node(Id, Options), 1636 ul(class(nav), 1637 \object_trees(Children, Target, Options)) 1638 ])). 1639object_tree(Id, Target, Options) --> 1640 !, 1641 { node_class(Id, Target, Class) }, 1642 html(li(class([obj|Class]), \node(Id, Options))). 1643 1644object_trees([], _, _) --> []. 1645object_trees([H|T], Target, Options) --> 1646 object_tree(H, Target, Options), 1647 object_trees(T, Target, Options). 1648 1649node_class(Ids, Current, Class) :- 1650 is_list(Ids), 1651 !, 1652 ( member(Id, Ids), memberchk(Id, Current) 1653 -> Class = [nav,current] 1654 ; Class = [nav] 1655 ). 1656node_class(Id, Current, Class) :- 1657 ( memberchk(Id, Current) 1658 -> Class = [nav,current] 1659 ; Class = [nav] 1660 ). 1661 1662node(file(File), Options) --> 1663 !, 1664 object_ref(file(File), [style(title)|Options]). 1665node(Id, Options) --> 1666 object_ref(Id, Options). 1667 1668 1669 /******************************* 1670 * SECTIONS * 1671 *******************************/ 1672 1673section(Type, Title) --> 1674 { string_codes(Title, Codes), 1675 wiki_codes_to_dom(Codes, [], Content0), 1676 strip_leading_par(Content0, Content), 1677 make_section(Type, Content, HTML) 1678 }, 1679 html(HTML). 1680 1681make_section(module, Title, h1(class=module, Title)). 1682make_section(section, Title, h1(class=section, Title)). 1683 1684 1685 /******************************* 1686 * PRED MODE HEADER * 1687 *******************************/
1695pred_dt(Modes, Class, Options) --> 1696 pred_dt(Modes, Class, [], _Done, Options). 1697 1698pred_dt([], _, Done, Done, _) --> 1699 []. 1700pred_dt([H|T], Class, Done0, Done, Options) --> 1701 { functor(Class, CSSClass, _) }, 1702 html(dt(class=CSSClass, 1703 [ \pred_mode(H, Done0, Done1, Options), 1704 \mode_anot(Class) 1705 ])), 1706 pred_dt(T, Class, Done1, Done, Options). 1707 1708mode_anot(privdef) --> 1709 !, 1710 html(span([class(anot), style('float:right')], 1711 '[private]')). 1712mode_anot(multidef(object(Obj))) --> 1713 !, 1714 { object_href(Obj, HREF) }, 1715 html(span([class(anot), style('float:right')], 1716 ['[', a(href(HREF), multifile), ']' 1717 ])). 1718mode_anot(multidef(file(File:_))) --> 1719 !, 1720 { file_name_on_path(File, Spec), 1721 unquote_filespec(Spec, Unquoted), 1722 doc_file_href(File, HREF) 1723 }, 1724 html(span([class(anot), style('float:right')], 1725 ['[multifile, ', a(href(HREF), '~q'-[Unquoted]), ']' 1726 ])). 1727mode_anot(multidef) --> 1728 !, 1729 html(span([class(anot), style('float:right')], 1730 '[multifile]')). 1731mode_anot(_) --> 1732 []. 1733 1734pred_mode(mode(Head,Vars), Done0, Done, Options) --> 1735 !, 1736 { bind_vars(Head, Vars) }, 1737 pred_mode(Head, Done0, Done, Options). 1738pred_mode(Head is Det, Done0, Done, Options) --> 1739 !, 1740 anchored_pred_head(Head, Done0, Done, Options), 1741 pred_det(Det). 1742pred_mode(Head, Done0, Done, Options) --> 1743 anchored_pred_head(Head, Done0, Done, Options). 1744 1745bind_vars(Term, Bindings) :- 1746 bind_vars(Bindings), 1747 anon_vars(Term). 1748 1749bind_vars([]). 1750bind_vars([Name=Var|T]) :- 1751 Var = '$VAR'(Name), 1752 bind_vars(T).
1759anon_vars(Var) :- 1760 var(Var), 1761 !, 1762 Var = '$VAR'('_'). 1763anon_vars(Term) :- 1764 compound(Term), 1765 !, 1766 Term =.. [_|Args], 1767 maplist(anon_vars, Args). 1768anon_vars(_). 1769 1770 1771anchored_pred_head(Head, Done0, Done, Options) --> 1772 { pred_anchor_name(Head, PI, Name) }, 1773 ( { memberchk(PI, Done0) } 1774 -> { Done = Done0 }, 1775 pred_head(Head) 1776 ; html([ span(style('float:right'), 1777 [ \pred_edit_or_source_button(Head, Options), 1778 &(nbsp) 1779 ]), 1780 a(name=Name, \pred_head(Head)) 1781 ]), 1782 { Done = [PI|Done0] } 1783 ). 1784 1785 (Head, Options) --> 1787 { option(edit(true), Options) }, 1788 !, 1789 pred_edit_button(Head, Options). 1790pred_edit_or_source_button(Head, Options) --> 1791 { option(source_link(true), Options) }, 1792 !, 1793 pred_source_button(Head, Options). 1794pred_edit_or_source_button(_, _) --> [].
1808pred_edit_button(_, Options) --> 1809 { \+ option(edit(true), Options) }, 1810 !. 1811pred_edit_button(PI0, Options0) --> 1812 { canonicalise_predref(PI0, PI, Options0, Options) }, 1813 pred_edit_button2(PI, Options). 1814 (Name/Arity, Options) --> 1816 { \+ ( memberchk(file(_), Options), % always edit if file and line 1817 memberchk(line(_), Options) % are given. 1818 ), 1819 functor(Head, Name, Arity), 1820 option(module(M), Options, _), 1821 \+ ( current_module(M), 1822 source_file(M:Head, _File) 1823 ) 1824 }, 1825 !. 1826pred_edit_button2(Name/Arity, Options) --> 1827 { include(edit_param, Options, Extra), 1828 http_link_to_id(pldoc_edit, 1829 [name(Name),arity(Arity)|Extra], 1830 EditHREF) 1831 }, 1832 html(a(onClick('HTTPrequest(\'' + EditHREF + '\')'), 1833 img([ class(action), 1834 alt('Edit predicate'), 1835 title('Edit predicate'), 1836 src(location_by_id(pldoc_resource)+'editpred.png') 1837 ]))). 1838pred_edit_button2(_, _) --> 1839 !, 1840 []. 1841 1842edit_param(module(_)). 1843edit_param(file(_)). 1844edit_param(line(_)).
1851object_edit_button(_, Options) --> 1852 { \+ option(edit(true), Options) }, 1853 !. 1854object_edit_button(PI, Options) --> 1855 { is_pi(PI) }, 1856 !, 1857 pred_edit_button(PI, Options). 1858object_edit_button(_, _) --> 1859 [].
1866pred_source_button(PI0, Options0) --> 1867 { canonicalise_predref(PI0, PI, Options0, Options), 1868 option(module(M), Options, _), 1869 pred_source_href(PI, M, HREF), ! 1870 }, 1871 html(a([ href(HREF), 1872 class(source) 1873 ], 1874 img([ class(action), 1875 alt('Source'), 1876 title('Show source'), 1877 src(location_by_id(pldoc_resource)+'source.png') 1878 ]))). 1879pred_source_button(_, _) --> 1880 [].
1887object_source_button(PI, Options) --> 1888 { is_pi(PI), 1889 option(source_link(true), Options, true) 1890 }, 1891 !, 1892 pred_source_button(PI, Options). 1893object_source_button(_, _) --> 1894 [].
module(M) to Options.1902canonicalise_predref(M:PI0, PI, Options0, [module(M)|Options]) :- 1903 !, 1904 canonicalise_predref(PI0, PI, Options0, Options). 1905canonicalise_predref(//(Head), PI, Options0, Options) :- 1906 !, 1907 functor(Head, Name, Arity), 1908 PredArity is Arity + 2, 1909 canonicalise_predref(Name/PredArity, PI, Options0, Options). 1910canonicalise_predref(Name//Arity, PI, Options0, Options) :- 1911 integer(Arity), Arity >= 0, 1912 !, 1913 PredArity is Arity + 2, 1914 canonicalise_predref(Name/PredArity, PI, Options0, Options). 1915canonicalise_predref(PI, PI, Options, Options) :- 1916 PI = Name/Arity, 1917 atom(Name), integer(Arity), Arity >= 0, 1918 !. 1919canonicalise_predref(Head, PI, Options0, Options) :- 1920 functor(Head, Name, Arity), 1921 canonicalise_predref(Name/Arity, PI, Options0, Options).
span using
class pred and the arguments and var using class arglist.1929pred_head(Var) --> 1930 { var(Var), 1931 !, 1932 instantiation_error(Var) 1933 }. 1934pred_head(//(Head)) --> 1935 !, 1936 pred_head(Head), 1937 html(//). 1938pred_head(M:Head) --> 1939 html([span(class=module, M), :]), 1940 pred_head(Head). 1941pred_head(Head) --> 1942 { atom(Head) }, 1943 !, 1944 html(b(class=pred, Head)). 1945pred_head(Head) --> % Infix operators 1946 { Head =.. [Functor,Left,Right], 1947 is_op_type(Functor, infix) 1948 }, 1949 !, 1950 html([ var(class=arglist, \pred_arg(Left, 1)), 1951 ' ', b(class=pred, Functor), ' ', 1952 var(class=arglist, \pred_arg(Right, 2)) 1953 ]). 1954pred_head(Head) --> % Prefix operators 1955 { Head =.. [Functor,Arg], 1956 is_op_type(Functor, prefix) 1957 }, 1958 !, 1959 html([ b(class=pred, Functor), ' ', 1960 var(class=arglist, \pred_arg(Arg, 1)) 1961 ]). 1962pred_head(Head) --> % Postfix operators 1963 { Head =.. [Functor,Arg], 1964 is_op_type(Functor, postfix) 1965 }, 1966 !, 1967 html([ var(class=arglist, \pred_arg(Arg, 1)), 1968 ' ', b(class=pred, Functor) 1969 ]). 1970pred_head({Head}) --> 1971 !, 1972 html([ b(class=pred, '{'), 1973 var(class=arglist, 1974 \pred_args([Head], 1)), 1975 b(class=pred, '}') 1976 ]). 1977pred_head(Head) --> % Plain terms 1978 { Head =.. [Functor|Args] }, 1979 html([ b(class=pred, Functor), 1980 var(class=arglist, 1981 [ '(', \pred_args(Args, 1), ')' ]) 1982 ]).
prefix,
infix or postfix.1989is_op_type(Functor, Type) :- 1990 current_op(_Pri, F, Functor), 1991 op_type(F, Type). 1992 1993op_type(fx, prefix). 1994op_type(fy, prefix). 1995op_type(xf, postfix). 1996op_type(yf, postfix). 1997op_type(xfx, infix). 1998op_type(xfy, infix). 1999op_type(yfx, infix). 2000op_type(yfy, infix). 2001 2002 2003pred_args([], _) --> 2004 []. 2005pred_args([H|T], I) --> 2006 pred_arg(H, I), 2007 ( {T==[]} 2008 -> [] 2009 ; html(', '), 2010 { I2 is I + 1 }, 2011 pred_args(T, I2) 2012 ). 2013 2014pred_arg(Var, I) --> 2015 { var(Var) }, 2016 !, 2017 html(['Arg', I]). 2018pred_arg(...(Term), I) --> 2019 !, 2020 pred_arg(Term, I), 2021 html('...'). 2022pred_arg(Term, I) --> 2023 { Term =.. [Ind,Arg], 2024 mode_indicator(Ind) 2025 }, 2026 !, 2027 html([Ind, \pred_arg(Arg, I)]). 2028pred_arg(Arg:Type, _) --> 2029 !, 2030 html([\argname(Arg), :, \argtype(Type)]). 2031pred_arg(Arg, _) --> 2032 argname(Arg). 2033 2034argname('$VAR'(Name)) --> 2035 !, 2036 html(Name). 2037argname(Name) --> 2038 !, 2039 html(Name). 2040 2041argtype(Term) --> 2042 { format(string(S), '~W', 2043 [ Term, 2044 [ quoted(true), 2045 numbervars(true) 2046 ] 2047 ]) }, 2048 html(S). 2049 2050pred_det(unknown) --> 2051 []. 2052pred_det(Det) --> 2053 html([' is ', b(class=det, Det)]).
doc_wiki.pl.
2062term(_, Atom, []) --> 2063 { atomic(Atom), 2064 !, 2065 format(string(S), '~W', [Atom,[quoted(true)]]) 2066 }, 2067 html(span(class=functor, S)). 2068term(_, Key:Type, [TypeName=Type]) --> 2069 { atomic(Key) 2070 }, 2071 !, 2072 html([span(class='pl-key', Key), :, span(class('pl-var'), TypeName)]). 2073term(_, Term, Bindings) --> 2074 { is_mode(Term is det), % HACK. Bit too strict? 2075 bind_vars(Bindings) 2076 }, 2077 !, 2078 pred_head(Term). 2079term(_, Term, Bindings) --> 2080 term(Term, 2081 [ variable_names(Bindings), 2082 quoued(true) 2083 ]). 2084 2085 2086 /******************************* 2087 * PREDREF * 2088 *******************************/
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.
2101predref(Term) --> 2102 { catch(nb_getval(pldoc_options, Options), _, Options = []) }, 2103 predref(Term, Options). 2104 2105predref(Obj, Options) --> 2106 { Obj = _:_, 2107 doc_comment(Obj, File:_Line, _, _), 2108 ( ( option(files(Map), Options) 2109 -> memberchk(file(File,_), Map) 2110 ; true 2111 ) 2112 -> object_href(Obj, HREF, Options) 2113 ; manref(Obj, HREF, Options) 2114 ) 2115 }, 2116 !, 2117 html(a(href(HREF), \object_name(Obj, [qualify(true)|Options]))). 2118predref(M:Term, Options) --> 2119 !, 2120 predref(Term, M, Options). 2121predref(Term, Options) --> 2122 predref(Term, _, Options). 2123 2124predref(Name/Arity, _, Options) --> % Builtin; cannot be overruled 2125 { prolog:doc_object_summary(Name/Arity, manual, _, _), 2126 !, 2127 manref(Name/Arity, HREF, Options) 2128 }, 2129 html(a([class=builtin, href=HREF], [Name, /, Arity])). 2130predref(Name/Arity, _, Options) --> % From packages 2131 { option(prefer(manual), Options), 2132 prolog:doc_object_summary(Name/Arity, Category, _, _), 2133 !, 2134 manref(Name/Arity, HREF, Options) 2135 }, 2136 html(a([class=Category, href=HREF], [Name, /, Arity])). 2137predref(Obj, Module, Options) --> % Local 2138 { doc_comment(Module:Obj, File:_Line, _, _), 2139 ( option(files(Map), Options) 2140 -> memberchk(file(File,_), Map) 2141 ; true 2142 ) 2143 }, 2144 !, 2145 object_ref(Module:Obj, Options). 2146predref(Name/Arity, Module, Options) --> 2147 { \+ option(files(_), Options), 2148 pred_href(Name/Arity, Module, HREF) 2149 }, 2150 !, 2151 html(a(href=HREF, [Name, /, Arity])). 2152predref(Name//Arity, Module, Options) --> 2153 { \+ option(files(_), Options), 2154 PredArity is Arity + 2, 2155 pred_href(Name/PredArity, Module, HREF) 2156 }, 2157 !, 2158 html(a(href=HREF, [Name, //, Arity])). 2159predref(PI, _, Options) --> % From packages 2160 { canonical_pi(PI, CPI, HTML), 2161 ( option(files(_), Options) 2162 -> Category = extmanual 2163 ; prolog:doc_object_summary(CPI, Category, _, _) 2164 ), 2165 manref(CPI, HREF, Options) 2166 }, 2167 html(a([class=Category, href=HREF], HTML)). 2168predref(PI, _, _Options) --> 2169 { canonical_pi(PI, _CPI, HTML) 2170 }, 2171 !, 2172 html(span(class=undef, HTML)). 2173predref(Callable, Module, Options) --> 2174 { callable(Callable), 2175 functor(Callable, Name, Arity) 2176 }, 2177 predref(Name/Arity, Module, Options). 2178 2179canonical_pi(Name/Arity, Name/Arity, [Name, /, Arity]) :- 2180 atom(Name), integer(Arity), 2181 !. 2182canonical_pi(Name//Arity, Name/Arity2, [Name, //, Arity]) :- 2183 atom(Name), integer(Arity), 2184 !, 2185 Arity2 is Arity+2.
name/arity, non-linking predicate indicator.
2191nopredref(PI) -->
2192 { canonical_pi(PI, _CPI, HTML)
2193 },
2194 !,
2195 html(span(class=nopredref, HTML)).
2203flagref(Flag) -->
2204 html(code(Flag)).2211cite(Citations) --> 2212 html('['), citations(Citations), html(']'). 2213 2214citations([]) --> []. 2215citations([H|T]) --> 2216 citation(H), 2217 ( {T==[]} 2218 -> [] 2219 ; [';'], 2220 citations(T) 2221 ). 2222 2223citation(H) --> 2224 html([@,H]).
man_server(+Server).2232manref(PI, HREF, Options) :- 2233 predname(PI, PredName), 2234 ( option(files(_Map), Options) 2235 -> option(man_server(Server), Options, 2236 'http://www.swi-prolog.org/pldoc'), 2237 uri_components(Server, Comp0), 2238 uri_data(path, Comp0, Path0), 2239 directory_file_path(Path0, man, Path), 2240 uri_data(path, Comp0, Path, Components), 2241 uri_query_components(Query, [predicate=PredName]), 2242 uri_data(search, Components, Query), 2243 uri_components(HREF, Components) 2244 ; http_link_to_id(pldoc_man, [predicate=PredName], HREF) 2245 ). 2246 2247predname(Name/Arity, PredName) :- 2248 !, 2249 format(atom(PredName), '~w/~d', [Name, Arity]). 2250predname(Module:Name/Arity, PredName) :- 2251 !, 2252 format(atom(PredName), '~w:~w/~d', [Module, Name, Arity]).
2266pred_href(Name/Arity, Module, HREF) :- 2267 format(string(FragmentId), '~w/~d', [Name, Arity]), 2268 uri_data(fragment, Components, FragmentId), 2269 functor(Head, Name, Arity), 2270 ( catch(relative_file(Module:Head, File), _, fail) 2271 -> uri_data(path, Components, File), 2272 uri_components(HREF, Components) 2273 ; in_file(Module:Head, File) 2274 -> ( current_prolog_flag(home, SWI), 2275 sub_atom(File, 0, _, _, SWI), 2276 prolog:doc_object_summary(Name/Arity, packages, _, _) 2277 -> http_link_to_id(pldoc_man, [predicate=FragmentId], HREF) 2278 ; http_location_by_id(pldoc_doc, DocHandler), 2279 atom_concat(DocHandler, File, Path), 2280 uri_data(path, Components, Path), 2281 uri_components(HREF, Components) 2282 ) 2283 ). 2284 2285relative_file(Head, '') :- 2286 b_getval(pldoc_file, CurrentFile), CurrentFile \== [], 2287 in_file(Head, CurrentFile), 2288 !. 2289relative_file(Head, RelFile) :- 2290 b_getval(pldoc_file, CurrentFile), CurrentFile \== [], 2291 in_file(Head, DefFile), 2292 relative_file_name(DefFile, CurrentFile, RelFile).
2298pred_source_href(Name/Arity, Module, HREF) :-
2299 format(string(FragmentId), '~w/~d', [Name, Arity]),
2300 uri_data(fragment, Components, FragmentId),
2301 uri_query_components(Query, [show=src]),
2302 uri_data(search, Components, Query),
2303 functor(Head, Name, Arity),
2304 ( catch(relative_file(Module:Head, File), _, fail)
2305 -> uri_data(path, Components, File),
2306 uri_components(HREF, Components)
2307 ; in_file(Module:Head, File0)
2308 -> insert_alias(File0, File),
2309 http_location_by_id(pldoc_doc, DocHandler),
2310 atom_concat(DocHandler, File, Path),
2311 uri_data(path, Components, Path),
2312 uri_components(HREF, Components)
2313 ).2322object_ref([], _) --> 2323 !, 2324 []. 2325object_ref([H|T], Options) --> 2326 !, 2327 object_ref(H, Options), 2328 ( {T == []} 2329 -> html(', '), 2330 object_ref(T, Options) 2331 ; [] 2332 ). 2333object_ref(Obj, Options) --> 2334 { object_href(Obj, HREF, Options) 2335 }, 2336 html(a(href(HREF), \object_name(Obj, Options))).
2343object_href(Obj, HREF) :- 2344 object_href(Obj, HREF, []). 2345 2346object_href(M:PI0, HREF, Options) :- 2347 option(files(Map), Options), 2348 ( module_property(M, file(File)) 2349 -> true 2350 ; xref_module(File, M) 2351 ), 2352 memberchk(file(File, DocFile), Map), 2353 !, 2354 file_base_name(DocFile, LocalFile), % TBD: proper directory index 2355 expand_pi(PI0, PI), 2356 term_to_string(PI, PIS), 2357 uri_data(path, Components, LocalFile), 2358 uri_data(fragment, Components, PIS), 2359 uri_components(HREF, Components). 2360object_href(file(File), HREF, _Options) :- 2361 doc_file_href(File, HREF), 2362 !. 2363object_href(directory(Dir), HREF, _Options) :- 2364 directory_file_path(Dir, 'index.html', Index), 2365 doc_file_href(Index, HREF), 2366 !. 2367object_href(Obj, HREF, _Options) :- 2368 prolog:doc_object_href(Obj, HREF), 2369 !. 2370object_href(Obj0, HREF, _Options) :- 2371 localise_object(Obj0, Obj), 2372 term_to_string(Obj, String), 2373 http_link_to_id(pldoc_object, [object=String], HREF). 2374 2375expand_pi(Name//Arity0, Name/Arity) :- 2376 !, 2377 Arity is Arity0+2. 2378expand_pi(PI, PI).
2386localise_object(Obj0, Obj) :- 2387 prolog:doc_canonical_object(Obj0, Obj), 2388 !. 2389localise_object(Obj, Obj).
2397term_to_string(Term, String) :-
2398 State = state(-),
2399 ( numbervars(Term, 0, _, [singletons(true)]),
2400 with_output_to(string(String),
2401 write_term(Term,
2402 [ numbervars(true),
2403 quoted(true)
2404 ])),
2405 nb_setarg(1, State, String),
2406 fail
2407 ; arg(1, State, String)
2408 ).inline or titlenumber, title or number_title2422object_name(Obj, Options) --> 2423 { option(style(Style), Options, inline) 2424 }, 2425 object_name(Style, Obj, Options). 2426 2427object_name(title, Obj, Options) --> 2428 { merge_options(Options, [secref_style(title)], Options1) }, 2429 prolog:doc_object_link(Obj, Options1), 2430 !. 2431object_name(inline, Obj, Options) --> 2432 prolog:doc_object_link(Obj, Options), 2433 !. 2434object_name(title, f(Name/Arity), _Options) --> 2435 !, 2436 html(['Function ', Name, /, Arity]). 2437object_name(inline, f(Name/Arity), _Options) --> 2438 !, 2439 html([Name, /, Arity]). 2440object_name(Style, PI, Options) --> 2441 { is_pi(PI) }, 2442 !, 2443 pi(Style, PI, Options). 2444object_name(inline, Module:module(_Title), _) --> 2445 !, 2446 { module_property(Module, file(File)), 2447 file_base_name(File, Base) 2448 }, 2449 !, 2450 html(Base). 2451object_name(title, Module:module(Title), _) --> 2452 { module_property(Module, file(File)), 2453 file_base_name(File, Base) 2454 }, 2455 !, 2456 html([Base, ' -- ', Title]). 2457object_name(title, file(File), _) --> 2458 { module_property(Module, file(File)), 2459 doc_comment(Module:module(Title), _, _, _), 2460 !, 2461 file_base_name(File, Base) 2462 }, 2463 html([Base, ' -- ', Title]). 2464object_name(_, file(File), _) --> 2465 { file_base_name(File, Base) }, 2466 html(Base). 2467object_name(_, directory(Dir), _) --> 2468 { file_base_name(Dir, Base) }, 2469 html(Base). 2470object_name(_, module(Title), _Options) --> 2471 { print_message(warning, 2472 pldoc(module_comment_outside_module(Title))) 2473 }. 2474 2475pi(title, PI, Options) --> 2476 pi_type(PI), 2477 pi(PI, Options). 2478pi(inline, PI, Options) --> 2479 pi(PI, Options). 2480 2481pi(M:PI, Options) --> 2482 !, 2483 ( { option(qualify(true), Options) } 2484 -> html([span(class(module), M), :]) 2485 ; [] 2486 ), 2487 pi(PI, Options). 2488pi(Name/Arity, _) --> 2489 !, 2490 html([Name, /, \arity(Arity)]). 2491pi(Name//Arity, _) --> 2492 html([Name, //, \arity(Arity)]). 2493 2494arity(Arity) --> 2495 { var(Arity) }, 2496 !, 2497 html('_'). 2498arity(Arity) --> 2499 html(Arity). 2500 2501pi_type(_:PI) --> 2502 !, 2503 pi_type(PI). 2504pi_type(_/_) --> 2505 html(['Predicate ']). 2506pi_type(_//_) --> 2507 html(['Grammar rule ']).
2519in_file(Module:Head, File) :- 2520 !, 2521 distinct(File, in_file(Module, Head, File)). 2522in_file(Head, File) :- 2523 distinct(File, in_file(_, Head, File)). 2524 2525in_file(Module, Head, File) :- 2526 var(Module), 2527 ( predicate_property(system:Head, foreign) 2528 -> !, 2529 fail 2530 ; predicate_property(system:Head, file(File)), 2531 \+ system_arithmetic_function(Head) 2532 -> ! 2533 ; predicate_property(Head, autoload(File0)) 2534 -> !, 2535 file_name_extension(File0, pl, File) 2536 ; exported_from(Module, Head, File), 2537 module_property(Module, class(library)) 2538 ). 2539in_file(Module, Head, File) :- 2540 nonvar(Module), 2541 predicate_property(Module:Head, file(File)), 2542 \+ predicate_property(Module:Head, imported_from(_)). 2543in_file(Module, Head, File) :- 2544 xref_defined(File, Head, How), 2545 xref_current_source(File), 2546 atom(File), % only plain files 2547 xref_module(File, Module), 2548 How \= imported(_From). 2549in_file(Module, Head, File) :- 2550 exported_from(Module, Head, File). 2551in_file(Module, Head, File) :- 2552 predicate_property(Module:Head, file(File)), 2553 \+ predicate_property(Module:Head, imported_from(_)). 2554in_file(Module, Head, File) :- 2555 current_module(Module), 2556 source_file(Module:Head, File). 2557 2558exported_from(Module, Head, File) :- 2559 distinct(Primary, 2560 ( predicate_property(Module:Head, exported), 2561 ( predicate_property(Module:Head, imported_from(Primary)) 2562 -> true 2563 ; Primary = Module 2564 ))), 2565 module_property(Primary, file(File)). 2566 2567:- multifile 2568 arithmetic:evaluable/2. 2569 2570system_arithmetic_function(Head) :- 2571 functor(Head, Name, Arity), 2572 FArith is Arity-1, 2573 FArith >= 0, 2574 functor(FHead, Name, FArith), 2575 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.2606file(File) --> 2607 file(File, []). 2608 2609file(File, Options) --> 2610 { catch(nb_getval(pldoc_options, GenOptions), _, GenOptions = []), 2611 merge_options(Options, GenOptions, FinalOptions) 2612 }, 2613 link_file(File, FinalOptions), 2614 !. 2615file(File, Options) --> 2616 { option(edit_handler(Handler), Options), 2617 http_current_request(Request), 2618 memberchk(path(Path), Request), 2619 absolute_file_name(File, Location, 2620 [ relative_to(Path) 2621 ]), 2622 http_link_to_id(Handler, [location(Location)], HREF), 2623 format(atom(Title), 'Click to create ~w', [File]) 2624 }, 2625 html(a([href(HREF), class(nofile), title(Title)], File)). 2626file(File, _) --> 2627 html(code(class(nofile), File)). 2628 2629link_file(File, Options) --> 2630 { file_href(File, HREF, Options), 2631 option(label(Label), Options, File), 2632 option(class(Class), Options, file) 2633 }, 2634 html(a([class(Class), href(HREF)], Label)).
2640file_href(_, HREF, Options) :- 2641 option(href(HREF), Options), 2642 !. 2643file_href(File, HREF, Options) :- 2644 file_href_real(File, HREF0, Options), 2645 map_extension(HREF0, HREF, Options).
map_extension(+Pairs)2653map_extension(HREF0, HREF, Options) :- 2654 option(map_extension(Map), Options), 2655 file_name_extension(Base, Old, HREF0), 2656 memberchk(Old-New, Map), 2657 !, 2658 file_name_extension(Base, New, HREF). 2659map_extension(HREF, HREF, _). 2660 2661 2662file_href_real(File, HREF, Options) :- 2663 ( option(absolute_path(Path), Options) 2664 ; existing_linked_file(File, Path) 2665 ), 2666 !, 2667 ( option(files(Map), Options), 2668 memberchk(file(Path, LinkFile), Map) 2669 -> true 2670 ; LinkFile = Path 2671 ), 2672 file_href(LinkFile, HREF). 2673file_href_real(File, HREF, _) :- 2674 directory_alias(Alias), 2675 Term =.. [Alias,File], 2676 absolute_file_name(Term, _, 2677 [ access(read), 2678 file_errors(fail) 2679 ]), 2680 !, 2681 http_absolute_location(Term, HREF, []). 2682 2683directory_alias(icons). 2684directory_alias(css).
pldoc_file.2694file_href(Path, HREF) :- % a loaded Prolog file 2695 source_file(Path), 2696 !, 2697 doc_file_href(Path, HREF). 2698file_href(Path, HREF) :- 2699 ( nb_current(pldoc_output, CFile) 2700 ; nb_current(pldoc_file, CFile) 2701 ), 2702 CFile \== [], 2703 !, 2704 relative_file_name(Path, CFile, HREF). 2705file_href(Path, Path).
2713existing_linked_file(File, Path) :-
2714 catch(b_getval(pldoc_file, CurrentFile), _, fail),
2715 CurrentFile \== [],
2716 absolute_file_name(File, Path,
2717 [ relative_to(CurrentFile),
2718 access(read),
2719 file_errors(fail)
2720 ]).include(File,
Type) terms in the DOM term generated by wiki.pl if it
encounters [[file.ext]].2730include(PI, predicate, _) --> 2731 !, 2732 ( html_tokens_for_predicates(PI, []) 2733 -> [] 2734 ; html(['[[', \predref(PI), ']]']) 2735 ). 2736include(File, image, Options) --> 2737 { file_name_extension(_, svg, File), 2738 file_href(File, HREF, Options), 2739 !, 2740 include(image_attribute, Options, Attrs0), 2741 merge_options(Attrs0, 2742 [ alt(File), 2743 data(HREF), 2744 type('image/svg+xml') 2745 ], Attrs) 2746 }, 2747 ( { option(caption(Caption), Options) } 2748 -> html(div(class(figure), 2749 [ div(class(image), object(Attrs, [])), 2750 div(class(caption), Caption) 2751 ])) 2752 ; html(object(Attrs, [])) 2753 ). 2754include(File, image, Options) --> 2755 { file_href(File, HREF, Options), 2756 !, 2757 include(image_attribute, Options, Attrs0), 2758 merge_options(Attrs0, 2759 [ alt(File), 2760 border(0), 2761 src(HREF) 2762 ], Attrs) 2763 }, 2764 ( { option(caption(Caption), Options) } 2765 -> html(div(class(figure), 2766 [ div(class(image), img(Attrs)), 2767 div(class(caption), Caption) 2768 ])) 2769 ; html(img(Attrs)) 2770 ). 2771include(File, wiki, _Options) --> % [[file.txt]] is included 2772 { access_file(File, read), 2773 !, 2774 read_file_to_codes(File, String, []), 2775 wiki_codes_to_dom(String, [], DOM) 2776 }, 2777 html(DOM). 2778include(File, _Type, Options) --> 2779 link_file(File, Options), 2780 !. 2781include(File, _, _) --> 2782 html(code(class(nofile), ['[[',File,']]'])). 2783 2784image_attribute(src(_)). 2785image_attribute(alt(_)). 2786image_attribute(title(_)). 2787image_attribute(align(_)). 2788image_attribute(width(_)). 2789image_attribute(height(_)). 2790image_attribute(border(_)). 2791image_attribute(class(_)). 2792image_attribute(style(_)).
* [[member/2]]
* [[append/3]]
2805html_tokens_for_predicates([], _Options) --> 2806 []. 2807html_tokens_for_predicates([H|T], Options) --> 2808 !, 2809 html_tokens_for_predicates(H, Options), 2810 html_tokens_for_predicates(T, Options). 2811html_tokens_for_predicates(PI, Options) --> 2812 { PI = _:_/_, 2813 !, 2814 ( doc_comment(PI, Pos, _Summary, Comment) 2815 -> true 2816 ; Comment = '' 2817 ) 2818 }, 2819 object(PI, [Pos-Comment], [dl], _, Options). 2820html_tokens_for_predicates(Spec, Options) --> 2821 { findall(PI, documented_pi(Spec, PI), List), 2822 List \== [], ! 2823 }, 2824 html_tokens_for_predicates(List, Options). 2825html_tokens_for_predicates(Spec, Options) --> 2826 man_page(Spec, 2827 [ links(false), % no header 2828 navtree(false), % no navigation tree 2829 footer(false), % no footer 2830 synopsis(false) % no synopsis 2831 | Options 2832 ]). 2833 2834 2835documented_pi(Spec, PI) :- 2836 generalise_spec(Spec, PI), 2837 doc_comment(PI, _Pos, _Summary, _Comment). 2838 2839generalise_spec(Name/Arity, _M:Name/Arity). 2840generalise_spec(Name//Arity, _M:Name//Arity). 2841 2842 2843 /******************************* 2844 * WIKI FILES * 2845 *******************************/
2852doc_for_wiki_file(FileSpec, Options) :- 2853 absolute_file_name(FileSpec, File, 2854 [ access(read) 2855 ]), 2856 read_file_to_codes(File, String, []), 2857 b_setval(pldoc_file, File), 2858 call_cleanup(reply_wiki_page(File, String, Options), 2859 nb_delete(pldoc_file)). 2860 2861reply_wiki_page(File, String, Options) :- 2862 wiki_codes_to_dom(String, [], DOM0), 2863 title(DOM0, File, Title), 2864 insert_edit_button(DOM0, File, DOM, Options), 2865 reply_html_page(pldoc(wiki), 2866 title(Title), 2867 [ \html_requires(pldoc) 2868 | DOM 2869 ]). 2870 2871title(DOM, _, Title) :- 2872 sub_term(h1(_,Title), DOM), 2873 !. 2874title(_, File, Title) :- 2875 file_base_name(File, Title). 2876 (DOM, _, DOM, Options) :- 2878 option(edit(false), Options, false), 2879 !. 2880insert_edit_button([h1(Attrs,Title)|DOM], File, 2881 [h1(Attrs,[ span(style('float:right'), 2882 \edit_button(File, [edit(true)])) 2883 | Title 2884 ])|DOM], _) :- !. 2885insert_edit_button(DOM, File, 2886 [ h1(class(wiki), 2887 [ span(style('float:right'), 2888 \edit_button(File, [edit(true)])) 2889 ]) 2890 | DOM 2891 ], _). 2892 2893 2894 /******************************* 2895 * ANCHORS * 2896 *******************************/
2902mode_anchor_name(Var, _) :- 2903 var(Var), 2904 !, 2905 instantiation_error(Var). 2906mode_anchor_name(mode(Head, _), Anchor) :- 2907 !, 2908 mode_anchor_name(Head, Anchor). 2909mode_anchor_name(Head is _Det, Anchor) :- 2910 !, 2911 mode_anchor_name(Head, Anchor). 2912mode_anchor_name(Head, Anchor) :- 2913 pred_anchor_name(Head, _, Anchor).
2920pred_anchor_name(//(Head), Name/Arity, Anchor) :- 2921 !, 2922 functor(Head, Name, DCGArity), 2923 Arity is DCGArity+2, 2924 format(atom(Anchor), '~w/~d', [Name, Arity]). 2925pred_anchor_name(Head, Name/Arity, Anchor) :- 2926 functor(Head, Name, Arity), 2927 format(atom(Anchor), '~w/~d', [Name, Arity]). 2928 2929:- multifile prolog:message//1. 2930 2931prologmessage(pldoc(module_comment_outside_module(Title))) --> 2932 [ '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.plinto HTML+CSS.