curses練習
pythonでcursesの練習を作ってみた。
padとstdscrを混ぜて使って画面が更新されないのに2時間くらいはまる。
cursesデバッグしにくいよ。
いまいち勝手がわからない。
#!/usr/bin/python # -*- coding:utf-8 -*- import curses import locale import os # 日本語文字化け対策 locale.setlocale(locale.LC_ALL, "") class CursesApp(object): __slots__=['stdscr', 'callbacks', 'input'] def __init__(self, stdscr): self.stdscr=stdscr curses.noecho() curses.cbreak() curses.curs_set(False) self.stdscr.keypad(1) self.callbacks={} self.callbacks[ord('q')]=self.quit self.x=0 self.y=0 (self.h, self.w)=self.stdscr.getmaxyx() def finalize(self): self.stdscr.keypad(0) def loop(self): while 1: c = self.stdscr.getch() if c in self.callbacks: if self.callbacks[c](): break else: self.default(c) def quit(self): return True def default(self, c): pass """ 表示領域を指定したpad """ class PadList(object): __slots__=['top', 'left', 'bottom', 'right', 'lines', 'topline', 'selected', 'items', 'pad', 'format'] def __init__(self, top, left, bottom, right, lines): self.top=top self.left=left self.right=right self.bottom=bottom self.lines=lines self.topline=0 self.selected=0 self.items={} self.format="%-"+("%d" % (self.right-self.left-1))+"s" self.pad=curses.newpad(self.lines, self.right-self.left) def setText(self, index, text, attrib=curses.A_NORMAL): if index<0: return if index>=self.lines: return self.items[index]=text self.pad.addstr(index, 0, (self.format % text), attrib) def select(self, index): height=self.bottom-self.top if index<0: index=0 if index>=self.lines: index=self.lines-1 if index<self.topline: self.topline=index if index>self.topline+height: self.topline=index-height if self.topline+height>self.lines: self.topline=self.lines-height if self.selected!=index: self.setText(self.selected, self.items[self.selected], curses.A_NORMAL) self.selected=index self.setText(self.selected, self.items[self.selected], curses.A_REVERSE) self.refresh() def next(self): self.select(self.selected+1) def prev(self): self.select(self.selected-1) def refresh(self): self.pad.refresh(self.topline, 0, self.top, self.left, self.bottom, self.right) def clear(self): self.pad.erase() self.refresh() """ ファイルシステムを移動するサンプル """ class Filer(CursesApp): def __init__(self, stdscr, path='/'): CursesApp.__init__(self, stdscr) self.selected=0 self.topline=0 self.format="%-"+("%d" % (self.w-1))+"s" self.pad=None self.setPath(path) # keyboard callbacks self.callbacks[ord('j')]=self.down self.callbacks[ord('k')]=self.up self.callbacks[ord('g')]=self.first self.callbacks[ord('G')]=self.last self.callbacks[0x0a]=self.enter def setPath(self, path): self.path=path self.children=[] if self.path!='/': self.children.append('..') for child in sorted(os.listdir(path)): self.children.append(child) # ディレクトリ移動時に表示をクリアする if self.pad: self.pad.clear() self.pad=PadList(0, 0, self.h-1, self.w-1, len(self.children)) for i, child in enumerate(self.children): self.pad.setText(i, child) self.pad.select(0) self.pad.refresh() def down(self): self.pad.next() def up(self): self.pad.prev() def first(self): self.pad.select(0) def last(self): self.pad.select(len(self.children)-1) def enter(self): selected=self.children[self.pad.selected] path=os.path.join(self.path, selected) path=os.path.abspath(path) if os.path.isdir(path): self.setPath(path) self.pad.select(0) def loop(self): while 1: c = self.pad.pad.getch() # stdscrのgetchだと画面が更新されない if c in self.callbacks: if self.callbacks[c](): break else: self.default(c) def main(stdscr): app=Filer(stdscr) app.loop() app.finalize() if __name__=='__main__': curses.wrapper(main)
ファイルシステムを移動するだけで他の機能は特にない。
簡単なファイラーみたいのなら作れるかも。
- j
- 下
- k
- 上
- g
- 一番上
- G
- 一番下
- enter
- ディレクトリの中に入る