Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple lines sent on pty input by expect are not seen by process #690

Closed
mmastrac opened this issue Mar 15, 2023 · 9 comments · Fixed by #761
Closed

Multiple lines sent on pty input by expect are not seen by process #690

mmastrac opened this issue Mar 15, 2023 · 9 comments · Fixed by #761

Comments

@mmastrac
Copy link

When sending input via expect, rustyline doesn't appear to process anything but the first line.

example.expect

spawn cargo run --example numeric_input
send "1\n2\n"
expect "123"

Run expect example.expect

spawn cargo run --example numeric_input
1
2
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/examples/numeric_input`
> 1
Num: 1
> ^C✘-INT ~/Documents/github/rustyline [master|✔] 

Expected:

Output should be Num 1 followed by Num 2.

Actual:

Output is just Num 1

Workaround:

It does work without using expect, however:

$ echo -e "1\n2" | cargo run --example numeric_input
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/examples/numeric_input`
Num: 1
Num: 2
Error: Eof
@mmastrac mmastrac changed the title Input send on pty by expect is not seen by process Multiple lines sent on pty input by expect is not seen by process Mar 15, 2023
@mmastrac mmastrac changed the title Multiple lines sent on pty input by expect is not seen by process Multiple lines sent on pty input by expect are not seen by process Mar 15, 2023
@gwenn
Copy link
Collaborator

gwenn commented Mar 16, 2023

I will try to reproduce.
Would you mind trying this setting: https://docs.rs/rustyline/latest/rustyline/config/enum.Behavior.html#variant.PreferTerm ?

    let config = Config::builder()
        .behavior(Behavior::PreferTerm)
        .build();
    let mut rl = DefaultEditor::with_config(config)?;

@gwenn
Copy link
Collaborator

gwenn commented Mar 16, 2023

Ok, I can reproduce.
Liner seems OK.
But not linenoise, replxx, ...
I tried with env_logger::init(); and export RUST_LOG=rustyline=debug but that didn't help.
It may be caused by the way we activate raw mode with TCSADRAIN here ?
I will try to investigate further...

@gwenn
Copy link
Collaborator

gwenn commented Mar 25, 2023

Ok,
rustyline uses a BufReader.
And the whole input "1\n2\n" is read at once but only "1\n" is treated ("2\n" is discarded).

diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index 23bfcce..70e02f4 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -144,6 +144,7 @@ impl Read for TtyIn {
                     return Err(error);
                 }
             } else {
+                debug!(target: "rustyline", "read: {:?}", &buf[..res as usize]);
                 #[allow(clippy::cast_sign_loss)]
                 return Ok(res as usize);
             }
[DEBUG rustyline] read: [49, 10, 50, 10]

The BufReader is used for bracketed paste.
See https://en.wikipedia.org/wiki/Bracketed-paste
Maybe we should set the buffer size to 1 when bracketed paste is disabled ?

@gwenn
Copy link
Collaborator

gwenn commented Mar 25, 2023

With the following patch, I manage to fix the issue:

diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index 23bfcce..ff96dd6 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -229,8 +229,13 @@ impl PosixRawReader {
         key_map: PosixKeyMap,
         pipe_reader: Option<PipeReader>,
     ) -> Self {
+        let buffer_size = if config.enable_bracketed_paste() {
+            1024
+        } else {
+            1
+        };
         Self {
-            tty_in: BufReader::with_capacity(1024, TtyIn { fd, sigwinch_pipe }),
+            tty_in: BufReader::with_capacity(buffer_size, TtyIn { fd, sigwinch_pipe }),
             timeout_ms: config.keyseq_timeout(),
             parser: Parser::new(),
             key_map,

Or maybe the expect file could be like this:

spawn cargo run --example numeric_input
send "1\n"
expect "1"
spawn cargo run --example numeric_input
send "2\n"
expect "2"

?

@cosmikwolf
Copy link

I think I am running into this issue when I pipe the output of a command with multiple lines into my app that uses rustyline,

here is a simulation of my example, I can create a code example if needed.

echo "test\ninput" | cargo run rustylineapp

Should produce:

Result: test
input

but it produces

Result: test
Result: input

@gwenn
Copy link
Collaborator

gwenn commented Sep 3, 2023

@cosmikwolf For me, this is the expected behaviour when stdin is not a tty (here a pipe). expect creates a pty.

liner % echo "test\ninput" | target/debug/examples/comments history
History file: history
[prompt]
% test
[prompt]
% nput
[prompt]
% exiting...
linenoise % echo "test\ninput" | ./linenoise_example
echo: 'test'
echo: 'input'
replxx % echo "test\ninput" | ./build/replxx-example-c-api
starting...
thanks for the input: test
thanks for the input: input

Exiting Replxx
isocline % echo "test\ninput" | ./example
...
-----
est
-----
-----
input
-----
done

@gwenn
Copy link
Collaborator

gwenn commented Jan 14, 2024

https://github.com/prompt-toolkit/python-prompt-toolkit/blob/0aa8a9762a51289e753a6e311edcb40b65224c66/src/prompt_toolkit/input/typeahead.py

To support type ahead, this module will store all the key strokes that were
read too early, so that they can be feed into to the next prompt() call

@gwenn gwenn mentioned this issue Jan 21, 2024
@gwenn
Copy link
Collaborator

gwenn commented Jan 21, 2024

@mmastrac could you please try #761 ?

@gwenn
Copy link
Collaborator

gwenn commented Mar 6, 2024

Version 14.0.0 released

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants