I think this is what you need. You were very close.
This first example demonstrates the basic code without redirecting the error stream.
io_test_1 :-
read_string(user_input, "\n", "\r", _, String),
(
String = "Error"
->
print_message(error,String)
;
format('~w~n',[String])
).
This code modifies the destination of the error stream using set_prolog_IO/3.
This redirects the error stream to a file. The OS is Windows but the file path is easily changed for any specific OS.
io_test_2 :-
setup_call_cleanup(
(
open("C:/Users/Eric/Documents/Projects/Prolog/swi-discourse_032/error.txt",write,Error,[]),
set_prolog_IO(user_input,user_output,Error)
),
(
read_string(user_input, "\n", "\r", _, String),
(
String = "Error"
->
print_message(error,String)
;
format('~w~n',[String])
)
),
close(Error)
).
Example run without an error
?- io_test_2.
|: Good
Good
true.
Example run with an error that is redirected to a file. Note that error does not appear on the console.
?- io_test_2.
|: Error
true.
Contents of error.txt
ERROR: Unknown message: "Error"
You might also want to take a look at the recently added library(intercept) . I have not had a chance to work with it, but might be using it today with sgml_parse/2
EDIT
Any answer I could give would be a pure guess at this point and there is so much that I would not know how to check, (C code underneath SWI-Prolog predicates) and the entry and exit points along the path.
However if you know all of the errors you want to catch originate via print_message/2 then it might be possible. Just a guess but simple enough to trace though the source code.