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

Use thread to respond to "\e[6n"(Cursor Position Report) as soon as possible #16

Open
tompng opened this issue Sep 16, 2024 · 0 comments

Comments

@tompng
Copy link
Member

tompng commented Sep 16, 2024

Description

In method write, yamatanooroti calls sync before and after writing to pty_input.

def write(str_to_write)
  sync
  @pty_input.write(str_to_write)
  sync
end

I think we don't need to sync before write, but removing it will make reline/irb's test fail.
It does not mean that sync before is necessary. We need to use Thread to fix the root cause.

Detail

Reline writes "\e[6n", Cursor Position Report, to get the actual cursor position.
Terminal emulator(== vterm) will respond to it with "\e[#{row};#{column}R".

I found that this test is working just by chance.

start_terminal(10, 10, 'irb')
write "1+2\n"
sleep 1
write "2+3\n"
assert_screen("irb(main):001>1+2\n=>3\nirb(main):002>2+3\n=>5\n")

Breaking it down

sync
@pty_input.write "1+2\n"
sync
sleep 1
sync
@pty_input.write "3+4\n"
sync

Breaking it down more

sync
@pty_input.write "1+2\n"
@vterm.write(@pty_output.read_nonblock(1024))
@pty_input.write(@vterm.read)
sleep 1
@vterm.write(@pty_output.read_nonblock(1024))
@pty_input.write(@vterm.read)
@pty_input.write "3+4\n"
sync

These are two cases how IRB, yamatanooroti and vterm interacts.

# Case 1, normal

@pty_input.write "1+2\n"
# irb receives "1+2\n"
# irb prints "\e[G1irb(main):001> 1+2\n=> 3\n\e[6n"
@vterm.write(@pty_output.read_nonblock(1024)) # yamatanooroti writes it to vterm
# vterm responds to "\e[6n" with "\e[2;1R"
@pty_input.write(@vterm.read)
# irb prints "irb(main):002>"
sleep 1
@vterm.write(@pty_output.read_nonblock(1024)) # nothing happens
@pty_input.write(@vterm.read) # nothing happens
@pty_input.write "3+4\n"
# irb receives "3+4\n"
sync
# Case 2, IRB prints "\e[6n" with a small delay

@pty_input.write "1+2\n"
# irb receives "1+2\n"
# irb prints "\e[G1irb(main):001> 1+2\n=> 3\n"
@vterm.write(@pty_output.read_nonblock(1024)) # yamatanooroti writes it to vterm
# irb prints "\e[6n" with a small delay
@pty_input.write(@vterm.read) # nothing happens
sleep 1 # irb is waiting for cursor position report and doing nothing
@vterm.write(@pty_output.read_nonblock(1024)) # yamatanooroti writes "\e[6n" to vterm
@pty_input.write(@vterm.read) # vterm responds to "\e[6n" with "\e[2;1R"
@pty_input.write "3+4\n" # IRB's prompt "irb(main):002>" is not ready yet
# irb prints "irb(main):002>"
# irb receives "3+4\n"
sync

Even with a long sleep, there is a chance that test won't run as expected.
While executing sleep 1, another thread should read from pty_output, write to vterm, and write cursor position report response to pty_input.

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

No branches or pull requests

1 participant