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)  2001-2016, 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(prolog_listing,
   37        [ listing/0,
   38          listing/1,
   39          portray_clause/1,             % +Clause
   40          portray_clause/2,             % +Stream, +Clause
   41          portray_clause/3              % +Stream, +Clause, +Options
   42        ]).   43:- use_module(library(lists)).   44:- use_module(library(settings)).   45:- use_module(library(option)).   46:- use_module(library(error)).   47:- set_prolog_flag(generate_debug_info, false).   48
   49:- module_transparent
   50    listing/0.   51:- meta_predicate
   52    listing(:),
   53    portray_clause(+,+,:).   54
   55:- predicate_options(portray_clause/3, 3, [pass_to(system:write_term/3, 3)]).   56
   57:- multifile
   58    prolog:locate_clauses/2.        % +Spec, -ClauseRefList

List programs and pretty print clauses

This module implements listing code from the internal representation in a human readable format.

Layout can be customized using library(settings). The effective settings can be listed using list_settings/1 as illustrated below. Settings can be changed using set_setting/2.

?- list_settings(listing).
========================================================================
Name                      Value (*=modified) Comment
========================================================================
listing:body_indentation  8              Indentation used goals in the body
listing:tab_distance      8              Distance between tab-stops.
...
To be done
- More settings, support Coding Guidelines for Prolog and make the suggestions there the default.
- Provide persistent user customization */
   88:- setting(listing:body_indentation, nonneg, 8,
   89           'Indentation used goals in the body').   90:- setting(listing:tab_distance, nonneg, 8,
   91           'Distance between tab-stops.  0 uses only spaces').   92:- setting(listing:cut_on_same_line, boolean, true,
   93           'Place cuts (!) on the same line').   94:- setting(listing:line_width, nonneg, 78,
   95           'Width of a line.  0 is infinite').
 listing
Lists all predicates defined in the calling module. Imported predicates are not listed. To list the content of the module mymodule, use:
?- mymodule:listing.
  108listing :-
  109    context_module(Context),
  110    list_module(Context).
  111
  112list_module(Module) :-
  113    (   current_predicate(_, Module:Pred),
  114        \+ predicate_property(Module:Pred, imported_from(_)),
  115        strip_module(Pred, _Module, Head),
  116        functor(Head, Name, _Arity),
  117        (   (   predicate_property(Pred, built_in)
  118            ;   sub_atom(Name, 0, _, _, $)
  119            )
  120        ->  current_prolog_flag(access_level, system)
  121        ;   true
  122        ),
  123        nl,
  124        list_predicate(Module:Head, Module),
  125        fail
  126    ;   true
  127    ).
 listing(:What)
