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