pyte icon indicating copy to clipboard operation
pyte copied to clipboard

Implement scroll up and down

Open zblz opened this issue 6 years ago • 3 comments

This PR implements handling of the SU and SD CSI commands in pyte.Stream and the corresponding scroll_up and scroll_down methods in pyte.Screen.

zblz avatar Nov 21 '17 17:11 zblz

Thanks for the contribution! Could you point me to documentation for these escape sequences?

superbobry avatar Dec 09 '17 23:12 superbobry

They are (sparsely) documented here: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html

The most common use of this is when you call clear inside of a tmux session with a status bar. Instead of clearin everything and redrawing the status bar, tmux will scroll the non-status-bar lines out of the screen using scroll up. We also looked at vttest requirements to check its behaviour.

zblz avatar Dec 10 '17 20:12 zblz

Any chance this can be merged?

I ran into the lack of scroll support when using the Python curses module. Scrolling can be invoked implicitly in ncurses (I believe this is due to hardscroll.c, which appears to detect 'scroll-like' updates, even if a scroll was not explicitly requested.)

Here is a script that demonstrates psuedo-scroll behavior. With TERM set to a terminal with scrolling capability (e.g. xterm-256color), this script fails to update the 0, 0 cell to 1 (i.e. the first assert should fail) because ncurses decides to send a scroll command. With TERM set to linux the script passes.

import curses
import pyte
import os


def psuedo_scroll(stdscr):
    stdscr.addstr(0, 0, '0')
    stdscr.addstr(2, 0, '1')
    stdscr.refresh()
    stdscr.addstr(0, 0, '1')
    stdscr.addstr(2, 0, '2')
    stdscr.refresh()


pid, fd = os.forkpty()
if pid == 0:
    curses.wrapper(psuedo_scroll)
else:
    screen = pyte.Screen(80, 24)
    stream = pyte.ByteStream(screen)
    # pass through bytes directly
    stream.select_other_charset('@')
    while True:
        try:
            output = os.read(fd, 1024)
            stream.feed(output)
        except OSError:
            break
    assert(screen.buffer[0][0].data == '1')
    assert(screen.buffer[2][0].data == '2')

I don't know of any easy way to set the term capabilities with greater granularlity than TERM (to disable scrolling but leave support for other features (e.g. color)), so I would prefer to not use TERM=linux. Additionally, merging this would save some time for others who run into the issue (it took some debugging to trace observed incorrect terminal state to the scroll behavior).

I tested this pull request and it solves both my original issue and causes the above test to pass.

mvilim avatar Feb 07 '19 03:02 mvilim