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-2023, University of Amsterdam
    7                              VU University Amsterdam
    8                              SWI-Prolog Solutions b.v.
    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_files,
   38          [ doc_save/2,                 % +File, +Options
   39            doc_pack/1                  % +Pack (re-export from doc_pack)
   40          ]).   41:- use_module(library(pldoc), []).   42:- use_module(pldoc(doc_html)).   43:- use_module(pldoc(doc_index)).   44:- use_module(pldoc(doc_pack)).   45:- use_module(library(option)).   46:- use_module(library(lists)).   47:- use_module(library(filesex)).

Create stand-alone documentation files

Create stand-alone documentation from a bundle of source-files. Typical use of the PlDoc package is to run it as a web-server from the project in progress, providing search and guaranteed consistency with the loaded version. Creating stand-alone files as provided by this file can be useful for printing or distribution.

To be done
- Generate a predicate index? */
   60:- predicate_options(doc_save/2, 2,
   61                     [ format(oneof([html])),
   62                       doc_root(atom),
   63                       man_server(atom),
   64                       index_file(atom),
   65                       if(oneof([loaded,true])),
   66                       recursive(boolean),
   67                       css(oneof([copy,inline])),
   68                       title(atom),
   69                       include_reexported(boolean)
   70                     ]).
 doc_save(+FileOrDir, +Options)
Save documentation for FileOrDir to file(s). Options include
format(+Format)
Currently only supports html.
doc_root(+Dir)
Save output to the given directory. Default is to save the documentation for a file in the same directory as the file and for a directory in a subdirectory doc.
title(+Title)
Title is an atom that provides the HTML title of the main (index) page. Only meaningful when generating documentation for a directory.
man_server(+RootURL)
Root of a manual server used for references to built-in predicates. Default is http://www.swi-prolog.org/pldoc/
index_file(+Base)
Filename for directory indices. Default is index.
if(Condition)
What to do with files in a directory. loaded (default) only documents files loaded into the Prolog image. true documents all files.
recursive(+Bool)
If true, recurse into subdirectories.
css(+Mode)
If copy, copy the CSS file to created directories. Using inline, include the CSS file into the created files. Currently, only the default copy is supported.
include_reexported(+Boolean)
When true (default false), include predicates that are re-exported from this module into the documentation of the module.
  116%   The typical use-case is to document the Prolog files that belong
  117%   to a project in the  current  directory.   To  do  this load the
  118%   Prolog  files  and  run  the   goal    below.   This  creates  a
  119%   sub-directory  =doc=  with  an  index  file  =|index.html|=.  It
  120%   replicates the directory structure  of   the  source  directory,
  121%   creating an HTML file for each Prolog file and an index file for
  122%   each sub-directory. A  copy  of  the   required  CSS  and  image
  123%   resources is copied to the =doc= directory.
  124%
  125%     ==
  126%     ?- doc_save(., [recursive(true)]).
  127%     ==
  128
  129doc_save(Spec, Options) :-
  130    doc_target(Spec, Target, Options),
  131    target_directory(Target, Dir),
  132    phrase(file_map(Target), FileMap),
  133    merge_options([ html_resources(pldoc_files),
  134                    source_link(false),
  135                    resource_directory(Dir)
  136                  ], Options, Options1),
  137    Options2 = [files(FileMap)|Options1],
  138    setup_call_cleanup(
  139        nb_setval(pldoc_options, Options2),
  140        generate(Target, Options2),
  141        nb_delete(pldoc_options)),
  142    copy_resources(Dir, Options2).
 generate(+Spec, +Options) is det
Generate documentation for the specification created by doc_target/2.
  150generate([], _).
  151generate([H|T], Options) :-
  152    \+ \+ generate(H, Options),
  153    generate(T, Options).
  154generate(file(PlFile, DocFile), Options) :-
  155    b_setval(pldoc_output, DocFile),
  156    setup_call_cleanup(
  157        open(DocFile, write, Out, [encoding(utf8)]),
  158        with_output_to(Out, doc_for_file(PlFile, Options)),
  159        close(Out)).
  160generate(directory(Dir, IndexFile, Members, DirOptions), Options) :-
  161    append(DirOptions, Options, AllOptions),
  162    b_setval(pldoc_output, IndexFile),
  163    setup_call_cleanup(
  164        open(IndexFile, write, Out, [encoding(utf8)]),
  165        with_output_to(
  166            Out,
  167            doc_for_dir(Dir,
  168                        [ members(Members)
  169                        | AllOptions
  170                        ])),
  171        close(Out)),
  172    generate(Members, Options).
 doc_target(+Spec, -Target, +Options) is semidet
Generate a structure describing what to document in what files. This structure is a term:
file(PlFile, DocFile)
Document PlFile in DocFile
directory(Dir, IndexFile, Members, Options)
Document Dir in IndexFile. Members is a list of documentation structures.
  187doc_target(FileOrDir, file(File, DocFile), Options) :-
  188    absolute_file_name(FileOrDir, File,
  189                       [ file_type(prolog),
  190                         file_errors(fail),
  191                         access(read)
  192                       ]),
  193    !,
  194    (   option(source_root(_), Options)
  195    ->  Options1 = Options
  196    ;   file_directory_name(File, FileDir),
  197        Options1 = [source_root(FileDir)|Options]
  198    ),
  199    document_file(File, DocFile, Options1).
  200doc_target(FileOrDir, directory(Dir, Index, Members, DirOptions), Options0) :-
  201    absolute_file_name(FileOrDir, Dir,
  202                       [ file_type(directory),
  203                         file_errors(fail),
  204                         access(read)
  205                       ]),
  206    !,
  207    (   option(source_root(_), Options0)            % recursive
  208    ->  Options = Options0
  209    ;   Options1 = [source_root(Dir)|Options0],     % top
  210        exclude(main_option, Options1, Options2),
  211        set_doc_root(Dir, Options2, Options)
  212    ),
  213    DirOptions = Options,
  214    document_file(Dir, Index, Options),
  215    findall(Member,
  216            (   prolog_file_in_dir(Dir, File, Options),
  217                doc_target(File, Member, Options)
  218            ),
  219            Members).
 main_option(?Option)
