1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2006-2020, University of Amsterdam 7 VU University Amsterdam 8 CWI, Amsterdam 9 All rights reserved. 10 11 Redistribution and use in source and binary forms, with or without 12 modification, are permitted provided that the following conditions 13 are met: 14 15 1. Redistributions of source code must retain the above copyright 16 notice, this list of conditions and the following disclaimer. 17 18 2. Redistributions in binary form must reproduce the above copyright 19 notice, this list of conditions and the following disclaimer in 20 the documentation and/or other materials provided with the 21 distribution. 22 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 POSSIBILITY OF SUCH DAMAGE. 35*/ 36 37:- module(pldoc_man, 38 [ man_page//2, % +Obj, +Options 39 man_overview//1, % +Options 40 41 man_param_object/2, % +Param, -Object 42 pldoc_href_object/2, % +HREF, -Object 43 man_object_uri/2, % +Object, -URI 44 man_uri_object/2, % +URI, -Object 45 xpce_object_label/2, % +Object, -Label 46 47 man_content_tree/2, % +Dir, -Tree 48 man_packages_tree/1 % -Tree 49 ]). 50:- use_module(library(xpath),[xpath/3, op(_,_,_)]). 51:- use_module(library(http/html_write)). 52:- use_module(library(debug),[assertion/1,debug/3]). 53 54:- autoload(doc_html, 55 [ object_tree/5, private/2, object_page_header/4, objects/4, 56 object_href/2, object_synopsis/4, object_footer/4, 57 object_page_footer/4, localise_object/2, 58 object_ref/4, object_page/4, 59 object_source_button//2 60 ]). 61:- autoload(doc_process,[doc_comment/4]). 62:- autoload(doc_search,[search_form/3]). 63:- autoload(doc_util,[atom_to_object/2,atom_pi/2]). 64:- autoload(man_index,[manual_object/5]). 65:- autoload(library(apply),[maplist/2,maplist/3,convlist/3]). 66:- autoload(library(error),[permission_error/3,existence_error/2]). 67:- autoload(library(filesex), 68 [directory_file_path/3,relative_file_name/3]). 69:- autoload(library(lists), 70 [select/4,append/3,member/2,last/2,selectchk/3]). 71:- autoload(library(option),[merge_options/3,option/2,option/3]). 72:- autoload(library(pairs),[pairs_values/2,pairs_keys/2]). 73:- autoload(library(prolog_xref),[xref_public_list/3]). 74:- autoload(library(sgml), 75 [ load_html/3, dtd/2, new_sgml_parser/2, set_sgml_parser/2, 76 sgml_parse/2, free_sgml_parser/1 77 ]). 78:- autoload(library(uri), 79 [uri_encoded/3, uri_components/2, uri_data/3, 80 uri_query_components/2]). 81:- autoload(library(www_browser),[expand_url_path/2]). 82:- autoload(library(http/html_head),[html_requires/3]). 83:- if(exists_source(library(http/http_dispatch))). 84:- use_module(library(http/http_dispatch), 85 [ http_link_to_id/3, http_location_by_id/2, 86 http_handler/3, http_reply_file/3, http_redirect/3 87 ]). 88:- endif. 89:- autoload(library(http/http_path),[http_absolute_location/3]). 90:- autoload(library(http/mimetype),[file_mime_type/2]). 91 92:- include(hooks).
98:- predicate_options(man_page//2, 2, 99 [ for(atom), 100 links(boolean), 101 navtree(boolean), 102 link_scheme(atom), 103 synopsis(boolean), 104 footer(boolean), 105 link_source(boolean), 106 no_manual(oneof([fail,error])), 107 search_in(oneof([all, app, man])), 108 search_match(oneof([name, summary])), 109 search_options(boolean) 110 ]). 111 112 113 /******************************* 114 * HIERARCHY * 115 *******************************/
ul list that
reflects the location of Obj in the manual.
(Obj, Options) -->
123 { ensure_man_tree,
124 man_nav_tree(Obj, Tree, Options),
125 TreeOptions = [ secref_style(title)
126 | Options
127 ]
128 },
129 html(ul(class(nav),
130 \object_tree(Tree, [Obj], TreeOptions))).139man_nav_tree(Obj, Tree, _Options) :- 140 man_child_of(Obj, Parent), 141 !, 142 findall(Neighbour, man_child_of(Neighbour, Parent), Neighbours0), 143 ( findall(Child, man_child_of(Child, Obj), Children), 144 Children \== [] 145 -> select(Obj, Neighbours0, node(Obj, Children), Neighbours) 146 ; Neighbours = Neighbours0 147 ), 148 path_up(node(Parent, Neighbours), Tree). 149man_nav_tree(Obj, node(Obj, Children), _Options) :- 150 findall(Child, man_child_of(Child, Obj), Children). 151 152 153path_up(Node, Tree) :- 154 node_id(Node, Id), 155 man_child_of(Id, Parent), 156 !, 157 ( Parent == root 158 -> findall(Neighbour, man_child_of(Neighbour, Parent), Neighbours0), 159 select(Id, Neighbours0, Node, Neighbours), 160 Tree = node(root, Neighbours) 161 ; path_up(node(Parent, [Node]), Tree) 162 ). 163path_up(Tree, Tree).
170man_child_of(Child, Parent) :- 171 term_hash(Child, ChildHash), 172 term_hash(Parent, ParentHash), 173 man_child_of(ChildHash, Child, ParentHash, Parent). 174 175:- dynamic 176 man_child_of/4, 177 man_tree_done/0.
183ensure_man_tree :- 184 man_tree_done, 185 !. 186ensure_man_tree :- 187 with_mutex(man_tree, 188 make_man_tree). 189 190make_man_tree :- 191 man_tree_done, 192 !. 193make_man_tree :- 194 man_content_tree(swi_man_manual('.'), ManTree), 195 man_packages_tree(PkgTree), 196 assert_tree(node(root, [ManTree, PkgTree])), 197 assertz(man_tree_done). 198 199assert_tree(node(Id, Children)) :- 200 !, 201 maplist(assert_parent(Id), Children), 202 maplist(assert_tree, Children). 203assert_tree(_). 204 205assert_parent(Id, Child) :- 206 node_id(Child, ChildId), 207 term_hash(Id, ParentHash), 208 term_hash(ChildId, ChildHash), 209 assertz(man_child_of(ChildHash, ChildId, ParentHash, Id)). 210 211node_id(node(Id, _), Id) :- !. 212node_id(Id, Id).
Contents.html for making the toplevel tree
that links to the individual files. Then we use
html_content_tree/2 to materialize the trees for the files.222man_content_tree(Spec, node(manual, Chapters)) :- 223 absolute_file_name(Spec, Dir, 224 [ file_type(directory), 225 access(read) 226 ]), 227 directory_file_path(Dir, 'Contents.html', ContentsFile), 228 load_html(ContentsFile, DOM, [cdata(string)]), 229 findall(Level-Path, 230 ( xpath(DOM, //div(@class=Class), DIV), 231 class_level(Class, Level), 232 xpath(DIV, a(@class=sec,@href=File), _), 233 \+ sub_atom(File, _, _, _, #), 234 directory_file_path(Dir, File, Path) 235 ), 236 Pairs), 237 index_chapters(Pairs, Chapters). 238 239class_level('toc-h1', 1). 240class_level('toc-h2', 2). 241class_level('toc-h3', 3). 242class_level('toc-h4', 4). 243 244index_chapters([], []). 245index_chapters([Level-File|T0], [node(Chapter, Children)|T]) :- 246 html_content_tree(File, Node), 247 Node = node(Chapter, Children0), 248 append(Children0, Sections, Children), 249 index_sections(T0, Level, Sections, T1), 250 index_chapters(T1, T). 251 252index_sections([], _, [], []) :- !. 253index_sections([SLevel-File|T0], Level, [Node|T], Rest) :- 254 SLevel > Level, 255 !, 256 html_content_tree(File, Node), 257 index_sections(T0, Level, T, Rest). 258index_sections(Rest, _, [], Rest).
xpce subtree so
xpce classes and their members appear in the navigation tree under
Documentation -> Packages -> XPCE.268man_packages_tree(node(packages, Packages)) :- 269 Section = section(0, _, _, _), 270 findall(File, 271 manual_object(Section, _Title, File, packages, _), 272 Files), 273 maplist(package_node, Files, Packages0), 274 ( man_xpce_tree(XpceTree) 275 -> Packages = [XpceTree|Packages0] 276 ; Packages = Packages0 277 ). 278 279man_xpce_tree(node(xpce, Chapters)) :- 280 catch(man_content_tree(swi_man_xpce('.'), node(_, Chapters)), 281 _, fail). 282 283package_node(File, Tree) :- 284 html_content_tree(File, Tree).
node(Object, ListOfTree).
297html_content_tree(FileIn, Tree) :- 298 absolute_file_name(FileIn, File), 299 findall(Offset-Obj, 300 manual_object(Obj, _Summary, File, _Class, Offset), 301 Pairs), 302 keysort(Pairs, Sorted), 303 pairs_values(Sorted, Objects), 304 make_tree(Objects, Trees), 305 assertion(Trees = [_]), 306 Trees = [Tree]. 307 308make_tree([], []). 309make_tree([Obj|T0], [node(Obj, Children)|T]) :- 310 children(T0, Obj, Children, T1), 311 make_tree(T1, T). 312 313children([], _, [], []) :- !. 314children([Obj|T0], Root, [Node|T], Rest) :- 315 section_level(Obj, ObjLevel), 316 section_level(Root, Level), 317 ObjLevel > Level, 318 !, 319 Node = node(Obj, Children), 320 children(T0, Obj, Children, T1), 321 children(T1, Root, T, Rest). 322children([Obj|T0], Root, [Obj|T], Rest) :- 323 \+ section_level(Obj, _), 324 !, 325 children(T0, Root, T, Rest). 326children(Rest, _, [], Rest). 327 328section_level(section(Level, _Nr, _Id, _File), Level). 329 330 331 /******************************* 332 * RETRIEVE * 333 *******************************/
342load_man_object(Obj, ParentSection, Path, DOM) :- 343 resolve_section(Obj, For), 344 For = section(_,SN,_ID,Path), 345 parent_section(For, ParentSection), 346 findall(Nr-Pos, section_start(Path, Nr, Pos), Pairs), 347 ( ( Pairs = [SN-_|_] 348 ; Pairs == [] 349 ) 350 -> !, 351 load_html(Path, DOM, [cdata(string)]) % Load whole file 352 ; append(_, [SN-Start|Rest], Pairs) 353 -> !, 354 ( member(N-End, Rest), 355 \+ sub_atom(N, 0, _, _, SN), 356 Len is End - Start, 357 Options = [content_length(Len)] 358 -> true 359 ; Options = [] 360 ), 361 open(Path, read, In, [type(binary)]), 362 seek(In, Start, bof, _), 363 dtd(html, DTD), 364 new_sgml_parser(Parser, 365 [ dtd(DTD) 366 ]), 367 set_sgml_parser(Parser, file(Path)), 368 set_sgml_parser(Parser, dialect(sgml)), 369 set_sgml_parser(Parser, encoding('utf-8')), 370 set_sgml_parser(Parser, shorttag(false)), 371 set_sgml_parser(Parser, defaults(false)), 372 call_cleanup(sgml_parse(Parser, 373 [ document(DOM), 374 source(In), 375 syntax_errors(quiet), 376 cdata(string) 377 | Options 378 ]), 379 ( free_sgml_parser(Parser), 380 close(In) 381 )) 382 ). 383load_man_object(For, Parent, Path, DOM) :- 384 object_spec(For, Obj), 385 manual_object(Obj, _, Path, _, Position), 386 ( object_section(Path, Position, Parent) 387 -> true 388 ; Parent = Path 389 ), 390 open(Path, read, In, [type(binary)]), 391 seek(In, Position, bof, _), 392 dtd(html, DTD), 393 new_sgml_parser(Parser, 394 [ dtd(DTD) 395 ]), 396 set_sgml_parser(Parser, file(Path)), 397 set_sgml_parser(Parser, dialect(sgml)), 398 set_sgml_parser(Parser, shorttag(false)), 399 set_sgml_parser(Parser, defaults(false)), 400 call_cleanup(parse_dts_upto_dd(Parser, In, DOM), 401 ( free_sgml_parser(Parser), 402 close(In) 403 )). 404 405parse_dts_upto_dd(Parser, In, Description) :- 406 sgml_parse(Parser, 407 [ document(DOM0), 408 cdata(string), 409 source(In), 410 parse(element), 411 syntax_errors(quiet) 412 ]), 413 ( DOM0 = [Element], 414 Element = element(dt, _, _) 415 -> Description = [Element|More], 416 parse_dts_upto_dd(Parser, In, More) 417 ; Description = DOM0 418 ). 419 420section_start(Path, Nr, Pos) :- 421 manual_object(section(_,Nr,_,_), _, Path, _, Pos).
429resolve_section(section(Level, No, Spec), Section) :- 430 !, 431 resolve_section(section(Level, No, _, Spec), Section). 432resolve_section(section(Level, No, ID, Path), 433 section(Level, No, ID, Path)) :- 434 nonvar(ID), 435 manual_object(section(Level,No,ID,Path), _, _, _, _), 436 !. 437resolve_section(section(Level, No, ID, Spec), 438 section(Level, No, ID, Path)) :- 439 ground(Spec), 440 absolute_file_name(Spec, Path, 441 [ access(read) 442 ]), 443 ( manual_object(section(Level, No, ID, Path), _, _, _, _) 444 -> true 445 ; path_allowed(Path) 446 -> true 447 ; permission_error(read, manual_file, Spec) 448 ). 449 450 451path_allowed(Path) :- % allow all files from swi/doc 452 absolute_file_name(swi(doc), Parent, 453 [ access(read), 454 file_type(directory) 455 ]), 456 sub_atom(Path, 0, _, _, Parent).
466parent_section(section(Level, Nr, _ID, File), Parent) :- 467 integer(Level), 468 Parent = section(PL, PNr, _PID, _PFile), 469 PL is Level - 1, 470 findall(B, sub_atom(Nr, B, _, _, '.'), BL), 471 last(BL, Before), 472 sub_atom(Nr, 0, Before, _, PNr), 473 ( manual_object(Parent, _, File, _, _) 474 -> true 475 ; manual_object(Parent, _, ParentFile, _, _), 476 same_dir(File, ParentFile) 477 -> true 478 ; manual_object(Parent, _, _, _, _) 479 ), 480 !. 481parent_section(section(Level, _, _, File), Parent) :- 482 Parent = section(ParentLevel, _, _, File), 483 manual_object(Parent, _, _, _, _), 484 ParentLevel < Level, 485 !. 486parent_section(section(_, _, _, File), File).
494object_section(Path, Pos, Section) :- 495 Section = section(_,_,_,_), 496 findall(Section, 497 (manual_object(Section, _, Path, _, SecPos), SecPos =< Pos), 498 List), 499 last(List, Section). 500 501same_dir(File1, File2) :- 502 file_directory_name(File1, Dir), 503 file_directory_name(File2, Dir).
510object_spec(Spec, Spec) :- 511 compound(Spec), 512 !. 513object_spec(Atom, Spec) :- 514 catch(atom_to_term(Atom, Spec, _), _, fail), 515 !, 516 Atom \== Spec. 517object_spec(Atom, PI) :- 518 atom_to_object(Atom, PI). 519 520 521 /******************************* 522 * EMIT * 523 *******************************/
f(Name/Arity)
display documentation of an arithmetic functionc(Function)
display documentation of a C API functionsection(Level, Number, Id, File)
Display a section of the manualsec(DocFile#Id)
Display a section of the manual (from short form)Options:
fail, fail instead of displaying a
not-found message.false, omit the synopsis linetrue (default), include links to the parent object;
if false, just emit the manual material.true (default), display the navigation tree, otherwise
suppress it.Scheme:Object IRIs rather
than as links into the PlDoc server. References that do not
resolve to a documentation object are removed. Used by
help/1 to create clickable terminal output. See
man_object_uri/2.570man_page(Obj, Options) --> 571 { ground(Obj), 572 special_node(Obj) 573 }, 574 !, 575 html_requires(pldoc), 576 man_links([], Options), 577 man_matches([Obj], Obj, Options). 578man_page(Obj0, Options) --> % Manual stuff 579 { full_page(Obj0, Obj), 580 findall((Parent+Path)-(Obj+DOM), 581 load_man_object(Obj, Parent, Path, DOM), 582 Matches), 583 Matches = [_|_], 584 !, 585 pairs_keys(Matches, ParentPaths), 586 Matches = [Parent+Path-_|_] 587 }, 588 html_requires(pldoc), 589 man_links(ParentPaths, Options), 590 man_matches(Matches, Obj, Options). 591man_page(Obj, Options) --> % PlDoc predicates, etc. 592 { full_object(Obj, Full), 593 findall(Full-File, visible_doc_comment(Full, File, Options), Pairs), 594 Pairs \== [], 595 pairs_keys(Pairs, Objs) 596 }, 597 !, 598 html_requires(pldoc), 599 ( { Pairs = [_-File] } 600 -> object_page_header(File, Options) 601 ; object_page_header(-, Options) 602 ), 603 { merge_options(Options, 604 [ synopsis(true), 605 navtree(true) 606 ], Options2) 607 }, 608 objects(Objs, Options2). 609man_page(Obj, Options) --> % failure 610 { \+ option(no_manual(fail), Options) 611 }, 612 html_requires(pldoc), 613 man_links([], Options), 614 html(p(class(noman), 615 [ 'Sorry, No manual entry for ', 616 b('~w'-[Obj]) 617 ])). 618 619% Show an object if it is not private or it is fully qualified and we 620% want to show all fully qualified objects. Used by help/1. 621 622visible_doc_comment(Obj, File, Options) :- 623 doc_comment(Obj, File:_, _, _), 624 \+ ( private(Obj, Options), 625 \+ ( Obj = _:_, 626 option(qualified(always), Options) 627 ) 628 ). 629 630%special_node(manual). % redirected to the Introduction section 631special_node(root). 632special_node(packages). 633special_node(xpce). 634 635full_page(Obj, _) :- 636 var(Obj), !, fail. 637full_page(Obj, Obj) :- 638 Obj = section(_,_,_,_), 639 !. 640full_page(section(ID), section(_,_,ID,_)) :- !. 641full_page(manual, section(_,_,'sec:intro',_)) :- !. 642full_page(Obj0, Obj) :- 643 ground(Obj0), 644 alt_obj(Obj0, Obj), 645 manual_object(Obj, _, _, _, _), 646 !. 647full_page(Obj, Obj) :- 648 ground(Obj). 649 650alt_obj(Obj, Obj). 651alt_obj(Name/Arity, Name//DCGArity) :- 652 integer(Arity), 653 Arity >= 2, 654 DCGArity is Arity - 2. 655alt_obj(Name//DCGArity, Name/Arity) :- 656 integer(DCGArity), 657 Arity is DCGArity + 2.
663full_object(Object, M:Obj) :- 664 qualify(Object, M:Obj0), 665 alt_obj(Obj0, Obj), 666 doc_comment(M:Obj, _, _, _), 667 !. 668 669qualify(M:O, M:O). 670qualify(O, _:O).
The tricky part is that there are cases where multiple modules export the same predicate. We must find from the title of the manual section which library is documented.
682man_qualified_object(Text, Parent, LibOpt, Object, Section) :- 683 atom(Text), 684 atom_pi(Text, PI), 685 ground(PI), 686 !, 687 man_qualified_object_2(PI, Parent, LibOpt, Object, Section). 688man_qualified_object(Object0, Parent, LibOpt, Object, Section) :- 689 man_qualified_object_2(Object0, Parent, LibOpt, Object, Section). 690 691man_qualified_object_2(Name/Arity, Parent, 692 LibOpt, Module:Name/Arity, Section) :- 693 object_module(Parent, Module, Section, LibOpt), 694 !. 695man_qualified_object_2(Object, Parent, [], Object, Parent).
703:- public 704 man_synopsis//2. % called from man_match//2 705 706man_synopsis(PI, Section) --> 707 man_synopsis(PI, Section, []). 708 709man_synopsis(PI, Section, Options) --> 710 { object_href(Section, HREF) 711 }, 712 object_synopsis(PI, [href(HREF)|Options]).
718object_module(Section0, Module, Section, [source(Term)]) :- 719 parent_section_ndet(Section0, Section), 720 manual_object(Section, Title, _File, _Class, _Offset), 721 ( once(sub_atom(Title, B, _, _, :)), 722 sub_atom(Title, 0, B, _, Atom), 723 catch(term_to_atom(Term, Atom), _, fail), 724 ground(Term), 725 Term = library(_) 726 -> !, 727 absolute_file_name(Term, PlFile, 728 [ file_type(prolog), 729 access(read), 730 file_errors(fail) 731 ]), 732 ( module_property(Module, file(PlFile)) 733 -> true 734 ; xref_public_list(PlFile, -, % module is not loaded 735 [ module(Module) 736 ]) 737 ) 738 ). 739 740parent_section_ndet(Section, Section). 741parent_section_ndet(Section, Parent) :- 742 parent_section(Section, Parent0), 743 parent_section_ndet(Parent0, Parent). 744 745 746man_matches(Matches, Object, Options) --> 747 { option(navtree(false), Options) }, 748 !, 749 man_matches_nt(Matches, Object, Options). 750man_matches(Matches, Object, Options) --> 751 html([ div(class(navtree), 752 div(class(navwindow), 753 \man_nav_tree(Object, Options))), 754 div(class(navcontent), 755 \man_matches_nt(Matches, Object, Options)) 756 ]). 757 758 759man_matches_nt([Match], Object, Options) --> 760 { option(footer(true), Options, true) }, 761 !, 762 man_match(Match, Object, Options), 763 object_page_footer(Object, []). 764man_matches_nt(Matches, Object, Options) --> 765 man_matches_list(Matches, Object, Options). 766 767man_matches_list([], _, _) --> []. 768man_matches_list([H|T], Obj, Options) --> 769 man_match(H, Obj, Options), 770 man_matches_list(T, Obj, Options).
777man_match(packages, packages, _) --> 778 !, 779 html({|html|| 780 <p> 781 Packages are relatively independent add-on libraries that 782 may not be available in all installations. Packages are 783 part of the source code releases of SWI-Prolog and may be 784 enabled or disabled during the build.</p> 785 786 <p> 787 See also <a href="/pack/list">Add-ons</a> for extensions 788 provided by the community that must be installed separately 789 using 790 <a href="/pldoc/doc_for?object=pack_install/1">pack_install/1</a>.</p> 791 |}). 792man_match(xpce, xpce, _) --> 793 !, 794 html({|html|| 795 <p> 796 XPCE is the native graphical toolkit of SWI-Prolog. The 797 reference manual below documents the class hierarchy, global 798 objects, and topical guides.</p> 799 |}). 800man_match(root, root, _) --> 801 !, 802 man_overview([]). 803man_match((Parent+Path)-(Obj+DOM), Obj, Options) --> 804 { \+ option(synopsis(false), Options), 805 DOM = [element(dt,A,C0)|DD], 806 convlist(dt_obj, DOM, Objs), 807 option(link_source(Link), Options, true), 808 man_qualified_object(Obj, Parent, LibOpt, QObj, Section), 809 !, 810 C = [ span(style('float:right;margin-left:5px;'), 811 \object_source_button(QObj, [source_link(Link)])) 812 | C0 813 ] 814 }, 815 dom_list([ element(dt,[],[\man_synopsis(QObj, Section, LibOpt)]), 816 element(dt,A,C) 817 | DD 818 ], Path, Options), 819 object_footer(Objs, Options). 820man_match((_Parent+Path)-(Obj+DOM), Obj, Options) --> 821 dom_list(DOM, Path, Options). 822 823dt_obj(element(dt,_,C), Obj) :- 824 xpath(C, //a(@id=Atom), _), 825 atom_to_object(Atom, Obj). 826 827:- html_meta 828 dom_list(, , , , ). 829 830dom_list(_:[], _, _) --> 831 !, 832 []. 833dom_list(M:[H|T], Path, Options) --> 834 dom(H, Path, Options), 835 dom_list(M:T, Path, Options). 836 837dom(element(E, Atts, Content), Path, Options) --> 838 !, 839 dom_element(E, Atts, Content, Path, Options). 840dom(CDATA, _, _) --> 841 html(CDATA). 842 843dom_element(a, _, [], _, _) --> % Useless back-references 844 !, 845 []. 846dom_element(a, Att, Content, Path, Options) --> 847 { memberchk(href=HREF, Att), 848 ( memberchk(class=Class, Att) 849 -> true 850 ; Class = unknown 851 ), 852 rewrite_ref(Class, HREF, Path, Myref, Options) 853 }, 854 !, 855 html(a(href(Myref), \dom_list(Content, Path, Options))). 856dom_element(a, _Att, Content, Path, Options) --> % unresolvable manual link 857 { option(link_scheme(_), Options) % there is nothing to click 858 }, 859 !, 860 dom_list(Content, Path, Options). 861dom_element(span, Att, [CDATA], _, Options) --> 862 { memberchk(class='pred-ext', Att), 863 atom_pi(CDATA, PI), 864 documented(PI), 865 ( option(link_scheme(Scheme), Options) 866 -> object_scheme_uri(Scheme, PI, HREF) 867 ; option(server(false), Options) 868 -> public_link(predicate(CDATA), HREF) 869 ; http_link_to_id(pldoc_man, [predicate=CDATA], HREF) 870 ) 871 }, 872 !, 873 html(a(href(HREF), CDATA)). 874dom_element(img, Att0, [], Path, _Options) --> 875 { selectchk(src=Src, Att0, Att1), 876 relative_file_name(ImgFile, Path, Src), 877 handler_alias(Handler, DirAlias), 878 absolute_file_name(DirAlias, Dir, 879 [ file_errors(fail), 880 solutions(all), 881 file_type(directory) 882 ]), 883 ensure_slash(Dir, DirS), 884 atom_concat(DirS, NewSrc, ImgFile), 885 !, 886 http_link_to_id(Handler, [], ManRef), 887 directory_file_path(ManRef, NewSrc, NewPath), 888 Begin =.. [img, src(NewPath) | Att1] 889 }, 890 html_begin(Begin), 891 html_end(img). 892dom_element(div, Att, _, _, _) --> 893 { memberchk(class=navigate, Att) }, 894 !. 895dom_element(html, _, Content, Path, Options) --> 896 !, % do not emit a html for the second time 897 dom_list(Content, Path, Options). 898dom_element(head, _, Content, Path, Options) --> 899 !, % do not emit a head for the second time 900 dom_list(Content, Path, Options). 901dom_element(title, _, _, _, _) --> !. 902dom_element(link, _, _, _, _) --> !. 903dom_element(body, _, Content, Path, Options) --> 904 !, % do not emit a body for the second time 905 dom_list(Content, Path, Options). 906dom_element(Name, Attrs, Content, Path, Options) --> 907 { Begin =.. [Name|Attrs] }, 908 html_begin(Begin), 909 dom_list(Content, Path, Options), 910 html_end(Name). 911 912handler_alias(manual_file, swi_man_manual(.)). 913handler_alias(pldoc_package, swi_man_packages(.)). 914 915ensure_slash(Dir, DirS) :- 916 ( sub_atom(Dir, _, _, 0, /) 917 -> DirS = Dir 918 ; atom_concat(Dir, /, DirS) 919 ).
928public_link(predicate(CDATA), HREF) :-
929 uri_encoded(query_value, CDATA, Encoded),
930 atom_concat('https://www.swi-prolog.org/pldoc/doc_for?object=',
931 Encoded, HREF).938documented(PI) :- 939 manual_object(PI, _, _, _, _), 940 !. 941documented(PI) :- 942 full_object(PI, _Obj).
/man?predicate=PI.section(Level, NT, ID, FilePath)section(Level, NT, ID, FilePath)#flag:Namesection(Level, NT, ID, FilePath)#gloss:Name
$ File#Name() Rewrite to /man/CAPI=Name
/doc_for?object=xpce(Class,Kind,Name). Kind is one
of send, get, both, ivar or classvar.sec lookup.986rewrite_ref(Class, Ref0, Path, ManRef, Options) :- 987 option(link_scheme(Scheme), Options), 988 !, 989 ref_object(Class, Ref0, Path, Object), 990 object_scheme_uri(Scheme, Object, ManRef). 991rewrite_ref(_Class, Ref, _Path, Ref, Options) :- 992 option(server(false), Options), 993 !. 994rewrite_ref(Class, Ref0, Path, ManRef, _Options) :- 995 rewrite_ref(Class, Ref0, Path, ManRef). 996 997rewrite_ref(pred, Ref0, _, Ref) :- % Predicate/DCG reference 998 ref_fragment(Ref0, _File, Fragment), 999 !, 1000 atom_to_object(Fragment, PI), 1001 manual_object(PI, _, _, _, _), 1002 uri_encoded(query_value, Fragment, Enc), 1003 http_location_by_id(pldoc_man, ManHandler), 1004 format(string(Ref), '~w?predicate=~w', [ManHandler, Enc]). 1005rewrite_ref(function, Ref0, _, Ref) :- % Arithmetic function reference 1006 ref_fragment(Ref0, _File, Fragment), 1007 !, 1008 atom_to_object(Fragment, PI), 1009 manual_object(PI, _, _, _, _), 1010 PI=f(Name/Arity), 1011 format(atom(PIName), '~w/~w', [Name,Arity]), 1012 uri_encoded(query_value, PIName, Enc), 1013 http_location_by_id(pldoc_man, ManHandler), 1014 format(string(Ref), '~w?function=~w', [ManHandler, Enc]). 1015rewrite_ref(func, Ref0, _, Ref) :- % C-API reference 1016 ref_fragment(Ref0, _File, Fragment), 1017 !, 1018 atom_to_object(Fragment, Obj), 1019 manual_object(Obj, _, _, _, _), 1020 Obj = c(Function), 1021 uri_encoded(query_value, Function, Enc), 1022 http_location_by_id(pldoc_man, ManHandler), 1023 format(string(Ref), '~w?CAPI=~w', [ManHandler, Enc]). 1024rewrite_ref(sec, Ref0, Path, Ref) :- % Section inside a file 1025 ref_fragment(Ref0, File, Fragment), 1026 !, 1027 referenced_section(Fragment, File, Path, Section), 1028 object_href(Section, Ref). 1029rewrite_ref(sec, File, Path, Ref) :- % Section is a file 1030 file_section(File, Path, Obj), 1031 !, 1032 object_href(Obj, Ref). 1033rewrite_ref(cite, Ref0, Path, Ref) :- % Citation (bit hard-wired) 1034 debug(pldoc(cite), 'Cite ref ~q ~q', [Ref0, Path]), 1035 ref_fragment(Ref0, _File, Fragment), 1036 !, 1037 uri_encoded(query_value, Fragment, Enc), 1038 http_location_by_id(pldoc_man, ManHandler), 1039 format(string(Ref), '~w?section=bibliography#~w', [ManHandler, Enc]). 1040rewrite_ref(flag, Ref0, Path, Ref) :- 1041 ref_fragment(Ref0, File, Fragment), 1042 !, 1043 file_section(File, Path, Obj), 1044 !, 1045 object_href(Obj, Ref1), 1046 format(string(Ref), '~w#~w', [Ref1, Fragment]). 1047rewrite_ref(gloss, Ref0, Path, Ref) :- 1048 ref_fragment(Ref0, File, Fragment), 1049 !, 1050 file_section(File, Path, Obj), 1051 !, 1052 object_href(Obj, Ref1), 1053 format(string(Ref), '~w#~w', [Ref1, Fragment]). 1054rewrite_ref(_, Ref0, _, Ref) :- % xpce class member reference 1055 xpce_member_ref(Ref0, Obj), 1056 !, 1057 object_href(Obj, Ref). 1058rewrite_ref(_, Ref0, Path, Ref) :- % section ref carrying class="" 1059 ref_fragment(Ref0, File, Fragment), % (xpce: class refs, objects) 1060 sub_atom(Fragment, 0, _, _, 'sec:'), 1061 referenced_section(Fragment, File, Path, Section), 1062 !, 1063 object_href(Section, Ref).
1070ref_fragment(Ref, File, Fragment) :-
1071 sub_atom(Ref, B, _, A, '#'),
1072 !,
1073 sub_atom(Ref, 0, B, _, File),
1074 sub_atom(Ref, _, A, 0, Fragment).
1081file_section(File, Path, Section) :-
1082 file_directory_name(Path, Dir),
1083 atomic_list_concat([Dir, /, File], SecPath),
1084 Section = section(_, _, _, SecPath),
1085 manual_object(Section, _, _, _, _).class-point-get-x.
1092xpce_member_ref(Ref, Obj) :-
1093 ref_fragment(Ref, _File, Fragment),
1094 atomic_list_concat([class, ClassA, KindA, Name], '-', Fragment),
1095 xpce_kind(KindA),
1096 xpce_canonical_object(ClassA, KindA, Name, Obj).link_scheme option of man_page//2. Flag and glossary
references resolve to the section that holds them.1106ref_object(pred, Ref, _, Obj) :- 1107 !, 1108 ref_fragment(Ref, _File, Fragment), 1109 atom_to_object(Fragment, Obj), 1110 manual_object(Obj, _, _, _, _). 1111ref_object(function, Ref, _, Obj) :- 1112 !, 1113 ref_fragment(Ref, _File, Fragment), 1114 atom_to_object(Fragment, Obj), 1115 Obj = f(_), 1116 manual_object(Obj, _, _, _, _). 1117ref_object(func, Ref, _, Obj) :- 1118 !, 1119 ref_fragment(Ref, _File, Fragment), 1120 atom_to_object(Fragment, Obj), 1121 Obj = c(_), 1122 manual_object(Obj, _, _, _, _). 1123ref_object(sec, Ref, Path, Obj) :- 1124 !, 1125 ( ref_fragment(Ref, File, Fragment) 1126 -> referenced_section(Fragment, File, Path, Obj) 1127 ; file_section(Ref, Path, Obj) 1128 ). 1129ref_object(Class, Ref, Path, Obj) :- 1130 section_ref_class(Class), 1131 !, 1132 ref_fragment(Ref, File, _Fragment), 1133 file_section(File, Path, Obj). 1134ref_object(_, Ref, _, Obj) :- % xpce class member reference 1135 xpce_member_ref(Ref, Obj), 1136 !. 1137ref_object(_, Ref, Path, Obj) :- % section ref carrying class="" 1138 ref_fragment(Ref, File, Fragment), 1139 sub_atom(Fragment, 0, _, _, 'sec:'), 1140 referenced_section(Fragment, File, Path, Obj). 1141 1142section_ref_class(flag). 1143section_ref_class(gloss). 1144 1145% The anchor id encodes the access form used at the call site 1146% (=|class-<class>-<kind>-<name>|=) but each method/instance variable 1147% has only one canonical xpce(...) data-obj. An ivar e.g. emits 1148% alias anchors for its send/get/both accessors, and a =both= anchor 1149% is a shorthand that resolves to whichever send/get/ivar form the 1150% class actually defines. Try the parsed kind first, then fall back 1151% to the alternative forms in order of likelihood. 1152 1153xpce_canonical_object(Class, Kind, Name, xpce(Class, Kind, Name)) :- 1154 manual_object(xpce(Class, Kind, Name), _, _, _, _), 1155 !. 1156xpce_canonical_object(Class, _, Name, Obj) :- 1157 member(K, [ivar, send, get, classvar, both]), 1158 Obj = xpce(Class, K, Name), 1159 manual_object(Obj, _, _, _, _), 1160 !. 1161 1162xpce_kind(send). 1163xpce_kind(get). 1164xpce_kind(both). 1165xpce_kind(ivar). 1166xpce_kind(classvar).
1170referenced_section(Fragment, File, Path, section(Level, Nr, ID, SecPath)) :-
1171 atom_concat('sec:', Nr, Fragment),
1172 ( File == ''
1173 -> SecPath = Path
1174 ; file_directory_name(Path, Dir),
1175 atomic_list_concat([Dir, /, File], SecPath)
1176 ),
1177 manual_object(section(Level, Nr, ID, SecPath), _, _, _, _).1184man_links(ParentPaths, Options) --> 1185 prolog:doc_page_header(parents(ParentPaths), Options), 1186 !. 1187man_links(ParentPaths, Options) --> 1188 { option(links(true), Options, true), 1189 option(header(true), Options, true) 1190 }, 1191 !, 1192 html([ div(class(navhdr), 1193 [ div(class(jump), \man_parent(ParentPaths)), 1194 div(class(search), \search_form(Options)), 1195 br(clear(right)) 1196 ]), 1197 p([]) 1198 ]). 1199man_links(_, _) --> 1200 []. 1201 1202man_parent(ParentPaths) --> 1203 { maplist(parent_to_section, ParentPaths, [Section|MoreSections]), 1204 maplist(=(Section), MoreSections) 1205 }, 1206 !, 1207 object_ref(Section, [secref_style(number_title)]). 1208man_parent(_) --> []. 1209 1210parent_to_section(X+_, X) :- 1211 X = section(_,_,_,_), 1212 !. 1213parent_to_section(File+_, Section) :- 1214 atom(File), 1215 manual_object(Section, _Title, File, _Class, _Offset), 1216 !.
number, title or number_title.1225section_link(Section, Options) --> 1226 { option(secref_style(Style), Options, number) 1227 }, 1228 section_link(Style, Section, Options). 1229 1230section_link(number, section(_, Number, _, _), _Options) --> 1231 !, 1232 ( {Number == '0'} % Title. Package? 1233 -> [] 1234 ; html(['Sec. ', Number]) 1235 ). 1236section_link(title, Obj, _Options) --> 1237 !, 1238 { manual_object(Obj, Title, _File, _Class, _Offset) 1239 }, 1240 html(Title). 1241section_link(_, Obj, _Options) --> 1242 !, 1243 { Obj = section(_, Number, _, _), 1244 manual_object(Obj, Title, _File, _Class, _Offset) 1245 }, 1246 ( { Number == '0' } 1247 -> html(Title) 1248 ; html([Number, ' ', Title]) 1249 ).
1255function_link(Function, _) --> 1256 html([Function, '()']). 1257 1258 1259 /******************************* 1260 * INDICES & OVERVIEW * 1261 *******************************/
1268man_overview(Options) --> 1269 { http_absolute_location(pldoc_man(.), RefMan, []) 1270 }, 1271 html([ h1('SWI-Prolog documentation'), 1272 blockquote(class(refman_link), 1273 a(href(RefMan), 1274 'SWI-Prolog reference manual')), 1275 \package_overview(Options), 1276 \paperback(Options) 1277 ]). 1278 1279package_overview(Options) --> 1280 html([ h2(class(package_doc_title), 1281 'SWI-Prolog package documentation'), 1282 blockquote(class(package_overview), 1283 \packages(Options)) 1284 ]). 1285 1286packages(Options) --> 1287 { findall(Pkg, current_package(Pkg), Pkgs) 1288 }, 1289 packages(Pkgs, Options). 1290 1291packages([], _) --> 1292 []. 1293packages([Pkg|T], Options) --> 1294 package(Pkg, Options), 1295 packages(T, Options). 1296 1297package(pkg(Title, HREF, HavePackage), Options) --> 1298 { package_class(HavePackage, Class, Options) 1299 }, 1300 html(div(class(Class), 1301 a([href(HREF)], Title))). 1302 1303package_class(true, pkg_link, _). 1304package_class(false, no_pkg_link, _). 1305 1306current_package(pkg(Title, HREF, HavePackage)) :- 1307 manual_object(section(0, _, _, _), Title, File, packages, _), 1308 file_base_name(File, FileNoDir), 1309 file_name_extension(Base, _, FileNoDir), 1310 ( exists_source(library(Base)) 1311 -> HavePackage = true 1312 ; HavePackage = false 1313 ), 1314 http_absolute_location(pldoc_pkg(FileNoDir), HREF, []). 1315 1316 1317:- if(current_predicate(http_handler/3)). 1318:- http_handler(pldoc(jpl), pldoc_jpl, [prefix]). 1319:- http_handler(pldoc_pkg(.), pldoc_package, [prefix]). 1320:- http_handler(pldoc_man(.), pldoc_refman, [prefix]). 1321:- http_handler(pldoc(packages), pldoc_package_overview, []).
1327pldoc_jpl(Request) :-
1328 memberchk(path_info(JPLFile), Request),
1329 atom_concat('doc/packages/jpl', JPLFile, Path),
1330 http_reply_file(swi(Path), [], Request).1339pldoc_package(Request) :- 1340 ( \+ option(path_info(_), Request) 1341 -> true 1342 ; option(path_info(/), Request) 1343 ), 1344 http_link_to_id(pldoc_object, [object=packages], HREF), 1345 http_redirect(see_other, HREF, Request). 1346pldoc_package(Request) :- 1347 memberchk(path_info(Img), Request), 1348 file_mime_type(Img, image/_), 1349 !, 1350 http_reply_file(swi_man_packages(Img), [], Request). 1351pldoc_package(Request) :- 1352 memberchk(path_info('jpl'), Request), 1353 !, 1354 memberchk(path(Path0), Request), 1355 atom_concat(Path0, /, Path), 1356 http_redirect(moved, Path, Request). 1357pldoc_package(Request) :- 1358 memberchk(path_info(JPLFile), Request), 1359 ( JPLFile == 'jpl/' 1360 -> Path = 'doc/packages/jpl/index.html' 1361 ; sub_atom(JPLFile, 0, _, _, 'jpl/') 1362 -> atom_concat('doc/packages/', JPLFile, Path) 1363 ), 1364 http_reply_file(swi(Path), [], Request). 1365pldoc_package(Request) :- 1366 memberchk(path_info(PkgDoc), Request), 1367 ensure_html_ext(PkgDoc, PkgHtml), 1368 atom_concat('packages/', PkgHtml, Path), 1369 term_to_atom(section(Path), Object), 1370 http_link_to_id(pldoc_object, [object=Object], HREF), 1371 http_redirect(see_other, HREF, Request). 1372 1373ensure_html_ext(Pkg, PkgHtml) :- 1374 file_name_extension(_, html, Pkg), 1375 !, 1376 PkgHtml = Pkg. 1377ensure_html_ext(Pkg, PkgHtml) :- 1378 file_name_extension(Pkg, html, PkgHtml).
1384pldoc_package_overview(_Request) :- 1385 reply_html_page( 1386 pldoc(packages), 1387 title('SWI-Prolog package documentation'), 1388 \package_overview([])). 1389:- endif.
1395paperback(_Options) -->
1396 { expand_url_path(swipl_book(.), HREF)
1397 },
1398 html([ h2('The manual as a book'),
1399 p([ 'A paperback version of the manual is ',
1400 a(href(HREF), 'available'), '.'
1401 ])
1402 ]).1409pldoc_refman(Request) :- 1410 memberchk(path_info(Section), Request), 1411 \+ sub_atom(Section, _, _, _, /), 1412 Obj = section(0,_,_,_), 1413 manual_object(Obj, Title, File, manual, _), 1414 file_base_name(File, Section), 1415 !, 1416 reply_html_page(pldoc(man), 1417 title(Title), 1418 \object_page(Obj, [])). 1419pldoc_refman(Request) :- % server Contents.html 1420 \+ memberchk(path_info(_), Request), 1421 !, 1422 http_link_to_id(pldoc_object, [object(manual)], HREF), 1423 http_redirect(see_other, HREF, Request). 1424pldoc_refman(Request) :- 1425 memberchk(path(Path), Request), 1426 existence_error(http_location, Path). 1427 1428 1429 /******************************* 1430 * HOOK SEARCH * 1431 *******************************/ 1432 1433prologdoc_object_summary(section(ID), Class, File, Summary) :- 1434 nonvar(ID), % when generating, only do full ones 1435 manual_object(section(_Level, _No, ID, _Path), Summary, File, Class, _Offset). 1436prologdoc_object_summary(Obj, Class, File, Summary) :- 1437 manual_object(Obj, Summary, File, Class, _Offset). 1438 1439prologdoc_object_page(Obj, Options) --> 1440 man_page(Obj, [no_manual(fail),footer(false)|Options]).
1446prologdoc_object_link(Obj, Options) --> 1447 { Obj = section(_,_,_,_) }, 1448 !, 1449 section_link(Obj, Options). 1450prologdoc_object_link(Obj0, Options) --> 1451 { Obj0 = section(ID), 1452 Obj = section(_Level, _No, ID, _Path), 1453 manual_object(Obj, _, _, _, _) 1454 }, 1455 !, 1456 section_link(Obj, Options). 1457prologdoc_object_link(Obj, Options) --> 1458 { Obj = c(Function) }, 1459 !, 1460 function_link(Function, Options). 1461prologdoc_object_link(root, _) --> 1462 !, 1463 html('Documentation'). 1464prologdoc_object_link(manual, _Options) --> 1465 !, 1466 html('Reference manual'). 1467prologdoc_object_link(packages, _) --> 1468 html('Packages'). 1469prologdoc_object_link(xpce, _) --> 1470 html('XPCE'). 1471 1472prologdoc_category(manual, 30, 'Reference Manual'). 1473prologdoc_category(packages, 40, 'Packages'). 1474 1475prologdoc_file_index_header(File, Options) --> 1476 { Section = section(_Level, _No, _ID, File), 1477 manual_object(Section, _Summary, File, _Cat, _Offset) 1478 }, 1479 !, 1480 html(tr(th([colspan(3), class(section)], 1481 [ \object_ref(Section, 1482 [ secref_style(number_title) 1483 | Options 1484 ]) 1485 ]))). 1486 1487prologdoc_object_title(Obj, Title) :- 1488 Obj = section(_,_,_,_), 1489 manual_object(Obj, Title, _, _, _), 1490 !. 1491prologdoc_object_title(xpce, 'XPCE'). 1492prologdoc_object_title(xpce(Class, Kind, Name), Title) :- 1493 xpce_object_label(xpce(Class, Kind, Name), Title). 1494 1495% xpce class members appear in the index as xpce(Class, Kind, Name) 1496% (see packages/pldoc/doc_util.pl atom_to_object/2 and packages/xpce/ 1497% man/refmanual). Render link text as the conventional xpce arrow 1498% notation -- Class->name / Class<-name / Class<->name / Class.name -- 1499% so the entries are recognisable next to predicates. 1500 1501prologdoc_object_link(xpce(Class, Kind, Name), _Options) --> 1502 { xpce_object_label(xpce(Class, Kind, Name), Label) }, 1503 html(Label).
1510xpce_object_label(xpce(Class, Kind, Name), Label) :- 1511 xpce_member_arrow(Kind, Arrow), 1512 atomic_list_concat([Class, Arrow, Name], Label). 1513 1514xpce_member_arrow(send, '->'). 1515xpce_member_arrow(get, '<-'). 1516xpce_member_arrow(both, '<->'). 1517xpce_member_arrow(ivar, '-'). 1518xpce_member_arrow(classvar, '.'). 1519 1520% Predicates such as get_class/4 live in module =pce_principal=, but 1521% the user-facing entry point is =|library(pce)|=, which re-exports 1522% the boot modules. Rewrite the synopsis so it says what users 1523% should actually type. 1524 1525prologpldoc_synopsis_spec(pce(prolog/boot/_), library(pce)). 1526 1527prologdoc_canonical_object(section(_Level, _No, ID, _Path), 1528 section(ID)).
1534prologdoc_object_href(section(ID), HREF) :- 1535 nonvar(ID), 1536 atom_concat('sec:', Sec, ID), 1537 http_link_to_id(pldoc_man, [section(Sec)], HREF). 1538prologdoc_object_href(section(_Level, _No, ID, _Path), HREF) :- 1539 nonvar(ID), 1540 atom_concat('sec:', Sec, ID), 1541 http_link_to_id(pldoc_man, [section(Sec)], HREF). 1542 1543 1544 /******************************* 1545 * RESOLVE LINKS * 1546 *******************************/
predicate(PI)function(PI)section(Id)object(Text)1561man_param_object(predicate(PI), Obj) :- 1562 atom_pi(PI, Obj). 1563man_param_object(function(PI), f(Name/Arity)) :- 1564 atom_pi(PI, Name/Arity), 1565 integer(Arity). 1566man_param_object('CAPI'(Name), c(Name)). 1567man_param_object(section(Sec), section(ID)) :- 1568 atom_concat('sec:', Sec, ID). 1569man_param_object(object(Text), Obj) :- 1570 ( catch(atom_to_term(Text, Obj0, _), error(_,_), fail) 1571 -> Obj = Obj0 1572 ; atom_to_object(Text, Obj) 1573 ).
1581pldoc_href_object(HREF, Object) :- 1582 uri_components(HREF, Components), 1583 uri_data(path, Components, Path), 1584 atom(Path), 1585 man_handler_location(Path), 1586 uri_data(search, Components, Search), 1587 atom(Search), 1588 uri_query_components(Search, Query), 1589 member(Name=Value, Query), 1590 Param =.. [Name,Value], 1591 man_param_object(Param, Object), 1592 !. 1593 1594% Note that the handlers are only registered if the PlDoc server has 1595% been loaded. If it is not, we cannot resolve the link. 1596 1597man_handler_location(Path) :- 1598 man_handler_id(Id), 1599 catch(http_location_by_id(Id, Path), error(_,_), fail), 1600 !. 1601 1602man_handler_id(pldoc_man). 1603man_handler_id(pldoc_object).
1614man_object_uri(Object, URI) :-
1615 object_scheme_uri(man, Object, URI).link_scheme option of man_page//2.1622object_scheme_uri(Scheme, Object0, URI) :- 1623 localise_object(Object0, Object), 1624 ground(Object), 1625 format(atom(URI), '~w:~q', [Scheme, Object]). 1626 1627man_uri_object(URI, Object) :- 1628 atom_concat('man:', Text, URI), 1629 catch(term_to_atom(Object, Text), _, fail), 1630 ground(Object). 1631 1632 /******************************* 1633 * NO HTTP * 1634 *******************************/ 1635 1636:- if(\+current_predicate(http_location_by_id/2)). 1637 1638http_location_by_id(Id, Location) :- 1639 format(atom(Location), '/pldoc/~w', [Id]). 1640 1641:- endif. 1642 1643:- if(\+current_predicate(http_link_to_id/3)). 1644 1645http_link_to_id(Id, Parameters, HREF) :- 1646 must_be(list, Parameters), 1647 format(atom(Location), '/pldoc/~w', [Id]), 1648 ( Parameters == [] 1649 -> HREF = Location 1650 ; uri_data(path, Components, Location), 1651 uri_query_components(String, Parameters), 1652 uri_data(search, Components, String), 1653 uri_components(HREF, Components) 1654 ). 1655 1656:- endif. 1657 1658 /******************************* 1659 * MESSAGES * 1660 *******************************/ 1661 1662:- multifile prolog:message//1. 1663 1664prologmessage(pldoc(no_section_id(File, Title))) --> 1665 [ 'PlDoc: ~w: no id for section "~w"'-[File, Title] ]. 1666prologmessage(pldoc(duplicate_ids(L))) --> 1667 [ 'PlDoc: duplicate manual section IDs:'-[], nl 1668 ], 1669 duplicate_ids(L). 1670 1671duplicate_ids([]) --> []. 1672duplicate_ids([H|T]) --> duplicate_id(H), duplicate_ids(T). 1673 1674duplicate_id(Id) --> 1675 { findall(File, manual_object(section(_,_,Id,File),_,_,_,_), Files) }, 1676 [ ' ~w: ~p'-[Id, Files], nl ]
Process SWI-Prolog HTML manuals