kevinlawler / kona

Open-source implementation of the K programming language
ISC License
1.36k stars 139 forks source link

how to evaluate an expression when stdin is not a tty? #533

Closed ngn closed 5 years ago

ngn commented 5 years ago

i tried:

$ echo '1 2+3' | ./k             # prints only whitespace
$ echo '1 2+3' >a.k && ./k a.k   # works only in a terminal (when stdin is a tty)
$ echo '`0:"hi"` >a.k && ./k a.k # works only when the result is a string (or a list of)

also, is there a way to suppress 2-space prompts and the initial line: kona \ for help. \\ to exit.?

this is for tio

tavmem commented 5 years ago

I included the initial prompt in boilerplate(), which can be suppressed by adding argument -b=0 b can be set to anything to achieve suppression.

$ 
$ echo '1 2+3' >a.k && ./k a.k
kona      \ for help. \\ to exit.

  4 5
\\
$ echo '1 2+3' >a.k && ./k -b=0 a.k
4 5
\\
$ 

Input can be from another k process. (more later)

bakul commented 5 years ago

Note that echo 1 2+3|k /dev/stdin works for k3 as expected (including the initial header) but not for kona. k3 does print a warning to /dev/stderr which can be suppressed but it does print 4 5.

tavmem commented 5 years ago

Agreed ... This is what I get using k2.8 with Linux:

$ 
$ echo 1 2+3 | ./k /dev/stdin
K 2.8 2000-10-10 Copyright (C) 1993-2000 Kx Systems
Evaluation. Not for commercial use. 
\ for help. \\ to exit.

/dev/stdin:
/dev/stdin.kr: file not found
  4 5

$ 
tavmem commented 5 years ago

In kona:

$ 
$ echo 1 2+3 | ./k /dev/stdin
/dev/stdin: file not found
$ 
bakul commented 5 years ago

/dev/fd/0 instead of /dev/stdin should work on most all unix machines.

Incidentally, rather than -b=0 option, a better choice may be to check if the input is a tty by isatty(0) function and if true, not print any prompt or the initial header line.

tavmem commented 5 years ago

Thanks, ... however ...

1) Unfortunately, kona doesn't display output when using /dev/fd/0 on a Fedora machine. (Need to research that further.)

$ 
$ echo 1 2+3 | ./k /dev/fd/0
/dev/fd/0: file not found
$ 

2) Using isatty() would be a better choice when using /dev/f/0, but the original request to suppress the banner came in as part of issue #507, to suppress the banner when running a script. Suppressing the banner when running a script by using a isatty() test does not work.

Modifying src/main.c to add a isatty() test;

int main(int argc,S*argv)
{
  kinit();
  if(isatty(STDIN))O("yes-tty\n"); else O("no-tty\n");
  args(argc,argv);
  attend(); //loop on stdin/inet
  R 0;
}

kona reports no-tty when using /dev/fd/0

$ 
$ echo 1 2+3 | ./k /dev/fd/0
no-tty
/dev/fd/0: file not found
$ 

yes-tty when started normally

$ 
$ ./k
yes-tty
kona      \ for help. \\ to exit.

  \\
$ 

but, also yes-tty when reading a script

$ 
$ echo '1 2+3' >a.k && ./k a.k
yes-tty
kona      \ for help. \\ to exit.

  4 5
\\
$ 
bakul commented 5 years ago
  1. No idea why fedora doesn't have /dev/fd/0.
  2. The issue here is whether stdin is connected to a tty or a pipe or a file or some non-tty device. The initial header and the prompt should be printed only if stdin is connected to a tty.
  3. ./k /dev/fd/0 is a trick to make kona to accept a k program from its input (when it is not a tty). I don't recall why k3 or kona behave this way. But this is a separate issue from 2. above.
tavmem commented 5 years ago

Regarding your points in the last post:

  1. Fedora does have /dev/fd/0. The following works in Fedora with k2.8. In k2.8, both files /dev/fd/0 and /dev/fd/0.kr are "not found", but the 4 5 result is produced. In kona, the file /dev/fd/0 is also "not found", but kona does not produce the 4 5 result.
    
    $ echo 1 2+3 | ./k /dev/fd/0
    K 2.8 2000-10-10 Copyright (C) 1993-2000 Kx Systems
    Evaluation. Not for commercial use. 
    \ for help. \\ to exit.

/dev/fd/0: /dev/fd/0.kr: file not found 4 5

$


2.   I agree that the primary issue is whether stdin is connected to a tty or some non-tty device.
When using the command `echo 1 2+3 | ./k /dev/fd/0` kona immediately recognizes that it is dealing with a non-tty device.
I was hoping that the command `echo '1 2+3' >a.k && ./k a.k` would also cause kona to immediately recognize that it is dealing with a non-tty device, but that does not happen.  The `isatty()` test probably needs to occur later in the kona code.
3.  I agree that there are 2 separate issues:
-  The "trick", which works in k2.8 (and k3), but not in kona (yet).
-  proper placement of the `isatty()` test, so that kona can determine whether it is dealing with a tty or a non-tty device before kona prints the banner (or the initial prompt).
tavmem commented 5 years ago

Let's go back to the initial requests on this issue (#533).

  1. Create kona commands in tio and send them to kona for execution.
  2. Kona should execute the command and return the result.
  3. Kona should suppress sending the banner and the initial prompt.

Suppressing the banner and initial prompt is already possible using the -b=0 argument. I agree that this could be done more elegantly by having kona determine that it is dealing with a stdin that is non-tty and automatically suppress the banner and initial prompt. Nevertheless, the suppression capability already exists for stdin that is tty or non-tty.

Currently, kona can accept and execute commands from several types of stdin that are non-tty, e.g., other kona instances, k-script files, as well as the kapi (the c interface to kona). Each of these examples currently has its own special case implementation that works.

We have generalized the requirements of this issue into a request to have kona accept commands from any non-tty source. Is this generalization the best way to go for a tio solution? Is kapi usable here? Not clear ... will think about this further.

ngn commented 5 years ago

Thanks for -b=0. The kapi sounds to me like an overkill for a use like this.

Maybe this line is wrong? It decides whether to print on stdout based on whether stdin is a tty. Actually, I don't understand why the display of results needs to be suppressed at all. #353 and #456 mention assignments in \l-ed scripts being too verbose, but that is no longer the case.

tavmem commented 5 years ago

Sorry that it took so long for me to respond ... I was travelling last night and today. Looks like you are correct. Very well done!!!!

If I make the following substitution for the line in src/kc.c that you indicated:

    //I o = isatty(STDIN); //display results to stdout?
    I o = 1;

then the kona results are:

$ 
$ echo 1 2+3 | ./k /dev/fd/0
/dev/fd/0: file not found
4 5
    $ 
$

And ... I did not have to use -b=0 to suppress the banner.

At some point, the original line was deemed necessary. Right now, I don't know whether it serves any purpose at all. (Maybe, when kona is communicating with another kona instance. I will check, when I get a chance.)

ngn commented 5 years ago

Thanks. I'll talk to the guy running tio to see if he wants to apply a temp patch. If not - there's absolutely no rush, we'll pull the fix whenever it may be ready.

/dev/fd/0 is not necessary, by the way. This pipe makes sure that neither stdin nor stdout is a tty: echo '1 2+3' | ./k | cat

tavmem commented 5 years ago

FYI: Interprocess communication between 2 kona processes seems to work fine.