In my Python script which uses Curses, I have a subwin to which some text is assigned. Because the text length may be longer than the window size, the text should be scrollable.
It doesn't seem that there is any CSS-"overflow" like attribute for Curses windows. The Python/Curses docs are also rather cryptic on this aspect.
Does anybody here have an idea how I can code a scrollable Curses subwindow using Python and actually scroll through it?
\edit: more precise question
Starting and ending a curses application If successful, initscr() returns a window object representing the entire screen; this is usually called stdscr after the name of the corresponding C variable.
To use the wrapper, create a function that takes one argument: the screen. Then, call wrapper() and pass it your function that will operate with the screen. The wrapper() function takes care of initializing the curses screen that is normally done with curses. initscr() and also takes care of calling curses.
OK with window.scroll
it was too complicated to move the content of the window. Instead, curses.newpad
did it for me.
Create a pad:
mypad = curses.newpad(40,60) mypad_pos = 0 mypad.refresh(mypad_pos, 0, 5, 5, 10, 60)
Then you can scroll by increasing/decreasing mypad_pos
depending on the input from window.getch()
in cmd
:
if cmd == curses.KEY_DOWN: mypad_pos += 1 mypad.refresh(mypad_pos, 0, 5, 5, 10, 60) elif cmd == curses.KEY_UP: mypad_pos -= 1 mypad.refresh(mypad_pos, 0, 5, 5, 10, 60)
Right, I was a bit confused on how to utilize pads (in order to scroll text), and still couldn't figure it out after reading this post; especially since I wanted to use it in a context of the content being an existing "array of lines". So I prepared a small example, that shows similarities (and differences) between newpad
and subpad
:
#!/usr/bin/env python2.7 import curses # content - array of lines (list) mylines = ["Line {0} ".format(id)*3 for id in range(1,11)] import pprint pprint.pprint(mylines) def main(stdscr): hlines = begin_y = begin_x = 5 ; wcols = 10 # calculate total content size padhlines = len(mylines) padwcols = 0 for line in mylines: if len(line) > padwcols: padwcols = len(line) padhlines += 2 ; padwcols += 2 # allow border stdscr.addstr("padhlines "+str(padhlines)+" padwcols "+str(padwcols)+"; ") # both newpad and subpad are <class '_curses.curses window'>: mypadn = curses.newpad(padhlines, padwcols) mypads = stdscr.subpad(padhlines, padwcols, begin_y, begin_x+padwcols+4) stdscr.addstr(str(type(mypadn))+" "+str(type(mypads)) + "\n") mypadn.scrollok(1) mypadn.idlok(1) mypads.scrollok(1) mypads.idlok(1) mypadn.border(0) # first ... mypads.border(0) # ... border for line in mylines: mypadn.addstr(padhlines-1,1, line) mypadn.scroll(1) mypads.addstr(padhlines-1,1, line) mypads.scroll(1) mypadn.border(0) # second ... mypads.border(0) # ... border # refresh parent first, to render the texts on top #~ stdscr.refresh() # refresh the pads next mypadn.refresh(0,0, begin_y,begin_x, begin_y+hlines, begin_x+padwcols) mypads.refresh() mypads.touchwin() mypadn.touchwin() stdscr.touchwin() # no real effect here #stdscr.refresh() # not here! overwrites newpad! mypadn.getch() # even THIS command erases newpad! # (unless stdscr.refresh() previously): stdscr.getch() curses.wrapper(main)
When you run this, at first you will get something like (newpad
left, subpad
right):
┌────────────────────────┐ ┌────────────────────────┐ │Line 1 Line 1 Line 1 ───│ │Line 1 Line 1 Line 1 ───│ │Line 2 Line 2 Line 2 │ │Line 2 Line 2 Line 2 │ │Line 3 Line 3 Line 3 │ │Line 3 Line 3 Line 3 │ │Line 4 Line 4 Line 4 │ │Line 4 Line 4 Line 4 │ │Line 5 Line 5 Line 5 │ │Line 5 Line 5 Line 5 │ │Line 6 Line 6 Line 6 │ │Line 7 Line 7 Line 7 │ │Line 8 Line 8 Line 8 │ │Line 9 Line 9 Line 9 │ │Line 10 Line 10 Line 10 │ └────────────────────────┘
Some notes:
newpad
and subpad
should have their width/height sized to the content (num lines/max line width of the array of lines) + eventual border spacescrollok()
- but not extra widthscroll()
up to make room for the nextrefresh
method that newpad
has, then allows for just a region of this "whole content" to be shown on screen; subpad
more-less has to be shown in the size it was instantiated in ───
piece shown at the ...Line 1 ───│
part). Useful links:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With