View source with formatted 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/projects/xpce/
    6    Copyright (c)  2011-2019, 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(prolog_colour,
   38          [ prolog_colourise_stream/3,  % +Stream, +SourceID, :ColourItem
   39            prolog_colourise_stream/4,  % +Stream, +SourceID, :ColourItem, +Opts
   40            prolog_colourise_term/4,    % +Stream, +SourceID, :ColourItem, +Opts
   41            prolog_colourise_query/3,   % +String, +SourceID, :ColourItem
   42            syntax_colour/2,            % +Class, -Attributes
   43            syntax_message//1           % +Class
   44          ]).   45:- use_module(library(prolog_xref)).   46:- use_module(library(predicate_options)).   47:- use_module(library(prolog_source)).   48:- use_module(library(lists)).   49:- use_module(library(operators)).   50:- use_module(library(debug)).   51:- use_module(library(error)).   52:- use_module(library(option)).   53:- use_module(library(record)).   54:- use_module(library(apply)).   55
   56:- meta_predicate
   57    prolog_colourise_stream(+, +, 3),
   58    prolog_colourise_stream(+, +, 3, +),
   59    prolog_colourise_query(+, +, 3),
   60    prolog_colourise_term(+, +, 3, +).   61
   62:- predicate_options(prolog_colourise_term/4, 4,
   63                     [ subterm_positions(-any)
   64                     ]).   65:- predicate_options(prolog_colourise_stream/4, 4,
   66                     [ operators(list(any))
   67                     ]).   68
   69/** <module> Prolog syntax colouring support.
   70
   71This module defines reusable code to colourise Prolog source.
   72
   73@tbd: The one-term version
   74*/
   75
   76
   77:- multifile
   78    style/2,                        % +ColourClass, -Attributes
   79    message//1,                     % +ColourClass
   80    term_colours/2,                 % +SourceTerm, -ColourSpec
   81    goal_colours/2,                 % +Goal, -ColourSpec
   82    goal_colours/3,                 % +Goal, +Class, -ColourSpec
   83    directive_colours/2,            % +Goal, -ColourSpec
   84    goal_classification/2,          % +Goal, -Class
   85    vararg_goal_classification/3.   % +Name, +Arity, -Class
   86
   87
   88:- record
   89    colour_state(source_id_list,
   90                 module,
   91                 stream,
   92                 closure,
   93                 singletons).   94
   95colour_state_source_id(State, SourceID) :-
   96    colour_state_source_id_list(State, SourceIDList),
   97    member(SourceID, SourceIDList).
   98
   99%!  prolog_colourise_stream(+Stream, +SourceID, :ColourItem) is det.
  100%!  prolog_colourise_stream(+Stream, +SourceID, :ColourItem, +Opts) is det.
  101%
  102%   Determine colour fragments for the data   on Stream. SourceID is
  103%   the  canonical  identifier  of  the  input    as  known  to  the
  104%   cross-referencer, i.e., as created using xref_source(SourceID).
  105%
  106%   ColourItem is a closure  that  is   called  for  each identified
  107%   fragment with three additional arguments:
  108%
  109%     * The syntactical category
  110%     * Start position (character offset) of the fragment
  111%     * Length of the fragment (in characters).
  112%
  113%   Options
  114%
  115%     - operators(+Ops)
  116%       Provide an initial list of additional operators.
  117
  118prolog_colourise_stream(Fd, SourceId, ColourItem) :-
  119    prolog_colourise_stream(Fd, SourceId, ColourItem, []).
  120prolog_colourise_stream(Fd, SourceId, ColourItem, Options) :-
  121    to_list(SourceId, SourceIdList),
  122    make_colour_state([ source_id_list(SourceIdList),
  123                        stream(Fd),
  124                        closure(ColourItem)
  125                      ],
  126                      TB),
  127    option(operators(Ops), Options, []),
  128    setup_call_cleanup(
  129        save_settings(TB, Ops, State),
  130        colourise_stream(Fd, TB),
  131        restore_settings(State)).
  132
  133to_list(List, List) :-
  134    is_list(List),
  135    !.
  136to_list(One, [One]).
  137
  138
  139colourise_stream(Fd, TB) :-
  140    (   peek_char(Fd, #)            % skip #! script line
  141    ->  skip(Fd, 10)
  142    ;   true
  143    ),
  144    repeat,
  145        colour_state_module(TB, SM),
  146        character_count(Fd, Start),
  147        catch(read_term(Fd, Term,
  148                        [ subterm_positions(TermPos),
  149                          singletons(Singletons0),
  150                          module(SM),
  151                          comments(Comments)
  152                        ]),
  153              E,
  154              read_error(E, TB, Start, Fd)),
  155        fix_operators(Term, SM, TB),
  156        warnable_singletons(Singletons0, Singletons),
  157        colour_state_singletons(TB, Singletons),
  158        (   colourise_term(Term, TB, TermPos, Comments)
  159        ->  true
  160        ;   arg(1, TermPos, From),
  161            print_message(warning,
  162                          format('Failed to colourise ~p at index ~d~n',
  163                                 [Term, From]))
  164        ),
  165        Term == end_of_file,
  166    !.
  167
  168save_settings(TB, Ops, state(Style, Flags, OSM, Xref)) :-
  169    (   source_module(TB, SM)
  170    ->  true
  171    ;   SM = prolog_colour_ops
  172    ),
  173    set_xref(Xref, true),
  174    '$set_source_module'(OSM, SM),
  175    colour_state_module(TB, SM),
  176    maplist(qualify_op(SM), Ops, QOps),
  177    push_operators(QOps),
  178    syntax_flags(Flags),
  179    '$style_check'(Style, Style).
  180
  181qualify_op(M, op(P,T,N), op(P,T,M:N)) :-
  182    atom(N), !.
  183qualify_op(M, op(P,T,L), op(P,T,QL)) :-
  184    is_list(L), !,
  185    maplist(qualify_op_name(M), L, QL).
  186qualify_op(_, Op, Op).
  187
  188qualify_op_name(M, N, M:N) :-
  189    atom(N),
  190    !.
  191qualify_op_name(_, N, N).
  192
  193restore_settings(state(Style, Flags, OSM, Xref)) :-
  194    restore_syntax_flags(Flags),
  195    '$style_check'(_, Style),
  196    pop_operators,
  197    '$set_source_module'(OSM),
  198    set_xref(_, Xref).
  199
  200set_xref(Old, New) :-
  201    current_prolog_flag(xref, Old),
  202    !,
  203    set_prolog_flag(xref, New).
  204set_xref(false, New) :-
  205    set_prolog_flag(xref, New).
  206
  207
  208syntax_flags(Pairs) :-
  209    findall(set_prolog_flag(Flag, Value),
  210            syntax_flag(Flag, Value),
  211            Pairs).
  212
  213syntax_flag(Flag, Value) :-
  214    syntax_flag(Flag),
  215    current_prolog_flag(Flag, Value).
  216
  217restore_syntax_flags([]).
  218restore_syntax_flags([set_prolog_flag(Flag, Value)|T]) :-
  219    set_prolog_flag(Flag, Value),
  220    restore_syntax_flags(T).
  221
  222%!  source_module(+State, -Module) is semidet.
  223%
  224%   True when Module is the module context   into  which the file is
  225%   loaded. This is the module of the file if File is a module file,
  226%   or the load context of  File  if   File  is  not included or the
  227%   module context of the file into which the file was included.
  228
  229source_module(TB, Module) :-
  230    colour_state_source_id_list(TB, []),
  231    !,
  232    colour_state_module(TB, Module).
  233source_module(TB, Module) :-
  234    colour_state_source_id(TB, SourceId),
  235    xref_option(SourceId, module(Module)),
  236    !.
  237source_module(TB, Module) :-
  238    (   colour_state_source_id(TB, File),
  239        atom(File)
  240    ;   colour_state_stream(TB, Fd),
  241        is_stream(Fd),
  242        stream_property(Fd, file_name(File))
  243    ),
  244    module_context(File, [], Module).
  245
  246module_context(File, _, Module) :-
  247    source_file_property(File, module(Module)),
  248    !.
  249module_context(File, Seen, Module) :-
  250    source_file_property(File, included_in(File2, _Line)),
  251    \+ memberchk(File, Seen),
  252    !,
  253    module_context(File2, [File|Seen], Module).
  254module_context(File, _, Module) :-
  255    source_file_property(File, load_context(Module, _, _)).
  256
  257
  258%!  read_error(+Error, +TB, +Start, +Stream) is failure.
  259%
  260%   If this is a syntax error, create a syntax-error fragment.
  261
  262read_error(Error, TB, Start, EndSpec) :-
  263    (   syntax_error(Error, Id, CharNo)
  264    ->  message_to_string(error(syntax_error(Id), _), Msg),
  265        (   integer(EndSpec)
  266        ->  End = EndSpec
  267        ;   character_count(EndSpec, End)
  268        ),
  269        show_syntax_error(TB, CharNo:Msg, Start-End),
  270        fail
  271    ;   throw(Error)
  272    ).
  273
  274syntax_error(error(syntax_error(Id), stream(_S, _Line, _LinePos, CharNo)),
  275             Id, CharNo).
  276syntax_error(error(syntax_error(Id), file(_S, _Line, _LinePos, CharNo)),
  277             Id, CharNo).
  278syntax_error(error(syntax_error(Id), string(_Text, CharNo)),
  279             Id, CharNo).
  280
  281%!  warnable_singletons(+Singletons, -Warn) is det.
  282%
  283%   Warn is the subset of the singletons that we warn about.
  284
  285warnable_singletons([], []).
  286warnable_singletons([H|T0], List) :-
  287    H = (Name=_Var),
  288    (   '$is_named_var'(Name)
  289    ->  List = [H|T]
  290    ;   List = T
  291    ),
  292    warnable_singletons(T0, T).
  293
  294%!  colour_item(+Class, +TB, +Pos) is det.
  295
  296colour_item(Class, TB, Pos) :-
  297    arg(1, Pos, Start),
  298    arg(2, Pos, End),
  299    Len is End - Start,
  300    colour_state_closure(TB, Closure),
  301    call(Closure, Class, Start, Len).
  302
  303
  304%!  safe_push_op(+Prec, +Type, :Name, +State)
  305%
  306%   Define operators into the default source module and register
  307%   them to be undone by pop_operators/0.
  308
  309safe_push_op(P, T, N0, State) :-
  310    colour_state_module(State, CM),
  311    strip_module(CM:N0, M, N),
  312    (   is_list(N),
  313        N \== []                                % define list as operator
  314    ->  acyclic_term(N),
  315        forall(member(Name, N),
  316               safe_push_op(P, T, M:Name, State))
  317    ;   push_op(P, T, M:N)
  318    ),
  319    debug(colour, ':- ~w.', [op(P,T,M:N)]).
  320
  321%!  fix_operators(+Term, +Module, +State) is det.
  322%
  323%   Fix flags that affect the  syntax,   such  as operators and some
  324%   style checking options. Src is the  canonical source as required
  325%   by the cross-referencer.
  326
  327fix_operators((:- Directive), M, Src) :-
  328    ground(Directive),
  329    catch(process_directive(Directive, M, Src), _, true),
  330    !.
  331fix_operators(_, _, _).
  332
  333process_directive(style_check(X), _, _) :-
  334    !,
  335    style_check(X).
  336process_directive(set_prolog_flag(Flag, Value), M, _) :-
  337    syntax_flag(Flag),
  338    !,
  339    set_prolog_flag(M:Flag, Value).
  340process_directive(M:op(P,T,N), _, Src) :-
  341    !,
  342    process_directive(op(P,T,N), M, Src).
  343process_directive(op(P,T,N), M, Src) :-
  344    !,
  345    safe_push_op(P, T, M:N, Src).
  346process_directive(module(_Name, Export), M, Src) :-
  347    !,
  348    forall(member(op(P,A,N), Export),
  349           safe_push_op(P,A,M:N, Src)).
  350process_directive(use_module(Spec), _, Src) :-
  351    !,
  352    catch(process_use_module1(Spec, Src), _, true).
  353process_directive(use_module(Spec, Imports), _, Src) :-
  354    !,
  355    catch(process_use_module2(Spec, Imports, Src), _, true).
  356process_directive(Directive, _, Src) :-
  357    prolog_source:expand((:-Directive), Src, _).
  358
  359syntax_flag(character_escapes).
  360syntax_flag(var_prefix).
  361syntax_flag(allow_variable_name_as_functor).
  362syntax_flag(allow_dot_in_atom).
  363
  364%!  process_use_module1(+Imports, +Src)
  365%
  366%   Get the exported operators from the referenced files.
  367
  368process_use_module1([], _) :- !.
  369process_use_module1([H|T], Src) :-
  370    !,
  371    process_use_module1(H, Src),
  372    process_use_module1(T, Src).
  373process_use_module1(File, Src) :-
  374    (   xref_public_list(File, Src,
  375                         [ exports(Exports),
  376                           silent(true),
  377                           path(Path)
  378                         ])
  379    ->  forall(member(op(P,T,N), Exports),
  380               safe_push_op(P,T,N,Src)),
  381        colour_state_module(Src, SM),
  382        (   member(Syntax/4, Exports),
  383            load_quasi_quotation_syntax(SM:Path, Syntax),
  384            fail
  385        ;   true
  386        )
  387    ;   true
  388    ).
  389
  390process_use_module2(File, Imports, Src) :-
  391    (   xref_public_list(File, Src,
  392                         [ exports(Exports),
  393                           silent(true),
  394                           path(Path)
  395                         ])
  396    ->  forall(( member(op(P,T,N), Exports),
  397                 member(op(P,T,N), Imports)),
  398               safe_push_op(P,T,N,Src)),
  399        colour_state_module(Src, SM),
  400        (   member(Syntax/4, Exports),
  401            member(Syntax/4, Imports),
  402            load_quasi_quotation_syntax(SM:Path, Syntax),
  403            fail
  404        ;   true
  405        )
  406    ;   true
  407    ).
  408
  409%!  prolog_colourise_query(+Query:string, +SourceId, :ColourItem)
  410%
  411%   Colourise a query, to be executed in the context of SourceId.
  412%
  413%   @arg    SourceId Execute Query in the context of
  414%           the cross-referenced environment SourceID.
  415
  416prolog_colourise_query(QueryString, SourceID, ColourItem) :-
  417    query_colour_state(SourceID, ColourItem, TB),
  418    setup_call_cleanup(
  419        save_settings(TB, State),
  420        colourise_query(QueryString, TB),
  421        restore_settings(State)).
  422
  423query_colour_state(module(Module), ColourItem, TB) :-
  424    !,
  425    make_colour_state([ source_id_list([]),
  426                        module(Module),
  427                        closure(ColourItem)
  428                      ],
  429                      TB).
  430query_colour_state(SourceID, ColourItem, TB) :-
  431    to_list(SourceID, SourceIDList),
  432    make_colour_state([ source_id_list(SourceIDList),
  433                        closure(ColourItem)
  434                      ],
  435                      TB).
  436
  437
  438colourise_query(QueryString, TB) :-
  439    colour_state_module(TB, SM),
  440    string_length(QueryString, End),
  441    (   catch(term_string(Query, QueryString,
  442                          [ subterm_positions(TermPos),
  443                            singletons(Singletons0),
  444                            module(SM),
  445                            comments(Comments)
  446                          ]),
  447              E,
  448              read_error(E, TB, 0, End))
  449    ->  warnable_singletons(Singletons0, Singletons),
  450        colour_state_singletons(TB, Singletons),
  451        colourise_comments(Comments, TB),
  452        (   Query == end_of_file
  453        ->  true
  454        ;   colourise_body(Query, TB, TermPos)
  455        )
  456    ;   true                        % only a syntax error
  457    ).
  458
  459%!  prolog_colourise_term(+Stream, +SourceID, :ColourItem, +Options)
  460%
  461%   Colourise    the    next     term      on     Stream.     Unlike
  462%   prolog_colourise_stream/3, this predicate assumes  it is reading
  463%   a single term rather than the   entire stream. This implies that
  464%   it cannot adjust syntax according to directives that preceed it.
  465%
  466%   Options:
  467%
  468%     * subterm_positions(-TermPos)
  469%     Return complete term-layout.  If an error is read, this is a
  470%     term error_position(StartClause, EndClause, ErrorPos)
  471
  472prolog_colourise_term(Stream, SourceId, ColourItem, Options) :-
  473    to_list(SourceId, SourceIdList),
  474    make_colour_state([ source_id_list(SourceIdList),
  475                        stream(Stream),
  476                        closure(ColourItem)
  477                      ],
  478                      TB),
  479    option(subterm_positions(TermPos), Options, _),
  480    findall(Op, xref_op(SourceId, Op), Ops),
  481    debug(colour, 'Ops from ~p: ~p', [SourceId, Ops]),
  482    findall(Opt, xref_flag_option(SourceId, Opt), Opts),
  483    character_count(Stream, Start),
  484    (   source_module(TB, Module)
  485    ->  true
  486    ;   Module = prolog_colour_ops
  487    ),
  488    read_source_term_at_location(
  489        Stream, Term,
  490        [ module(Module),
  491          operators(Ops),
  492          error(Error),
  493          subterm_positions(TermPos),
  494          singletons(Singletons0),
  495          comments(Comments)
  496        | Opts
  497        ]),
  498    (   var(Error)
  499    ->  warnable_singletons(Singletons0, Singletons),
  500        colour_state_singletons(TB, Singletons),
  501        colour_item(range, TB, TermPos),            % Call to allow clearing
  502        colourise_term(Term, TB, TermPos, Comments)
  503    ;   character_count(Stream, End),
  504        TermPos = error_position(Start, End, Pos),
  505        colour_item(range, TB, TermPos),
  506        show_syntax_error(TB, Error, Start-End),
  507        Error = Pos:_Message
  508    ).
  509
  510xref_flag_option(TB, var_prefix(Bool)) :-
  511    xref_prolog_flag(TB, var_prefix, Bool, _Line).
  512
  513show_syntax_error(TB, Pos:Message, Range) :-
  514    integer(Pos),
  515    !,
  516    End is Pos + 1,
  517    colour_item(syntax_error(Message, Range), TB, Pos-End).
  518show_syntax_error(TB, _:Message, Range) :-
  519    colour_item(syntax_error(Message, Range), TB, Range).
  520
  521
  522singleton(Var, TB) :-
  523    colour_state_singletons(TB, Singletons),
  524    member_var(Var, Singletons).
  525
  526member_var(V, [_=V2|_]) :-
  527    V == V2,
  528    !.
  529member_var(V, [_|T]) :-
  530    member_var(V, T).
  531
  532%!  colourise_term(+Term, +TB, +Termpos, +Comments)
  533%
  534%   Colourise the next Term.
  535%
  536%   @bug    The colour spec is closed with =fullstop=, but the
  537%           position information does not include the full stop
  538%           location, so all we can do is assume it is behind the
  539%           term.
  540
  541colourise_term(Term, TB, TermPos, Comments) :-
  542    colourise_comments(Comments, TB),
  543    (   Term == end_of_file
  544    ->  true
  545    ;   colourise_term(Term, TB, TermPos),
  546        colourise_fullstop(TB, TermPos)
  547    ).
  548
  549colourise_fullstop(TB, TermPos) :-
  550    arg(2, TermPos, EndTerm),
  551    Start is EndTerm,
  552    End is Start+1,
  553    colour_item(fullstop, TB, Start-End).
  554
  555colourise_comments(-, _).
  556colourise_comments([], _).
  557colourise_comments([H|T], TB) :-
  558    colourise_comment(H, TB),
  559    colourise_comments(T, TB).
  560
  561colourise_comment((-)-_, _) :- !.
  562colourise_comment(Pos-Comment, TB) :-
  563    comment_style(Comment, Style),
  564    stream_position_data(char_count, Pos, Start),
  565    string_length(Comment, Len),
  566    End is Start + Len + 1,
  567    colour_item(comment(Style), TB, Start-End).
  568
  569comment_style(Comment, structured) :-           % Starts %%, %! or /**
  570    structured_comment_start(Start),
  571    sub_string(Comment, 0, Len, _, Start),
  572    Next is Len+1,
  573    string_code(Next, Comment, NextCode),
  574    code_type(NextCode, space),
  575    !.
  576comment_style(Comment, line) :-                 % Starts %
  577    sub_string(Comment, 0, _, _, '%'),
  578    !.
  579comment_style(_, block).                        % Starts /*
  580
  581%!  structured_comment_start(-Start)
  582%
  583%   Copied from library(pldoc/doc_process). Unfortunate,   but we do
  584%   not want to force loading pldoc.
  585
  586structured_comment_start('%%').
  587structured_comment_start('%!').
  588structured_comment_start('/**').
  589
  590%!  colourise_term(+Term, +TB, +Pos)
  591%
  592%   Colorise a file toplevel term.
  593
  594colourise_term(Var, TB, Start-End) :-
  595    var(Var),
  596    !,
  597    colour_item(instantiation_error, TB, Start-End).
  598colourise_term(_, _, Pos) :-
  599    var(Pos),
  600    !.
  601colourise_term(Term, TB, parentheses_term_position(PO,PC,Pos)) :-
  602    !,
  603    colour_item(parentheses, TB, PO-PC),
  604    colourise_term(Term, TB, Pos).
  605colourise_term(Term, TB, Pos) :-
  606    term_colours(Term, FuncSpec-ArgSpecs),
  607    !,
  608    Pos = term_position(F,T,FF,FT,ArgPos),
  609    colour_item(term, TB, F-T),     % TBD: Allow specifying by term_colours/2?
  610    specified_item(FuncSpec, Term, TB, FF-FT),
  611    specified_items(ArgSpecs, Term, TB, ArgPos).
  612colourise_term((Head :- Body), TB,
  613               term_position(F,T,FF,FT,[HP,BP])) :-
  614    !,
  615    colour_item(clause,         TB, F-T),
  616    colour_item(neck(clause),   TB, FF-FT),
  617    colourise_clause_head(Head, TB, HP),
  618    colourise_body(Body, Head,  TB, BP).
  619colourise_term(((Head,RHC) --> Body), TB,
  620               term_position(F,T,FF,FT,
  621                             [ term_position(_,_,_,_,[HP,RHCP]),
  622                               BP
  623                             ])) :-
  624    !,
  625    colour_item(grammar_rule,       TB, F-T),
  626    colour_item(dcg_right_hand_ctx, TB, RHCP),
  627    colourise_term_arg(RHC, TB, RHCP),
  628    colour_item(neck(grammar_rule), TB, FF-FT),
  629    colourise_extended_head(Head, 2, TB, HP),
  630    colourise_dcg(Body, Head,       TB, BP).
  631colourise_term((Head --> Body), TB,                     % TBD: expansion!
  632               term_position(F,T,FF,FT,[HP,BP])) :-
  633    !,
  634    colour_item(grammar_rule,       TB, F-T),
  635    colour_item(neck(grammar_rule), TB, FF-FT),
  636    colourise_extended_head(Head, 2, TB, HP),
  637    colourise_dcg(Body, Head,       TB, BP).
  638colourise_term(:->(Head, Body), TB,
  639               term_position(F,T,FF,FT,[HP,BP])) :-
  640    !,
  641    colour_item(method,             TB, F-T),
  642    colour_item(neck(method(send)), TB, FF-FT),
  643    colour_method_head(send(Head),  TB, HP),
  644    colourise_method_body(Body,     TB, BP).
  645colourise_term(:<-(Head, Body), TB,
  646               term_position(F,T,FF,FT,[HP,BP])) :-
  647    !,
  648    colour_item(method,            TB, F-T),
  649    colour_item(neck(method(get)), TB, FF-FT),
  650    colour_method_head(get(Head),  TB, HP),
  651    colourise_method_body(Body,    TB, BP).
  652colourise_term((:- Directive), TB, Pos) :-
  653    !,
  654    colour_item(directive, TB, Pos),
  655    Pos = term_position(_F,_T,FF,FT,[ArgPos]),
  656    colour_item(neck(directive), TB, FF-FT),
  657    colourise_directive(Directive, TB, ArgPos).
  658colourise_term((?- Directive), TB, Pos) :-
  659    !,
  660    colourise_term((:- Directive), TB, Pos).
  661colourise_term(end_of_file, _, _) :- !.
  662colourise_term(Fact, TB, Pos) :-
  663    !,
  664    colour_item(clause, TB, Pos),
  665    colourise_clause_head(Fact, TB, Pos).
  666
  667%!  colourise_extended_head(+Head, +ExtraArgs, +TB, +Pos) is det.
  668%
  669%   Colourise a clause-head that  is   extended  by  term_expansion,
  670%   getting ExtraArgs more  arguments  (e.g.,   DCGs  add  two  more
  671%   arguments.
  672
  673colourise_extended_head(Head, N, TB, Pos) :-
  674    extend(Head, N, TheHead),
  675    colourise_clause_head(TheHead, TB, Pos).
  676
  677extend(M:Head, N, M:ExtHead) :-
  678    nonvar(Head),
  679    !,
  680    extend(Head, N, ExtHead).
  681extend(Head, N, ExtHead) :-
  682    compound(Head),
  683    !,
  684    compound_name_arguments(Head, Name, Args),
  685    length(Extra, N),
  686    append(Args, Extra, NArgs),
  687    compound_name_arguments(ExtHead, Name, NArgs).
  688extend(Head, N, ExtHead) :-
  689    atom(Head),
  690    !,
  691    length(Extra, N),
  692    compound_name_arguments(ExtHead, Head, Extra).
  693extend(Head, _, Head).
  694
  695
  696colourise_clause_head(_, _, Pos) :-
  697    var(Pos),
  698    !.
  699colourise_clause_head(Head, TB, parentheses_term_position(PO,PC,Pos)) :-
  700    colour_item(parentheses, TB, PO-PC),
  701    colourise_clause_head(Head, TB, Pos).
  702colourise_clause_head(M:Head, TB, QHeadPos) :-
  703    QHeadPos = term_position(_,_,QF,QT,[MPos,HeadPos]),
  704    head_colours(M:Head, meta-[_, ClassSpec-ArgSpecs]),
  705    !,
  706    colourise_module(M, TB, MPos),
  707    colour_item(functor, TB, QF-QT),
  708    functor_position(HeadPos, FPos, ArgPos),
  709    (   ClassSpec == classify
  710    ->  classify_head(TB, Head, Class)
  711    ;   Class = ClassSpec
  712    ),
  713    colour_item(head_term(Class, Head), TB, QHeadPos),
  714    colour_item(head(Class, Head), TB, FPos),
  715    specified_items(ArgSpecs, Head, TB, ArgPos).
  716colourise_clause_head(Head, TB, Pos) :-
  717    head_colours(Head, ClassSpec-ArgSpecs),
  718    !,
  719    functor_position(Pos, FPos, ArgPos),
  720    (   ClassSpec == classify
  721    ->  classify_head(TB, Head, Class)
  722    ;   Class = ClassSpec
  723    ),
  724    colour_item(head_term(Class, Head), TB, Pos),
  725    colour_item(head(Class, Head), TB, FPos),
  726    specified_items(ArgSpecs, Head, TB, ArgPos).
  727colourise_clause_head(:=(Eval, Ret), TB,
  728                      term_position(_,_,AF,AT,
  729                                    [ term_position(_,_,SF,ST,
  730                                                    [ SelfPos,
  731                                                      FuncPos
  732                                                    ]),
  733                                      RetPos
  734                                    ])) :-
  735    Eval =.. [.,M,Func],
  736    FuncPos = term_position(_,_,FF,FT,_),
  737    !,
  738    colourise_term_arg(M, TB, SelfPos),
  739    colour_item(func_dot, TB, SF-ST),               % .
  740    colour_item(dict_function(Func), TB, FF-FT),
  741    colourise_term_args(Func, TB, FuncPos),
  742    colour_item(dict_return_op, TB, AF-AT),         % :=
  743    colourise_term_arg(Ret, TB, RetPos).
  744colourise_clause_head(Head, TB, Pos) :-
  745    functor_position(Pos, FPos, _),
  746    classify_head(TB, Head, Class),
  747    colour_item(head_term(Class, Head), TB, Pos),
  748    colour_item(head(Class, Head), TB, FPos),
  749    colourise_term_args(Head, TB, Pos).
  750
  751%!  colourise_extern_head(+Head, +Module, +TB, +Pos)
  752%
  753%   Colourise the head specified as Module:Head. Normally used for
  754%   adding clauses to multifile predicates in other modules.
  755
  756colourise_extern_head(Head, M, TB, Pos) :-
  757    functor_position(Pos, FPos, _),
  758    colour_item(head(extern(M), Head), TB, FPos),
  759    colourise_term_args(Head, TB, Pos).
  760
  761colour_method_head(SGHead, TB, Pos) :-
  762    arg(1, SGHead, Head),
  763    functor_name(SGHead, SG),
  764    functor_position(Pos, FPos, _),
  765    colour_item(method(SG), TB, FPos),
  766    colourise_term_args(Head, TB, Pos).
  767
  768%!  functor_position(+Term, -FunctorPos, -ArgPosList)
  769%
  770%   Get the position of a functor   and  its argument. Unfortunately
  771%   this goes wrong for lists, who have two `functor-positions'.
  772
  773functor_position(term_position(_,_,FF,FT,ArgPos), FF-FT, ArgPos) :- !.
  774functor_position(list_position(F,_T,Elms,none), F-FT, Elms) :-
  775    !,
  776    FT is F + 1.
  777functor_position(dict_position(_,_,FF,FT,KVPos), FF-FT, KVPos) :- !.
  778functor_position(brace_term_position(F,T,Arg), F-T, [Arg]) :- !.
  779functor_position(Pos, Pos, []).
  780
  781colourise_module(Term, TB, Pos) :-
  782    (   var(Term)
  783    ;   atom(Term)
  784    ),
  785    !,
  786    colour_item(module(Term), TB, Pos).
  787colourise_module(_, TB, Pos) :-
  788    colour_item(type_error(module), TB, Pos).
  789
  790%!  colourise_directive(+Body, +TB, +Pos)
  791%
  792%   Colourise the body of a directive.
  793
  794colourise_directive(_,_,Pos) :-
  795    var(Pos),
  796    !.
  797colourise_directive(Dir, TB, parentheses_term_position(PO,PC,Pos)) :-
  798    !,
  799    colour_item(parentheses, TB, PO-PC),
  800    colourise_directive(Dir, TB, Pos).
  801colourise_directive((A,B), TB, term_position(_,_,_,_,[PA,PB])) :-
  802    !,
  803    colourise_directive(A, TB, PA),
  804    colourise_directive(B, TB, PB).
  805colourise_directive(Body, TB, Pos) :-
  806    nonvar(Body),
  807    directive_colours(Body, ClassSpec-ArgSpecs),   % specified
  808    !,
  809    functor_position(Pos, FPos, ArgPos),
  810    (   ClassSpec == classify
  811    ->  goal_classification(TB, Body, [], Class)
  812    ;   Class = ClassSpec
  813    ),
  814    colour_item(goal(Class, Body), TB, FPos),
  815    specified_items(ArgSpecs, Body, TB, ArgPos).
  816colourise_directive(Body, TB, Pos) :-
  817    colourise_body(Body, TB, Pos).
  818
  819
  820%       colourise_body(+Body, +TB, +Pos)
  821%
  822%       Breaks down to colourise_goal/3.
  823
  824colourise_body(Body, TB, Pos) :-
  825    colourise_body(Body, [], TB, Pos).
  826
  827colourise_body(Body, Origin, TB, Pos) :-
  828    colour_item(body, TB, Pos),
  829    colourise_goals(Body, Origin, TB, Pos).
  830
  831%!  colourise_method_body(+MethodBody, +TB, +Pos)
  832%
  833%   Colourise the optional "comment":: as pce(comment) and proceed
  834%   with the body.
  835%
  836%   @tbd    Get this handled by a hook.
  837
  838colourise_method_body(_, _, Pos) :-
  839    var(Pos),
  840    !.
  841colourise_method_body(Body, TB, parentheses_term_position(PO,PC,Pos)) :-
  842    !,
  843    colour_item(parentheses, TB, PO-PC),
  844    colourise_method_body(Body, TB, Pos).
  845colourise_method_body(::(_Comment,Body), TB,
  846                      term_position(_F,_T,_FF,_FT,[CP,BP])) :-
  847    !,
  848    colour_item(comment(string), TB, CP),
  849    colourise_body(Body, TB, BP).
  850colourise_method_body(Body, TB, Pos) :-         % deal with pri(::) < 1000
  851    Body =.. [F,A,B],
  852    control_op(F),
  853    !,
  854    Pos = term_position(_F,_T,FF,FT,
  855                        [ AP,
  856                          BP
  857                        ]),
  858    colour_item(control, TB, FF-FT),
  859    colourise_method_body(A, TB, AP),
  860    colourise_body(B, TB, BP).
  861colourise_method_body(Body, TB, Pos) :-
  862    colourise_body(Body, TB, Pos).
  863
  864control_op(',').
  865control_op((;)).
  866control_op((->)).
  867control_op((*->)).
  868
  869%!  colourise_goals(+Body, +Origin, +TB, +Pos)
  870%
  871%   Colourise the goals in a body.
  872
  873colourise_goals(_, _, _, Pos) :-
  874    var(Pos),
  875    !.
  876colourise_goals(Body, Origin, TB, parentheses_term_position(PO,PC,Pos)) :-
  877    !,
  878    colour_item(parentheses, TB, PO-PC),
  879    colourise_goals(Body, Origin, TB, Pos).
  880colourise_goals(Body, Origin, TB, term_position(_,_,FF,FT,ArgPos)) :-
  881    body_compiled(Body),
  882    !,
  883    colour_item(control, TB, FF-FT),
  884    colourise_subgoals(ArgPos, 1, Body, Origin, TB).
  885colourise_goals(Goal, Origin, TB, Pos) :-
  886    colourise_goal(Goal, Origin, TB, Pos).
  887
  888colourise_subgoals([], _, _, _, _).
  889colourise_subgoals([Pos|T], N, Body, Origin, TB) :-
  890    arg(N, Body, Arg),
  891    colourise_goals(Arg, Origin, TB, Pos),
  892    NN is N + 1,
  893    colourise_subgoals(T, NN, Body, Origin, TB).
  894
  895%!  colourise_dcg(+Body, +Head, +TB, +Pos)
  896%
  897%   Breaks down to colourise_dcg_goal/3.
  898
  899colourise_dcg(Body, Head, TB, Pos) :-
  900    colour_item(dcg, TB, Pos),
  901    (   dcg_extend(Head, Origin)
  902    ->  true
  903    ;   Origin = Head
  904    ),
  905    colourise_dcg_goals(Body, Origin, TB, Pos).
  906
  907colourise_dcg_goals(Var, _, TB, Pos) :-
  908    var(Var),
  909    !,
  910    colour_item(goal(meta,Var), TB, Pos).
  911colourise_dcg_goals(_, _, _, Pos) :-
  912    var(Pos),
  913    !.
  914colourise_dcg_goals(Body, Origin, TB, parentheses_term_position(PO,PC,Pos)) :-
  915    !,
  916    colour_item(parentheses, TB, PO-PC),
  917    colourise_dcg_goals(Body, Origin, TB, Pos).
  918colourise_dcg_goals({Body}, Origin, TB, brace_term_position(F,T,Arg)) :-
  919    !,
  920    colour_item(dcg(plain), TB, F-T),
  921    colourise_goals(Body, Origin, TB, Arg).
  922colourise_dcg_goals([], _, TB, Pos) :-
  923    !,
  924    colour_item(dcg(terminal), TB, Pos).
  925colourise_dcg_goals(List, _, TB, list_position(F,T,Elms,Tail)) :-
  926    List = [_|_],
  927    !,
  928    colour_item(dcg(terminal), TB, F-T),
  929    colourise_list_args(Elms, Tail, List, TB, classify).
  930colourise_dcg_goals(_, _, TB, string_position(F,T)) :-
  931    integer(F),
  932    !,
  933    colour_item(dcg(string), TB, F-T).
  934colourise_dcg_goals(Body, Origin, TB, term_position(_,_,FF,FT,ArgPos)) :-
  935    dcg_body_compiled(Body),       % control structures
  936    !,
  937    colour_item(control, TB, FF-FT),
  938    colourise_dcg_subgoals(ArgPos, 1, Body, Origin, TB).
  939colourise_dcg_goals(Goal, Origin, TB, Pos) :-
  940    colourise_dcg_goal(Goal, Origin, TB, Pos).
  941
  942colourise_dcg_subgoals([], _, _, _, _).
  943colourise_dcg_subgoals([Pos|T], N, Body, Origin, TB) :-
  944    arg(N, Body, Arg),
  945    colourise_dcg_goals(Arg, Origin, TB, Pos),
  946    NN is N + 1,
  947    colourise_dcg_subgoals(T, NN, Body, Origin, TB).
  948
  949dcg_extend(Term, _) :-
  950    var(Term), !, fail.
  951dcg_extend(M:Term, M:Goal) :-
  952    dcg_extend(Term, Goal).
  953dcg_extend(Term, Goal) :-
  954    compound(Term),
  955    !,
  956    compound_name_arguments(Term, Name, Args),
  957    append(Args, [_,_], NArgs),
  958    compound_name_arguments(Goal, Name, NArgs).
  959dcg_extend(Term, Goal) :-
  960    atom(Term),
  961    !,
  962    compound_name_arguments(Goal, Term, [_,_]).
  963
  964dcg_body_compiled(G) :-
  965    body_compiled(G),
  966    !.
  967dcg_body_compiled((_|_)).
  968
  969%       colourise_dcg_goal(+Goal, +Origin, +TB, +Pos).
  970
  971colourise_dcg_goal(!, Origin, TB, TermPos) :-
  972    !,
  973    colourise_goal(!, Origin, TB, TermPos).
  974colourise_dcg_goal(Goal, Origin, TB, TermPos) :-
  975    dcg_extend(Goal, TheGoal),
  976    !,
  977    colourise_goal(TheGoal, Origin, TB, TermPos).
  978colourise_dcg_goal(Goal, _, TB, Pos) :-
  979    colourise_term_args(Goal, TB, Pos).
  980
  981
  982%!  colourise_goal(+Goal, +Origin, +TB, +Pos)
  983%
  984%   Colourise access to a single goal.
  985%
  986%   @tbd Quasi Quotations are coloured as a general term argument.
  987%   Possibly we should do something with the goal information it
  988%   refers to, in particular if this goal is not defined.
  989
  990                                        % Deal with list as goal (consult)
  991colourise_goal(_,_,_,Pos) :-
  992    var(Pos),
  993    !.
  994colourise_goal(Goal, Origin, TB, parentheses_term_position(PO,PC,Pos)) :-
  995    !,
  996    colour_item(parentheses, TB, PO-PC),
  997    colourise_goal(Goal, Origin, TB, Pos).
  998colourise_goal(Goal, _, TB, Pos) :-
  999    Pos = list_position(F,T,Elms,TailPos),
 1000    Goal = [_|_],
 1001    !,
 1002    FT is F + 1,
 1003    AT is T - 1,
 1004    colour_item(goal_term(built_in, Goal), TB, Pos),
 1005    colour_item(goal(built_in, Goal), TB, F-FT),
 1006    colour_item(goal(built_in, Goal), TB, AT-T),
 1007    colourise_file_list(Goal, TB, Elms, TailPos, any).
 1008colourise_goal(Goal, Origin, TB, Pos) :-
 1009    Pos = list_position(F,T,Elms,Tail),
 1010    callable(Goal),
 1011    Goal =.. [_,GH,GT|_],
 1012    !,
 1013    goal_classification(TB, Goal, Origin, Class),
 1014    FT is F + 1,
 1015    AT is T - 1,
 1016    colour_item(goal_term(Class, Goal), TB, Pos),
 1017    colour_item(goal(Class, Goal), TB, F-FT),
 1018    colour_item(goal(Class, Goal), TB, AT-T),
 1019    colourise_list_args(Elms, Tail, [GH|GT], TB, classify).
 1020colourise_goal(Goal, _Origin, TB, Pos) :-
 1021    Pos = quasi_quotation_position(_F,_T,_QQType,_QQTypePos,_CPos),
 1022    !,
 1023    colourise_term_arg(Goal, TB, Pos).
 1024colourise_goal(Goal, Origin, TB, Pos) :-
 1025    strip_module(Goal, _, PGoal),
 1026    nonvar(PGoal),
 1027    (   goal_classification(TB, Goal, Origin, ClassInferred),
 1028        call_goal_colours(Goal, ClassInferred, ClassSpec-ArgSpecs)
 1029    ->  true
 1030    ;   call_goal_colours(Goal, ClassSpec-ArgSpecs)
 1031    ),
 1032    !,                                          % specified
 1033    functor_position(Pos, FPos, ArgPos),
 1034    (   ClassSpec == classify
 1035    ->  goal_classification(TB, Goal, Origin, Class)
 1036    ;   Class = ClassSpec
 1037    ),
 1038    colour_item(goal_term(Class, Goal), TB, Pos),
 1039    colour_item(goal(Class, Goal), TB, FPos),
 1040    colour_dict_braces(TB, Pos),
 1041    specified_items(ArgSpecs, Goal, TB, ArgPos).
 1042colourise_goal(Module:Goal, _Origin, TB, QGoalPos) :-
 1043    QGoalPos = term_position(_,_,QF,QT,[PM,PG]),
 1044    !,
 1045    colourise_module(Module, TB, PM),
 1046    colour_item(functor, TB, QF-QT),
 1047    (   PG = term_position(_,_,FF,FT,_)
 1048    ->  FP = FF-FT
 1049    ;   FP = PG
 1050    ),
 1051    (   callable(Goal)
 1052    ->  qualified_goal_classification(Module:Goal, TB, Class),
 1053        colour_item(goal_term(Class, Goal), TB, QGoalPos),
 1054        colour_item(goal(Class, Goal), TB, FP),
 1055        colourise_goal_args(Goal, Module, TB, PG)
 1056    ;   var(Goal)
 1057    ->  colourise_term_arg(Goal, TB, PG)
 1058    ;   colour_item(type_error(callable), TB, PG)
 1059    ).
 1060colourise_goal(Op, _Origin, TB, Pos) :-
 1061    nonvar(Op),
 1062    Op = op(_,_,_),
 1063    !,
 1064    colourise_op_declaration(Op, TB, Pos).
 1065colourise_goal(Goal, Origin, TB, Pos) :-
 1066    goal_classification(TB, Goal, Origin, Class),
 1067    (   Pos = term_position(_,_,FF,FT,_ArgPos)
 1068    ->  FPos = FF-FT
 1069    ;   FPos = Pos
 1070    ),
 1071    colour_item(goal_term(Class, Goal), TB, Pos),
 1072    colour_item(goal(Class, Goal), TB, FPos),
 1073    colourise_goal_args(Goal, TB, Pos).
 1074
 1075% make sure to emit a fragment for the braces of tag{k:v, ...} or
 1076% {...} that is mapped to something else.
 1077
 1078colour_dict_braces(TB, dict_position(_F,T,_TF,TT,_KVPos)) :-
 1079    !,
 1080    BStart is TT+1,
 1081    colour_item(dict_content, TB, BStart-T).
 1082colour_dict_braces(TB, brace_term_position(F,T,_Arg)) :-
 1083    !,
 1084    colour_item(brace_term, TB, F-T).
 1085colour_dict_braces(_, _).
 1086
 1087%!  colourise_goal_args(+Goal, +TB, +Pos)
 1088%
 1089%   Colourise the arguments to a goal. This predicate deals with
 1090%   meta- and database-access predicates.
 1091
 1092colourise_goal_args(Goal, TB, Pos) :-
 1093    colourization_module(TB, Module),
 1094    colourise_goal_args(Goal, Module, TB, Pos).
 1095
 1096colourization_module(TB, Module) :-
 1097    (   colour_state_source_id(TB, SourceId),
 1098        xref_module(SourceId, Module)
 1099    ->  true
 1100    ;   Module = user
 1101    ).
 1102
 1103colourise_goal_args(Goal, M, TB, term_position(_,_,_,_,ArgPos)) :-
 1104    !,
 1105    (   meta_args(Goal, TB, MetaArgs)
 1106    ->  colourise_meta_args(1, Goal, M, MetaArgs, TB, ArgPos)
 1107    ;   colourise_goal_args(1, Goal, M, TB, ArgPos)
 1108    ).
 1109colourise_goal_args(Goal, M, TB, brace_term_position(_,_,ArgPos)) :-
 1110    !,
 1111    (   meta_args(Goal, TB, MetaArgs)
 1112    ->  colourise_meta_args(1, Goal, M, MetaArgs, TB, [ArgPos])
 1113    ;   colourise_goal_args(1, Goal, M, TB, [ArgPos])
 1114    ).
 1115colourise_goal_args(_, _, _, _).                % no arguments
 1116
 1117colourise_goal_args(_, _, _, _, []) :- !.
 1118colourise_goal_args(N, Goal, Module, TB, [P0|PT]) :-
 1119    colourise_option_arg(Goal, Module, N, TB, P0),
 1120    !,
 1121    NN is N + 1,
 1122    colourise_goal_args(NN, Goal, Module, TB, PT).
 1123colourise_goal_args(N, Goal, Module, TB, [P0|PT]) :-
 1124    arg(N, Goal, Arg),
 1125    colourise_term_arg(Arg, TB, P0),
 1126    NN is N + 1,
 1127    colourise_goal_args(NN, Goal, Module, TB, PT).
 1128
 1129
 1130colourise_meta_args(_, _, _, _, _, []) :- !.
 1131colourise_meta_args(N, Goal, Module, MetaArgs, TB, [P0|PT]) :-
 1132    colourise_option_arg(Goal, Module, N, TB, P0),
 1133    !,
 1134    NN is N + 1,
 1135    colourise_meta_args(NN, Goal, Module, MetaArgs, TB, PT).
 1136colourise_meta_args(N, Goal, Module, MetaArgs, TB, [P0|PT]) :-
 1137    arg(N, Goal, Arg),
 1138    arg(N, MetaArgs, MetaSpec),
 1139    colourise_meta_arg(MetaSpec, Arg, TB, P0),
 1140    NN is N + 1,
 1141    colourise_meta_args(NN, Goal, Module, MetaArgs, TB, PT).
 1142
 1143colourise_meta_arg(MetaSpec, Arg, TB, Pos) :-
 1144    nonvar(Arg),
 1145    expand_meta(MetaSpec, Arg, Expanded),
 1146    !,
 1147    colourise_goal(Expanded, [], TB, Pos). % TBD: recursion
 1148colourise_meta_arg(MetaSpec, Arg, TB, Pos) :-
 1149    nonvar(Arg),
 1150    MetaSpec == //,
 1151    !,
 1152    colourise_dcg_goals(Arg, //, TB, Pos).
 1153colourise_meta_arg(_, Arg, TB, Pos) :-
 1154    colourise_term_arg(Arg, TB, Pos).
 1155
 1156%!  meta_args(+Goal, +TB, -ArgSpec) is semidet.
 1157%
 1158%   Return a copy of Goal, where   each  meta-argument is an integer
 1159%   representing the number of extra arguments   or  the atom // for
 1160%   indicating a DCG  body.  The   non-meta  arguments  are  unbound
 1161%   variables.
 1162%
 1163%   E.g. meta_args(maplist(foo,x,y), X) --> X = maplist(2,_,_)
 1164%
 1165%   NOTE: this could be cached if performance becomes an issue.
 1166
 1167meta_args(Goal, TB, VarGoal) :-
 1168    colour_state_source_id(TB, SourceId),
 1169    xref_meta(SourceId, Goal, _),
 1170    !,
 1171    compound_name_arity(Goal, Name, Arity),
 1172    compound_name_arity(VarGoal, Name, Arity),
 1173    xref_meta(SourceId, VarGoal, MetaArgs),
 1174    instantiate_meta(MetaArgs).
 1175
 1176instantiate_meta([]).
 1177instantiate_meta([H|T]) :-
 1178    (   var(H)
 1179    ->  H = 0
 1180    ;   H = V+N
 1181    ->  V = N
 1182    ;   H = //(V)
 1183    ->  V = (//)
 1184    ),
 1185    instantiate_meta(T).
 1186
 1187%!  expand_meta(+MetaSpec, +Goal, -Expanded) is semidet.
 1188%
 1189%   Add extra arguments to the goal if the meta-specifier is an
 1190%   integer (see above).
 1191
 1192expand_meta(MetaSpec, Goal, Goal) :-
 1193    MetaSpec == 0.
 1194expand_meta(MetaSpec, M:Goal, M:Expanded) :-
 1195    atom(M),
 1196    !,
 1197    expand_meta(MetaSpec, Goal, Expanded).
 1198expand_meta(MetaSpec, Goal, Expanded) :-
 1199    integer(MetaSpec),
 1200    MetaSpec > 0,
 1201    (   atom(Goal)
 1202    ->  functor(Expanded, Goal, MetaSpec)
 1203    ;   compound(Goal)
 1204    ->  compound_name_arguments(Goal, Name, Args0),
 1205        length(Extra, MetaSpec),
 1206        append(Args0, Extra, Args),
 1207        compound_name_arguments(Expanded, Name, Args)
 1208    ).
 1209
 1210%!  colourise_setof(+Term, +TB, +Pos)
 1211%
 1212%   Colourise the 2nd argument of setof/bagof
 1213
 1214colourise_setof(Var^G, TB, term_position(_,_,FF,FT,[VP,GP])) :-
 1215    !,
 1216    colourise_term_arg(Var, TB, VP),
 1217    colour_item(ext_quant, TB, FF-FT),
 1218    colourise_setof(G, TB, GP).
 1219colourise_setof(Term, TB, Pos) :-
 1220    colourise_goal(Term, [], TB, Pos).
 1221
 1222%       colourise_db(+Arg, +TB, +Pos)
 1223%
 1224%       Colourise database modification calls (assert/1, retract/1 and
 1225%       friends.
 1226
 1227colourise_db((Head:-_Body), TB, term_position(_,_,_,_,[HP,_])) :-
 1228    !,
 1229    colourise_db(Head, TB, HP).
 1230colourise_db(Module:Head, TB, term_position(_,_,QF,QT,[MP,HP])) :-
 1231    !,
 1232    colourise_module(Module, TB, MP),
 1233    colour_item(functor, TB, QF-QT),
 1234    (   atom(Module),
 1235        colour_state_source_id(TB, SourceId),
 1236        xref_module(SourceId, Module)
 1237    ->  colourise_db(Head, TB, HP)
 1238    ;   colourise_db(Head, TB, HP)
 1239    ).
 1240colourise_db(Head, TB, Pos) :-
 1241    colourise_goal(Head, '<db-change>', TB, Pos).
 1242
 1243
 1244%!  colourise_option_args(+Goal, +Module, +Arg:integer,
 1245%!                        +TB, +ArgPos) is semidet.
 1246%
 1247%   Colourise  predicate  options  for  the    Arg-th   argument  of
 1248%   Module:Goal
 1249
 1250colourise_option_arg(Goal, Module, Arg, TB, ArgPos) :-
 1251    goal_name_arity(Goal, Name, Arity),
 1252    current_option_arg(Module:Name/Arity, Arg),
 1253    current_predicate_options(Module:Name/Arity, Arg, OptionDecl),
 1254    debug(emacs, 'Colouring option-arg ~w of ~p',
 1255          [Arg, Module:Name/Arity]),
 1256    arg(Arg, Goal, Options),
 1257    colourise_option(Options, Module, Goal, Arg, OptionDecl, TB, ArgPos).
 1258
 1259colourise_option(Options0, Module, Goal, Arg, OptionDecl, TB, Pos0) :-
 1260    strip_option_module_qualifier(Goal, Module, Arg, TB,
 1261                                  Options0, Pos0, Options, Pos),
 1262    (   Pos = list_position(F, T, ElmPos, TailPos)
 1263    ->  colour_item(list, TB, F-T),
 1264        colourise_option_list(Options, OptionDecl, TB, ElmPos, TailPos)
 1265    ;   (   var(Options)
 1266        ;   Options == []
 1267        )
 1268    ->  colourise_term_arg(Options, TB, Pos)
 1269    ;   colour_item(type_error(list), TB, Pos)
 1270    ).
 1271
 1272strip_option_module_qualifier(Goal, Module, Arg, TB,
 1273                              M:Options, term_position(_,_,_,_,[MP,Pos]),
 1274                              Options, Pos) :-
 1275    predicate_property(Module:Goal, meta_predicate(Head)),
 1276    arg(Arg, Head, :),
 1277    !,
 1278    colourise_module(M, TB, MP).
 1279strip_option_module_qualifier(_, _, _, _,
 1280                              Options, Pos, Options, Pos).
 1281
 1282
 1283colourise_option_list(_, _, _, [], none) :- !.
 1284colourise_option_list(Tail, _, TB, [], TailPos) :-
 1285    !,
 1286    colourise_term_arg(Tail, TB, TailPos).
 1287colourise_option_list([H|T], OptionDecl, TB, [HPos|TPos], TailPos) :-
 1288    colourise_option(H, OptionDecl, TB, HPos),
 1289    colourise_option_list(T, OptionDecl, TB, TPos, TailPos).
 1290
 1291colourise_option(Opt, _, TB, Pos) :-
 1292    var(Opt),
 1293    !,
 1294    colourise_term_arg(Opt, TB, Pos).
 1295colourise_option(Opt, OptionDecl, TB, term_position(_,_,FF,FT,ValPosList)) :-
 1296    !,
 1297    generalise_term(Opt, GenOpt),
 1298    (   memberchk(GenOpt, OptionDecl)
 1299    ->  colour_item(option_name, TB, FF-FT),
 1300        Opt =.. [Name|Values],
 1301        GenOpt =.. [Name|Types],
 1302        colour_option_values(Values, Types, TB, ValPosList)
 1303    ;   colour_item(no_option_name, TB, FF-FT),
 1304        colourise_term_args(ValPosList, 1, Opt, TB)
 1305    ).
 1306colourise_option(_, _, TB, Pos) :-
 1307    colour_item(type_error(option), TB, Pos).
 1308
 1309colour_option_values([], [], _, _).
 1310colour_option_values([V0|TV], [T0|TT], TB, [P0|TP]) :-
 1311    (   (   var(V0)
 1312        ;   is_of_type(T0, V0)
 1313        ;   T0 = list(_),
 1314            member(E, V0),
 1315            var(E)
 1316        ;   functor(V0, '.', 2),
 1317            V0 \= [_|_]
 1318        )
 1319    ->  colourise_term_arg(V0, TB, P0)
 1320    ;   callable(V0),
 1321        (   T0 = callable
 1322        ->  N = 0
 1323        ;   T0 = (callable+N)
 1324        )
 1325    ->  colourise_meta_arg(N, V0, TB, P0)
 1326    ;   colour_item(type_error(T0), TB, P0)
 1327    ),
 1328    colour_option_values(TV, TT, TB, TP).
 1329
 1330
 1331%!  colourise_files(+Arg, +TB, +Pos, +Why)
 1332%
 1333%   Colourise the argument list of one of the file-loading predicates.
 1334%
 1335%   @param Why is one of =any= or =imported=
 1336
 1337colourise_files(List, TB, list_position(F,T,Elms,TailPos), Why) :-
 1338    !,
 1339    colour_item(list, TB, F-T),
 1340    colourise_file_list(List, TB, Elms, TailPos, Why).
 1341colourise_files(M:Spec, TB, term_position(_,_,_,_,[MP,SP]), Why) :-
 1342    !,
 1343    colourise_module(M, TB, MP),
 1344    colourise_files(Spec, TB, SP, Why).
 1345colourise_files(Var, TB, P, _) :-
 1346    var(Var),
 1347    !,
 1348    colour_item(var, TB, P).
 1349colourise_files(Spec0, TB, Pos, Why) :-
 1350    strip_module(Spec0, _, Spec),
 1351    (   colour_state_source_id(TB, Source),
 1352        prolog_canonical_source(Source, SourceId),
 1353        catch(xref_source_file(Spec, Path, SourceId, [silent(true)]),
 1354              _, fail)
 1355    ->  (   Why = imported,
 1356            \+ resolves_anything(TB, Path),
 1357            exports_something(TB, Path)
 1358        ->  colour_item(file_no_depend(Path), TB, Pos)
 1359        ;   colour_item(file(Path), TB, Pos)
 1360        )
 1361    ;   colour_item(nofile, TB, Pos)
 1362    ).
 1363
 1364%!  colourise_file_list(+Files, +TB, +ElmPos, +TailPos, +Why)
 1365
 1366colourise_file_list([], _, [], none, _).
 1367colourise_file_list(Last, TB, [], TailPos, _Why) :-
 1368    (   var(Last)
 1369    ->  colourise_term(Last, TB, TailPos)
 1370    ;   colour_item(type_error(list), TB, TailPos)
 1371    ).
 1372colourise_file_list([H|T], TB, [PH|PT], TailPos, Why) :-
 1373    colourise_files(H, TB, PH, Why),
 1374    colourise_file_list(T, TB, PT, TailPos, Why).
 1375
 1376resolves_anything(TB, Path) :-
 1377    colour_state_source_id(TB, SourceId),
 1378    xref_defined(SourceId, Head, imported(Path)),
 1379    xref_called(SourceId, Head, _),
 1380    !.
 1381
 1382exports_something(TB, Path) :-
 1383    colour_state_source_id(TB, SourceId),
 1384    xref_defined(SourceId, _, imported(Path)),
 1385    !.
 1386
 1387%!  colourise_directory(+Arg, +TB, +Pos)
 1388%
 1389%   Colourise argument that should be an existing directory.
 1390
 1391colourise_directory(Spec, TB, Pos) :-
 1392    (   colour_state_source_id(TB, SourceId),
 1393        catch(xref_source_file(Spec, Path, SourceId,
 1394                               [ file_type(directory),
 1395                                 silent(true)
 1396                               ]),
 1397              _, fail)
 1398    ->  colour_item(directory(Path), TB, Pos)
 1399    ;   colour_item(nofile, TB, Pos)
 1400    ).
 1401
 1402%!  colourise_langoptions(+Term, +TB, +Pos) is det.
 1403%
 1404%   Colourise the 3th argument of module/3
 1405
 1406colourise_langoptions([], _, _) :- !.
 1407colourise_langoptions([H|T], TB, list_position(PF,PT,[HP|TP],_)) :-
 1408    !,
 1409    colour_item(list, TB, PF-PT),
 1410    colourise_langoptions(H, TB, HP),
 1411    colourise_langoptions(T, TB, TP).
 1412colourise_langoptions(Spec, TB, Pos) :-
 1413    colourise_files(library(dialect/Spec), TB, Pos, imported).
 1414
 1415%!  colourise_class(ClassName, TB, Pos)
 1416%
 1417%   Colourise an XPCE class.
 1418
 1419colourise_class(ClassName, TB, Pos) :-
 1420    colour_state_source_id(TB, SourceId),
 1421    classify_class(SourceId, ClassName, Classification),
 1422    colour_item(class(Classification, ClassName), TB, Pos).
 1423
 1424%!  classify_class(+SourceId, +ClassName, -Classification)
 1425%
 1426%   Classify an XPCE class. As long as   this code is in this module
 1427%   rather than using hooks, we do not   want to load xpce unless it
 1428%   is already loaded.
 1429
 1430classify_class(SourceId, Name, Class) :-
 1431    xref_defined_class(SourceId, Name, Class),
 1432    !.
 1433classify_class(_SourceId, Name, Class) :-
 1434    current_predicate(pce:send_class/3),
 1435    (   current_predicate(classify_class/2)
 1436    ->  true
 1437    ;   use_module(library(pce_meta), [classify_class/2])
 1438    ),
 1439    member(G, [classify_class(Name, Class)]),
 1440    call(G).
 1441
 1442%!  colourise_term_args(+Term, +TB, +Pos)
 1443%
 1444%   colourise head/body principal terms.
 1445
 1446colourise_term_args(Term, TB,
 1447                    term_position(_,_,_,_,ArgPos)) :-
 1448    !,
 1449    colourise_term_args(ArgPos, 1, Term, TB).
 1450colourise_term_args(_, _, _).
 1451
 1452colourise_term_args([], _, _, _).
 1453colourise_term_args([Pos|T], N, Term, TB) :-
 1454    arg(N, Term, Arg),
 1455    colourise_term_arg(Arg, TB, Pos),
 1456    NN is N + 1,
 1457    colourise_term_args(T, NN, Term, TB).
 1458
 1459colourise_term_arg(_, _, Pos) :-
 1460    var(Pos),
 1461    !.
 1462colourise_term_arg(Arg, TB, parentheses_term_position(PO,PC,Pos)) :-
 1463    !,
 1464    colour_item(parentheses, TB, PO-PC),
 1465    colourise_term_arg(Arg, TB, Pos).
 1466colourise_term_arg(Var, TB, Pos) :-                     % variable
 1467    var(Var), Pos = _-_,
 1468    !,
 1469    (   singleton(Var, TB)
 1470    ->  colour_item(singleton, TB, Pos)
 1471    ;   colour_item(var, TB, Pos)
 1472    ).
 1473colourise_term_arg(List, TB, list_position(F, T, Elms, Tail)) :-
 1474    !,
 1475    colour_item(list, TB, F-T),
 1476    colourise_list_args(Elms, Tail, List, TB, classify).    % list
 1477colourise_term_arg(String, TB, string_position(F, T)) :-       % string
 1478    !,
 1479    (   string(String)
 1480    ->  colour_item(string, TB, F-T)
 1481    ;   String = [H|_]
 1482    ->  (   integer(H)
 1483        ->  colour_item(codes, TB, F-T)
 1484        ;   colour_item(chars, TB, F-T)
 1485        )
 1486    ;   String == []
 1487    ->  colour_item(codes, TB, F-T)
 1488    ).
 1489colourise_term_arg(_, TB,
 1490                   quasi_quotation_position(F,T,QQType,QQTypePos,CPos)) :-
 1491    !,
 1492    colourise_qq_type(QQType, TB, QQTypePos),
 1493    functor_name(QQType, Type),
 1494    colour_item(qq_content(Type), TB, CPos),
 1495    arg(1, CPos, SE),
 1496    SS is SE-2,
 1497    FE is F+2,
 1498    TS is T-2,
 1499    colour_item(qq(open),  TB, F-FE),
 1500    colour_item(qq(sep),   TB, SS-SE),
 1501    colour_item(qq(close), TB, TS-T).
 1502colourise_term_arg({Term}, TB, brace_term_position(F,T,Arg)) :-
 1503    !,
 1504    colour_item(brace_term, TB, F-T),
 1505    colourise_term_arg(Term, TB, Arg).
 1506colourise_term_arg(Map, TB, dict_position(F,T,TF,TT,KVPos)) :-
 1507    !,
 1508    is_dict(Map, Tag),
 1509    colour_item(dict, TB, F-T),
 1510    TagPos = TF-TT,
 1511    (   var(Tag)
 1512    ->  (   singleton(Tag, TB)
 1513        ->  colour_item(singleton, TB, TagPos)
 1514        ;   colour_item(var, TB, TagPos)
 1515        )
 1516    ;   colour_item(dict_tag, TB, TagPos)
 1517    ),
 1518    BStart is TT+1,
 1519    colour_item(dict_content, TB, BStart-T),
 1520    colourise_dict_kv(Map, TB, KVPos).
 1521colourise_term_arg([](List,Term), TB,                   % [] as operator
 1522                   term_position(_,_,0,0,[ListPos,ArgPos])) :-
 1523    !,
 1524    colourise_term_arg(List, TB, ListPos),
 1525    colourise_term_arg(Term, TB, ArgPos).
 1526colourise_term_arg(Compound, TB, Pos) :-                % compound
 1527    compound(Compound),
 1528    !,
 1529    (   Pos = term_position(_F,_T,FF,FT,_ArgPos)
 1530    ->  colour_item(functor, TB, FF-FT)             % TBD: Infix/Postfix?
 1531    ;   true                                        % TBD: When is this
 1532    ),
 1533    colourise_term_args(Compound, TB, Pos).
 1534colourise_term_arg(EmptyList, TB, Pos) :-
 1535    EmptyList == [],
 1536    !,
 1537    colour_item(empty_list, TB, Pos).
 1538colourise_term_arg(Atom, TB, Pos) :-
 1539    atom(Atom),
 1540    !,
 1541    colour_item(atom, TB, Pos).
 1542colourise_term_arg(Integer, TB, Pos) :-
 1543    integer(Integer),
 1544    !,
 1545    colour_item(int, TB, Pos).
 1546colourise_term_arg(Float, TB, Pos) :-
 1547    float(Float),
 1548    !,
 1549    colour_item(float, TB, Pos).
 1550colourise_term_arg(_Arg, _TB, _Pos) :-
 1551    true.
 1552
 1553colourise_list_args([HP|TP], Tail, [H|T], TB, How) :-
 1554    specified_item(How, H, TB, HP),
 1555    colourise_list_args(TP, Tail, T, TB, How).
 1556colourise_list_args([], none, _, _, _) :- !.
 1557colourise_list_args([], TP, T, TB, How) :-
 1558    specified_item(How, T, TB, TP).
 1559
 1560%!  colourise_qq_type(+QQType, +TB, +QQTypePos)
 1561%
 1562%   Colouring the type part of a quasi quoted term
 1563
 1564colourise_qq_type(QQType, TB, QQTypePos) :-
 1565    functor_position(QQTypePos, FPos, _),
 1566    colour_item(qq_type, TB, FPos),
 1567    colourise_term_args(QQType, TB, QQTypePos).
 1568
 1569qq_position(quasi_quotation_position(_,_,_,_,_)).
 1570
 1571%!  colourise_dict_kv(+Dict, +TB, +KVPosList)
 1572%
 1573%   Colourise the name-value pairs in the dict
 1574
 1575colourise_dict_kv(_, _, []) :- !.
 1576colourise_dict_kv(Dict, TB, [key_value_position(_F,_T,SF,ST,K,KP,VP)|KV]) :-
 1577    colour_item(dict_key, TB, KP),
 1578    colour_item(dict_sep, TB, SF-ST),
 1579    get_dict(K, Dict, V),
 1580    colourise_term_arg(V, TB, VP),
 1581    colourise_dict_kv(Dict, TB, KV).
 1582
 1583
 1584%!  colourise_exports(+List, +TB, +Pos)
 1585%
 1586%   Colourise the module export-list (or any other list holding
 1587%   terms of the form Name/Arity referring to predicates).
 1588
 1589colourise_exports([], TB, Pos) :- !,
 1590    colourise_term_arg([], TB, Pos).
 1591colourise_exports(List, TB, list_position(F,T,ElmPos,Tail)) :-
 1592    !,
 1593    colour_item(list, TB, F-T),
 1594    (   Tail == none
 1595    ->  true
 1596    ;   colour_item(type_error(list), TB, Tail)
 1597    ),
 1598    colourise_exports2(List, TB, ElmPos).
 1599colourise_exports(_, TB, Pos) :-
 1600    colour_item(type_error(list), TB, Pos).
 1601
 1602colourise_exports2([G0|GT], TB, [P0|PT]) :-
 1603    !,
 1604    colourise_declaration(G0, export, TB, P0),
 1605    colourise_exports2(GT, TB, PT).
 1606colourise_exports2(_, _, _).
 1607
 1608
 1609%!  colourise_imports(+List, +File, +TB, +Pos)
 1610%
 1611%   Colourise import list from use_module/2, importing from File.
 1612
 1613colourise_imports(List, File, TB, Pos) :-
 1614    (   colour_state_source_id(TB, SourceId),
 1615        ground(File),
 1616        catch(xref_public_list(File, SourceId,
 1617                               [ path(Path),
 1618                                 public(Public),
 1619                                 silent(true)
 1620                               ] ), _, fail)
 1621    ->  true
 1622    ;   Public = [],
 1623        Path = (-)
 1624    ),
 1625    colourise_imports(List, Path, Public, TB, Pos).
 1626
 1627colourise_imports([], _, _, TB, Pos) :-
 1628    !,
 1629    colour_item(empty_list, TB, Pos).
 1630colourise_imports(List, File, Public, TB, list_position(F,T,ElmPos,Tail)) :-
 1631    !,
 1632    colour_item(list, TB, F-T),
 1633    (   Tail == none
 1634    ->  true
 1635    ;   colour_item(type_error(list), TB, Tail)
 1636    ),
 1637    colourise_imports2(List, File, Public, TB, ElmPos).
 1638colourise_imports(except(Except), File, Public, TB,
 1639                  term_position(_,_,FF,FT,[LP])) :-
 1640    !,
 1641    colour_item(keyword(except), TB, FF-FT),
 1642    colourise_imports(Except, File, Public, TB, LP).
 1643colourise_imports(_, _, _, TB, Pos) :-
 1644    colour_item(type_error(list), TB, Pos).
 1645
 1646colourise_imports2([G0|GT], File, Public, TB, [P0|PT]) :-
 1647    !,
 1648    colourise_import(G0, File, TB, P0),
 1649    colourise_imports2(GT, File, Public, TB, PT).
 1650colourise_imports2(_, _, _, _, _).
 1651
 1652
 1653colourise_import(PI as Name, File, TB, term_position(_,_,FF,FT,[PP,NP])) :-
 1654    pi_to_term(PI, Goal),
 1655    !,
 1656    colour_item(goal(imported(File), Goal), TB, PP),
 1657    rename_goal(Goal, Name, NewGoal),
 1658    goal_classification(TB, NewGoal, [], Class),
 1659    colour_item(goal(Class, NewGoal), TB, NP),
 1660    colour_item(keyword(as), TB, FF-FT).
 1661colourise_import(PI, File, TB, Pos) :-
 1662    pi_to_term(PI, Goal),
 1663    colour_state_source_id(TB, SourceID),
 1664    (   \+ xref_defined(SourceID, Goal, imported(File))
 1665    ->  colour_item(undefined_import, TB, Pos)
 1666    ;   \+ xref_called(SourceID, Goal, _)
 1667    ->  colour_item(unused_import, TB, Pos)
 1668    ),
 1669    !.
 1670colourise_import(PI, _, TB, Pos) :-
 1671    colourise_declaration(PI, import, TB, Pos).
 1672
 1673%!  colourise_declaration(+Decl, ?Which, +TB, +Pos) is det.
 1674%
 1675%   Colourise declaration sequences as used  by module/2, dynamic/1,
 1676%   etc.
 1677
 1678colourise_declaration(PI, _, TB, term_position(F,T,FF,FT,[NamePos,ArityPos])) :-
 1679    pi_to_term(PI, Goal),
 1680    !,
 1681    goal_classification(TB, Goal, [], Class),
 1682    colour_item(predicate_indicator(Class, Goal), TB, F-T),
 1683    colour_item(goal(Class, Goal), TB, NamePos),
 1684    colour_item(predicate_indicator, TB, FF-FT),
 1685    colour_item(arity, TB, ArityPos).
 1686colourise_declaration(Module:PI, _, TB,
 1687                      term_position(_,_,QF,QT,[PM,PG])) :-
 1688    atom(Module), pi_to_term(PI, Goal),
 1689    !,
 1690    colourise_module(M, TB, PM),
 1691    colour_item(functor, TB, QF-QT),
 1692    colour_item(predicate_indicator(extern(M), Goal), TB, PG),
 1693    PG = term_position(_,_,FF,FT,[NamePos,ArityPos]),
 1694    colour_item(goal(extern(M), Goal), TB, NamePos),
 1695    colour_item(predicate_indicator, TB, FF-FT),
 1696    colour_item(arity, TB, ArityPos).
 1697colourise_declaration(op(N,T,P), Which, TB, Pos) :-
 1698    (   Which == export
 1699    ;   Which == import
 1700    ),
 1701    !,
 1702    colour_item(exported_operator, TB, Pos),
 1703    colourise_op_declaration(op(N,T,P), TB, Pos).
 1704colourise_declaration(Goal, table, TB, term_position(_F,_T,FF,FT,ArgPos)) :-
 1705    callable(Goal),
 1706    !,
 1707    compound_name_arguments(Goal, _, Args),
 1708    goal_classification(TB, Goal, [], Class),
 1709    colour_item(goal(Class, Goal), TB, FF-FT),
 1710    colourise_table_modes(Args, TB, ArgPos).
 1711colourise_declaration(Goal, table, TB, Pos) :-
 1712    atom(Goal),
 1713    !,
 1714    goal_classification(TB, Goal, [], Class),
 1715    colour_item(goal(Class, Goal), TB, Pos).
 1716colourise_declaration(Partial, _Which, TB, Pos) :-
 1717    compatible_with_pi(Partial),
 1718    !,
 1719    colourise_term_arg(Partial, TB, Pos).
 1720colourise_declaration(_, Which, TB, Pos) :-
 1721    colour_item(type_error(declaration(Which)), TB, Pos).
 1722
 1723compatible_with_pi(Term) :-
 1724    var(Term),
 1725    !.
 1726compatible_with_pi(Name/Arity) :-
 1727    !,
 1728    var_or_atom(Name),
 1729    var_or_nonneg(Arity).
 1730compatible_with_pi(Name//Arity) :-
 1731    !,
 1732    var_or_atom(Name),
 1733    var_or_nonneg(Arity).
 1734compatible_with_pi(M:T) :-
 1735    var_or_atom(M),
 1736    compatible_with_pi(T).
 1737
 1738var_or_atom(X) :- var(X), !.
 1739var_or_atom(X) :- atom(X).
 1740var_or_nonneg(X) :- var(X), !.
 1741var_or_nonneg(X) :- integer(X), X >= 0, !.
 1742
 1743pi_to_term(Name/Arity, Term) :-
 1744    atom(Name), integer(Arity), Arity >= 0,
 1745    !,
 1746    functor(Term, Name, Arity).
 1747pi_to_term(Name//Arity0, Term) :-
 1748    atom(Name), integer(Arity0), Arity0 >= 0,
 1749    !,
 1750    Arity is Arity0 + 2,
 1751    functor(Term, Name, Arity).
 1752
 1753colourise_meta_declarations((Head,Tail), Extra, TB,
 1754                            term_position(_,_,_,_,[PH,PT])) :-
 1755    !,
 1756    colourise_meta_declaration(Head, Extra, TB, PH),
 1757    colourise_meta_declarations(Tail, Extra, TB, PT).
 1758colourise_meta_declarations(Last, Extra, TB, Pos) :-
 1759    colourise_meta_declaration(Last, Extra, TB, Pos).
 1760
 1761colourise_meta_declaration(M:Head, Extra, TB,
 1762                           term_position(_,_,QF,QT,
 1763                                         [ MP,
 1764                                           term_position(_,_,FF,FT,ArgPos)
 1765                                         ])) :-
 1766    compound(Head),
 1767    !,
 1768    colourise_module(M, TB, MP),
 1769    colour_item(functor, TB, QF-QT),
 1770    colour_item(goal(extern(M),Head), TB, FF-FT),
 1771    compound_name_arguments(Head, _, Args),
 1772    colourise_meta_decls(Args, Extra, TB, ArgPos).
 1773colourise_meta_declaration(Head, Extra, TB, term_position(_,_,FF,FT,ArgPos)) :-
 1774    compound(Head),
 1775    !,
 1776    goal_classification(TB, Head, [], Class),
 1777    colour_item(goal(Class, Head), TB, FF-FT),
 1778    compound_name_arguments(Head, _, Args),
 1779    colourise_meta_decls(Args, Extra, TB, ArgPos).
 1780colourise_meta_declaration([H|T], Extra, TB, list_position(LF,LT,[HP],TP)) :-
 1781    !,
 1782    colour_item(list, TB, LF-LT),
 1783    colourise_meta_decls([H,T], Extra, TB, [HP,TP]).
 1784colourise_meta_declaration(_, _, TB, Pos) :-
 1785    !,
 1786    colour_item(type_error(compound), TB, Pos).
 1787
 1788colourise_meta_decls([], _, _, []).
 1789colourise_meta_decls([Arg|ArgT], Extra, TB, [PosH|PosT]) :-
 1790    colourise_meta_decl(Arg, Extra, TB, PosH),
 1791    colourise_meta_decls(ArgT, Extra, TB, PosT).
 1792
 1793colourise_meta_decl(Arg, Extra, TB, Pos) :-
 1794    nonvar(Arg),
 1795    (   valid_meta_decl(Arg)
 1796    ->  true
 1797    ;   memberchk(Arg, Extra)
 1798    ),
 1799    colour_item(meta(Arg), TB, Pos).
 1800colourise_meta_decl(_, _, TB, Pos) :-
 1801    colour_item(error, TB, Pos).
 1802
 1803valid_meta_decl(:).
 1804valid_meta_decl(*).
 1805valid_meta_decl(//).
 1806valid_meta_decl(^).
 1807valid_meta_decl(?).
 1808valid_meta_decl(+).
 1809valid_meta_decl(-).
 1810valid_meta_decl(I) :- integer(I), between(0,9,I).
 1811
 1812%!  colourise_declarations(+Term, +Which, +TB, +Pos)
 1813%
 1814%   Colourise  specification  for  dynamic/1,   table/1,  etc.  Includes
 1815%   processing options such as ``:- dynamic p/1 as incremental.``.
 1816
 1817colourise_declarations(List, Which, TB, list_position(F,T,Elms,none)) :-
 1818    !,
 1819    colour_item(list, TB, F-T),
 1820    colourise_list_declarations(List, Which, TB, Elms).
 1821colourise_declarations(Term, Which, TB, parentheses_term_position(PO,PC,Pos)) :-
 1822    !,
 1823    colour_item(parentheses, TB, PO-PC),
 1824    colourise_declarations(Term, Which, TB, Pos).
 1825colourise_declarations((Head,Tail), Which, TB,
 1826                             term_position(_,_,_,_,[PH,PT])) :-
 1827    !,
 1828    colourise_declarations(Head, Which, TB, PH),
 1829    colourise_declarations(Tail, Which, TB, PT).
 1830colourise_declarations(as(Spec, Options), Which, TB,
 1831                             term_position(_,_,FF,FT,[PH,PT])) :-
 1832    !,
 1833    colour_item(keyword(as), TB, FF-FT),
 1834    colourise_declarations(Spec, Which, TB, PH),
 1835    colourise_decl_options(Options, Which, TB, PT).
 1836colourise_declarations(PI, Which, TB, Pos) :-
 1837    colourise_declaration(PI, Which, TB, Pos).
 1838
 1839colourise_list_declarations([], _, _, []).
 1840colourise_list_declarations([H|T], Which, TB, [HP|TP]) :-
 1841    colourise_declaration(H, Which, TB, HP),
 1842    colourise_list_declarations(T, Which, TB, TP).
 1843
 1844
 1845colourise_table_modes([], _, _).
 1846colourise_table_modes([H|T], TB, [PH|PT]) :-
 1847    colourise_table_mode(H, TB, PH),
 1848    colourise_table_modes(T, TB, PT).
 1849
 1850colourise_table_mode(H, TB, Pos) :-
 1851    table_mode(H, Mode),
 1852    !,
 1853    colour_item(table_mode(Mode), TB, Pos).
 1854colourise_table_mode(lattice(Spec), TB, term_position(_F,_T,FF,FT,[ArgPos])) :-
 1855    !,
 1856    colour_item(table_mode(lattice), TB, FF-FT),
 1857    table_moded_call(Spec, 3, TB, ArgPos).
 1858colourise_table_mode(po(Spec), TB, term_position(_F,_T,FF,FT,[ArgPos])) :-
 1859    !,
 1860    colour_item(table_mode(po), TB, FF-FT),
 1861    table_moded_call(Spec, 2, TB, ArgPos).
 1862colourise_table_mode(_, TB, Pos) :-
 1863    colour_item(type_error(table_mode), TB, Pos).
 1864
 1865table_mode(Var, index) :-
 1866    var(Var),
 1867    !.
 1868table_mode(+, index).
 1869table_mode(index, index).
 1870table_mode(-, first).
 1871table_mode(first, first).
 1872table_mode(last, last).
 1873table_mode(min, min).
 1874table_mode(max, max).
 1875table_mode(sum, sum).
 1876
 1877table_moded_call(Atom, Arity, TB, Pos) :-
 1878    atom(Atom),
 1879    functor(Head, Atom, Arity),
 1880    goal_classification(TB, Head, [], Class),
 1881    colour_item(goal(Class, Head), TB, Pos).
 1882table_moded_call(Atom/Arity, Arity, TB,
 1883                 term_position(_,_,FF,FT,[NP,AP])) :-
 1884    atom(Atom),
 1885    !,
 1886    functor(Head, Atom, Arity),
 1887    goal_classification(TB, Head, [], Class),
 1888    colour_item(goal(Class, Head), TB, NP),
 1889    colour_item(predicate_indicator, TB, FF-FT),
 1890    colour_item(arity, TB, AP).
 1891table_moded_call(Head, Arity, TB, Pos) :-
 1892    Pos = term_position(_,_,FF,FT,_),
 1893    compound(Head),
 1894    !,
 1895    compound_name_arity(Head, _Name, Arity),
 1896    goal_classification(TB, Head, [], Class),
 1897    colour_item(goal(Class, Head), TB, FF-FT),
 1898    colourise_term_args(Head, TB, Pos).
 1899table_moded_call(_, _, TB, Pos) :-
 1900    colour_item(type_error(predicate_name_or_indicator), TB, Pos).
 1901
 1902colourise_decl_options(Options, Which, TB,
 1903                       parentheses_term_position(_,_,Pos)) :-
 1904    !,
 1905    colourise_decl_options(Options, Which, TB, Pos).
 1906colourise_decl_options((Head,Tail), Which, TB,
 1907                        term_position(_,_,_,_,[PH,PT])) :-
 1908    !,
 1909    colourise_decl_options(Head, Which, TB, PH),
 1910    colourise_decl_options(Tail, Which, TB, PT).
 1911colourise_decl_options(Option, Which, TB, Pos) :-
 1912    ground(Option),
 1913    valid_decl_option(Option, Which),
 1914    !,
 1915    functor(Option, Name, _),
 1916    colour_item(decl_option(Name), TB, Pos).
 1917colourise_decl_options(_, Which, TB, Pos) :-
 1918    colour_item(type_error(decl_option(Which)), TB, Pos).
 1919
 1920valid_decl_option(subsumptive,   table).
 1921valid_decl_option(variant,       table).
 1922valid_decl_option(incremental,   table).
 1923valid_decl_option(incremental,   dynamic).
 1924valid_decl_option(abstract(0),   dynamic).
 1925valid_decl_option(shared,        table).
 1926valid_decl_option(private,       table).
 1927valid_decl_option(shared,        dynamic).
 1928valid_decl_option(private,       dynamic).
 1929valid_decl_option(local,         dynamic).
 1930valid_decl_option(multifile,     _).
 1931valid_decl_option(discontiguous, _).
 1932valid_decl_option(volatile,      _).
 1933
 1934%!  colourise_op_declaration(Op, TB, Pos) is det.
 1935
 1936colourise_op_declaration(op(P,T,N), TB, term_position(_,_,FF,FT,[PP,TP,NP])) :-
 1937    colour_item(goal(built_in, op(N,T,P)), TB, FF-FT),
 1938    colour_op_priority(P, TB, PP),
 1939    colour_op_type(T, TB, TP),
 1940    colour_op_name(N, TB, NP).
 1941
 1942colour_op_name(_, _, Pos) :-
 1943    var(Pos),
 1944    !.
 1945colour_op_name(Name, TB, parentheses_term_position(PO,PC,Pos)) :-
 1946    !,
 1947    colour_item(parentheses, TB, PO-PC),
 1948    colour_op_name(Name, TB, Pos).
 1949colour_op_name(Name, TB, Pos) :-
 1950    var(Name),
 1951    !,
 1952    colour_item(var, TB, Pos).
 1953colour_op_name(Name, TB, Pos) :-
 1954    (atom(Name) ; Name == []),
 1955    !,
 1956    colour_item(identifier, TB, Pos).
 1957colour_op_name(Module:Name, TB, term_position(_F,_T,QF,QT,[MP,NP])) :-
 1958    !,
 1959    colourise_module(Module, TB, MP),
 1960    colour_item(functor, TB, QF-QT),
 1961    colour_op_name(Name, TB, NP).
 1962colour_op_name(List, TB, list_position(F,T,Elems,none)) :-
 1963    !,
 1964    colour_item(list, TB, F-T),
 1965    colour_op_names(List, TB, Elems).
 1966colour_op_name(_, TB, Pos) :-
 1967    colour_item(error, TB, Pos).
 1968
 1969colour_op_names([], _, []).
 1970colour_op_names([H|T], TB, [HP|TP]) :-
 1971    colour_op_name(H, TB, HP),
 1972    colour_op_names(T, TB, TP).
 1973
 1974colour_op_type(Type, TB, Pos) :-
 1975    var(Type),
 1976    !,
 1977    colour_item(var, TB, Pos).
 1978colour_op_type(Type, TB, Pos) :-
 1979    op_type(Type),
 1980    !,
 1981    colour_item(op_type(Type), TB, Pos).
 1982colour_op_type(_, TB, Pos) :-
 1983    colour_item(error, TB, Pos).
 1984
 1985colour_op_priority(Priority, TB, Pos) :-
 1986    var(Priority), colour_item(var, TB, Pos).
 1987colour_op_priority(Priority, TB, Pos) :-
 1988    integer(Priority),
 1989    between(0, 1200, Priority),
 1990    !,
 1991    colour_item(int, TB, Pos).
 1992colour_op_priority(_, TB, Pos) :-
 1993    colour_item(error, TB, Pos).
 1994
 1995op_type(fx).
 1996op_type(fy).
 1997op_type(xf).
 1998op_type(yf).
 1999op_type(xfy).
 2000op_type(xfx).
 2001op_type(yfx).
 2002
 2003
 2004%!  colourise_prolog_flag_name(+Name, +TB, +Pos)
 2005%
 2006%   Colourise the name of a Prolog flag
 2007
 2008colourise_prolog_flag_name(_, _, Pos) :-
 2009    var(Pos),
 2010    !.
 2011colourise_prolog_flag_name(Name, TB, parentheses_term_position(PO,PC,Pos)) :-
 2012    !,
 2013    colour_item(parentheses, TB, PO-PC),
 2014    colourise_prolog_flag_name(Name, TB, Pos).
 2015colourise_prolog_flag_name(Name, TB, Pos) :-
 2016    atom(Name),
 2017    !,
 2018    (   current_prolog_flag(Name, _)
 2019    ->  colour_item(flag_name(Name), TB, Pos)
 2020    ;   colour_item(no_flag_name(Name), TB, Pos)
 2021    ).
 2022colourise_prolog_flag_name(Name, TB, Pos) :-
 2023    colourise_term(Name, TB, Pos).
 2024
 2025
 2026                 /*******************************
 2027                 *        CONFIGURATION         *
 2028                 *******************************/
 2029
 2030%       body_compiled(+Term)
 2031%
 2032%       Succeeds if term is a construct handled by the compiler.
 2033
 2034body_compiled((_,_)).
 2035body_compiled((_->_)).
 2036body_compiled((_*->_)).
 2037body_compiled((_;_)).
 2038body_compiled(\+_).
 2039
 2040%!  goal_classification(+TB, +Goal, +Origin, -Class)
 2041%
 2042%   Classify Goal appearing in TB and called from a clause with head
 2043%   Origin.  For directives, Origin is [].
 2044
 2045goal_classification(_, QGoal, _, Class) :-
 2046    strip_module(QGoal, _, Goal),
 2047    (   var(Goal)
 2048    ->  !, Class = meta
 2049    ;   \+ callable(Goal)
 2050    ->  !, Class = not_callable
 2051    ).
 2052goal_classification(_, Goal, Origin, recursion) :-
 2053    callable(Origin),
 2054    generalise_term(Goal, Origin),
 2055    !.
 2056goal_classification(TB, Goal, _, How) :-
 2057    colour_state_source_id(TB, SourceId),
 2058    xref_defined(SourceId, Goal, How),
 2059    How \= public(_),
 2060    !.
 2061goal_classification(_TB, Goal, _, Class) :-
 2062    call_goal_classification(Goal, Class),
 2063    !.
 2064goal_classification(TB, Goal, _, How) :-
 2065    colour_state_module(TB, Module),
 2066    atom(Module),
 2067    Module \== prolog_colour_ops,
 2068    predicate_property(Module:Goal, imported_from(From)),
 2069    !,
 2070    How = imported(From).
 2071goal_classification(_TB, _Goal, _, undefined).
 2072
 2073%!  goal_classification(+Goal, -Class)
 2074%
 2075%   Multifile hookable classification for non-local goals.
 2076
 2077call_goal_classification(Goal, Class) :-
 2078    catch(goal_classification(Goal, Class), _,
 2079          Class = type_error(callable)).
 2080
 2081goal_classification(Goal, built_in) :-
 2082    built_in_predicate(Goal),
 2083    !.
 2084goal_classification(Goal, autoload(From)) :-    % SWI-Prolog
 2085    predicate_property(Goal, autoload(From)).
 2086goal_classification(Goal, global) :-            % SWI-Prolog
 2087    strip_module(Goal, _, PGoal),
 2088    current_predicate(_, user:PGoal),
 2089    !.
 2090goal_classification(Goal, Class) :-
 2091    compound(Goal),
 2092    compound_name_arity(Goal, Name, Arity),
 2093    vararg_goal_classification(Name, Arity, Class).
 2094
 2095%!  vararg_goal_classification(+Name, +Arity, -Class) is semidet.
 2096%
 2097%   Multifile hookable classification for _vararg_ predicates.
 2098
 2099vararg_goal_classification(call, Arity, built_in) :-
 2100    Arity >= 1.
 2101vararg_goal_classification(send_super, Arity, expanded) :- % XPCE (TBD)
 2102    Arity >= 2.
 2103vararg_goal_classification(get_super, Arity, expanded) :-  % XPCE (TBD)
 2104    Arity >= 3.
 2105
 2106%!  qualified_goal_classification(:Goal, +TB, -Class)
 2107%
 2108%   Classify an explicitly qualified goal.
 2109
 2110qualified_goal_classification(Goal, TB, Class) :-
 2111    goal_classification(TB, Goal, [], Class),
 2112    Class \== undefined,
 2113    !.
 2114qualified_goal_classification(Module:Goal, _, extern(Module, How)) :-
 2115    predicate_property(Module:Goal, visible),
 2116    !,
 2117    (   (   predicate_property(Module:Goal, public)
 2118        ;   predicate_property(Module:Goal, exported)
 2119        )
 2120    ->  How = (public)
 2121    ;   How = (private)
 2122    ).
 2123qualified_goal_classification(Module:_, _, extern(Module, unknown)).
 2124
 2125%!  classify_head(+TB, +Head, -Class)
 2126%
 2127%   Classify a clause head
 2128
 2129classify_head(TB, Goal, exported) :-
 2130    colour_state_source_id(TB, SourceId),
 2131    xref_exported(SourceId, Goal),
 2132    !.
 2133classify_head(_TB, Goal, hook) :-
 2134    xref_hook(Goal),
 2135    !.
 2136classify_head(TB, Goal, hook) :-
 2137    colour_state_source_id(TB, SourceId),
 2138    xref_module(SourceId, M),
 2139    xref_hook(M:Goal),
 2140    !.
 2141classify_head(TB, Goal, Class) :-
 2142    built_in_predicate(Goal),
 2143    (   system_module(TB)
 2144    ->  (   predicate_property(system:Goal, iso)
 2145        ->  Class = def_iso
 2146        ;   goal_name(Goal, Name),
 2147            \+ sub_atom(Name, 0, _, _, $)
 2148        ->  Class = def_swi
 2149        )
 2150    ;   (   predicate_property(system:Goal, iso)
 2151        ->  Class = iso
 2152        ;   Class = built_in
 2153        )
 2154    ).
 2155classify_head(TB, Goal, unreferenced) :-
 2156    colour_state_source_id(TB, SourceId),
 2157    \+ (xref_called(SourceId, Goal, By), By \= Goal),
 2158    !.
 2159classify_head(TB, Goal, How) :-
 2160    colour_state_source_id(TB, SourceId),
 2161    (   xref_defined(SourceId, Goal, imported(From))
 2162    ->  How = imported(From)
 2163    ;   xref_defined(SourceId, Goal, How)
 2164    ),
 2165    !.
 2166classify_head(_TB, _Goal, undefined).
 2167
 2168built_in_predicate(Goal) :-
 2169    predicate_property(system:Goal, built_in),
 2170    !.
 2171built_in_predicate(module(_, _)).       % reserved expanded constructs
 2172built_in_predicate(module(_, _, _)).
 2173built_in_predicate(if(_)).
 2174built_in_predicate(elif(_)).
 2175built_in_predicate(else).
 2176built_in_predicate(endif).
 2177
 2178goal_name(_:G, Name) :- nonvar(G), !, goal_name(G, Name).
 2179goal_name(G, Name) :- callable(G), functor_name(G, Name).
 2180
 2181system_module(TB) :-
 2182    colour_state_source_id(TB, SourceId),
 2183    xref_module(SourceId, M),
 2184    module_property(M, class(system)).
 2185
 2186generalise_term(Specific, General) :-
 2187    (   compound(Specific)
 2188    ->  compound_name_arity(Specific, Name, Arity),
 2189        compound_name_arity(General0, Name, Arity),
 2190        General = General0
 2191    ;   General = Specific
 2192    ).
 2193
 2194rename_goal(Goal0, Name, Goal) :-
 2195    (   compound(Goal0)
 2196    ->  compound_name_arity(Goal0, _, Arity),
 2197        compound_name_arity(Goal, Name, Arity)
 2198    ;   Goal = Name
 2199    ).
 2200
 2201functor_name(Term, Name) :-
 2202    (   compound(Term)
 2203    ->  compound_name_arity(Term, Name, _)
 2204    ;   atom(Term)
 2205    ->  Name = Term
 2206    ).
 2207
 2208goal_name_arity(Goal, Name, Arity) :-
 2209    (   compound(Goal)
 2210    ->  compound_name_arity(Goal, Name, Arity)
 2211    ;   atom(Goal)
 2212    ->  Name = Goal, Arity = 0
 2213    ).
 2214
 2215
 2216call_goal_colours(Term, Colours) :-
 2217    goal_colours(Term, Colours),
 2218    !.
 2219call_goal_colours(Term, Colours) :-
 2220    def_goal_colours(Term, Colours).
 2221
 2222call_goal_colours(Term, Class, Colours) :-
 2223    goal_colours(Term, Class, Colours),
 2224    !.
 2225%call_goal_colours(Term, Class, Colours) :-
 2226%    def_goal_colours(Term, Class, Colours).
 2227
 2228
 2229%       Specify colours for individual goals.
 2230
 2231def_goal_colours(module(_,_),            built_in-[identifier,exports]).
 2232def_goal_colours(module(_,_,_),          built_in-[identifier,exports,langoptions]).
 2233def_goal_colours(use_module(_),          built_in-[imported_file]).
 2234def_goal_colours(use_module(File,_),     built_in-[file,imports(File)]).
 2235def_goal_colours(reexport(_),            built_in-[file]).
 2236def_goal_colours(reexport(File,_),       built_in-[file,imports(File)]).
 2237def_goal_colours(dynamic(_),             built_in-[declarations(dynamic)]).
 2238def_goal_colours(thread_local(_),        built_in-[declarations(thread_local)]).
 2239def_goal_colours(module_transparent(_),  built_in-[declarations(module_transparent)]).
 2240def_goal_colours(discontiguous(_),       built_in-[declarations(discontiguous)]).
 2241def_goal_colours(multifile(_),           built_in-[declarations(multifile)]).
 2242def_goal_colours(volatile(_),            built_in-[declarations(volatile)]).
 2243def_goal_colours(public(_),              built_in-[declarations(public)]).
 2244def_goal_colours(table(_),               built_in-[declarations(table)]).
 2245def_goal_colours(meta_predicate(_),      built_in-[meta_declarations]).
 2246def_goal_colours(consult(_),             built_in-[file]).
 2247def_goal_colours(include(_),             built_in-[file]).
 2248def_goal_colours(ensure_loaded(_),       built_in-[file]).
 2249def_goal_colours(load_files(_),          built_in-[file]).
 2250def_goal_colours(load_files(_,_),        built_in-[file,options]).
 2251def_goal_colours(setof(_,_,_),           built_in-[classify,setof,classify]).
 2252def_goal_colours(bagof(_,_,_),           built_in-[classify,setof,classify]).
 2253def_goal_colours(predicate_options(_,_,_), built_in-[predicate,classify,classify]).
 2254% Database access
 2255def_goal_colours(assert(_),              built_in-[db]).
 2256def_goal_colours(asserta(_),             built_in-[db]).
 2257def_goal_colours(assertz(_),             built_in-[db]).
 2258def_goal_colours(assert(_,_),            built_in-[db,classify]).
 2259def_goal_colours(asserta(_,_),           built_in-[db,classify]).
 2260def_goal_colours(assertz(_,_),           built_in-[db,classify]).
 2261def_goal_colours(retract(_),             built_in-[db]).
 2262def_goal_colours(retractall(_),          built_in-[db]).
 2263def_goal_colours(clause(_,_),            built_in-[db,classify]).
 2264def_goal_colours(clause(_,_,_),          built_in-[db,classify,classify]).
 2265% misc
 2266def_goal_colours(set_prolog_flag(_,_),   built_in-[prolog_flag_name,classify]).
 2267def_goal_colours(current_prolog_flag(_,_), built_in-[prolog_flag_name,classify]).
 2268% XPCE stuff
 2269def_goal_colours(pce_autoload(_,_),      classify-[classify,file]).
 2270def_goal_colours(pce_image_directory(_), classify-[directory]).
 2271def_goal_colours(new(_, _),              built_in-[classify,pce_new]).
 2272def_goal_colours(send_list(_,_,_),       built_in-pce_arg_list).
 2273def_goal_colours(send(_,_),              built_in-[pce_arg,pce_selector]).
 2274def_goal_colours(get(_,_,_),             built_in-[pce_arg,pce_selector,pce_arg]).
 2275def_goal_colours(send_super(_,_),        built_in-[pce_arg,pce_selector]).
 2276def_goal_colours(get_super(_,_),         built_in-[pce_arg,pce_selector,pce_arg]).
 2277def_goal_colours(get_chain(_,_,_),       built_in-[pce_arg,pce_selector,pce_arg]).
 2278def_goal_colours(Pce,                    built_in-pce_arg) :-
 2279    compound(Pce),
 2280    functor_name(Pce, Functor),
 2281    pce_functor(Functor).
 2282
 2283pce_functor(send).
 2284pce_functor(get).
 2285pce_functor(send_super).
 2286pce_functor(get_super).
 2287
 2288
 2289                 /*******************************
 2290                 *        SPECIFIC HEADS        *
 2291                 *******************************/
 2292
 2293head_colours(file_search_path(_,_), hook-[identifier,classify]).
 2294head_colours(library_directory(_),  hook-[file]).
 2295head_colours(resource(_,_),         hook-[identifier,file]).
 2296head_colours(resource(_,_,_),       hook-[identifier,file,classify]).
 2297
 2298head_colours(Var, _) :-
 2299    var(Var),
 2300    !,
 2301    fail.
 2302head_colours(M:H, Colours) :-
 2303    M == user,
 2304    head_colours(H, HC),
 2305    HC = hook - _,
 2306    !,
 2307    Colours = meta-[module(user), HC ].
 2308head_colours(M:H, Colours) :-
 2309    atom(M), callable(H),
 2310    xref_hook(M:H),
 2311    !,
 2312    Colours = meta-[module(M), hook-classify ].
 2313head_colours(M:_, meta-[module(M),extern(M)]).
 2314
 2315
 2316                 /*******************************
 2317                 *             STYLES           *
 2318                 *******************************/
 2319
 2320%!  def_style(+Pattern, -Style)
 2321%
 2322%   Define the style used for the   given  pattern. Definitions here
 2323%   can     be     overruled     by       defining     rules     for
 2324%   emacs_prolog_colours:style/2
 2325
 2326def_style(goal(built_in,_),        [colour(blue)]).
 2327def_style(goal(imported(_),_),     [colour(blue)]).
 2328def_style(goal(autoload(_),_),     [colour(navy_blue)]).
 2329def_style(goal(global,_),          [colour(navy_blue)]).
 2330def_style(goal(undefined,_),       [colour(red)]).
 2331def_style(goal(thread_local(_),_), [colour(magenta), underline(true)]).
 2332def_style(goal(dynamic(_),_),      [colour(magenta)]).
 2333def_style(goal(multifile(_),_),    [colour(navy_blue)]).
 2334def_style(goal(expanded,_),        [colour(blue), underline(true)]).
 2335def_style(goal(extern(_),_),       [colour(blue), underline(true)]).
 2336def_style(goal(extern(_,private),_), [colour(red)]).
 2337def_style(goal(extern(_,public),_), [colour(blue)]).
 2338def_style(goal(recursion,_),       [underline(true)]).
 2339def_style(goal(meta,_),            [colour(red4)]).
 2340def_style(goal(foreign(_),_),      [colour(darkturquoise)]).
 2341def_style(goal(local(_),_),        []).
 2342def_style(goal(constraint(_),_),   [colour(darkcyan)]).
 2343def_style(goal(not_callable,_),    [background(orange)]).
 2344
 2345def_style(option_name,             [colour('#3434ba')]).
 2346def_style(no_option_name,          [colour(red)]).
 2347
 2348def_style(head(exported,_),        [colour(blue), bold(true)]).
 2349def_style(head(public(_),_),       [colour('#016300'), bold(true)]).
 2350def_style(head(extern(_),_),       [colour(blue), bold(true)]).
 2351def_style(head(dynamic,_),         [colour(magenta), bold(true)]).
 2352def_style(head(multifile,_),       [colour(navy_blue), bold(true)]).
 2353def_style(head(unreferenced,_),    [colour(red), bold(true)]).
 2354def_style(head(hook,_),            [colour(blue), underline(true)]).
 2355def_style(head(meta,_),            []).
 2356def_style(head(constraint(_),_),   [colour(darkcyan), bold(true)]).
 2357def_style(head(imported(_),_),     [colour(darkgoldenrod4), bold(true)]).
 2358def_style(head(built_in,_),        [background(orange), bold(true)]).
 2359def_style(head(iso,_),             [background(orange), bold(true)]).
 2360def_style(head(def_iso,_),         [colour(blue), bold(true)]).
 2361def_style(head(def_swi,_),         [colour(blue), bold(true)]).
 2362def_style(head(_,_),               [bold(true)]).
 2363
 2364def_style(module(_),               [colour(dark_slate_blue)]).
 2365def_style(comment(_),              [colour(dark_green)]).
 2366
 2367def_style(directive,               [background(grey90)]).
 2368def_style(method(_),               [bold(true)]).
 2369
 2370def_style(var,                     [colour(red4)]).
 2371def_style(singleton,               [bold(true), colour(red4)]).
 2372def_style(unbound,                 [colour(red), bold(true)]).
 2373def_style(quoted_atom,             [colour(navy_blue)]).
 2374def_style(string,                  [colour(navy_blue)]).
 2375def_style(codes,                   [colour(navy_blue)]).
 2376def_style(chars,                   [colour(navy_blue)]).
 2377def_style(nofile,                  [colour(red)]).
 2378def_style(file(_),                 [colour(blue), underline(true)]).
 2379def_style(file_no_depend(_),       [colour(blue), underline(true), background(pink)]).
 2380def_style(directory(_),            [colour(blue)]).
 2381def_style(class(built_in,_),       [colour(blue), underline(true)]).
 2382def_style(class(library(_),_),     [colour(navy_blue), underline(true)]).
 2383def_style(class(local(_,_,_),_),   [underline(true)]).
 2384def_style(class(user(_),_),        [underline(true)]).
 2385def_style(class(user,_),           [underline(true)]).
 2386def_style(class(undefined,_),      [colour(red), underline(true)]).
 2387def_style(prolog_data,             [colour(blue), underline(true)]).
 2388def_style(flag_name(_),            [colour(blue)]).
 2389def_style(no_flag_name(_),         [colour(red)]).
 2390def_style(unused_import,           [colour(blue), background(pink)]).
 2391def_style(undefined_import,        [colour(red)]).
 2392
 2393def_style(constraint(_),           [colour(darkcyan)]).
 2394
 2395def_style(keyword(_),              [colour(blue)]).
 2396def_style(identifier,              [bold(true)]).
 2397def_style(delimiter,               [bold(true)]).
 2398def_style(expanded,                [colour(blue), underline(true)]).
 2399def_style(hook(_),                 [colour(blue), underline(true)]).
 2400def_style(op_type(_),              [colour(blue)]).
 2401
 2402def_style(qq_type,                 [bold(true)]).
 2403def_style(qq(_),                   [colour(blue), bold(true)]).
 2404def_style(qq_content(_),           [colour(red4)]).
 2405
 2406def_style(dict_tag,                [bold(true)]).
 2407def_style(dict_key,                [bold(true)]).
 2408def_style(dict_function(_),        [colour(navy_blue)]).
 2409def_style(dict_return_op,          [colour(blue)]).
 2410
 2411def_style(hook,                    [colour(blue), underline(true)]).
 2412def_style(dcg_right_hand_ctx,      [background('#d4ffe3')]).
 2413
 2414def_style(error,                   [background(orange)]).
 2415def_style(type_error(_),           [background(orange)]).
 2416def_style(syntax_error(_,_),       [background(orange)]).
 2417def_style(instantiation_error,     [background(orange)]).
 2418
 2419def_style(decl_option(_),	   [bold(true)]).
 2420def_style(table_mode(_),	   [bold(true)]).
 2421
 2422%!  syntax_colour(?Class, ?Attributes) is nondet.
 2423%
 2424%   True when a range  classified  Class   must  be  coloured  using
 2425%   Attributes.  Attributes is a list of:
 2426%
 2427%     * colour(ColourName)
 2428%     * background(ColourName)
 2429%     * bold(Boolean)
 2430%     * underline(Boolean)
 2431%
 2432%   Attributes may be the empty list. This   is used for cases where
 2433%   -for example- a  menu  is  associated   with  the  fragment.  If
 2434%   syntax_colour/2 fails, no fragment is created for the region.
 2435
 2436syntax_colour(Class, Attributes) :-
 2437    (   style(Class, Attributes)            % user hook
 2438    ;   def_style(Class, Attributes)        % system default
 2439    ).
 2440
 2441
 2442%!  term_colours(+Term, -FunctorColour, -ArgColours)
 2443%
 2444%   Define colourisation for specific terms.
 2445
 2446term_colours((?- Directive), Colours) :-
 2447    term_colours((:- Directive), Colours).
 2448term_colours((prolog:Head --> _),
 2449             neck(grammar_rule) - [ expanded - [ module(prolog),
 2450                                                 hook(message) - [ identifier
 2451                                                                 ]
 2452                                               ],
 2453                                    dcg_body(prolog:Head)
 2454                                  ]) :-
 2455    prolog_message_hook(Head).
 2456
 2457prolog_message_hook(message(_)).
 2458prolog_message_hook(error_message(_)).
 2459prolog_message_hook(message_context(_)).
 2460prolog_message_hook(message_location(_)).
 2461
 2462%       XPCE rules
 2463
 2464term_colours(variable(_, _, _, _),
 2465             expanded - [ identifier,
 2466                          classify,
 2467                          classify,
 2468                          comment(string)
 2469                        ]).
 2470term_colours(variable(_, _, _),
 2471             expanded - [ identifier,
 2472                          classify,
 2473                          atom
 2474                        ]).
 2475term_colours(handle(_, _, _),
 2476             expanded - [ classify,
 2477                          classify,
 2478                          classify
 2479                        ]).
 2480term_colours(handle(_, _, _, _),
 2481             expanded - [ classify,
 2482                          classify,
 2483                          classify,
 2484                          classify
 2485                        ]).
 2486term_colours(class_variable(_,_,_,_),
 2487             expanded - [ identifier,
 2488                          pce(type),
 2489                          pce(default),
 2490                          comment(string)
 2491                        ]).
 2492term_colours(class_variable(_,_,_),
 2493             expanded - [ identifier,
 2494                          pce(type),
 2495                          pce(default)
 2496                        ]).
 2497term_colours(delegate_to(_),
 2498             expanded - [ classify
 2499                        ]).
 2500term_colours((:- encoding(_)),
 2501             expanded - [ expanded - [ classify
 2502                                     ]
 2503                        ]).
 2504term_colours((:- pce_begin_class(_, _, _)),
 2505             expanded - [ expanded - [ identifier,
 2506                                       pce_new,
 2507                                       comment(string)
 2508                                     ]
 2509                        ]).
 2510term_colours((:- pce_begin_class(_, _)),
 2511             expanded - [ expanded - [ identifier,
 2512                                       pce_new
 2513                                     ]
 2514                        ]).
 2515term_colours((:- pce_extend_class(_)),
 2516             expanded - [ expanded - [ identifier
 2517                                     ]
 2518                        ]).
 2519term_colours((:- pce_end_class),
 2520             expanded - [ expanded
 2521                        ]).
 2522term_colours((:- pce_end_class(_)),
 2523             expanded - [ expanded - [ identifier
 2524                                     ]
 2525                        ]).
 2526term_colours((:- use_class_template(_)),
 2527             expanded - [ expanded - [ pce_new
 2528                                     ]
 2529                        ]).
 2530term_colours((:- emacs_begin_mode(_,_,_,_,_)),
 2531             expanded - [ expanded - [ identifier,
 2532                                       classify,
 2533                                       classify,
 2534                                       classify,
 2535                                       classify
 2536                                     ]
 2537                        ]).
 2538term_colours((:- emacs_extend_mode(_,_)),
 2539             expanded - [ expanded - [ identifier,
 2540                                       classify
 2541                                     ]
 2542                        ]).
 2543term_colours((:- pce_group(_)),
 2544             expanded - [ expanded - [ identifier
 2545                                     ]
 2546                        ]).
 2547term_colours((:- pce_global(_, new(_))),
 2548             expanded - [ expanded - [ identifier,
 2549                                       pce_arg
 2550                                     ]
 2551                        ]).
 2552term_colours((:- emacs_end_mode),
 2553             expanded - [ expanded
 2554                        ]).
 2555term_colours(pce_ifhostproperty(_,_),
 2556             expanded - [ classify,
 2557                          classify
 2558                        ]).
 2559term_colours((_,_),
 2560             error - [ classify,
 2561                       classify
 2562                     ]).
 2563
 2564%!  specified_item(+Specified, +Term, +TB, +TermPosition) is det.
 2565%
 2566%   Colourise an item that is explicitly   classified  by the user using
 2567%   term_colours/2 or goal_colours/2.
 2568
 2569specified_item(_Class, _Term, _TB, Pos) :-
 2570    var(Pos),
 2571    !.
 2572specified_item(Class, Term, TB, parentheses_term_position(PO,PC,Pos)) :-
 2573    !,
 2574    colour_item(parentheses, TB, PO-PC),
 2575    specified_item(Class, Term, TB, Pos).
 2576specified_item(_, Var, TB, Pos) :-
 2577    (   var(Var)
 2578    ;   qq_position(Pos)
 2579    ),
 2580    !,
 2581    colourise_term_arg(Var, TB, Pos).
 2582                                        % generic classification
 2583specified_item(classify, Term, TB, Pos) :-
 2584    !,
 2585    colourise_term_arg(Term, TB, Pos).
 2586                                        % classify as head
 2587specified_item(head, Term, TB, Pos) :-
 2588    !,
 2589    colourise_clause_head(Term, TB, Pos).
 2590                                        % expanded head (DCG=2, ...)
 2591specified_item(head(+N), Term, TB, Pos) :-
 2592    !,
 2593    colourise_extended_head(Term, N, TB, Pos).
 2594                                        % M:Head
 2595specified_item(extern(M), Term, TB, Pos) :-
 2596    !,
 2597    colourise_extern_head(Term, M, TB, Pos).
 2598                                        % classify as body
 2599specified_item(body, Term, TB, Pos) :-
 2600    !,
 2601    colourise_body(Term, TB, Pos).
 2602specified_item(body(Goal), _Term0, TB, Pos) :-
 2603    !,
 2604    colourise_body(Goal, TB, Pos).
 2605specified_item(dcg_body(Head), Term, TB, Pos) :-
 2606    !,
 2607    colourise_dcg(Term, Head, TB, Pos).
 2608specified_item(setof, Term, TB, Pos) :-
 2609    !,
 2610    colourise_setof(Term, TB, Pos).
 2611specified_item(meta(MetaSpec), Term, TB, Pos) :-
 2612    !,
 2613    colourise_meta_arg(MetaSpec, Term, TB, Pos).
 2614                                        % DCG goal in body
 2615specified_item(dcg, Term, TB, Pos) :-
 2616    !,
 2617    colourise_dcg(Term, [], TB, Pos).
 2618                                        % assert/retract arguments
 2619specified_item(db, Term, TB, Pos) :-
 2620    !,
 2621    colourise_db(Term, TB, Pos).
 2622                                        % error(Error)
 2623specified_item(error(Error), _Term, TB, Pos) :-
 2624    colour_item(Error, TB, Pos).
 2625                                        % files
 2626specified_item(file(Path), _Term, TB, Pos) :-
 2627    !,
 2628    colour_item(file(Path), TB, Pos).
 2629specified_item(file, Term, TB, Pos) :-
 2630    !,
 2631    colourise_files(Term, TB, Pos, any).
 2632specified_item(imported_file, Term, TB, Pos) :-
 2633    !,
 2634    colourise_files(Term, TB, Pos, imported).
 2635specified_item(langoptions, Term, TB, Pos) :-
 2636    !,
 2637    colourise_langoptions(Term, TB, Pos).
 2638
 2639                                        % directory
 2640specified_item(directory, Term, TB, Pos) :-
 2641    !,
 2642    colourise_directory(Term, TB, Pos).
 2643                                        % [Name/Arity, ...]
 2644specified_item(exports, Term, TB, Pos) :-
 2645    !,
 2646    colourise_exports(Term, TB, Pos).
 2647                                        % [Name/Arity, ...]
 2648specified_item(imports(File), Term, TB, Pos) :-
 2649    !,
 2650    colourise_imports(Term, File, TB, Pos).
 2651                                        % Name/Arity
 2652specified_item(import(File), Term, TB, Pos) :-
 2653    !,
 2654    colourise_import(Term, File, TB, Pos).
 2655                                        % Name/Arity, ...
 2656specified_item(predicates, Term, TB, Pos) :-
 2657    !,
 2658    colourise_declarations(Term, predicate_indicator, TB, Pos).
 2659                                        % Name/Arity
 2660specified_item(predicate, Term, TB, Pos) :-
 2661    !,
 2662    colourise_declaration(Term, predicate_indicator, TB, Pos).
 2663                                        % head(Arg, ...)
 2664specified_item(meta_declarations, Term, TB, Pos) :-
 2665    !,
 2666    colourise_meta_declarations(Term, [], TB, Pos).
 2667specified_item(meta_declarations(Extra), Term, TB, Pos) :-
 2668    !,
 2669    colourise_meta_declarations(Term, Extra, TB, Pos).
 2670specified_item(declarations(Which), Term, TB, Pos) :-
 2671    !,
 2672    colourise_declarations(Term, Which, TB, Pos).
 2673                                        % set_prolog_flag(Name, _)
 2674specified_item(prolog_flag_name, Term, TB, Pos) :-
 2675    !,
 2676    colourise_prolog_flag_name(Term, TB, Pos).
 2677                                        % XPCE new argument
 2678specified_item(pce_new, Term, TB, Pos) :-
 2679    !,
 2680    (   atom(Term)
 2681    ->  colourise_class(Term, TB, Pos)
 2682    ;   compound(Term)
 2683    ->  functor_name(Term, Class),
 2684        Pos = term_position(_,_,FF, FT, ArgPos),
 2685        colourise_class(Class, TB, FF-FT),
 2686        specified_items(pce_arg, Term, TB, ArgPos)
 2687    ;   colourise_term_arg(Term, TB, Pos)
 2688    ).
 2689                                        % Generic XPCE arguments
 2690specified_item(pce_arg, new(X), TB,
 2691               term_position(_,_,_,_,[ArgPos])) :-
 2692    !,
 2693    specified_item(pce_new, X, TB, ArgPos).
 2694specified_item(pce_arg, new(X, T), TB,
 2695               term_position(_,_,_,_,[P1, P2])) :-
 2696    !,
 2697    colourise_term_arg(X, TB, P1),
 2698    specified_item(pce_new, T, TB, P2).
 2699specified_item(pce_arg, @(Ref), TB, Pos) :-
 2700    !,
 2701    colourise_term_arg(@(Ref), TB, Pos).
 2702specified_item(pce_arg, prolog(Term), TB,
 2703               term_position(_,_,FF,FT,[ArgPos])) :-
 2704    !,
 2705    colour_item(prolog_data, TB, FF-FT),
 2706    colourise_term_arg(Term, TB, ArgPos).
 2707specified_item(pce_arg, Term, TB, Pos) :-
 2708    compound(Term),
 2709    Term \= [_|_],
 2710    !,
 2711    specified_item(pce_new, Term, TB, Pos).
 2712specified_item(pce_arg, Term, TB, Pos) :-
 2713    !,
 2714    colourise_term_arg(Term, TB, Pos).
 2715                                        % List of XPCE arguments
 2716specified_item(pce_arg_list, List, TB, list_position(F,T,Elms,Tail)) :-
 2717    !,
 2718    colour_item(list, TB, F-T),
 2719    colourise_list_args(Elms, Tail, List, TB, pce_arg).
 2720specified_item(pce_arg_list, Term, TB, Pos) :-
 2721    !,
 2722    specified_item(pce_arg, Term, TB, Pos).
 2723                                        % XPCE selector
 2724specified_item(pce_selector, Term, TB,
 2725               term_position(_,_,_,_,ArgPos)) :-
 2726    !,
 2727    specified_items(pce_arg, Term, TB, ArgPos).
 2728specified_item(pce_selector, Term, TB, Pos) :-
 2729    colourise_term_arg(Term, TB, Pos).
 2730                                        % Nested specification
 2731specified_item(FuncSpec-ArgSpecs, Term, TB,
 2732               term_position(_,_,FF,FT,ArgPos)) :-
 2733    !,
 2734    specified_item(FuncSpec, Term, TB, FF-FT),
 2735    specified_items(ArgSpecs, Term, TB, ArgPos).
 2736                                        % Nested for {...}
 2737specified_item(FuncSpec-[ArgSpec], {Term}, TB,
 2738               brace_term_position(F,T,ArgPos)) :-
 2739    !,
 2740    specified_item(FuncSpec, {Term}, TB, F-T),
 2741    specified_item(ArgSpec, Term, TB, ArgPos).
 2742                                        % Specified
 2743specified_item(FuncSpec-ElmSpec, List, TB,
 2744               list_position(F,T,ElmPos,TailPos)) :-
 2745    !,
 2746    colour_item(FuncSpec, TB, F-T),
 2747    specified_list(ElmSpec, List, TB, ElmPos, TailPos).
 2748specified_item(Class, _, TB, Pos) :-
 2749    colour_item(Class, TB, Pos).
 2750
 2751%!  specified_items(+Spec, +Term, +TB, +PosList)
 2752
 2753specified_items(Specs, Term, TB, PosList) :-
 2754    is_dict(Term),
 2755    !,
 2756    specified_dict_kv(PosList, Term, TB, Specs).
 2757specified_items(Specs, Term, TB, PosList) :-
 2758    is_list(Specs),
 2759    !,
 2760    specified_arglist(Specs, 1, Term, TB, PosList).
 2761specified_items(Spec, Term, TB, PosList) :-
 2762    specified_argspec(PosList, Spec, 1, Term, TB).
 2763
 2764
 2765specified_arglist([], _, _, _, _).
 2766specified_arglist(_, _, _, _, []) :- !.         % Excess specification args
 2767specified_arglist([S0|ST], N, T, TB, [P0|PT]) :-
 2768    (   S0 == options,
 2769        colourization_module(TB, Module),
 2770        colourise_option_arg(T, Module, N, TB, P0)
 2771    ->  true
 2772    ;   arg(N, T, Term),
 2773        specified_item(S0, Term, TB, P0)
 2774    ),
 2775    NN is N + 1,
 2776    specified_arglist(ST, NN, T, TB, PT).
 2777
 2778specified_argspec([], _, _, _, _).
 2779specified_argspec([P0|PT], Spec, N, T, TB) :-
 2780    arg(N, T, Term),
 2781    specified_item(Spec, Term, TB, P0),
 2782    NN is N + 1,
 2783    specified_argspec(PT, Spec, NN, T, TB).
 2784
 2785
 2786%       specified_list(+Spec, +List, +TB, +PosList, TailPos)
 2787
 2788specified_list([], [], _, [], _).
 2789specified_list([HS|TS], [H|T], TB, [HP|TP], TailPos) :-
 2790    !,
 2791    specified_item(HS, H, TB, HP),
 2792    specified_list(TS, T, TB, TP, TailPos).
 2793specified_list(Spec, [H|T], TB, [HP|TP], TailPos) :-
 2794    specified_item(Spec, H, TB, HP),
 2795    specified_list(Spec, T, TB, TP, TailPos).
 2796specified_list(_, _, _, [], none) :- !.
 2797specified_list(Spec, Tail, TB, [], TailPos) :-
 2798    specified_item(Spec, Tail, TB, TailPos).
 2799
 2800%!  specified_dict_kv(+PosList, +Term, +TB, +Specs)
 2801%
 2802%   @arg Specs is a list of dict_kv(+Key, +KeySpec, +ArgSpec)
 2803
 2804specified_dict_kv([], _, _, _).
 2805specified_dict_kv([key_value_position(_F,_T,SF,ST,K,KP,VP)|Pos],
 2806                  Dict, TB, Specs) :-
 2807    specified_dict_kv1(K, Specs, KeySpec, ValueSpec),
 2808    colour_item(KeySpec, TB, KP),
 2809    colour_item(dict_sep, TB, SF-ST),
 2810    get_dict(K, Dict, V),
 2811    specified_item(ValueSpec, V, TB, VP),
 2812    specified_dict_kv(Pos, Dict, TB, Specs).
 2813
 2814specified_dict_kv1(Key, Specs, KeySpec, ValueSpec) :-
 2815    Specs = [_|_],
 2816    memberchk(dict_kv(Key, KeySpec, ValueSpec), Specs),
 2817    !.
 2818specified_dict_kv1(Key, dict_kv(Key2, KeySpec, ValueSpec), KeySpec, ValueSpec) :-
 2819    \+ Key \= Key2,
 2820    !.              % do not bind Key2
 2821specified_dict_kv1(_, _, dict_key, classify).
 2822
 2823
 2824                 /*******************************
 2825                 *         DESCRIPTIONS         *
 2826                 *******************************/
 2827
 2828syntax_message(Class) -->
 2829    message(Class),
 2830    !.
 2831syntax_message(qq(_)) -->
 2832    [ 'Quasi quote delimiter' ].
 2833syntax_message(qq_type) -->
 2834    [ 'Quasi quote type term' ].
 2835syntax_message(qq_content(Type)) -->
 2836    [ 'Quasi quote content (~w syntax)'-[Type] ].
 2837syntax_message(goal(Class, Goal)) -->
 2838    !,
 2839    goal_message(Class, Goal).
 2840syntax_message(class(Type, Class)) -->
 2841    !,
 2842    xpce_class_message(Type, Class).
 2843syntax_message(dict_return_op) -->
 2844    !,
 2845    [ ':= separates function from return value' ].
 2846syntax_message(dict_function) -->
 2847    !,
 2848    [ 'Function on a dict' ].
 2849syntax_message(ext_quant) -->
 2850    !,
 2851    [ 'Existential quantification operator' ].
 2852syntax_message(hook(message)) -->
 2853    [ 'Rule for print_message/2' ].
 2854syntax_message(module(Module)) -->
 2855    (   { current_module(Module) }
 2856    ->  (   { module_property(Module, file(File)) }
 2857        ->  [ 'Module ~w defined in ~w'-[Module,File] ]
 2858        ;   [ 'Module ~w'-[Module] ]
 2859        )
 2860    ;   [ 'Module ~w (not loaded)'-[Module] ]
 2861    ).
 2862syntax_message(decl_option(incremental)) -->
 2863    [ 'Keep affected tables consistent' ].
 2864syntax_message(decl_option(abstract)) -->
 2865    [ 'Add abstracted goal to table dependency graph' ].
 2866syntax_message(decl_option(volatile)) -->
 2867    [ 'Do not include predicate in a saved program' ].
 2868syntax_message(decl_option(multifile)) -->
 2869    [ 'Clauses are spread over multiple files' ].
 2870syntax_message(decl_option(discontiguous)) -->
 2871    [ 'Clauses are not contiguous' ].
 2872syntax_message(decl_option(private)) -->
 2873    [ 'Tables or clauses are private to a thread' ].
 2874syntax_message(decl_option(local)) -->
 2875    [ 'Tables or clauses are private to a thread' ].
 2876syntax_message(decl_option(shared)) -->
 2877    [ 'Tables or clauses are shared between threads' ].
 2878syntax_message(decl_option(_Opt)) -->
 2879    [ 'Predicate property' ].
 2880
 2881goal_message(meta, _) -->
 2882    [ 'Meta call' ].
 2883goal_message(not_callable, _) -->
 2884    [ 'Goal is not callable (type error)' ].
 2885goal_message(expanded, _) -->
 2886    [ 'Expanded goal' ].
 2887goal_message(Class, Goal) -->
 2888    { predicate_name(Goal, PI) },
 2889    [ 'Call to ~q'-PI ],
 2890    goal_class(Class).
 2891
 2892goal_class(recursion) -->
 2893    [ ' (recursive call)' ].
 2894goal_class(undefined) -->
 2895    [ ' (undefined)' ].
 2896goal_class(global) -->
 2897    [ ' (Auto-imported from module user)' ].
 2898goal_class(imported(From)) -->
 2899    [ ' (imported from ~q)'-[From] ].
 2900goal_class(extern(_, private)) -->
 2901    [ ' (WARNING: private predicate)' ].
 2902goal_class(extern(_, public)) -->
 2903    [ ' (public predicate)' ].
 2904goal_class(extern(_)) -->
 2905    [ ' (cross-module call)' ].
 2906goal_class(Class) -->
 2907    [ ' (~p)'-[Class] ].
 2908
 2909xpce_class_message(Type, Class) -->
 2910    [ 'XPCE ~w class ~q'-[Type, Class] ]