Options that apply only to the main directory.
  225main_option(title(_)).
  226main_option(readme(_)).
  227main_option(todo(_)).
  228
  229target_directory(directory(_, Index, _, _), Dir) :-
  230    file_directory_name(Index, Dir).
  231target_directory(file(_, DocFile), Dir) :-
  232    file_directory_name(DocFile, Dir).
  233
  234set_doc_root(_Dir, Options0, Options) :-
  235    option(doc_root(_), Options0),
  236    !,
  237    Options = Options0.
  238set_doc_root(Dir, Options0, Options) :-
  239    directory_file_path(Dir, doc, DocRoot),
  240    Options = [doc_root(DocRoot)|Options0].
 file_map(+DocStruct, -List)
Create a list of file(PlFile, DocFile) for files that need to be documented.
  247file_map([]) -->
  248    [].
  249file_map([H|T]) -->
  250    file_map(H),
  251    file_map(T).
  252file_map(file(Src, Doc)) -->
  253    [ file(Src, Doc) ].
  254file_map(directory(_Dir, _Doc, Members, _Options)) -->
  255    file_map(Members).
 document_file(+FileOrDir, -DocFile, +Options) is semidet
DocFile is the file into which to write the documentation for File. File must be a canonical Prolog source-file.
  264document_file(FileOrDir, DocFile, Options) :-
  265    must_document(FileOrDir, Options),
  266    option(format(Format), Options, html),
  267    doc_extension(Format, Ext),
  268    (   exists_directory(FileOrDir)
  269    ->  option(index_file(IndexBase), Options, index),
  270        file_name_extension(IndexBase, Ext, Index),
  271        directory_file_path(FileOrDir, Index, DocFile0)
  272    ;   file_name_extension(Base, _, FileOrDir),
  273        file_name_extension(Base, Ext, DocFile0)
  274    ),
  275    (   option(doc_root(Dir), Options)
  276    ->  (   option(source_root(SrcTop), Options)
  277        ->  true
  278        ;   working_directory(SrcTop, SrcTop)
  279        ),
  280        directory_file_path(SrcTop, Local, DocFile0),
  281        directory_file_path(Dir, Local, DocFile),
  282        file_directory_name(DocFile, DocDir),
  283        make_directory_path(DocDir)
  284    ;   DocFile = DocFile0
  285    ).
  286
  287must_document(_FileOrDir, Options) :-
  288    \+ option(if(loaded), Options, loaded),
  289    !.
  290must_document(File, _Options) :-
  291    source_file(File),
  292    !.
  293must_document(Dir, _Options) :-
  294    exists_directory(Dir),
  295    source_file(SrcFile),
  296    sub_atom(SrcFile, 0, _, _, Dir),
  297    !.
 doc_extension(+Format, -Extension) is det
  301doc_extension(html, html).
  302doc_extension(latex, tex).
 prolog_file_in_dir(+Dir, -File, +Options) is nondet
File is a file in Dir that must be documented. Options:
recursive(+Bool)
If true, also generate subdirectories
  312prolog_file_in_dir(Dir, File, Options) :-
  313    (   option(if(loaded), Options, loaded)
  314    ->  source_file(File),
  315        file_directory_name(File, Dir)
  316    ;   user:prolog_file_type(Ext, prolog),
  317        \+ user:prolog_file_type(Ext, qlf),
  318        atomic_list_concat([Dir, '/*.', Ext], Pattern),
  319        expand_file_name(Pattern, Files),
  320        member(File, Files)
  321    ),
  322    file_base_name(File, Base),
  323    \+ blocked(Base).
  324prolog_file_in_dir(Dir, SubDir, Options) :-
  325    option(recursive(true), Options, false),
  326    option(doc_root(DocRoot), Options),
  327    atom_concat(Dir, '/*', Pattern),
  328    expand_file_name(Pattern, Matches),
  329    member(SubDir, Matches),
  330    SubDir \== DocRoot,
  331    exists_directory(SubDir).
 blocked(+File) is semidet
True if File is blocked from documentation.
  337blocked('INDEX.pl').
  338
  339
  340                 /*******************************
  341                 *           RESOURCES          *
  342                 *******************************/
 copy_resources(+Dir, +Options)
  346copy_resources(Dir, Options) :-
  347    option(format(Format), Options, html),
  348    forall(doc_resource(Format, Res),
  349           ( absolute_file_name(pldoc(Res), File, [access(read)]),
  350             copy_file(File, Dir))).
  351
  352doc_resource(html, 'pldoc.css').
  353doc_resource(html, 'h1-bg.png').
  354doc_resource(html, 'h2-bg.png').
  355doc_resource(html, 'multi-bg.png').
  356doc_resource(html, 'priv-bg.png').
  357doc_resource(html, 'pub-bg.png')