When I use get_code/2 with user_input, I always get a prompt “|: ”, even when input isn’t from a tty. Is there a way to turn off the prompt (or a way to add a check for isatty to get_code/2)?
"Don’t use read_codes/2" is not a solution; I’m getting this from json_read_dict/3, which uses read_codes/2.
@jan - the documentation for prompt/2 seems to have a bug – read/1 is for reading terms, but prompt/2 also affects get_code/2 (and perhaps other predicates).
Also, shouldn’t the prompt be output only if user_input is a tty (according to isatty(3))? (It seems that the isatty information is available in the stream, as it’s an option to set_stream/2 and can be checked with stream_property/2.)
Disclaimer: I like to cite my sources. I am almost certain that this tip was handed down to me by Ulrich Neumerkel aka “false” years ago on Stackoverflow. It was a comment to a comment or something like this because I cannot find it. Back then I tried to read the code to figure out what is this magic but I must have given up. Maybe someone who knows their stuff can explain.
It was a bit of a mess. Cleared up the docs and avoid prompting if user_input does not have the tty property. I’m not entirely sure about the latter. The rule now is that you have use prompt/2 and prompt1/1 to control the prompt, but the prompt is ignored if user_input is not a tty. The alternative would be to set the prompt to '' if user_input is not a tty. That sounds simpler (and thus better), but there is also some value that you can disable prompting globally, even if an application using different prompt defines in different locations.
P.s. --no-tty doesn’t make Prolog think there is no tty. It prevents it from changing the tty properties to achieve raw input and/or do line editing.
BTW, the reason I didn’t find prompt/2 is that I expected to find it within current_prolog_flag/2.
@jan - based on Boris’s comment, it seems you need a bit more of doc change … it needs to mention the conditions of user_output that turn off prompting. [At first, I thought that this was crazy, but then I realized that redirected output wouldn’t be seen, so a prompt would be pointless … however, a case could be made that if input is from /dev/tty, then the prompt should go to /dev/tty, regardless of output redirection – that’s what the MTS operating system did IIRC.]
Could have been, I guess. AFAIK, prompt/2 originates from Edinburgh C Prolog In fact, there is a flag toplevel_prompt that determines the ?- prompt.
I think that is all a bit over the top. As is, the rule is now quite simple: prompt only if user_input is a terminal. As you can control whether Prolog should consider user_input a terminal, this gives you full control. Just tested with bash. cat -u | bash doesn’t prompt, while bash | cat -u does, which is consistent with what we do now.
Finally, if you want Prolog to run some goals inside a (shell) script, it might be easier to use -g goal. Note that you can repeat this option. If you combine this with -t halt you should have pretty much what you typically want: run some goals and exit with status 0 if all went right and stop with status not 0 on a failure or exception.
I just tested with cat -u and swipl does not prompt. (Using 8.1.20 on Ubuntu 18.0.4, with gnome-terminal and also with an emacs shell.)
I have no strong opinion either way on the behavior of swipl when it’s outputting to a non-tty; but in the meantime it’d be nice if the documentation mentions that prompting only occurs if user_output is a tty. [The code has this, which I assume means a check for user_output being a tty: if ( Soutput && true(Soutput, SIO_ISATTY) )
(You can ignore my comments about prompting from /dev/tty – that was merely to show an alternative philosophy from an operating system that I admire.)
Oops. That is not what the new docs say and not what bash does. Pushed a fix. The rule is (now) simple: pompting is active is user_input has the tty property set to true. The prompt itself is defined by prompt/2. The toplevel ?- is defined by the Prolog flag toplevel_prompt.
So, if you want to suppress the prompt in case you read from a tty, call set_stream(user_input, tty(false)). In a similar way you can force a prompt using set_stream(user_input, tty(true)) even if Prolog is reading from something else than a tty.