View source with raw comments or as raw
    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)).

Documentation server

The module library(pldoc/http) provides an embedded HTTP documentation server that allows for browsing the documentation of all files loaded after library(pldoc) has been loaded. */

   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).
 doc_enable(+Boolean)
Actually activate the PlDoc server. Merely loading the server does not do so to avoid incidental loading in a user HTTP server making the documentation available.
   96doc_enable(true) :-
   97    (   doc_enabled
   98    ->  true
   99    ;   assertz(doc_enabled)
  100    ).
  101doc_enable(false) :-
  102    retractall(doc_enabled).
 doc_server(?Port) is det
 doc_server(?Port, +Options) is det
Start a documentation server in the current Prolog process. The server is started in a separate thread. Options are handed to http_server/2. In addition, the following options are recognised:
allow(HostOrIP)
Allow connections from HostOrIP. If HostOrIP is an atom it is matched to the hostname. It if starts with a ., suffix match is done, matching the domain. Finally it can be a term ip(A,B,C,D). See tcp_host_to_address/2 for details.
deny(HostOrIP)
See allow(HostOrIP).
edit(Bool)
Allow editing from localhost connections? Default: true.

The predicate doc_server/1 is defined as below, which provides a good default for development.

doc_server(Port) :-
        doc_server(Port,
                   [ allow(localhost)
                   ]).
See also
- doc_browser/1
  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)).
 doc_current_server(-Port) is det
TCP/IP port of the documentation server. Fails if no server is running. Note that in the current infrastructure we can easily be embedded into another Prolog HTTP server. If we are not started from doc_server/2, we return the port of a running HTTP server.
Errors
- existence_error(http_server, pldoc)
To be done
- Trap destruction of the server.
  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    ).
 doc_browser is det
 doc_browser(+What) is semidet
Open user's default browser on the documentation server.
  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).
 prepare_editor
Start XPCE as edit requests comming from the document server can only be handled if XPCE is running.
  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]).
 pldoc_root(+Request)
Reply using the index-page of the Prolog working directory. There are various options for the start directory. For example we could also use the file or directory of the file that would be edited using edit/0.
  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).
 pldoc_index(+Request)
HTTP handle for /index.html, providing an overall overview of the available documentation.
  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                    ]).
 pldoc_file(+Request)
Hander for /file?file=File, providing documentation for File.
  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, []).
 pldoc_edit(+Request)
HTTP handler that starts the user's default editor on the host running the server. This handler can only accessed if the browser connection originates from localhost. The call can edit files using the file attribute or a predicate if both name and arity is given and optionally module.
  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))).
 go_place(+Request)
HTTP handler to handle the places menu.
  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    ).
 allowed_directory(+Dir) is semidet
True if we are allowed to produce and index for Dir.
  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).
 allowed_file(+File) is semidet
True if we are allowed to serve File. Currently means we have predicates loaded from File or the directory must be allowed.
  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).
 pldoc_resource(+Request)
Handler for /res/File, serving CSS, JS and image files.
  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').
 pldoc_doc(+Request)
Handler for /doc/Path

Reply documentation of a file. Path is the absolute path of the file for which to return the documentation. Extension is either none, the Prolog extension or the HTML extension.

Note that we reply with pldoc.css if the file basename is pldoc.css to allow for a relative link from any directory.

  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).
 edit_options(+Request, -Options) is det
Return edit(true) in Options if the connection is from the localhost.
  603edit_options(Request, [edit(true)]) :-
  604    catch(http:authenticate(pldoc(edit), Request, _), _, fail),
  605    !.
  606edit_options(_, []).
 pl_file(+File, -PlFile) is semidet
  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).
 wiki_file(+File, -TxtFile) is semidet
True if TxtFile is an existing file that must be served as wiki file.
  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).
 clean_path(+AfterDoc, -AbsPath)
Restore the path, Notably deals Windows issues
  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).
 pldoc_man(+Request)
Handler for /man, offering one of the parameters:
predicate=PI
providing documentation from the manual on the predicate PI.
function=PI
providing documentation from the manual on the function PI.
CAPI=F
providing documentation from the manual on the C-function F.
  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]).
 pldoc_object(+Request)
Handler for /doc_for?object=Term, Provide documentation for the given term.
  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])).
 pldoc_search(+Request)
Search the collected PlDoc comments and Prolog manual.
  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      ])