Intercepting the printing of a message

After a message is parsed, but before the message is printed out, print_message/2 calls

     user:message_hook(+Message,+Severity,+Lines)
     

where Lines is of the form [Line1, Line2, ...], where each Linei is of the form [Control_1-Args_1,Control_2-Args_2, ...].

In our example,

     message_hook(world(flat,wet),error,
         [['The world is ~w and ~w.'-[flat,wet]]])
     

would be called.

If the call to user:message_hook/3 succeeds, print_message/2 succeeds without further processing. Otherwise, the built-in message display is used.

An example of using a hook to redirect output can be seen in the reference page for print_message_lines/3.

It is often useful for a message hook to execute some code for its effects, and then fail. This allows other message hooks a chance to run, and allows the printing of the message to proceed normally.

For example, we might want to ring a bell when printing an error message, and print a count of error messages seen so far. This could be done as follows:

     :- dynamic error_count/1.
     
     user:message_hook(_, error, _) :-
             put(7),                         % ASCII 7 rings bell
             (   error_count(N) -> true
             ;   N = 1
             ),
             format('! Error ~w:~n', [N]),
             N1 is N+1,
             retractall(error_count(_)),
             assert(error_count(N1)),
             fail.