List matching clauses. What is either a plain specification or a list of specifications. Plain specifications are:
  148listing(M:Spec) :-
  149    var(Spec),
  150    !,
  151    list_module(M).
  152listing(M:List) :-
  153    is_list(List),
  154    !,
  155    forall(member(Spec, List),
  156           listing(M:Spec)).
  157listing(X) :-
  158    (   prolog:locate_clauses(X, ClauseRefs)
  159    ->  list_clauserefs(ClauseRefs)
  160    ;   '$find_predicate'(X, Preds),
  161        list_predicates(Preds, X)
  162    ).
  163
  164list_clauserefs([]) :- !.
  165list_clauserefs([H|T]) :-
  166    !,
  167    list_clauserefs(H),
  168    list_clauserefs(T).
  169list_clauserefs(Ref) :-
  170    clause(Head, Body, Ref),
  171    portray_clause((Head :- Body)).
 list_predicates(:Preds:list(pi), :Spec) is det
  175list_predicates(PIs, Context:X) :-
  176    member(PI, PIs),
  177    pi_to_head(PI, Pred),
  178    unify_args(Pred, X),
  179    list_define(Pred, DefPred),
  180    list_predicate(DefPred, Context),
  181    nl,
  182    fail.
  183list_predicates(_, _).
  184
  185list_define(Head, LoadModule:Head) :-
  186    compound(Head),
  187    Head \= (_:_),
  188    functor(Head, Name, Arity),
  189    '$find_library'(_, Name, Arity, LoadModule, Library),
  190    !,
  191    use_module(Library, []).
  192list_define(M:Pred, DefM:Pred) :-
  193    '$define_predicate'(M:Pred),
  194    (   predicate_property(M:Pred, imported_from(DefM))
  195    ->  true
  196    ;   DefM = M
  197    ).
  198
  199pi_to_head(PI, _) :-
  200    var(PI),
  201    !,
  202    instantiation_error(PI).
  203pi_to_head(M:PI, M:Head) :-
  204    !,
  205    pi_to_head(PI, Head).
  206pi_to_head(Name/Arity, Head) :-
  207    functor(Head, Name, Arity).
  208
  209
  210%       Unify the arguments of the specification with the given term,
  211%       so we can partially instantate the head.
  212
  213unify_args(_, _/_) :- !.                % Name/arity spec
  214unify_args(X, X) :- !.
  215unify_args(_:X, X) :- !.
  216unify_args(_, _).
  217
  218list_predicate(Pred, Context) :-
  219    predicate_property(Pred, undefined),
  220    !,
  221    decl_term(Pred, Context, Decl),
  222    format('%   Undefined: ~q~n', [Decl]).
  223list_predicate(Pred, Context) :-
  224    predicate_property(Pred, foreign),
  225    !,
  226    decl_term(Pred, Context, Decl),
  227    format('%   Foreign: ~q~n', [Decl]).
  228list_predicate(Pred, Context) :-
  229    notify_changed(Pred, Context),
  230    list_declarations(Pred, Context),
  231    list_clauses(Pred, Context).
  232
  233decl_term(Pred, Context, Decl) :-
  234    strip_module(Pred, Module, Head),
  235    functor(Head, Name, Arity),
  236    (   hide_module(Module, Context, Head)
  237    ->  Decl = Name/Arity
  238    ;   Decl = Module:Name/Arity
  239    ).
  240
  241
  242decl(thread_local, thread_local).
  243decl(dynamic,      dynamic).
  244decl(volatile,     volatile).
  245decl(multifile,    multifile).
  246decl(public,       public).
  247
  248declaration(Pred, Source, Decl) :-
  249    decl(Prop, Declname),
  250    predicate_property(Pred, Prop),
  251    decl_term(Pred, Source, Funct),
  252    Decl =.. [ Declname, Funct ].
  253declaration(Pred, Source, Decl) :-
  254    predicate_property(Pred, meta_predicate(Head)),
  255    strip_module(Pred, Module, _),
  256    (   (Module == system; Source == Module)
  257    ->  Decl = meta_predicate(Head)
  258    ;   Decl = meta_predicate(Module:Head)
  259    ),
  260    (   meta_implies_transparent(Head)
  261    ->  !                                   % hide transparent
  262    ;   true
  263    ).
  264declaration(Pred, Source, Decl) :-
  265    predicate_property(Pred, transparent),
  266    decl_term(Pred, Source, PI),
  267    Decl = module_transparent(PI).
 meta_implies_transparent(+Head) is semidet
