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