Skip to content

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

@tompng

Description

@tompng

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions