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