True if the meta-declaration Head implies that the predicate is transparent.
  274meta_implies_transparent(Head):-
  275    compound(Head),
  276    arg(_, Head, Arg),
  277    implies_transparent(Arg),
  278    !.
  279
  280implies_transparent(Arg) :-
  281    integer(Arg),
  282    !.
  283implies_transparent(:).
  284implies_transparent(//).
  285implies_transparent(^).
  286
  287
  288list_declarations(Pred, Source) :-
  289    findall(Decl, declaration(Pred, Source, Decl), Decls),
  290    (   Decls == []
  291    ->  true
  292    ;   write_declarations(Decls, Source),
  293        format('~n', [])
  294    ).
  295
  296
  297write_declarations([], _) :- !.
  298write_declarations([H|T], Module) :-
  299    format(':- ~q.~n', [H]),
  300    write_declarations(T, Module).
  301
  302list_clauses(Pred, Source) :-
  303    strip_module(Pred, Module, Head),
  304    (   clause(Pred, Body),
  305        write_module(Module, Source, Head),
  306        portray_clause((Head:-Body)),
  307        fail
  308    ;   true
  309    ).
  310
  311write_module(Module, Context, Head) :-
  312    hide_module(Module, Context, Head),
  313    !.
  314write_module(Module, _, _) :-
  315    format('~q:', [Module]).
  316
  317hide_module(system, Module, Head) :-
  318    predicate_property(Module:Head, imported_from(M)),
  319    predicate_property(system:Head, imported_from(M)),
  320    !.
  321hide_module(Module, Module, _) :- !.
  322
  323notify_changed(Pred, Context) :-
  324    strip_module(Pred, user, Head),
  325    predicate_property(Head, built_in),
  326    \+ predicate_property(Head, (dynamic)),
  327    !,
  328    decl_term(Pred, Context, Decl),
  329    format('%   NOTE: system definition has been overruled for ~q~n',
  330           [Decl]).
  331notify_changed(_, _).
 portray_clause(+Clause) is det
 portray_clause(+Out:stream, +Clause) is det
 portray_clause(+Out:stream, +Clause, +Options) is det
Portray `Clause' on the current output stream. Layout of the clause is to our best standards. As the actual variable names are not available we use A, B, ... Deals with ';', '|', '->' and calls via meta-call predicates as determined using the predicate property meta_predicate. If Clause contains attributed variables, these are treated as normal variables.

If Options is provided, the option-list is passed to write_term/3 that does the final writing of arguments.

  347%       The prolog_list_goal/1 hook is  a  dubious   as  it  may lead to
  348%       confusion if the heads relates to other   bodies.  For now it is
  349%       only used for XPCE methods and works just nice.
  350%
  351%       Not really ...  It may confuse the source-level debugger.
  352
  353%portray_clause(Head :- _Body) :-
  354%       user:prolog_list_goal(Head), !.
  355portray_clause(Term) :-
  356    current_output(Out),
  357    portray_clause(Out, Term).
  358
  359portray_clause(Stream, Term) :-
  360    must_be(stream, Stream),
  361    portray_clause(Stream, Term, []).
  362
  363portray_clause(Stream, Term, M:Options) :-
  364    must_be(list, Options),
  365    meta_options(is_meta, M:Options, QOptions),
  366    \+ \+ ( copy_term_nat(Term, Copy),
  367            numbervars(Copy, 0, _,
  368                       [ singletons(true)
  369                       ]),
  370            do_portray_clause(Stream, Copy, QOptions)
  371          ).
  372
  373is_meta(portray_goal).
  374
  375do_portray_clause(Out, Var, Options) :-
  376    var(Var),
  377    !,
  378    pprint(Out, Var, 1200, Options).
  379do_portray_clause(Out, (Head :- true), Options) :-
  380    !,
  381    pprint(Out, Head, 1200, Options),
  382    full_stop(Out).
  383do_portray_clause(Out, Term, Options) :-
  384    clause_term(Term, Head, Neck, Body),
  385    !,
  386    inc_indent(0, 1, Indent),
  387    infix_op(Neck, RightPri, LeftPri),
  388    pprint(Out, Head, LeftPri, Options),
  389    format(Out, ' ~w', [Neck]),
  390    (   nonvar(Body),
  391        Body = Module:LocalBody,
  392        \+ primitive(LocalBody)
  393    ->  nlindent(Out, Indent),
  394        format(Out, '~q', [Module]),
  395        '$put_token'(Out, :),
  396        nlindent(Out, Indent),
  397        write(Out, '(   '),
  398        inc_indent(Indent, 1, BodyIndent),
  399        portray_body(LocalBody, BodyIndent, noindent, 1200, Out, Options),
  400        nlindent(Out, Indent),
  401        write(Out, ')')
  402    ;   setting(listing:body_indentation, BodyIndent),
  403        portray_body(Body, BodyIndent, indent, RightPri, Out, Options)
  404    ),
  405    full_stop(Out).
  406do_portray_clause(Out, (:-use_module(File, Imports)), Options) :-
  407    length(Imports, Len),
  408    Len > 3,
  409    !,
  410    format(Out, ':- use_module(~q,', [File]),
  411    portray_list(Imports, 14, Out, Options),
  412    write(Out, ').\n').
  413do_portray_clause(Out, (:-module(Module, Exports)), Options) :-
  414    !,
  415    format(Out, ':- module(~q,', [Module]),
  416    portray_list(Exports, 10, Out, Options),
  417    write(Out, ').\n').
  418do_portray_clause(Out, (:-Directive), Options) :-
  419    !,
  420    write(Out, ':- '),
  421    portray_body(Directive, 3, noindent, 1199, Out, Options),
  422    full_stop(Out).
  423do_portray_clause(Out, Fact, Options) :-
  424    portray_body(Fact, 0, noindent, 1200, Out, Options),
  425    full_stop(Out).
  426
  427clause_term((Head:-Body), Head, :-, Body).
  428clause_term((Head-->Body), Head, -->, Body).
  429
  430full_stop(Out) :-
  431    '$put_token'(Out, '.'),
  432    nl(Out).
 portray_body(+Term, +Indent, +DoIndent, +Priority, +Out, +Options)
Write Term at current indentation. If DoIndent is 'indent' we must first call nlindent/2 before emitting anything.
  440portray_body(Var, _, _, Pri, Out, Options) :-
  441    var(Var),
  442    !,
  443    pprint(Out, Var, Pri, Options).
  444portray_body(!, _, _, _, Out, _) :-
  445    setting(listing:cut_on_same_line, true),
  446    !,
  447    write(Out, ' !').
  448portray_body((!, Clause), Indent, _, Pri, Out, Options) :-
  449    setting(listing:cut_on_same_line, true),
  450    \+ term_needs_braces((_,_), Pri),
  451    !,
  452    write(Out, ' !,'),
  453    portray_body(Clause, Indent, indent, 1000, Out, Options).
  454portray_body(Term, Indent, indent, Pri, Out, Options) :-
  455    !,
  456    nlindent(Out, Indent),
  457    portray_body(Term, Indent, noindent, Pri, Out, Options).
  458portray_body(Or, Indent, _, _, Out, Options) :-
  459    or_layout(Or),
  460    !,
  461    write(Out, '(   '),
  462    portray_or(Or, Indent, 1200, Out, Options),
  463    nlindent(Out, Indent),
  464    write(Out, ')').
  465portray_body(Term, Indent, _, Pri, Out, Options) :-
  466    term_needs_braces(Term, Pri),
  467    !,
  468    write(Out, '( '),
  469    ArgIndent is Indent + 2,
  470    portray_body(Term, ArgIndent, noindent, 1200, Out, Options),
  471    nlindent(Out, Indent),
  472    write(Out, ')').
  473portray_body((A,B), Indent, _, _Pri, Out, Options) :-
  474    !,
  475    infix_op(',', LeftPri, RightPri),
  476    portray_body(A, Indent, noindent, LeftPri, Out, Options),
  477    write(Out, ','),
  478    portray_body(B, Indent, indent, RightPri, Out, Options).
  479portray_body(\+(Goal), Indent, _, _Pri, Out, Options) :-
  480    !,
  481    write(Out, \+), write(Out, ' '),
  482    prefix_op(\+, ArgPri),
  483    ArgIndent is Indent+3,
  484    portray_body(Goal, ArgIndent, noindent, ArgPri, Out, Options).
  485portray_body(Call, _, _, _, Out, Options) :- % requires knowledge on the module!
  486    m_callable(Call),
  487    option(module(M), Options, user),
  488    predicate_property(M:Call, meta_predicate(Meta)),
  489    !,
  490    portray_meta(Out, Call, Meta, Options).
  491portray_body(Clause, _, _, Pri, Out, Options) :-
  492    pprint(Out, Clause, Pri, Options).
  493
  494m_callable(Term) :-
  495    strip_module(Term, _, Plain),
  496    callable(Plain),
  497    Plain \= (_:_).
  498
  499term_needs_braces(Term, Pri) :-
  500    callable(Term),
  501    functor(Term, Name, _Arity),
  502    current_op(OpPri, _Type, Name),
  503    OpPri > Pri,
  504    !.
 portray_or(+Term, +Indent, +Priority, +Out) is det
  508portray_or(Term, Indent, Pri, Out, Options) :-
  509    term_needs_braces(Term, Pri),
  510    !,
  511    inc_indent(Indent, 1, NewIndent),
  512    write(Out, '(   '),
  513    portray_or(Term, NewIndent, Out, Options),
  514    nlindent(Out, NewIndent),
  515    write(Out, ')').
  516portray_or(Term, Indent, _Pri, Out, Options) :-
  517    or_layout(Term),
  518    !,
  519    portray_or(Term, Indent, Out, Options).
  520portray_or(Term, Indent, Pri, Out, Options) :-
  521    inc_indent(Indent, 1, NestIndent),
  522    portray_body(Term, NestIndent, noindent, Pri, Out, Options).
  523
  524
  525portray_or((If -> Then ; Else), Indent, Out, Options) :-
  526    !,
  527    inc_indent(Indent, 1, NestIndent),
  528    infix_op((->), LeftPri, RightPri),
  529    portray_body(If, NestIndent, noindent, LeftPri, Out, Options),
  530    nlindent(Out, Indent),
  531    write(Out, '->  '),
  532    portray_body(Then, NestIndent, noindent, RightPri, Out, Options),
  533    nlindent(Out, Indent),
  534    write(Out, ';   '),
  535    infix_op(;, _LeftPri, RightPri2),
  536    portray_or(Else, Indent, RightPri2, Out, Options).
  537portray_or((If *-> Then ; Else), Indent, Out, Options) :-
  538    !,
  539    inc_indent(Indent, 1, NestIndent),
  540    infix_op((*->), LeftPri, RightPri),
  541    portray_body(If, NestIndent, noindent, LeftPri, Out, Options),
  542    nlindent(Out, Indent),
  543    write(Out, '*-> '),
  544    portray_body(Then, NestIndent, noindent, RightPri, Out, Options),
  545    nlindent(Out, Indent),
  546    write(Out, ';   '),
  547    infix_op(;, _LeftPri, RightPri2),
  548    portray_or(Else, Indent, RightPri2, Out, Options).
  549portray_or((If -> Then), Indent, Out, Options) :-
  550    !,
  551    inc_indent(Indent, 1, NestIndent),
  552    infix_op((->), LeftPri, RightPri),
  553    portray_body(If, NestIndent, noindent, LeftPri, Out, Options),
  554    nlindent(Out, Indent),
  555    write(Out, '->  '),
  556    portray_or(Then, Indent, RightPri, Out, Options).
  557portray_or((If *-> Then), Indent, Out, Options) :-
  558    !,
  559    inc_indent(Indent, 1, NestIndent),
  560    infix_op((->), LeftPri, RightPri),
  561    portray_body(If, NestIndent, noindent, LeftPri, Out, Options),
  562    nlindent(Out, Indent),
  563    write(Out, '*-> '),
  564    portray_or(Then, Indent, RightPri, Out, Options).
  565portray_or((A;B), Indent, Out, Options) :-
  566    !,
  567    inc_indent(Indent, 1, NestIndent),
  568    infix_op(;, LeftPri, RightPri),
  569    portray_body(A, NestIndent, noindent, LeftPri, Out, Options),
  570    nlindent(Out, Indent),
  571    write(Out, ';   '),
  572    portray_or(B, Indent, RightPri, Out, Options).
  573portray_or((A|B), Indent, Out, Options) :-
  574    !,
  575    inc_indent(Indent, 1, NestIndent),
  576    infix_op('|', LeftPri, RightPri),
  577    portray_body(A, NestIndent, noindent, LeftPri, Out, Options),
  578    nlindent(Out, Indent),
  579    write(Out, '|   '),
  580    portray_or(B, Indent, RightPri, Out, Options).
 infix_op(+Op, -Left, -Right) is semidet
True if Op is an infix operator and Left is the max priority of its left hand and Right is the max priority of its right hand.
  588infix_op(Op, Left, Right) :-
  589    current_op(Pri, Assoc, Op),
  590    infix_assoc(Assoc, LeftMin, RightMin),
  591    !,
  592    Left is Pri - LeftMin,
  593    Right is Pri - RightMin.
  594
  595infix_assoc(xfx, 1, 1).
  596infix_assoc(xfy, 1, 0).
  597infix_assoc(yfx, 0, 1).
  598
  599prefix_op(Op, ArgPri) :-
  600    current_op(Pri, Assoc, Op),
  601    pre_assoc(Assoc, ArgMin),
  602    !,
  603    ArgPri is Pri - ArgMin.
  604
  605pre_assoc(fx, 1).
  606pre_assoc(fy, 0).
  607
  608postfix_op(Op, ArgPri) :-
  609    current_op(Pri, Assoc, Op),
  610    post_assoc(Assoc, ArgMin),
  611    !,
  612    ArgPri is Pri - ArgMin.
  613
  614post_assoc(xf, 1).
  615post_assoc(yf, 0).
 or_layout(@Term) is semidet
True if Term is a control structure for which we want to use clean layout.
To be done
- Change name.
  624or_layout(Var) :-
  625    var(Var), !, fail.
  626or_layout((_;_)).
  627or_layout((_->_)).
  628or_layout((_*->_)).
  629
  630primitive(G) :-
  631    or_layout(G), !, fail.
  632primitive((_,_)) :- !, fail.
  633primitive(_).
 portray_meta(+Out, +Call, +MetaDecl, +Options)
Portray a meta-call. If Call contains non-primitive meta-calls we put each argument on a line and layout the body. Otherwise we simply print the goal.
  642portray_meta(Out, Call, Meta, Options) :-
  643    contains_non_primitive_meta_arg(Call, Meta),
  644    !,
  645    Call =.. [Name|Args],
  646    Meta =.. [_|Decls],
  647    format(Out, '~q(', [Name]),
  648    line_position(Out, Indent),
  649    portray_meta_args(Decls, Args, Indent, Out, Options),
  650    format(Out, ')', []).
  651portray_meta(Out, Call, _, Options) :-
  652    pprint(Out, Call, 999, Options).
  653
  654contains_non_primitive_meta_arg(Call, Decl) :-
  655    arg(I, Call, CA),
  656    arg(I, Decl, DA),
  657    integer(DA),
  658    \+ primitive(CA),
  659    !.
  660
  661portray_meta_args([], [], _, _, _).
  662portray_meta_args([D|DT], [A|AT], Indent, Out, Options) :-
  663    portray_meta_arg(D, A, Out, Options),
  664    (   DT == []
  665    ->  true
  666    ;   format(Out, ',', []),
  667        nlindent(Out, Indent),
  668        portray_meta_args(DT, AT, Indent, Out, Options)
  669    ).
  670
  671portray_meta_arg(I, A, Out, Options) :-
  672    integer(I),
  673    !,
  674    line_position(Out, Indent),
  675    portray_body(A, Indent, noindent, 999, Out, Options).
  676portray_meta_arg(_, A, Out, Options) :-
  677    pprint(Out, A, 999, Options).
 portray_list(+List, +Indent, +Out)
Portray a list like this. Right side for improper lists
[ element1,             [ element1
  element2,     OR      | tail
]                       ]
  687portray_list([], _, Out, _) :-
  688    !,
  689    write(Out, []).
  690portray_list(List, Indent, Out, Options) :-
  691    nlindent(Out, Indent),
  692    write(Out, '[ '),
  693    EIndent is Indent + 2,
  694    portray_list_elements(List, EIndent, Out, Options),
  695    nlindent(Out, Indent),
  696    write(Out, ']').
  697
  698portray_list_elements([H|T], EIndent, Out, Options) :-
  699    pprint(Out, H, 999, Options),
  700    (   T == []
  701    ->  true
  702    ;   nonvar(T), T = [_|_]
  703    ->  write(Out, ','),
  704        nlindent(Out, EIndent),
  705        portray_list_elements(T, EIndent, Out, Options)
  706    ;   Indent is EIndent - 2,
  707        nlindent(Out, Indent),
  708        write(Out, '| '),
  709        pprint(Out, T, 999, Options)
  710    ).
 pprint(+Out, +Term, +Priority, +Options)
Print Term at Priority. This also takes care of several formatting options, in particular:
To be done
- Decide when and how to wrap long terms.
  724pprint(Out, Term, _, Options) :-
  725    nonvar(Term),
  726    Term = {}(Arg),
  727    line_position(Out, Indent),
  728    ArgIndent is Indent + 2,
  729    format(Out, '{ ', []),
  730    portray_body(Arg, ArgIndent, noident, 1000, Out, Options),
  731    nlindent(Out, Indent),
  732    format(Out, '}', []).
  733pprint(Out, Term, Pri, Options) :-
  734    (   compound(Term)
  735    ->  compound_name_arity(Term, _, Arity),
  736        Arity > 0
  737    ;   is_dict(Term)
  738    ),
  739    \+ nowrap_term(Term),
  740    setting(listing:line_width, Width),
  741    Width > 0,
  742    (   write_length(Term, Len, [max_length(Width)|Options])
  743    ->  true
  744    ;   Len = Width
  745    ),
  746    line_position(Out, Indent),
  747    Indent + Len > Width,
  748    Len > Width/4,                 % ad-hoc rule for deeply nested goals
  749    !,
  750    pprint_wrapped(Out, Term, Pri, Options).
  751pprint(Out, Term, Pri, Options) :-
  752    listing_write_options(Pri, WrtOptions, Options),
  753    write_term(Out, Term, WrtOptions).
  754
  755nowrap_term('$VAR'(_)) :- !.
  756nowrap_term(_{}) :- !.                  % empty dict
  757nowrap_term(Term) :-
  758    functor(Term, Name, Arity),
  759    current_op(_, _, Name),
  760    (   Arity == 2
  761    ->  infix_op(Name, _, _)
  762    ;   Arity == 1
  763    ->  (   prefix_op(Name, _)
  764        ->  true
  765        ;   postfix_op(Name, _)
  766        )
  767    ).
  768
  769
  770pprint_wrapped(Out, Term, _, Options) :-
  771    Term = [_|_],
  772    !,
  773    line_position(Out, Indent),
  774    portray_list(Term, Indent, Out, Options).
  775pprint_wrapped(Out, Dict, _, Options) :-
  776    is_dict(Dict),
  777    !,
  778    dict_pairs(Dict, Tag, Pairs),
  779    pprint(Out, Tag, 1200, Options),
  780    format(Out, '{ ', []),
  781    line_position(Out, Indent),
  782    pprint_nv(Pairs, Indent, Out, Options),
  783    nlindent(Out, Indent-2),
  784    format(Out, '}', []).
  785pprint_wrapped(Out, Term, _, Options) :-
  786    Term =.. [Name|Args],
  787    format(Out, '~q(', Name),
  788    line_position(Out, Indent),
  789    pprint_args(Args, Indent, Out, Options),
  790    format(Out, ')', []).
  791
  792pprint_args([], _, _, _).
  793pprint_args([H|T], Indent, Out, Options) :-
  794    pprint(Out, H, 999, Options),
  795    (   T == []
  796    ->  true
  797    ;   format(Out, ',', []),
  798        nlindent(Out, Indent),
  799        pprint_args(T, Indent, Out, Options)
  800    ).
  801
  802
  803pprint_nv([], _, _, _).
  804pprint_nv([Name-Value|T], Indent, Out, Options) :-
  805    pprint(Out, Name, 999, Options),
  806    format(Out, ':', []),
  807    pprint(Out, Value, 999, Options),
  808    (   T == []
  809    ->  true
  810    ;   format(Out, ',', []),
  811        nlindent(Out, Indent),
  812        pprint_nv(T, Indent, Out, Options)
  813    ).
 listing_write_options(+Priority, -WriteOptions) is det
WriteOptions are write_term/3 options for writing a term at priority Priority.
  821listing_write_options(Pri,
  822                      [ quoted(true),
  823                        numbervars(true),
  824                        priority(Pri),
  825                        spacing(next_argument)
  826                      | Options
  827                      ],
  828                      Options).
 nlindent(+Out, +Indent)
Write newline and indent to column Indent. Uses the setting listing:tab_distance to determine the mapping between tabs and spaces.
  836nlindent(Out, N) :-
  837    nl(Out),
  838    setting(listing:tab_distance, D),
  839    (   D =:= 0
  840    ->  tab(Out, N)
  841    ;   Tab is N // D,
  842        Space is N mod D,
  843        put_tabs(Out, Tab),
  844        tab(Out, Space)
  845    ).
  846
  847put_tabs(Out, N) :-
  848    N > 0,
  849    !,
  850    put(Out, 0'\t),
  851    NN is N - 1,
  852    put_tabs(Out, NN).
  853put_tabs(_, _).
 inc_indent(+Indent0, +Inc, -Indent)
Increment the indent with logical steps.
  860inc_indent(Indent0, Inc, Indent) :-
  861    Indent is Indent0 + Inc*4.
  862
  863:- multifile
  864    sandbox:safe_meta/2.  865
  866sandbox:safe_meta(listing(What), []) :-
  867    not_qualified(What).
  868
  869not_qualified(Var) :-
  870    var(Var),
  871    !.
  872not_qualified(_:_) :- !, fail.
  873not_qualified(_)