When using SWI-prolog, it will print output that doesn't need to be quoted (output that doesn't contain special characters), without quotes. As an example:
?- p('this_is_a_string').
true.
?- p(X).
X = this_is_a_string.
I would like Prolog to always output with quotes. It is okay if my output ends up quoting stuff like functor names, which were not originally quoted when input. How can I achieve this?
To change the default behaviour of SWI-Prolog's top-level output, you want to look towards setting a flag. If you query the appropriate flag, you should find this is your default output:
?- current_prolog_flag(print_write_options, Options).
Options = [portray('true'), quoted('true'), numbervars('true')].
In this particular case, the needed flag is already set: we have portray('true')
in our Options
.
portray/1
is a dynamic predicate that you can assert. It's called with a ground term when it is being printed, if it succeeds then it's assumed the the term has been printed.
So in your case you can assert the following:
portray(Term) :- atom(Term), format("'~s'", Term).
Now you'll get the desired behaviour:
?- p(this_is_an_atom).
true.
?- p(X).
X = 'this_is_an_atom'.
You could add this to your .swiplrc
file if it's something you want all the time. Note, this will have no effect on write/1
and similar predicates, you'll need to use this instead:
?- write_term(foo, [portray(true)]).
'foo'.
To add the additional requirement of escaping characters in the the atom, you'll either need to implement your own DCG to the ISO standard for escaping characters, or abuse the built-in one. To do this you can write out to an atom and see if you need to add your single-quotes, or if they would already be there. The case of X = (\).
is most easily handled in its own clause, you can then choose if you wish to print '\\'
or (\)
.
portray(\) :-
format("'\\\\'"), !.
portray(Term) :-
atom(Term), \+ Term = (\),
( with_output_to(chars(['\''|_]),
write_term(Term, [quoted(true), character_escapes(true), portrayed(false)]))
-> format("~q", Term)
; format("'~s'", Term)
).