Ich wollte einen Scroll-Pad verwenden, um Inhalte von einigen großen Textdateien angezeigt werden, aber dies auch nicht funktioniert, weil Texte Zeilenumbrüche haben können und es war ziemlich hart, wie viele Zeichen, um herauszufinden, an einem anzuzeigen Zeit, um die gute Anzahl von Spalten und Zeilen anzupassen.
Also entschied ich mich, meine Textdateien zuerst in Zeilen mit exakt COLUMNS-Zeichen zu teilen und mit Leerzeichen zu füllen, wenn die Zeilen zu kurz waren. Dann wird das Scrollen des Textes einfacher.
Hier ist ein Beispielcode eine beliebige Textdatei anzuzeigen:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import curses
import locale
import sys
def main(filename, filecontent, encoding="utf-8"):
try:
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
curses.curs_set(0)
stdscr.keypad(1)
rows, columns = stdscr.getmaxyx()
stdscr.border()
bottom_menu = u"(↓) Next line | (↑) Previous line | (→) Next page | (←) Previous page | (q) Quit".encode(encoding).center(columns - 4)
stdscr.addstr(rows - 1, 2, bottom_menu, curses.A_REVERSE)
out = stdscr.subwin(rows - 2, columns - 2, 1, 1)
out_rows, out_columns = out.getmaxyx()
out_rows -= 1
lines = map(lambda x: x + " " * (out_columns - len(x)), reduce(lambda x, y: x + y, [[x[i:i+out_columns] for i in xrange(0, len(x), out_columns)] for x in filecontent.expandtabs(4).splitlines()]))
stdscr.refresh()
line = 0
while 1:
top_menu = (u"Lines %d to %d of %d of %s" % (line + 1, min(len(lines), line + out_rows), len(lines), filename)).encode(encoding).center(columns - 4)
stdscr.addstr(0, 2, top_menu, curses.A_REVERSE)
out.addstr(0, 0, "".join(lines[line:line+out_rows]))
stdscr.refresh()
out.refresh()
c = stdscr.getch()
if c == ord("q"):
break
elif c == curses.KEY_DOWN:
if len(lines) - line > out_rows:
line += 1
elif c == curses.KEY_UP:
if line > 0:
line -= 1
elif c == curses.KEY_RIGHT:
if len(lines) - line >= 2 * out_rows:
line += out_rows
elif c == curses.KEY_LEFT:
if line >= out_rows:
line -= out_rows
finally:
curses.nocbreak(); stdscr.keypad(0); curses.echo(); curses.curs_set(1)
curses.endwin()
if __name__ == '__main__':
locale.setlocale(locale.LC_ALL, '')
encoding = locale.getpreferredencoding()
try:
filename = sys.argv[1]
except:
print "Usage: python %s FILENAME" % __file__
else:
try:
with open(filename) as f:
filecontent = f.read()
except:
print "Unable to open file %s" % filename
else:
main(filename, filecontent, encoding)
Der wichtigste Trick ist die Zeile:
lines = map(lambda x: x + " " * (out_columns - len(x)), reduce(lambda x, y: x + y, [[x[i:i+out_columns] for i in xrange(0, len(x), out_columns)] for x in filecontent.expandtabs(4).splitlines()]))
Zuerst Tabellierungen im Text in Leerzeichen umgewandelt werden, dann habe ich splitlines() -Methode, um meinen Text in ein Array von Zeilen zu konvertieren. Aber einige Zeilen können länger als unsere COLUMNS-Nummer sein, daher habe ich jede Zeile in einen Block von COLUMNS-Zeichen aufgeteilt und dann reduce verwendet, um die resultierende Liste in eine Liste von Zeilen umzuwandeln. Schließlich habe ich map verwendet, um jede Zeile mit abschließenden Leerzeichen aufzufüllen, so dass ihre Länge genau COLUMNS-Zeichen ist.
Hoffe, das hilft.
Das Fenster akzeptiert Texte, die die eigene Größe überschreiten. Es ist möglich, mit window.scroll (1) zu scrollen. Dann müssen die gescrollten Zeilen neu gezeichnet werden, was in den Dokumenten nicht erklärt wird. Das Scrollen von Curses-Fenstern erfordert also mehrere Schritte, von denen mir noch einige fehlen. – lecodesportif