- commit
- b8879d299a1d6868216f6aa923a13756109b2f23
- parent
- a7771dbef586a628ac172d5bc76445f61572b89c
- Author
- Tobias Bengfort <tobias.bengfort@gmx.net>
- Date
- 2014-10-06 20:15
create dirtywords dirtywords is a curses replacement. It is build on a minimal set of functions that can be implemented with a variety of backend, e.g. curses or pygame. It is relatively hard to install either curses or pygame. They can not simply be installed with pip. So dirtywords offers an abstraction layer that provides the best possible experience on the target machiene.
Diffstat
| A | laneya/dirtywords/__init__.py | 11 | +++++++++++ |
| A | laneya/dirtywords/base.py | 83 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | laneya/dirtywords/curses_dirtywords.py | 33 | +++++++++++++++++++++++++++++++++ |
| A | laneya/dirtywords/example.py | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | laneya/dirtywords/pygame_dirtywords.py | 41 | +++++++++++++++++++++++++++++++++++++++++ |
| A | laneya/dirtywords/stupid_dirtywords.py | 28 | ++++++++++++++++++++++++++++ |
6 files changed, 250 insertions, 0 deletions
diff --git a/laneya/dirtywords/__init__.py b/laneya/dirtywords/__init__.py
@@ -0,0 +1,11 @@ -1 1 # flake8: noqa -1 2 -1 3 try: -1 4 from pygame_dirtywords import Screen -1 5 except ImportError: -1 6 try: -1 7 from curses_dirtywords import Screen -1 8 except ImportError: -1 9 from stupid_dirtywords import Screen -1 10 -1 11 from base import Window
diff --git a/laneya/dirtywords/base.py b/laneya/dirtywords/base.py
@@ -0,0 +1,83 @@
-1 1 class BaseScreen(object):
-1 2 def __init__(self, height, width):
-1 3 """Initialize screen."""
-1 4 self.height = height
-1 5 self.width = width
-1 6 self.data = [[' ' for xx in range(width)] for yy in range(height)]
-1 7
-1 8 def getch(self):
-1 9 """Get next keystroke (blocking)."""
-1 10 raise NotImplementedError
-1 11
-1 12 def putstr(self, y, x, s):
-1 13 """Write string to position."""
-1 14 for i, ch in enumerate(s):
-1 15 try:
-1 16 self.data[y][x + i] = ch
-1 17 except IndexError:
-1 18 pass
-1 19
-1 20 def refresh(self):
-1 21 """Print the current state to the screen."""
-1 22 raise NotImplementedError
-1 23
-1 24 def cleanup(self):
-1 25 """Deinitialize screen."""
-1 26 pass
-1 27
-1 28
-1 29 class Screen(BaseScreen):
-1 30 """Additional utility functions for :py:class:`BaseScreen`."""
-1 31
-1 32 def delch(self, y, x):
-1 33 """Delete character at position."""
-1 34 self.putstr(y, x, ' ')
-1 35
-1 36 def fill_row(self, y, ch):
-1 37 """Fill a complete row with character."""
-1 38 self.putstr(y, 0, ch * self.width)
-1 39
-1 40 def fill_column(self, x, ch):
-1 41 """Fill a complete column with character."""
-1 42 for y in range(self.height):
-1 43 self.putstr(y, x, ch)
-1 44
-1 45 def fill(self, ch):
-1 46 """Fill whole screen with character."""
-1 47 for y in range(self.height):
-1 48 self.row(y, ch)
-1 49
-1 50 def clear(self):
-1 51 """Clear whole screen."""
-1 52 self.fill(' ')
-1 53
-1 54 def border(self, ls='|', rs='|', ts='-', bs='-',
-1 55 tl='+', tr='+', bl='+', br='+'):
-1 56 """Draw border around screen."""
-1 57 self.fill_column(0, ls)
-1 58 self.fill_column(self.width - 1, rs)
-1 59 self.fill_row(0, ts)
-1 60 self.fill_row(self.height - 1, bs)
-1 61 self.putstr(0, 0, tl)
-1 62 self.putstr(0, self.width - 1, tr)
-1 63 self.putstr(self.height - 1, 0, bl)
-1 64 self.putstr(self.height - 1, self.width - 1, br)
-1 65
-1 66
-1 67 class Window(Screen):
-1 68 """A screen that is rendered onto another screen."""
-1 69
-1 70 def __init__(self, parent, height, width, y, x):
-1 71 super(Window, self).__init__(height, width)
-1 72 self.parent = parent
-1 73 self.y = y
-1 74 self.x = x
-1 75
-1 76 def getch(self):
-1 77 return self.parent.getch()
-1 78
-1 79 def refresh(self):
-1 80 for y in range(self.height):
-1 81 for x in range(self.width):
-1 82 self.parent.putstr(self.y + y, self.x + x, self.data[y][x])
-1 83 self.parent.refresh()
diff --git a/laneya/dirtywords/curses_dirtywords.py b/laneya/dirtywords/curses_dirtywords.py
@@ -0,0 +1,33 @@ -1 1 try: -1 2 from ncurses import curses -1 3 except ImportError: -1 4 import curses -1 5 -1 6 import base -1 7 -1 8 -1 9 class Screen(base.Screen): -1 10 def __init__(self, height, width): -1 11 self.height = height -1 12 self.width = width -1 13 -1 14 curses.initscr() -1 15 curses.noecho() -1 16 curses.curs_set(0) -1 17 self.curses_window = curses.newwin(height, width, 0, 0) -1 18 -1 19 def getch(self): -1 20 return self.curses_window.getch() -1 21 -1 22 def putstr(self, y, x, s): -1 23 for i, ch in enumerate(s): -1 24 try: -1 25 self.curses_window.addstr(y, x + i, ch) -1 26 except: -1 27 pass -1 28 -1 29 def refresh(self): -1 30 self.curses_window.refresh() -1 31 -1 32 def cleanup(self): -1 33 curses.endwin()
diff --git a/laneya/dirtywords/example.py b/laneya/dirtywords/example.py
@@ -0,0 +1,54 @@
-1 1 import sys
-1 2
-1 3 try:
-1 4 from pygame_dirtywords import Screen
-1 5 except ImportError:
-1 6 try:
-1 7 from curses_dirtywords import Screen
-1 8 except ImportError:
-1 9 from stupid_dirtywords import Screen
-1 10
-1 11
-1 12 class Player(object):
-1 13 def __init__(self, win):
-1 14 self.win = win
-1 15 self.y = win.height / 2
-1 16 self.x = win.width / 2
-1 17
-1 18 def move(self, direction):
-1 19 self.win.putstr(self.y, self.x, ' ')
-1 20
-1 21 if direction == 'up':
-1 22 self.y -= 1
-1 23 elif direction == 'right':
-1 24 self.x += 1
-1 25 elif direction == 'down':
-1 26 self.y += 1
-1 27 elif direction == 'left':
-1 28 self.x -= 1
-1 29
-1 30 self.win.putstr(self.y, self.x, 'X')
-1 31 self.win.refresh()
-1 32
-1 33
-1 34 if __name__ == '__main__':
-1 35 scr = Screen(32, 100)
-1 36
-1 37 scr.border()
-1 38
-1 39 player = Player(scr)
-1 40 player.move('down') # initial refresh
-1 41
-1 42 while 1:
-1 43 ch = scr.getch()
-1 44 if ch == ord('h'):
-1 45 player.move('left')
-1 46 elif ch == ord('j'):
-1 47 player.move('down')
-1 48 elif ch == ord('k'):
-1 49 player.move('up')
-1 50 elif ch == ord('l'):
-1 51 player.move('right')
-1 52 elif ch == ord('q'):
-1 53 scr.cleanup()
-1 54 sys.exit()
diff --git a/laneya/dirtywords/pygame_dirtywords.py b/laneya/dirtywords/pygame_dirtywords.py
@@ -0,0 +1,41 @@
-1 1 import pygame
-1 2 from pygame.locals import KEYDOWN
-1 3
-1 4 import base
-1 5
-1 6
-1 7 class Screen(base.Screen):
-1 8 def __init__(self, height, width):
-1 9 super(Screen, self).__init__(height, width)
-1 10
-1 11 pygame.init()
-1 12 self.clock = pygame.time.Clock()
-1 13
-1 14 self.fg_color = pygame.Color('white')
-1 15 self.bg_color = pygame.Color('black')
-1 16
-1 17 self.font = pygame.font.SysFont('monospace', 10)
-1 18 _width, self.fontheight = self.font.size(' ' * self.width)
-1 19 _height = height * self.fontheight
-1 20
-1 21 self.pygame_screen = pygame.display.set_mode((_width, _height))
-1 22
-1 23 def getch(self):
-1 24 while True:
-1 25 event = pygame.event.wait()
-1 26 if event.type == KEYDOWN:
-1 27 return event.key
-1 28
-1 29 def refresh(self):
-1 30 self.pygame_screen.fill(self.bg_color)
-1 31
-1 32 for y in range(self.height):
-1 33 s = ''.join(self.data[y])
-1 34 rendered = self.font.render(s, True, self.fg_color, self.bg_color)
-1 35 self.pygame_screen.blit(rendered, (0, y * self.fontheight))
-1 36
-1 37 self.clock.tick()
-1 38 pygame.display.flip()
-1 39
-1 40 def cleanup(self):
-1 41 pygame.quit()
diff --git a/laneya/dirtywords/stupid_dirtywords.py b/laneya/dirtywords/stupid_dirtywords.py
@@ -0,0 +1,28 @@ -1 1 import sys -1 2 -1 3 import base -1 4 -1 5 -1 6 class Screen(base.Screen): -1 7 def getch(self): -1 8 # http://code.activestate.com/recipes/134892/ -1 9 -1 10 try: -1 11 import msvcrt -1 12 return msvcrt.getch() -1 13 except ImportError: -1 14 import termios -1 15 import tty -1 16 fd = sys.stdin.fileno() -1 17 old_settings = termios.tcgetattr(fd) -1 18 try: -1 19 tty.setraw(sys.stdin.fileno()) -1 20 ch = sys.stdin.read(1) -1 21 finally: -1 22 termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) -1 23 return ord(ch) -1 24 -1 25 def refresh(self): -1 26 spacing = '\n' * self.height * 2 -1 27 s = '\n'.join([''.join(row) for row in self.data]) -1 28 print(spacing + s)