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
Add a timeout to cursor_pos
and warn if terminal does not respond to cursor position query
#674
Comments
cursor_pos
and warn if terminal does not respond to cursor position reportcursor_pos
and warn if terminal does not respond to cursor position query
Ah I was about to create an issue for this. Here's a repro script: if ARGV.first == "prompt"
require "readline"
puts Readline.name
puts Readline.readline("Prompt: ").upcase
else
require "pty"
output = ""
PTY.spawn("ruby", __FILE__, "prompt") do |read, write, pid|
loop do
output += read.readpartial(4096)
$stderr.puts(output.inspect)
$stderr.puts(output)
write.puts("hello") if output.end_with?(": ")
rescue EOFError, SystemCallError
Process.waitpid(pid)
break
end
end
puts
puts "Output:", output
end You can test this with a real terminal (podman can be replaced by docker): $ podman run --rm -ti -v $PWD:/app ruby:3.2 ruby /app/bug.rb prompt
Readline
Prompt: readline
READLINE
$ podman run --rm -ti -v $PWD:/app ruby:3.3 ruby /app/bug.rb prompt
Reline
Prompt: reline
RELINE But if we use $ podman run --rm -ti -v $PWD:/app ruby:3.2 ruby /app/bug.rb
"Readline\r\n"
Readline
"Readline\r\n\e[?2004hPrompt: "
Readline
Prompt:
"Readline\r\n\e[?2004hPrompt: hello\r\n\e[?2004l\rHELLO\r\n"
Readline
Prompt: hello
HELLO
Output:
Readline
Prompt: hello
HELLO
$ podman run --rm -ti -v $PWD:/app ruby:3.3 ruby /app/bug.rb
"Reline\r\n"
Reline
"Reline\r\n\e[1G\xE2\x96\xBD\e[6n"
Reline
▽
^[[37;2R^C/app/bug.rb:14:in `readpartial': Interrupt
from /app/bug.rb:14:in `block (2 levels) in <main>'
from <internal:kernel>:187:in `loop'
from /app/bug.rb:13:in `block in <main>'
from /app/bug.rb:12:in `spawn'
from /app/bug.rb:12:in `<main>' As you mentioned, we can see "\e[6n", then we can even see the result from the terminal Using $ podman run --rm -ti -v $PWD:/app -e TERM=dumb ruby:3.3 ruby /app/bug.rb
"Reline\r\n"
Reline
"Reline\r\nPrompt: Prompt: "
Reline
Prompt: Prompt:
"Reline\r\nPrompt: Prompt: hello\r\n"
Reline
Prompt: Prompt: hello
"Reline\r\nPrompt: Prompt: hello\r\nPrompt: hPrompt: h"
Reline
Prompt: Prompt: hello
Prompt: hPrompt: h
"Reline\r\nPrompt: Prompt: hello\r\nPrompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: hel"
Reline
Prompt: Prompt: hello
Prompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: hel
"Reline\r\nPrompt: Prompt: hello\r\nPrompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: helPrompt: hell"
Reline
Prompt: Prompt: hello
Prompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: helPrompt: hell
"Reline\r\nPrompt: Prompt: hello\r\nPrompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: helPrompt: hellPrompt: hellPrompt: hello"
Reline
Prompt: Prompt: hello
Prompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: helPrompt: hellPrompt: hellPrompt: hello
"Reline\r\nPrompt: Prompt: hello\r\nPrompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: helPrompt: hellPrompt: hellPrompt: helloPrompt: hello"
Reline
Prompt: Prompt: hello
Prompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: helPrompt: hellPrompt: hellPrompt: helloPrompt: hello
"Reline\r\nPrompt: Prompt: hello\r\nPrompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: helPrompt: hellPrompt: hellPrompt: helloPrompt: helloHELLO\r\n"
Reline
Prompt: Prompt: hello
Prompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: helPrompt: hellPrompt: hellPrompt: helloPrompt: helloHELLO
Output:
Reline
Prompt: Prompt: hello
Prompt: hPrompt: hPrompt: hePrompt: hePrompt: helPrompt: helPrompt: hellPrompt: hellPrompt: helloPrompt: helloHELLO @tompng Do you know if there's a way to work around this without using |
In my understanding, using PTY means that the program is expected to act like a terminal emulator. PTY.spawn("ruby", __FILE__, "prompt") do |read, write, pid|
# Spawned process can check if it is executed in terminal emulator by `IO#tty?`. When spawned by PTY, it returns true.
loop do
s = read.readpartial(4096)
if s.include?("\e[6n")
# If terminal emulator(==this program) receives "\e[6n", terminal emulator should report cursor position
# Since this program is not a full terminal emulator, report dummy cursor position
cursor_col, cursor_row = 1, 1
# Or you can report real cursor position retrieved from current terminal, virtual terminal library, another process, from remote, whatever. PTY doesn't support this part.
write.write "\e[#{cursor_row};#{cursor_col}R"
end
output += s
end
end This is too hard, so there is |
Description
If terminal emulator does not respond to cursor position query
"\e[6n"
, Reline will wait forever with▽
displayed in terminal.Reline can add a timeout to at least work in such case. Warning message will help debugging.
Example:
TERM=dumb
in terminal emulator that does not support cursor position reportPTY.spawn
Terminal Emulator
Pseudo terminal launched by
PTY.spawn
The text was updated successfully, but these errors were encountered: