1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2006-2017, University of Amsterdam 7 VU University Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(pldoc_http, 37 [ doc_enable/1, % +Boolean 38 doc_server/1, % ?Port 39 doc_server/2, % ?Port, +Options 40 doc_browser/0, 41 doc_browser/1 % +What 42 ]). 43:- use_module(library(pldoc)). 44:- use_module(library(http/thread_httpd)). 45:- use_module(library(http/http_parameters)). 46:- use_module(library(http/html_write)). 47:- use_module(library(http/mimetype)). 48:- use_module(library(dcg/basics)). 49:- use_module(library(http/http_dispatch)). 50:- use_module(library(http/http_hook)). 51:- use_module(library(http/http_path)). 52:- use_module(library(http/http_wrapper)). 53:- use_module(library(uri)). 54:- use_module(library(debug)). 55:- use_module(library(lists)). 56:- use_module(library(url)). 57:- use_module(library(socket)). 58:- use_module(library(option)). 59:- use_module(library(error)). 60:- use_module(library(www_browser)). 61:- use_module(pldoc(doc_process)). 62:- use_module(pldoc(doc_htmlsrc)). 63:- use_module(pldoc(doc_html)). 64:- use_module(pldoc(doc_index)). 65:- use_module(pldoc(doc_search)). 66:- use_module(pldoc(doc_man)). 67:- use_module(pldoc(doc_wiki)). 68:- use_module(pldoc(doc_util)). 69:- use_module(pldoc(doc_access)). 70:- use_module(pldoc(doc_pack)). 71:- use_module(pldoc(man_index)). 72 73/** <module> Documentation server 74 75The module library(pldoc/http) provides an embedded HTTP documentation 76server that allows for browsing the documentation of all files loaded 77_after_ library(pldoc) has been loaded. 78*/ 79 80:- dynamic 81 doc_server_port/1, 82 doc_enabled/0. 83 84http:location(pldoc, root(pldoc), []). 85http:location(pldoc_man, pldoc(refman), []). 86http:location(pldoc_pkg, pldoc(package), []). 87http:location(pldoc_resource, Path, []) :- 88 http_location_by_id(pldoc_resource, Path). 89 90%! doc_enable(+Boolean) 91% 92% Actually activate the PlDoc server. Merely loading the server does 93% not do so to avoid incidental loading in a user HTTP server making 94% the documentation available. 95 96doc_enable(true) :- 97 ( doc_enabled 98 -> true 99 ; assertz(doc_enabled) 100 ). 101doc_enable(false) :- 102 retractall(doc_enabled). 103 104%! doc_server(?Port) is det. 105%! doc_server(?Port, +Options) is det. 106% 107% Start a documentation server in the current Prolog process. The 108% server is started in a separate thread. Options are handed to 109% http_server/2. In addition, the following options are 110% recognised: 111% 112% * allow(HostOrIP) 113% Allow connections from HostOrIP. If HostOrIP is an atom 114% it is matched to the hostname. It if starts with a ., 115% suffix match is done, matching the domain. Finally it 116% can be a term ip(A,B,C,D). See tcp_host_to_address/2 for 117% details. 118% 119% * deny(HostOrIP) 120% See allow(HostOrIP). 121% 122% * edit(Bool) 123% Allow editing from localhost connections? Default: 124% =true=. 125% 126% The predicate doc_server/1 is defined as below, which provides a 127% good default for development. 128% 129% == 130% doc_server(Port) :- 131% doc_server(Port, 132% [ allow(localhost) 133% ]). 134% == 135% 136% @see doc_browser/1 137 138doc_server(Port) :- 139 doc_server(Port, 140 [ allow(localhost), 141 allow(ip(127,0,0,1)) % Windows ip-->host often fails 142 ]). 143 144doc_server(Port, _) :- 145 doc_enable(true), 146 catch(doc_current_server(Port), _, fail), 147 !. 148doc_server(Port, Options) :- 149 doc_enable(true), 150 prepare_editor, 151 host_access_options(Options, ServerOptions), 152 http_absolute_location(pldoc('.'), Entry, []), 153 merge_options(ServerOptions, 154 [ port(Port), 155 entry_page(Entry) 156 ], HTTPOptions), 157 http_server(http_dispatch, HTTPOptions), 158 assertz(doc_server_port(Port)). 159 160%! doc_current_server(-Port) is det. 161% 162% TCP/IP port of the documentation server. Fails if no server is 163% running. Note that in the current infrastructure we can easily 164% be embedded into another Prolog HTTP server. If we are not 165% started from doc_server/2, we return the port of a running 166% HTTP server. 167% 168% @tbd Trap destruction of the server. 169% @error existence_error(http_server, pldoc) 170 171doc_current_server(Port) :- 172 ( doc_server_port(P) 173 -> Port = P 174 ; http_current_server(_:_, P) 175 -> Port = P 176 ; existence_error(http_server, pldoc) 177 ). 178 179%! doc_browser is det. 180%! doc_browser(+What) is semidet. 181% 182% Open user's default browser on the documentation server. 183 184doc_browser :- 185 doc_browser([]). 186doc_browser(Spec) :- 187 catch(doc_current_server(Port), 188 error(existence_error(http_server, pldoc), _), 189 doc_server(Port)), 190 browser_url(Spec, Request), 191 format(string(URL), 'http://localhost:~w~w', [Port, Request]), 192 www_open_url(URL). 193 194browser_url([], Root) :- 195 !, 196 http_location_by_id(pldoc_root, Root). 197browser_url(Name, URL) :- 198 atom(Name), 199 !, 200 browser_url(Name/_, URL). 201browser_url(Name//Arity, URL) :- 202 must_be(atom, Name), 203 integer(Arity), 204 !, 205 PredArity is Arity+2, 206 browser_url(Name/PredArity, URL). 207browser_url(Name/Arity, URL) :- 208 !, 209 must_be(atom, Name), 210 ( man_object_property(Name/Arity, summary(_)) 211 -> format(string(S), '~q/~w', [Name, Arity]), 212 http_link_to_id(pldoc_man, [predicate=S], URL) 213 ; browser_url(_:Name/Arity, URL) 214 ). 215browser_url(Spec, URL) :- 216 !, 217 Spec = M:Name/Arity, 218 doc_comment(Spec, _Pos, _Summary, _Comment), 219 !, 220 ( var(M) 221 -> format(string(S), '~q/~w', [Name, Arity]) 222 ; format(string(S), '~q:~q/~w', [M, Name, Arity]) 223 ), 224 http_link_to_id(pldoc_object, [object=S], URL). 225 226%! prepare_editor 227% 228% Start XPCE as edit requests comming from the document server can 229% only be handled if XPCE is running. 230 231prepare_editor :- 232 current_prolog_flag(editor, pce_emacs), 233 !, 234 start_emacs. 235prepare_editor. 236 237 238 /******************************* 239 * USER REPLIES * 240 *******************************/ 241 242:- http_handler(pldoc(.), pldoc_root, 243 [ prefix, 244 authentication(pldoc(read)), 245 condition(doc_enabled) 246 ]). 247:- http_handler(pldoc('index.html'), pldoc_index, []). 248:- http_handler(pldoc(file), pldoc_file, []). 249:- http_handler(pldoc(place), go_place, []). 250:- http_handler(pldoc(edit), pldoc_edit, 251 [authentication(pldoc(edit))]). 252:- http_handler(pldoc(doc), pldoc_doc, [prefix]). 253:- http_handler(pldoc(man), pldoc_man, []). 254:- http_handler(pldoc(doc_for), pldoc_object, [id(pldoc_doc_for)]). 255:- http_handler(pldoc(search), pldoc_search, []). 256:- http_handler(pldoc('res/'), pldoc_resource, [prefix]). 257 258 259%! pldoc_root(+Request) 260% 261% Reply using the index-page of the Prolog working directory. 262% There are various options for the start directory. For example 263% we could also use the file or directory of the file that would 264% be edited using edit/0. 265 266pldoc_root(Request) :- 267 http_parameters(Request, 268 [ empty(Empty, [ oneof([true,false]), 269 default(false) 270 ]) 271 ]), 272 pldoc_root(Request, Empty). 273 274pldoc_root(Request, false) :- 275 http_location_by_id(pldoc_root, Root), 276 memberchk(path(Path), Request), 277 Root \== Path, 278 !, 279 existence_error(http_location, Path). 280pldoc_root(_Request, false) :- 281 working_directory(Dir0, Dir0), 282 allowed_directory(Dir0), 283 !, 284 ensure_slash_end(Dir0, Dir1), 285 doc_file_href(Dir1, Ref0), 286 atom_concat(Ref0, 'index.html', Index), 287 throw(http_reply(see_other(Index))). 288pldoc_root(Request, _) :- 289 pldoc_index(Request). 290 291 292%! pldoc_index(+Request) 293% 294% HTTP handle for /index.html, providing an overall overview 295% of the available documentation. 296 297pldoc_index(_Request) :- 298 reply_html_page(pldoc(index), 299 title('SWI-Prolog documentation'), 300 [ \doc_links('', []), 301 h1('SWI-Prolog documentation'), 302 \man_overview([]) 303 ]). 304 305 306%! pldoc_file(+Request) 307% 308% Hander for /file?file=File, providing documentation for File. 309 310pldoc_file(Request) :- 311 http_parameters(Request, 312 [ file(File, []) 313 ]), 314 ( source_file(File) 315 -> true 316 ; throw(http_reply(forbidden(File))) 317 ), 318 doc_for_file(File, []). 319 320%! pldoc_edit(+Request) 321% 322% HTTP handler that starts the user's default editor on the host 323% running the server. This handler can only accessed if the 324% browser connection originates from =localhost=. The call can 325% edit files using the =file= attribute or a predicate if both 326% =name= and =arity= is given and optionally =module=. 327 328pldoc_edit(Request) :- 329 http:authenticate(pldoc(edit), Request, _), 330 http_parameters(Request, 331 [ file(File, 332 [ optional(true), 333 description('Name of the file to edit') 334 ]), 335 line(Line, 336 [ optional(true), 337 integer, 338 description('Line in the file') 339 ]), 340 name(Name, 341 [ optional(true), 342 description('Name of a Prolog predicate to edit') 343 ]), 344 arity(Arity, 345 [ integer, 346 optional(true), 347 description('Arity of a Prolog predicate to edit') 348 ]), 349 module(Module, 350 [ optional(true), 351 description('Name of a Prolog module to search for predicate') 352 ]) 353 ]), 354 ( atom(File) 355 -> allowed_file(File) 356 ; true 357 ), 358 ( atom(File), integer(Line) 359 -> Edit = file(File, line(Line)) 360 ; atom(File) 361 -> Edit = file(File) 362 ; atom(Name), integer(Arity) 363 -> ( atom(Module) 364 -> Edit = (Module:Name/Arity) 365 ; Edit = (Name/Arity) 366 ) 367 ), 368 edit(Edit), 369 format('Content-type: text/plain~n~n'), 370 format('Started ~q~n', [edit(Edit)]). 371pldoc_edit(_Request) :- 372 http_location_by_id(pldoc_edit, Location), 373 throw(http_reply(forbidden(Location))). 374 375 376%! go_place(+Request) 377% 378% HTTP handler to handle the places menu. 379 380go_place(Request) :- 381 http_parameters(Request, 382 [ place(Place, []) 383 ]), 384 places(Place). 385 386places(':packs:') :- 387 !, 388 http_link_to_id(pldoc_pack, [], HREF), 389 throw(http_reply(moved(HREF))). 390places(Dir0) :- 391 expand_alias(Dir0, Dir), 392 ( allowed_directory(Dir) 393 -> format(string(IndexFile), '~w/index.html', [Dir]), 394 doc_file_href(IndexFile, HREF), 395 throw(http_reply(moved(HREF))) 396 ; throw(http_reply(forbidden(Dir))) 397 ). 398 399 400%! allowed_directory(+Dir) is semidet. 401% 402% True if we are allowed to produce and index for Dir. 403 404allowed_directory(Dir) :- 405 source_directory(Dir), 406 !. 407allowed_directory(Dir) :- 408 working_directory(CWD, CWD), 409 same_file(CWD, Dir). 410allowed_directory(Dir) :- 411 prolog:doc_directory(Dir). 412 413 414%! allowed_file(+File) is semidet. 415% 416% True if we are allowed to serve File. Currently means we have 417% predicates loaded from File or the directory must be allowed. 418 419allowed_file(File) :- 420 source_file(_, File), 421 !. 422allowed_file(File) :- 423 absolute_file_name(File, Canonical), 424 file_directory_name(Canonical, Dir), 425 allowed_directory(Dir). 426 427 428%! pldoc_resource(+Request) 429% 430% Handler for /res/File, serving CSS, JS and image files. 431 432pldoc_resource(Request) :- 433 http_location_by_id(pldoc_resource, ResRoot), 434 memberchk(path(Path), Request), 435 atom_concat(ResRoot, File, Path), 436 file(File, Local), 437 http_reply_file(pldoc(Local), [], Request). 438 439file('pldoc.css', 'pldoc.css'). 440file('pllisting.css', 'pllisting.css'). 441file('pldoc.js', 'pldoc.js'). 442file('edit.png', 'edit.png'). 443file('editpred.png', 'editpred.png'). 444file('up.gif', 'up.gif'). 445file('source.png', 'source.png'). 446file('public.png', 'public.png'). 447file('private.png', 'private.png'). 448file('reload.png', 'reload.png'). 449file('favicon.ico', 'favicon.ico'). 450file('h1-bg.png', 'h1-bg.png'). 451file('h2-bg.png', 'h2-bg.png'). 452file('pub-bg.png', 'pub-bg.png'). 453file('priv-bg.png', 'priv-bg.png'). 454file('multi-bg.png', 'multi-bg.png'). 455 456 457%! pldoc_doc(+Request) 458% 459% Handler for /doc/Path 460% 461% Reply documentation of a file. Path is the absolute path of the 462% file for which to return the documentation. Extension is either 463% none, the Prolog extension or the HTML extension. 464% 465% Note that we reply with pldoc.css if the file basename is 466% pldoc.css to allow for a relative link from any directory. 467 468pldoc_doc(Request) :- 469 memberchk(path(ReqPath), Request), 470 http_location_by_id(pldoc_doc, Me), 471 atom_concat(Me, AbsFile0, ReqPath), 472 ( sub_atom(ReqPath, _, _, 0, /) 473 -> atom_concat(ReqPath, 'index.html', File), 474 throw(http_reply(moved(File))) 475 ; clean_path(AbsFile0, AbsFile1), 476 expand_alias(AbsFile1, AbsFile), 477 is_absolute_file_name(AbsFile) 478 -> documentation(AbsFile, Request) 479 ). 480 481documentation(Path, Request) :- 482 file_base_name(Path, Base), 483 file(_, Base), % serve pldoc.css, etc. 484 !, 485 http_reply_file(pldoc(Base), [], Request). 486documentation(Path, Request) :- 487 file_name_extension(_, Ext, Path), 488 autolink_extension(Ext, image), 489 http_reply_file(Path, [unsafe(true)], Request). 490documentation(Path, Request) :- 491 Index = '/index.html', 492 sub_atom(Path, _, _, 0, Index), 493 atom_concat(Dir, Index, Path), 494 exists_directory(Dir), % Directory index 495 !, 496 ( allowed_directory(Dir) 497 -> edit_options(Request, EditOptions), 498 doc_for_dir(Dir, EditOptions) 499 ; throw(http_reply(forbidden(Dir))) 500 ). 501documentation(File, Request) :- 502 wiki_file(File, WikiFile), 503 !, 504 ( allowed_file(WikiFile) 505 -> true 506 ; throw(http_reply(forbidden(File))) 507 ), 508 edit_options(Request, Options), 509 doc_for_wiki_file(WikiFile, Options). 510documentation(Path, Request) :- 511 pl_file(Path, File), 512 !, 513 ( allowed_file(File) 514 -> true 515 ; throw(http_reply(forbidden(File))) 516 ), 517 doc_reply_file(File, Request). 518documentation(Path, _) :- 519 throw(http_reply(not_found(Path))). 520 521:- public 522 doc_reply_file/2. 523 524doc_reply_file(File, Request) :- 525 http_parameters(Request, 526 [ public_only(Public), 527 reload(Reload), 528 show(Show), 529 format_comments(FormatComments) 530 ], 531 [ attribute_declarations(param) 532 ]), 533 ( exists_file(File) 534 -> true 535 ; throw(http_reply(not_found(File))) 536 ), 537 ( Reload == true, 538 source_file(File) 539 -> load_files(File, [if(changed), imports([])]) 540 ; true 541 ), 542 edit_options(Request, EditOptions), 543 ( Show == src 544 -> format('Content-type: text/html~n~n', []), 545 source_to_html(File, stream(current_output), 546 [ skin(src_skin(Request, Show, FormatComments)), 547 format_comments(FormatComments) 548 ]) 549 ; Show == raw 550 -> http_reply_file(File, 551 [ unsafe(true), % is already validated 552 mime_type(text/plain) 553 ], Request) 554 ; doc_for_file(File, 555 [ public_only(Public), 556 source_link(true) 557 | EditOptions 558 ]) 559 ). 560 561 562:- public src_skin/5. % called through source_to_html/3. 563 564src_skin(Request, _Show, FormatComments, header, Out) :- 565 memberchk(request_uri(ReqURI), Request), 566 negate(FormatComments, AltFormatComments), 567 replace_parameters(ReqURI, [show(raw)], RawLink), 568 replace_parameters(ReqURI, [format_comments(AltFormatComments)], CmtLink), 569 phrase(html(div(class(src_formats), 570 [ 'View source with ', 571 a(href(CmtLink), \alt_view(AltFormatComments)), 572 ' or as ', 573 a(href(RawLink), raw) 574 ])), Tokens), 575 print_html(Out, Tokens). 576 577alt_view(true) --> 578 html('formatted comments'). 579alt_view(false) --> 580 html('raw comments'). 581 582negate(true, false). 583negate(false, true). 584 585replace_parameters(ReqURI, Extra, URI) :- 586 uri_components(ReqURI, C0), 587 uri_data(search, C0, Search0), 588 ( var(Search0) 589 -> uri_query_components(Search, Extra) 590 ; uri_query_components(Search0, Form0), 591 merge_options(Extra, Form0, Form), 592 uri_query_components(Search, Form) 593 ), 594 uri_data(search, C0, Search, C), 595 uri_components(URI, C). 596 597 598%! edit_options(+Request, -Options) is det. 599% 600% Return edit(true) in Options if the connection is from the 601% localhost. 602 603edit_options(Request, [edit(true)]) :- 604 catch(http:authenticate(pldoc(edit), Request, _), _, fail), 605 !. 606edit_options(_, []). 607 608 609%! pl_file(+File, -PlFile) is semidet. 610 611pl_file(File, PlFile) :- 612 file_name_extension(Base, html, File), 613 !, 614 absolute_file_name(Base, 615 PlFile, 616 [ file_errors(fail), 617 file_type(prolog), 618 access(read) 619 ]). 620pl_file(File, File). 621 622%! wiki_file(+File, -TxtFile) is semidet. 623% 624% True if TxtFile is an existing file that must be served as wiki 625% file. 626 627wiki_file(File, TxtFile) :- 628 file_name_extension(_, Ext, File), 629 wiki_file_extension(Ext), 630 !, 631 TxtFile = File. 632wiki_file(File, TxtFile) :- 633 file_base_name(File, Base), 634 autolink_file(Base, wiki), 635 !, 636 TxtFile = File. 637wiki_file(File, TxtFile) :- 638 file_name_extension(Base, html, File), 639 wiki_file_extension(Ext), 640 file_name_extension(Base, Ext, TxtFile), 641 access_file(TxtFile, read). 642 643wiki_file_extension(md). 644wiki_file_extension(txt). 645 646 647%! clean_path(+AfterDoc, -AbsPath) 648% 649% Restore the path, Notably deals Windows issues 650 651clean_path(Path0, Path) :- 652 current_prolog_flag(windows, true), 653 sub_atom(Path0, 2, _, _, :), 654 !, 655 sub_atom(Path0, 1, _, 0, Path). 656clean_path(Path, Path). 657 658 659%! pldoc_man(+Request) 660% 661% Handler for /man, offering one of the parameters: 662% 663% * predicate=PI 664% providing documentation from the manual on the predicate PI. 665% * function=PI 666% providing documentation from the manual on the function PI. 667% * 'CAPI'=F 668% providing documentation from the manual on the C-function F. 669 670pldoc_man(Request) :- 671 http_parameters(Request, 672 [ predicate(PI, [optional(true)]), 673 function(Fun, [optional(true)]), 674 'CAPI'(F, [optional(true)]), 675 section(Sec, [optional(true)]) 676 ]), 677 ( ground(PI) 678 -> atom_pi(PI, Obj) 679 ; ground(Fun) 680 -> atomic_list_concat([Name,ArityAtom], /, Fun), 681 atom_number(ArityAtom, Arity), 682 Obj = f(Name/Arity) 683 ; ground(F) 684 -> Obj = c(F) 685 ; ground(Sec) 686 -> atom_concat('sec:', Sec, SecID), 687 Obj = section(SecID) 688 ), 689 man_title(Obj, Title), 690 reply_html_page( 691 pldoc(object(Obj)), 692 title(Title), 693 \man_page(Obj, [])). 694 695man_title(f(Obj), Title) :- 696 !, 697 format(atom(Title), 'SWI-Prolog -- function ~w', [Obj]). 698man_title(c(Obj), Title) :- 699 !, 700 format(atom(Title), 'SWI-Prolog -- API-function ~w', [Obj]). 701man_title(section(_Id), Title) :- 702 !, 703 format(atom(Title), 'SWI-Prolog -- Manual', []). 704man_title(Obj, Title) :- 705 format(atom(Title), 'SWI-Prolog -- ~w', [Obj]). 706 707%! pldoc_object(+Request) 708% 709% Handler for /doc_for?object=Term, Provide documentation for the 710% given term. 711 712pldoc_object(Request) :- 713 http_parameters(Request, 714 [ object(Atom, []), 715 header(Header, [default(true)]) 716 ]), 717 ( catch(atom_to_term(Atom, Obj, _), error(_,_), fail) 718 -> true 719 ; atom_to_object(Atom, Obj) 720 ), 721 ( prolog:doc_object_title(Obj, Title) 722 -> true 723 ; Title = Atom 724 ), 725 edit_options(Request, EditOptions), 726 reply_html_page( 727 pldoc(object(Obj)), 728 title(Title), 729 \object_page(Obj, [header(Header)|EditOptions])). 730 731 732%! pldoc_search(+Request) 733% 734% Search the collected PlDoc comments and Prolog manual. 735 736pldoc_search(Request) :- 737 http_parameters(Request, 738 [ for(For, 739 [ optional(true), 740 description('String to search for') 741 ]), 742 page(Page, 743 [ integer, 744 default(1), 745 description('Page of search results to view') 746 ]), 747 in(In, 748 [ oneof([all,app,noapp,man,lib,pack,wiki]), 749 default(all), 750 description('Search everying, application only or manual only') 751 ]), 752 match(Match, 753 [ oneof([name,summary]), 754 default(summary), 755 description('Match only the name or also the summary') 756 ]), 757 resultFormat(Format, 758 [ oneof(long,summary), 759 default(summary), 760 description('Return full documentation or summary-lines') 761 ]) 762 ]), 763 edit_options(Request, EditOptions), 764 format(string(Title), 'Prolog search -- ~w', [For]), 765 reply_html_page(pldoc(search(For)), 766 title(Title), 767 \search_reply(For, 768 [ resultFormat(Format), 769 search_in(In), 770 search_match(Match), 771 page(Page) 772 | EditOptions 773 ])). 774 775 776 /******************************* 777 * HTTP PARAMETER TYPES * 778 *******************************/ 779 780:- public 781 param/2. % used in pack documentation server 782 783param(public_only, 784 [ boolean, 785 default(true), 786 description('If true, hide private predicates') 787 ]). 788param(reload, 789 [ boolean, 790 default(false), 791 description('Reload the file and its documentation') 792 ]). 793param(show, 794 [ oneof([doc,src,raw]), 795 default(doc), 796 description('How to show the file') 797 ]). 798param(format_comments, 799 [ boolean, 800 default(true), 801 description('If true, use PlDoc for rendering structured comments') 802 ]). 803