Catch string from print_term/2 via with_output_to/2 fails for HTTP server

27 views
Skip to first unread message

Falco Nogatz

unread,
Jan 30, 2019, 6:42:20 AM1/30/19
to SWI-Prolog
Hi all,

I want to use print_term/2 to generate a nicely formatted string representation of a Prolog term. Normally, I just wrap it in with_output_to/2 to put it in a string for later use:
with_output_to(string(String),
   print_term
(Term, [indent_arguments(2),tab_width(0)]))

However, this does not work inside an HTTP server, as the output is always written to user_output instead of the string(String). I set up a minimal example that should return the nicely formatted Prolog term as part of a JSON response (code also attached):

%% swipl -s server.pl --quiet -g "server('127.0.0.1':8082)"
%% curl -i -X GET http://localhost:8082/

:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_json)).

:- http_handler(/, handle, []).

server
(Port) :-
   http_server
(http_dispatch,[port(Port)]),
   format
(user_output,"Started server on port ~p.~n",[Port]).

handle
(_Request) :-
   
Term = a(b([c,d]),e(f)),
   with_output_to
(string(String),
      print_term
(Term, [indent_arguments(2),tab_width(0)])),
   reply_json_dict
(_{ term: String }).

With SWI-Prolog v7.6.4, this just returns an empty string in the term property of the resulting JSON. The nicely formatted Prolog term is printed to the console.

What's the best way to catch the output of print_term/2 in an HTTP server setup, so I can used it as part of a JSON response?

Thank you,
Falco




server.pl

Jan Wielemaker

unread,
Jan 30, 2019, 6:46:01 AM1/30/19
to Falco Nogatz, SWI-Prolog
Hi Falco,

Use output(current_output) in the option list.

Cheers --- Jan

On 1/30/19 12:42 PM, Falco Nogatz wrote:
> Hi all,
>
> I want to use print_term/2
> <http://www.swi-prolog.org/pldoc/doc/_SWI_/library/pprint.pl> to
> generate a nicely formatted string representation of a Prolog term.
> Normally, I just wrap it in with_output_to/2
> <http://www.swi-prolog.org/pldoc/doc_for?object=with_output_to/2> to put
> it in a string for later use:
> |
> with_output_to(string(String),
>    print_term(Term,[indent_arguments(2),tab_width(0)]))
> |
>
> However, this does not work inside an HTTP server, as the output is
> always written to user_output instead of the string(String). I set up a
> minimal example that should return the nicely formatted Prolog term as
> part of a JSON response (code also attached):
>
> |
> %%swipl -s server.pl --quiet -g "server('127.0.0.1':8082)"
> %%curl -i -X GET http://localhost:8082/
>
> :-use_module(library(http/thread_httpd)).
> :-use_module(library(http/http_dispatch)).
> :-use_module(library(http/http_json)).
>
> :-http_handler(/,handle,[]).
>
> server(Port):-
>    http_server(http_dispatch,[port(Port)]),
>    format(user_output,"Started server on port ~p.~n",[Port]).
>
> handle(_Request):-
> Term=a(b([c,d]),e(f)),
>    with_output_to(string(String),
>       print_term(Term,[indent_arguments(2),tab_width(0)])),
>    reply_json_dict(_{term:String}).
> |
>
> With SWI-Prolog v7.6.4, this just returns an empty string in the term
> property of the resulting JSON. The nicely formatted Prolog term is
> printed to the console.
>
> What's the best way to catch the output of print_term/2 in an HTTP
> server setup, so I can used it as part of a JSON response?
>
> Thank you,
> Falco
>
>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to swi-prolog+...@googlegroups.com
> <mailto:swi-prolog+...@googlegroups.com>.
> Visit this group at https://groups.google.com/group/swi-prolog.
> For more options, visit https://groups.google.com/d/optout.

Peter Ludemann

unread,
Jan 30, 2019, 7:05:53 AM1/30/19
to Jan Wielemaker, Falco Nogatz, SWI-Prolog
This works for me:

%! print_term_cleaned(+Term, +Options, -TermStr) is det.
%% print_term, cleaned up
print_term_cleaned(Term, Options, TermStr) :-
    with_output_to(
            string(TermStr0),
            (current_output(TermStream),
             print_term(Term, [output(TermStream)|Options]))),
 %% print_term leaves trailing whitespace, so remove it
 re_replace(" *\n"/g, "\n", TermStr0, TermStr).

To unsubscribe from this group and stop receiving emails from it, send an email to swi-prolog+...@googlegroups.com.

Falco Nogatz

unread,
Jan 30, 2019, 7:20:32 AM1/30/19
to SWI-Prolog
Hi Jan and Peter,

thank you both for your quick responses, both versions work like a charm! I tried it with various combinations of the output option, even together with the current_output/1, but was not able to make it. Thank you for your assistance :)

Best,
Falco
Reply all
Reply to author
Forward
0 new messages