Added color! Added setup.py

This commit is contained in:
Michael Lazar
2015-02-02 21:43:06 -08:00
parent d01393e4b4
commit c9c38dc264
14 changed files with 108 additions and 1739 deletions

View File

@@ -1,216 +0,0 @@
#!/usr/bin/env python
# life.py -- A curses-based version of Conway's Game of Life.
# Contributed by AMK
#
# An empty board will be displayed, and the following commands are available:
# E : Erase the board
# R : Fill the board randomly
# S : Step for a single generation
# C : Update continuously until a key is struck
# Q : Quit
# Cursor keys : Move the cursor around the board
# Space or Enter : Toggle the contents of the cursor's position
#
# TODO :
# Support the mouse
# Use colour if available
# Make board updates faster
#
import random, string, traceback
import curses
class LifeBoard:
"""Encapsulates a Life board
Attributes:
X,Y : horizontal and vertical size of the board
state : dictionary mapping (x,y) to 0 or 1
Methods:
display(update_board) -- If update_board is true, compute the
next generation. Then display the state
of the board and refresh the screen.
erase() -- clear the entire board
makeRandom() -- fill the board randomly
set(y,x) -- set the given cell to Live; doesn't refresh the screen
toggle(y,x) -- change the given cell from live to dead, or vice
versa, and refresh the screen display
"""
def __init__(self, scr, char=ord('*')):
"""Create a new LifeBoard instance.
scr -- curses screen object to use for display
char -- character used to render live cells (default: '*')
"""
self.state = {}
self.scr = scr
Y, X = self.scr.getmaxyx()
self.X, self.Y = X-2, Y-2-1
self.char = char
self.scr.clear()
# Draw a border around the board
border_line = '+'+(self.X*'-')+'+'
self.scr.addstr(0, 0, border_line)
self.scr.addstr(self.Y+1,0, border_line)
for y in range(0, self.Y):
self.scr.addstr(1+y, 0, '|')
self.scr.addstr(1+y, self.X+1, '|')
self.scr.refresh()
def set(self, y, x):
"""Set a cell to the live state"""
if x<0 or self.X<=x or y<0 or self.Y<=y:
raise ValueError, "Coordinates out of range %i,%i"% (y,x)
self.state[x,y] = 1
def toggle(self, y, x):
"""Toggle a cell's state between live and dead"""
if x<0 or self.X<=x or y<0 or self.Y<=y:
raise ValueError, "Coordinates out of range %i,%i"% (y,x)
if self.state.has_key( (x,y) ):
del self.state[x,y]
self.scr.addch(y+1, x+1, ' ')
else:
self.state[x,y] = 1
self.scr.addch(y+1, x+1, self.char)
self.scr.refresh()
def erase(self):
"""Clear the entire board and update the board display"""
self.state = {}
self.display(update_board=False)
def display(self, update_board=True):
"""Display the whole board, optionally computing one generation"""
M,N = self.X, self.Y
if not update_board:
for i in range(0, M):
for j in range(0, N):
if self.state.has_key( (i,j) ):
self.scr.addch(j+1, i+1, self.char)
else:
self.scr.addch(j+1, i+1, ' ')
self.scr.refresh()
return
d = {}
self.boring = 1
for i in range(0, M):
L = range( max(0, i-1), min(M, i+2) )
for j in range(0, N):
s = 0
live = self.state.has_key( (i,j) )
for k in range( max(0, j-1), min(N, j+2) ):
for l in L:
if self.state.has_key( (l,k) ):
s += 1
s -= live
if s == 3:
# Birth
d[i,j] = 1
self.scr.addch(j+1, i+1, self.char)
if not live: self.boring = 0
elif s == 2 and live: d[i,j] = 1 # Survival
elif live:
# Death
self.scr.addch(j+1, i+1, ' ')
self.boring = 0
self.state = d
self.scr.refresh()
def makeRandom(self):
"Fill the board with a random pattern"
self.state = {}
for i in range(0, self.X):
for j in range(0, self.Y):
if random.random() > 0.5:
self.set(j,i)
def erase_menu(stdscr, menu_y):
"Clear the space where the menu resides"
stdscr.move(menu_y, 0)
stdscr.clrtoeol()
stdscr.move(menu_y+1, 0)
stdscr.clrtoeol()
def display_menu(stdscr, menu_y):
"Display the menu of possible keystroke commands"
erase_menu(stdscr, menu_y)
stdscr.addstr(menu_y, 4,
'Use the cursor keys to move, and space or Enter to toggle a cell.')
stdscr.addstr(menu_y+1, 4,
'E)rase the board, R)andom fill, S)tep once or C)ontinuously, Q)uit')
def keyloop(stdscr):
# Clear the screen and display the menu of keys
stdscr.clear()
stdscr_y, stdscr_x = stdscr.getmaxyx()
menu_y = (stdscr_y-3)-1
display_menu(stdscr, menu_y)
# Allocate a subwindow for the Life board and create the board object
subwin = stdscr.subwin(stdscr_y-3, stdscr_x, 0, 0)
board = LifeBoard(subwin, char=ord('*'))
board.display(update_board=False)
# xpos, ypos are the cursor's position
xpos, ypos = board.X//2, board.Y//2
# Main loop:
while (1):
stdscr.move(1+ypos, 1+xpos) # Move the cursor
c = stdscr.getch() # Get a keystroke
if 0<c<256:
c = chr(c)
if c in ' \n':
board.toggle(ypos, xpos)
elif c in 'Cc':
erase_menu(stdscr, menu_y)
stdscr.addstr(menu_y, 6, ' Hit any key to stop continuously '
'updating the screen.')
stdscr.refresh()
# Activate nodelay mode; getch() will return -1
# if no keystroke is available, instead of waiting.
stdscr.nodelay(1)
while (1):
c = stdscr.getch()
if c != -1:
break
stdscr.addstr(0,0, '/')
stdscr.refresh()
board.display()
stdscr.addstr(0,0, '+')
stdscr.refresh()
stdscr.nodelay(0) # Disable nodelay mode
display_menu(stdscr, menu_y)
elif c in 'Ee':
board.erase()
elif c in 'Qq':
break
elif c in 'Rr':
board.makeRandom()
board.display(update_board=False)
elif c in 'Ss':
board.display()
else: pass # Ignore incorrect keys
elif c == curses.KEY_UP and ypos>0: ypos -= 1
elif c == curses.KEY_DOWN and ypos<board.Y-1: ypos += 1
elif c == curses.KEY_LEFT and xpos>0: xpos -= 1
elif c == curses.KEY_RIGHT and xpos<board.X-1: xpos += 1
else:
# Ignore incorrect keys
pass
def main(stdscr):
keyloop(stdscr) # Enter the main loop
if __name__ == '__main__':
curses.wrapper(main)

View File

@@ -1,273 +0,0 @@
#!/usr/bin/env python
#
# $Id$
#
# (n)curses exerciser in Python, an interactive test for the curses
# module. Currently, only the panel demos are ported.
import curses
from curses import panel
def wGetchar(win = None):
if win is None: win = stdscr
return win.getch()
def Getchar():
wGetchar()
#
# Panels tester
#
def wait_a_while():
if nap_msec == 1:
Getchar()
else:
curses.napms(nap_msec)
def saywhat(text):
stdscr.move(curses.LINES - 1, 0)
stdscr.clrtoeol()
stdscr.addstr(text)
def mkpanel(color, rows, cols, tly, tlx):
win = curses.newwin(rows, cols, tly, tlx)
pan = panel.new_panel(win)
if curses.has_colors():
if color == curses.COLOR_BLUE:
fg = curses.COLOR_WHITE
else:
fg = curses.COLOR_BLACK
bg = color
curses.init_pair(color, fg, bg)
win.bkgdset(ord(' '), curses.color_pair(color))
else:
win.bkgdset(ord(' '), curses.A_BOLD)
return pan
def pflush():
panel.update_panels()
curses.doupdate()
def fill_panel(pan):
win = pan.window()
num = pan.userptr()[1]
win.move(1, 1)
win.addstr("-pan%c-" % num)
win.clrtoeol()
win.box()
maxy, maxx = win.getmaxyx()
for y in range(2, maxy - 1):
for x in range(1, maxx - 1):
win.move(y, x)
win.addch(num)
def demo_panels(win):
global stdscr, nap_msec, mod
stdscr = win
nap_msec = 1
mod = ["test", "TEST", "(**)", "*()*", "<-->", "LAST"]
stdscr.refresh()
for y in range(0, curses.LINES - 1):
for x in range(0, curses.COLS):
stdscr.addstr("%d" % ((y + x) % 10))
for y in range(0, 1):
p1 = mkpanel(curses.COLOR_RED,
curses.LINES // 2 - 2,
curses.COLS // 8 + 1,
0,
0)
p1.set_userptr("p1")
p2 = mkpanel(curses.COLOR_GREEN,
curses.LINES // 2 + 1,
curses.COLS // 7,
curses.LINES // 4,
curses.COLS // 10)
p2.set_userptr("p2")
p3 = mkpanel(curses.COLOR_YELLOW,
curses.LINES // 4,
curses.COLS // 10,
curses.LINES // 2,
curses.COLS // 9)
p3.set_userptr("p3")
p4 = mkpanel(curses.COLOR_BLUE,
curses.LINES // 2 - 2,
curses.COLS // 8,
curses.LINES // 2 - 2,
curses.COLS // 3)
p4.set_userptr("p4")
p5 = mkpanel(curses.COLOR_MAGENTA,
curses.LINES // 2 - 2,
curses.COLS // 8,
curses.LINES // 2,
curses.COLS // 2 - 2)
p5.set_userptr("p5")
fill_panel(p1)
fill_panel(p2)
fill_panel(p3)
fill_panel(p4)
fill_panel(p5)
p4.hide()
p5.hide()
pflush()
saywhat("press any key to continue")
wait_a_while()
saywhat("h3 s1 s2 s4 s5;press any key to continue")
p1.move(0, 0)
p3.hide()
p1.show()
p2.show()
p4.show()
p5.show()
pflush()
wait_a_while()
saywhat("s1; press any key to continue")
p1.show()
pflush()
wait_a_while()
saywhat("s2; press any key to continue")
p2.show()
pflush()
wait_a_while()
saywhat("m2; press any key to continue")
p2.move(curses.LINES // 3 + 1, curses.COLS // 8)
pflush()
wait_a_while()
saywhat("s3; press any key to continue")
p3.show()
pflush()
wait_a_while()
saywhat("m3; press any key to continue")
p3.move(curses.LINES // 4 + 1, curses.COLS // 15)
pflush()
wait_a_while()
saywhat("b3; press any key to continue")
p3.bottom()
pflush()
wait_a_while()
saywhat("s4; press any key to continue")
p4.show()
pflush()
wait_a_while()
saywhat("s5; press any key to continue")
p5.show()
pflush()
wait_a_while()
saywhat("t3; press any key to continue")
p3.top()
pflush()
wait_a_while()
saywhat("t1; press any key to continue")
p1.show()
pflush()
wait_a_while()
saywhat("t2; press any key to continue")
p2.show()
pflush()
wait_a_while()
saywhat("t3; press any key to continue")
p3.show()
pflush()
wait_a_while()
saywhat("t4; press any key to continue")
p4.show()
pflush()
wait_a_while()
for itmp in range(0, 6):
w4 = p4.window()
w5 = p5.window()
saywhat("m4; press any key to continue")
w4.move(curses.LINES // 8, 1)
w4.addstr(mod[itmp])
p4.move(curses.LINES // 6, itmp * curses.COLS // 8)
w5.move(curses.LINES // 6, 1)
w5.addstr(mod[itmp])
pflush()
wait_a_while()
saywhat("m5; press any key to continue")
w4.move(curses.LINES // 6, 1)
w4.addstr(mod[itmp])
p5.move(curses.LINES // 3 - 1, itmp * 10 + 6)
w5.move(curses.LINES // 8, 1)
w5.addstr(mod[itmp])
pflush()
wait_a_while()
saywhat("m4; press any key to continue")
p4.move(curses.LINES // 6, (itmp + 1) * curses.COLS // 8)
pflush()
wait_a_while()
saywhat("t5; press any key to continue")
p5.top()
pflush()
wait_a_while()
saywhat("t2; press any key to continue")
p2.top()
pflush()
wait_a_while()
saywhat("t1; press any key to continue")
p1.top()
pflush()
wait_a_while()
saywhat("d2; press any key to continue")
del p2
pflush()
wait_a_while()
saywhat("h3; press any key to continue")
p3.hide()
pflush()
wait_a_while()
saywhat("d1; press any key to continue")
del p1
pflush()
wait_a_while()
saywhat("d4; press any key to continue")
del p4
pflush()
wait_a_while()
saywhat("d5; press any key to continue")
del p5
pflush()
wait_a_while()
if nap_msec == 1:
break
nap_msec = 100
#
# one fine day there'll be the menu at this place
#
curses.wrapper(demo_panels)

View File

@@ -1,94 +0,0 @@
#!/usr/bin/env python
#
# $Id$
#
# somebody should probably check the randrange()s...
import curses
from random import randrange
def next_j(j):
if j == 0:
j = 4
else:
j -= 1
if curses.has_colors():
z = randrange(0, 3)
color = curses.color_pair(z)
if z:
color = color | curses.A_BOLD
stdscr.attrset(color)
return j
def main(win):
# we know that the first argument from curses.wrapper() is stdscr.
# Initialize it globally for convenience.
global stdscr
stdscr = win
if curses.has_colors():
bg = curses.COLOR_BLACK
curses.init_pair(1, curses.COLOR_BLUE, bg)
curses.init_pair(2, curses.COLOR_CYAN, bg)
curses.nl()
curses.noecho()
# XXX curs_set() always returns ERR
# curses.curs_set(0)
stdscr.timeout(0)
c = curses.COLS - 4
r = curses.LINES - 4
xpos = [0] * c
ypos = [0] * r
for j in range(4, -1, -1):
xpos[j] = randrange(0, c) + 2
ypos[j] = randrange(0, r) + 2
j = 0
while True:
x = randrange(0, c) + 2
y = randrange(0, r) + 2
stdscr.addch(y, x, ord('.'))
stdscr.addch(ypos[j], xpos[j], ord('o'))
j = next_j(j)
stdscr.addch(ypos[j], xpos[j], ord('O'))
j = next_j(j)
stdscr.addch( ypos[j] - 1, xpos[j], ord('-'))
stdscr.addstr(ypos[j], xpos[j] - 1, "|.|")
stdscr.addch( ypos[j] + 1, xpos[j], ord('-'))
j = next_j(j)
stdscr.addch( ypos[j] - 2, xpos[j], ord('-'))
stdscr.addstr(ypos[j] - 1, xpos[j] - 1, "/ \\")
stdscr.addstr(ypos[j], xpos[j] - 2, "| O |")
stdscr.addstr(ypos[j] + 1, xpos[j] - 1, "\\ /")
stdscr.addch( ypos[j] + 2, xpos[j], ord('-'))
j = next_j(j)
stdscr.addch( ypos[j] - 2, xpos[j], ord(' '))
stdscr.addstr(ypos[j] - 1, xpos[j] - 1, " ")
stdscr.addstr(ypos[j], xpos[j] - 2, " ")
stdscr.addstr(ypos[j] + 1, xpos[j] - 1, " ")
stdscr.addch( ypos[j] + 2, xpos[j], ord(' '))
xpos[j] = x
ypos[j] = y
ch = stdscr.getch()
if ch == ord('q') or ch == ord('Q'):
return
elif ch == ord('s'):
stdscr.nodelay(0)
elif ch == ord(' '):
stdscr.nodelay(1)
curses.napms(50)
curses.wrapper(main)

View File

@@ -1,58 +0,0 @@
#! /usr/bin/env python
"""repeat <shell-command>
This simple program repeatedly (at 1-second intervals) executes the
shell command given on the command line and displays the output (or as
much of it as fits on the screen). It uses curses to paint each new
output on top of the old output, so that if nothing changes, the
screen doesn't change. This is handy to watch for changes in e.g. a
directory or process listing.
To end, hit Control-C.
"""
# Author: Guido van Rossum
# Disclaimer: there's a Linux program named 'watch' that does the same
# thing. Honestly, I didn't know of its existence when I wrote this!
# To do: add features until it has the same functionality as watch(1);
# then compare code size and development time.
import os
import sys
import time
import curses
def main():
if not sys.argv[1:]:
print __doc__
sys.exit(0)
cmd = " ".join(sys.argv[1:])
p = os.popen(cmd, "r")
text = p.read()
sts = p.close()
if sts:
print >>sys.stderr, "Exit code:", sts
sys.exit(sts)
w = curses.initscr()
try:
while True:
w.erase()
try:
w.addstr(text)
except curses.error:
pass
w.refresh()
time.sleep(1)
p = os.popen(cmd, "r")
text = p.read()
sts = p.close()
if sts:
print >>sys.stderr, "Exit code:", sts
sys.exit(sts)
finally:
curses.endwin()
main()

View File

@@ -1,147 +0,0 @@
#!/usr/bin/env python
#
# $Id$
#
# From tclock.c, Copyright Howard Jones <ha.jones@ic.ac.uk>, September 1994.
from math import *
import curses, time
ASPECT = 2.2
def sign(_x):
if _x < 0: return -1
return 1
def A2XY(angle, radius):
return (int(round(ASPECT * radius * sin(angle))),
int(round(radius * cos(angle))))
def plot(x, y, col):
stdscr.addch(y, x, col)
# draw a diagonal line using Bresenham's algorithm
def dline(pair, from_x, from_y, x2, y2, ch):
if curses.has_colors():
stdscr.attrset(curses.color_pair(pair))
dx = x2 - from_x
dy = y2 - from_y
ax = abs(dx * 2)
ay = abs(dy * 2)
sx = sign(dx)
sy = sign(dy)
x = from_x
y = from_y
if ax > ay:
d = ay - ax // 2
while True:
plot(x, y, ch)
if x == x2:
return
if d >= 0:
y += sy
d -= ax
x += sx
d += ay
else:
d = ax - ay // 2
while True:
plot(x, y, ch)
if y == y2:
return
if d >= 0:
x += sx
d -= ay
y += sy
d += ax
def main(win):
global stdscr
stdscr = win
lastbeep = -1
my_bg = curses.COLOR_BLACK
stdscr.nodelay(1)
stdscr.timeout(0)
# curses.curs_set(0)
if curses.has_colors():
curses.init_pair(1, curses.COLOR_RED, my_bg)
curses.init_pair(2, curses.COLOR_MAGENTA, my_bg)
curses.init_pair(3, curses.COLOR_GREEN, my_bg)
cx = (curses.COLS - 1) // 2
cy = curses.LINES // 2
ch = min( cy-1, int(cx // ASPECT) - 1)
mradius = (3 * ch) // 4
hradius = ch // 2
sradius = 5 * ch // 6
for i in range(0, 12):
sangle = (i + 1) * 2.0 * pi / 12.0
sdx, sdy = A2XY(sangle, sradius)
stdscr.addstr(cy - sdy, cx + sdx, "%d" % (i + 1))
stdscr.addstr(0, 0,
"ASCII Clock by Howard Jones <ha.jones@ic.ac.uk>, 1994")
sradius = max(sradius-4, 8)
while True:
curses.napms(1000)
tim = time.time()
t = time.localtime(tim)
hours = t[3] + t[4] / 60.0
if hours > 12.0:
hours -= 12.0
mangle = t[4] * 2 * pi / 60.0
mdx, mdy = A2XY(mangle, mradius)
hangle = hours * 2 * pi / 12.0
hdx, hdy = A2XY(hangle, hradius)
sangle = t[5] * 2 * pi / 60.0
sdx, sdy = A2XY(sangle, sradius)
dline(3, cx, cy, cx + mdx, cy - mdy, ord('#'))
stdscr.attrset(curses.A_REVERSE)
dline(2, cx, cy, cx + hdx, cy - hdy, ord('.'))
stdscr.attroff(curses.A_REVERSE)
if curses.has_colors():
stdscr.attrset(curses.color_pair(1))
plot(cx + sdx, cy - sdy, ord('O'))
if curses.has_colors():
stdscr.attrset(curses.color_pair(0))
stdscr.addstr(curses.LINES - 2, 0, time.ctime(tim))
stdscr.refresh()
if (t[5] % 5) == 0 and t[5] != lastbeep:
lastbeep = t[5]
curses.beep()
ch = stdscr.getch()
if ch == ord('q'):
return 0
plot(cx + sdx, cy - sdy, ord(' '))
dline(0, cx, cy, cx + hdx, cy - hdy, ord(' '))
dline(0, cx, cy, cx + mdx, cy - mdy, ord(' '))
curses.wrapper(main)

View File

@@ -1,906 +0,0 @@
# asciixmas
# December 1989 Larry Bartz Indianapolis, IN
#
# $Id$
#
# I'm dreaming of an ascii character-based monochrome Christmas,
# Just like the ones I used to know!
# Via a full duplex communications channel,
# At 9600 bits per second,
# Even though it's kinda slow.
#
# I'm dreaming of an ascii character-based monochrome Christmas,
# With ev'ry C program I write!
# May your screen be merry and bright!
# And may all your Christmases be amber or green,
# (for reduced eyestrain and improved visibility)!
#
#
# Notes on the Python version:
# I used a couple of `try...except curses.error' to get around some functions
# returning ERR. The errors come from using wrapping functions to fill
# windows to the last character cell. The C version doesn't have this problem,
# it simply ignores any return values.
#
import curses
import sys
FROMWHO = "Thomas Gellekum <tg@FreeBSD.org>"
def set_color(win, color):
if curses.has_colors():
n = color + 1
curses.init_pair(n, color, my_bg)
win.attroff(curses.A_COLOR)
win.attron(curses.color_pair(n))
def unset_color(win):
if curses.has_colors():
win.attrset(curses.color_pair(0))
def look_out(msecs):
curses.napms(msecs)
if stdscr.getch() != -1:
curses.beep()
sys.exit(0)
def boxit():
for y in range(0, 20):
stdscr.addch(y, 7, ord('|'))
for x in range(8, 80):
stdscr.addch(19, x, ord('_'))
for x in range(0, 80):
stdscr.addch(22, x, ord('_'))
return
def seas():
stdscr.addch(4, 1, ord('S'))
stdscr.addch(6, 1, ord('E'))
stdscr.addch(8, 1, ord('A'))
stdscr.addch(10, 1, ord('S'))
stdscr.addch(12, 1, ord('O'))
stdscr.addch(14, 1, ord('N'))
stdscr.addch(16, 1, ord("'"))
stdscr.addch(18, 1, ord('S'))
return
def greet():
stdscr.addch(3, 5, ord('G'))
stdscr.addch(5, 5, ord('R'))
stdscr.addch(7, 5, ord('E'))
stdscr.addch(9, 5, ord('E'))
stdscr.addch(11, 5, ord('T'))
stdscr.addch(13, 5, ord('I'))
stdscr.addch(15, 5, ord('N'))
stdscr.addch(17, 5, ord('G'))
stdscr.addch(19, 5, ord('S'))
return
def fromwho():
stdscr.addstr(21, 13, FROMWHO)
return
def tree():
set_color(treescrn, curses.COLOR_GREEN)
treescrn.addch(1, 11, ord('/'))
treescrn.addch(2, 11, ord('/'))
treescrn.addch(3, 10, ord('/'))
treescrn.addch(4, 9, ord('/'))
treescrn.addch(5, 9, ord('/'))
treescrn.addch(6, 8, ord('/'))
treescrn.addch(7, 7, ord('/'))
treescrn.addch(8, 6, ord('/'))
treescrn.addch(9, 6, ord('/'))
treescrn.addch(10, 5, ord('/'))
treescrn.addch(11, 3, ord('/'))
treescrn.addch(12, 2, ord('/'))
treescrn.addch(1, 13, ord('\\'))
treescrn.addch(2, 13, ord('\\'))
treescrn.addch(3, 14, ord('\\'))
treescrn.addch(4, 15, ord('\\'))
treescrn.addch(5, 15, ord('\\'))
treescrn.addch(6, 16, ord('\\'))
treescrn.addch(7, 17, ord('\\'))
treescrn.addch(8, 18, ord('\\'))
treescrn.addch(9, 18, ord('\\'))
treescrn.addch(10, 19, ord('\\'))
treescrn.addch(11, 21, ord('\\'))
treescrn.addch(12, 22, ord('\\'))
treescrn.addch(4, 10, ord('_'))
treescrn.addch(4, 14, ord('_'))
treescrn.addch(8, 7, ord('_'))
treescrn.addch(8, 17, ord('_'))
treescrn.addstr(13, 0, "//////////// \\\\\\\\\\\\\\\\\\\\\\\\")
treescrn.addstr(14, 11, "| |")
treescrn.addstr(15, 11, "|_|")
unset_color(treescrn)
treescrn.refresh()
w_del_msg.refresh()
return
def balls():
treescrn.overlay(treescrn2)
set_color(treescrn2, curses.COLOR_BLUE)
treescrn2.addch(3, 9, ord('@'))
treescrn2.addch(3, 15, ord('@'))
treescrn2.addch(4, 8, ord('@'))
treescrn2.addch(4, 16, ord('@'))
treescrn2.addch(5, 7, ord('@'))
treescrn2.addch(5, 17, ord('@'))
treescrn2.addch(7, 6, ord('@'))
treescrn2.addch(7, 18, ord('@'))
treescrn2.addch(8, 5, ord('@'))
treescrn2.addch(8, 19, ord('@'))
treescrn2.addch(10, 4, ord('@'))
treescrn2.addch(10, 20, ord('@'))
treescrn2.addch(11, 2, ord('@'))
treescrn2.addch(11, 22, ord('@'))
treescrn2.addch(12, 1, ord('@'))
treescrn2.addch(12, 23, ord('@'))
unset_color(treescrn2)
treescrn2.refresh()
w_del_msg.refresh()
return
def star():
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
set_color(treescrn2, curses.COLOR_YELLOW)
treescrn2.addch(0, 12, ord('*'))
treescrn2.standend()
unset_color(treescrn2)
treescrn2.refresh()
w_del_msg.refresh()
return
def strng1():
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
set_color(treescrn2, curses.COLOR_WHITE)
treescrn2.addch(3, 13, ord('\''))
treescrn2.addch(3, 12, ord(':'))
treescrn2.addch(3, 11, ord('.'))
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
unset_color(treescrn2)
treescrn2.refresh()
w_del_msg.refresh()
return
def strng2():
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
set_color(treescrn2, curses.COLOR_WHITE)
treescrn2.addch(5, 14, ord('\''))
treescrn2.addch(5, 13, ord(':'))
treescrn2.addch(5, 12, ord('.'))
treescrn2.addch(5, 11, ord(','))
treescrn2.addch(6, 10, ord('\''))
treescrn2.addch(6, 9, ord(':'))
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
unset_color(treescrn2)
treescrn2.refresh()
w_del_msg.refresh()
return
def strng3():
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
set_color(treescrn2, curses.COLOR_WHITE)
treescrn2.addch(7, 16, ord('\''))
treescrn2.addch(7, 15, ord(':'))
treescrn2.addch(7, 14, ord('.'))
treescrn2.addch(7, 13, ord(','))
treescrn2.addch(8, 12, ord('\''))
treescrn2.addch(8, 11, ord(':'))
treescrn2.addch(8, 10, ord('.'))
treescrn2.addch(8, 9, ord(','))
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
unset_color(treescrn2)
treescrn2.refresh()
w_del_msg.refresh()
return
def strng4():
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
set_color(treescrn2, curses.COLOR_WHITE)
treescrn2.addch(9, 17, ord('\''))
treescrn2.addch(9, 16, ord(':'))
treescrn2.addch(9, 15, ord('.'))
treescrn2.addch(9, 14, ord(','))
treescrn2.addch(10, 13, ord('\''))
treescrn2.addch(10, 12, ord(':'))
treescrn2.addch(10, 11, ord('.'))
treescrn2.addch(10, 10, ord(','))
treescrn2.addch(11, 9, ord('\''))
treescrn2.addch(11, 8, ord(':'))
treescrn2.addch(11, 7, ord('.'))
treescrn2.addch(11, 6, ord(','))
treescrn2.addch(12, 5, ord('\''))
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
unset_color(treescrn2)
treescrn2.refresh()
w_del_msg.refresh()
return
def strng5():
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
set_color(treescrn2, curses.COLOR_WHITE)
treescrn2.addch(11, 19, ord('\''))
treescrn2.addch(11, 18, ord(':'))
treescrn2.addch(11, 17, ord('.'))
treescrn2.addch(11, 16, ord(','))
treescrn2.addch(12, 15, ord('\''))
treescrn2.addch(12, 14, ord(':'))
treescrn2.addch(12, 13, ord('.'))
treescrn2.addch(12, 12, ord(','))
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
unset_color(treescrn2)
# save a fully lit tree
treescrn2.overlay(treescrn)
treescrn2.refresh()
w_del_msg.refresh()
return
def blinkit():
treescrn8.touchwin()
for cycle in range(5):
if cycle == 0:
treescrn3.overlay(treescrn8)
treescrn8.refresh()
w_del_msg.refresh()
break
elif cycle == 1:
treescrn4.overlay(treescrn8)
treescrn8.refresh()
w_del_msg.refresh()
break
elif cycle == 2:
treescrn5.overlay(treescrn8)
treescrn8.refresh()
w_del_msg.refresh()
break
elif cycle == 3:
treescrn6.overlay(treescrn8)
treescrn8.refresh()
w_del_msg.refresh()
break
elif cycle == 4:
treescrn7.overlay(treescrn8)
treescrn8.refresh()
w_del_msg.refresh()
break
treescrn8.touchwin()
# ALL ON
treescrn.overlay(treescrn8)
treescrn8.refresh()
w_del_msg.refresh()
return
def deer_step(win, y, x):
win.mvwin(y, x)
win.refresh()
w_del_msg.refresh()
look_out(5)
def reindeer():
y_pos = 0
for x_pos in range(70, 62, -1):
if x_pos < 66: y_pos = 1
for looper in range(0, 4):
dotdeer0.addch(y_pos, x_pos, ord('.'))
dotdeer0.refresh()
w_del_msg.refresh()
dotdeer0.erase()
dotdeer0.refresh()
w_del_msg.refresh()
look_out(50)
y_pos = 2
for x_pos in range(x_pos - 1, 50, -1):
for looper in range(0, 4):
if x_pos < 56:
y_pos = 3
try:
stardeer0.addch(y_pos, x_pos, ord('*'))
except curses.error:
pass
stardeer0.refresh()
w_del_msg.refresh()
stardeer0.erase()
stardeer0.refresh()
w_del_msg.refresh()
else:
dotdeer0.addch(y_pos, x_pos, ord('*'))
dotdeer0.refresh()
w_del_msg.refresh()
dotdeer0.erase()
dotdeer0.refresh()
w_del_msg.refresh()
x_pos = 58
for y_pos in range(2, 5):
lildeer0.touchwin()
lildeer0.refresh()
w_del_msg.refresh()
for looper in range(0, 4):
deer_step(lildeer3, y_pos, x_pos)
deer_step(lildeer2, y_pos, x_pos)
deer_step(lildeer1, y_pos, x_pos)
deer_step(lildeer2, y_pos, x_pos)
deer_step(lildeer3, y_pos, x_pos)
lildeer0.touchwin()
lildeer0.refresh()
w_del_msg.refresh()
x_pos -= 2
x_pos = 35
for y_pos in range(5, 10):
middeer0.touchwin()
middeer0.refresh()
w_del_msg.refresh()
for looper in range(2):
deer_step(middeer3, y_pos, x_pos)
deer_step(middeer2, y_pos, x_pos)
deer_step(middeer1, y_pos, x_pos)
deer_step(middeer2, y_pos, x_pos)
deer_step(middeer3, y_pos, x_pos)
middeer0.touchwin()
middeer0.refresh()
w_del_msg.refresh()
x_pos -= 3
look_out(300)
y_pos = 1
for x_pos in range(8, 16):
deer_step(bigdeer4, y_pos, x_pos)
deer_step(bigdeer3, y_pos, x_pos)
deer_step(bigdeer2, y_pos, x_pos)
deer_step(bigdeer1, y_pos, x_pos)
deer_step(bigdeer2, y_pos, x_pos)
deer_step(bigdeer3, y_pos, x_pos)
deer_step(bigdeer4, y_pos, x_pos)
deer_step(bigdeer0, y_pos, x_pos)
x_pos -= 1
for looper in range(0, 6):
deer_step(lookdeer4, y_pos, x_pos)
deer_step(lookdeer3, y_pos, x_pos)
deer_step(lookdeer2, y_pos, x_pos)
deer_step(lookdeer1, y_pos, x_pos)
deer_step(lookdeer2, y_pos, x_pos)
deer_step(lookdeer3, y_pos, x_pos)
deer_step(lookdeer4, y_pos, x_pos)
deer_step(lookdeer0, y_pos, x_pos)
for y_pos in range(y_pos, 10):
for looper in range(0, 2):
deer_step(bigdeer4, y_pos, x_pos)
deer_step(bigdeer3, y_pos, x_pos)
deer_step(bigdeer2, y_pos, x_pos)
deer_step(bigdeer1, y_pos, x_pos)
deer_step(bigdeer2, y_pos, x_pos)
deer_step(bigdeer3, y_pos, x_pos)
deer_step(bigdeer4, y_pos, x_pos)
deer_step(bigdeer0, y_pos, x_pos)
y_pos -= 1
deer_step(lookdeer3, y_pos, x_pos)
return
def main(win):
global stdscr
stdscr = win
global my_bg, y_pos, x_pos
global treescrn, treescrn2, treescrn3, treescrn4
global treescrn5, treescrn6, treescrn7, treescrn8
global dotdeer0, stardeer0
global lildeer0, lildeer1, lildeer2, lildeer3
global middeer0, middeer1, middeer2, middeer3
global bigdeer0, bigdeer1, bigdeer2, bigdeer3, bigdeer4
global lookdeer0, lookdeer1, lookdeer2, lookdeer3, lookdeer4
global w_holiday, w_del_msg
my_bg = curses.COLOR_BLACK
# curses.curs_set(0)
treescrn = curses.newwin(16, 27, 3, 53)
treescrn2 = curses.newwin(16, 27, 3, 53)
treescrn3 = curses.newwin(16, 27, 3, 53)
treescrn4 = curses.newwin(16, 27, 3, 53)
treescrn5 = curses.newwin(16, 27, 3, 53)
treescrn6 = curses.newwin(16, 27, 3, 53)
treescrn7 = curses.newwin(16, 27, 3, 53)
treescrn8 = curses.newwin(16, 27, 3, 53)
dotdeer0 = curses.newwin(3, 71, 0, 8)
stardeer0 = curses.newwin(4, 56, 0, 8)
lildeer0 = curses.newwin(7, 53, 0, 8)
lildeer1 = curses.newwin(2, 4, 0, 0)
lildeer2 = curses.newwin(2, 4, 0, 0)
lildeer3 = curses.newwin(2, 4, 0, 0)
middeer0 = curses.newwin(15, 42, 0, 8)
middeer1 = curses.newwin(3, 7, 0, 0)
middeer2 = curses.newwin(3, 7, 0, 0)
middeer3 = curses.newwin(3, 7, 0, 0)
bigdeer0 = curses.newwin(10, 23, 0, 0)
bigdeer1 = curses.newwin(10, 23, 0, 0)
bigdeer2 = curses.newwin(10, 23, 0, 0)
bigdeer3 = curses.newwin(10, 23, 0, 0)
bigdeer4 = curses.newwin(10, 23, 0, 0)
lookdeer0 = curses.newwin(10, 25, 0, 0)
lookdeer1 = curses.newwin(10, 25, 0, 0)
lookdeer2 = curses.newwin(10, 25, 0, 0)
lookdeer3 = curses.newwin(10, 25, 0, 0)
lookdeer4 = curses.newwin(10, 25, 0, 0)
w_holiday = curses.newwin(1, 27, 3, 27)
w_del_msg = curses.newwin(1, 20, 23, 60)
try:
w_del_msg.addstr(0, 0, "Hit any key to quit")
except curses.error:
pass
try:
w_holiday.addstr(0, 0, "H A P P Y H O L I D A Y S")
except curses.error:
pass
# set up the windows for our various reindeer
lildeer1.addch(0, 0, ord('V'))
lildeer1.addch(1, 0, ord('@'))
lildeer1.addch(1, 1, ord('<'))
lildeer1.addch(1, 2, ord('>'))
try:
lildeer1.addch(1, 3, ord('~'))
except curses.error:
pass
lildeer2.addch(0, 0, ord('V'))
lildeer2.addch(1, 0, ord('@'))
lildeer2.addch(1, 1, ord('|'))
lildeer2.addch(1, 2, ord('|'))
try:
lildeer2.addch(1, 3, ord('~'))
except curses.error:
pass
lildeer3.addch(0, 0, ord('V'))
lildeer3.addch(1, 0, ord('@'))
lildeer3.addch(1, 1, ord('>'))
lildeer3.addch(1, 2, ord('<'))
try:
lildeer2.addch(1, 3, ord('~')) # XXX
except curses.error:
pass
middeer1.addch(0, 2, ord('y'))
middeer1.addch(0, 3, ord('y'))
middeer1.addch(1, 2, ord('0'))
middeer1.addch(1, 3, ord('('))
middeer1.addch(1, 4, ord('='))
middeer1.addch(1, 5, ord(')'))
middeer1.addch(1, 6, ord('~'))
middeer1.addch(2, 3, ord('\\'))
middeer1.addch(2, 5, ord('/'))
middeer2.addch(0, 2, ord('y'))
middeer2.addch(0, 3, ord('y'))
middeer2.addch(1, 2, ord('0'))
middeer2.addch(1, 3, ord('('))
middeer2.addch(1, 4, ord('='))
middeer2.addch(1, 5, ord(')'))
middeer2.addch(1, 6, ord('~'))
middeer2.addch(2, 3, ord('|'))
middeer2.addch(2, 5, ord('|'))
middeer3.addch(0, 2, ord('y'))
middeer3.addch(0, 3, ord('y'))
middeer3.addch(1, 2, ord('0'))
middeer3.addch(1, 3, ord('('))
middeer3.addch(1, 4, ord('='))
middeer3.addch(1, 5, ord(')'))
middeer3.addch(1, 6, ord('~'))
middeer3.addch(2, 3, ord('/'))
middeer3.addch(2, 5, ord('\\'))
bigdeer1.addch(0, 17, ord('\\'))
bigdeer1.addch(0, 18, ord('/'))
bigdeer1.addch(0, 19, ord('\\'))
bigdeer1.addch(0, 20, ord('/'))
bigdeer1.addch(1, 18, ord('\\'))
bigdeer1.addch(1, 20, ord('/'))
bigdeer1.addch(2, 19, ord('|'))
bigdeer1.addch(2, 20, ord('_'))
bigdeer1.addch(3, 18, ord('/'))
bigdeer1.addch(3, 19, ord('^'))
bigdeer1.addch(3, 20, ord('0'))
bigdeer1.addch(3, 21, ord('\\'))
bigdeer1.addch(4, 17, ord('/'))
bigdeer1.addch(4, 18, ord('/'))
bigdeer1.addch(4, 19, ord('\\'))
bigdeer1.addch(4, 22, ord('\\'))
bigdeer1.addstr(5, 7, "^~~~~~~~~// ~~U")
bigdeer1.addstr(6, 7, "( \\_____( /") # ))
bigdeer1.addstr(7, 8, "( ) /")
bigdeer1.addstr(8, 9, "\\\\ /")
bigdeer1.addstr(9, 11, "\\>/>")
bigdeer2.addch(0, 17, ord('\\'))
bigdeer2.addch(0, 18, ord('/'))
bigdeer2.addch(0, 19, ord('\\'))
bigdeer2.addch(0, 20, ord('/'))
bigdeer2.addch(1, 18, ord('\\'))
bigdeer2.addch(1, 20, ord('/'))
bigdeer2.addch(2, 19, ord('|'))
bigdeer2.addch(2, 20, ord('_'))
bigdeer2.addch(3, 18, ord('/'))
bigdeer2.addch(3, 19, ord('^'))
bigdeer2.addch(3, 20, ord('0'))
bigdeer2.addch(3, 21, ord('\\'))
bigdeer2.addch(4, 17, ord('/'))
bigdeer2.addch(4, 18, ord('/'))
bigdeer2.addch(4, 19, ord('\\'))
bigdeer2.addch(4, 22, ord('\\'))
bigdeer2.addstr(5, 7, "^~~~~~~~~// ~~U")
bigdeer2.addstr(6, 7, "(( )____( /") # ))
bigdeer2.addstr(7, 7, "( / |")
bigdeer2.addstr(8, 8, "\\/ |")
bigdeer2.addstr(9, 9, "|> |>")
bigdeer3.addch(0, 17, ord('\\'))
bigdeer3.addch(0, 18, ord('/'))
bigdeer3.addch(0, 19, ord('\\'))
bigdeer3.addch(0, 20, ord('/'))
bigdeer3.addch(1, 18, ord('\\'))
bigdeer3.addch(1, 20, ord('/'))
bigdeer3.addch(2, 19, ord('|'))
bigdeer3.addch(2, 20, ord('_'))
bigdeer3.addch(3, 18, ord('/'))
bigdeer3.addch(3, 19, ord('^'))
bigdeer3.addch(3, 20, ord('0'))
bigdeer3.addch(3, 21, ord('\\'))
bigdeer3.addch(4, 17, ord('/'))
bigdeer3.addch(4, 18, ord('/'))
bigdeer3.addch(4, 19, ord('\\'))
bigdeer3.addch(4, 22, ord('\\'))
bigdeer3.addstr(5, 7, "^~~~~~~~~// ~~U")
bigdeer3.addstr(6, 6, "( ()_____( /") # ))
bigdeer3.addstr(7, 6, "/ / /")
bigdeer3.addstr(8, 5, "|/ \\")
bigdeer3.addstr(9, 5, "/> \\>")
bigdeer4.addch(0, 17, ord('\\'))
bigdeer4.addch(0, 18, ord('/'))
bigdeer4.addch(0, 19, ord('\\'))
bigdeer4.addch(0, 20, ord('/'))
bigdeer4.addch(1, 18, ord('\\'))
bigdeer4.addch(1, 20, ord('/'))
bigdeer4.addch(2, 19, ord('|'))
bigdeer4.addch(2, 20, ord('_'))
bigdeer4.addch(3, 18, ord('/'))
bigdeer4.addch(3, 19, ord('^'))
bigdeer4.addch(3, 20, ord('0'))
bigdeer4.addch(3, 21, ord('\\'))
bigdeer4.addch(4, 17, ord('/'))
bigdeer4.addch(4, 18, ord('/'))
bigdeer4.addch(4, 19, ord('\\'))
bigdeer4.addch(4, 22, ord('\\'))
bigdeer4.addstr(5, 7, "^~~~~~~~~// ~~U")
bigdeer4.addstr(6, 6, "( )______( /") # )
bigdeer4.addstr(7, 5, "(/ \\") # )
bigdeer4.addstr(8, 0, "v___= ----^")
lookdeer1.addstr(0, 16, "\\/ \\/")
lookdeer1.addstr(1, 17, "\\Y/ \\Y/")
lookdeer1.addstr(2, 19, "\\=/")
lookdeer1.addstr(3, 17, "^\\o o/^")
lookdeer1.addstr(4, 17, "//( )")
lookdeer1.addstr(5, 7, "^~~~~~~~~// \\O/")
lookdeer1.addstr(6, 7, "( \\_____( /") # ))
lookdeer1.addstr(7, 8, "( ) /")
lookdeer1.addstr(8, 9, "\\\\ /")
lookdeer1.addstr(9, 11, "\\>/>")
lookdeer2.addstr(0, 16, "\\/ \\/")
lookdeer2.addstr(1, 17, "\\Y/ \\Y/")
lookdeer2.addstr(2, 19, "\\=/")
lookdeer2.addstr(3, 17, "^\\o o/^")
lookdeer2.addstr(4, 17, "//( )")
lookdeer2.addstr(5, 7, "^~~~~~~~~// \\O/")
lookdeer2.addstr(6, 7, "(( )____( /") # ))
lookdeer2.addstr(7, 7, "( / |")
lookdeer2.addstr(8, 8, "\\/ |")
lookdeer2.addstr(9, 9, "|> |>")
lookdeer3.addstr(0, 16, "\\/ \\/")
lookdeer3.addstr(1, 17, "\\Y/ \\Y/")
lookdeer3.addstr(2, 19, "\\=/")
lookdeer3.addstr(3, 17, "^\\o o/^")
lookdeer3.addstr(4, 17, "//( )")
lookdeer3.addstr(5, 7, "^~~~~~~~~// \\O/")
lookdeer3.addstr(6, 6, "( ()_____( /") # ))
lookdeer3.addstr(7, 6, "/ / /")
lookdeer3.addstr(8, 5, "|/ \\")
lookdeer3.addstr(9, 5, "/> \\>")
lookdeer4.addstr(0, 16, "\\/ \\/")
lookdeer4.addstr(1, 17, "\\Y/ \\Y/")
lookdeer4.addstr(2, 19, "\\=/")
lookdeer4.addstr(3, 17, "^\\o o/^")
lookdeer4.addstr(4, 17, "//( )")
lookdeer4.addstr(5, 7, "^~~~~~~~~// \\O/")
lookdeer4.addstr(6, 6, "( )______( /") # )
lookdeer4.addstr(7, 5, "(/ \\") # )
lookdeer4.addstr(8, 0, "v___= ----^")
###############################################
curses.cbreak()
stdscr.nodelay(1)
while 1:
stdscr.clear()
treescrn.erase()
w_del_msg.touchwin()
treescrn.touchwin()
treescrn2.erase()
treescrn2.touchwin()
treescrn8.erase()
treescrn8.touchwin()
stdscr.refresh()
look_out(150)
boxit()
stdscr.refresh()
look_out(150)
seas()
stdscr.refresh()
greet()
stdscr.refresh()
look_out(150)
fromwho()
stdscr.refresh()
look_out(150)
tree()
look_out(150)
balls()
look_out(150)
star()
look_out(150)
strng1()
strng2()
strng3()
strng4()
strng5()
# set up the windows for our blinking trees
#
# treescrn3
treescrn.overlay(treescrn3)
# balls
treescrn3.addch(4, 18, ord(' '))
treescrn3.addch(7, 6, ord(' '))
treescrn3.addch(8, 19, ord(' '))
treescrn3.addch(11, 22, ord(' '))
# star
treescrn3.addch(0, 12, ord('*'))
# strng1
treescrn3.addch(3, 11, ord(' '))
# strng2
treescrn3.addch(5, 13, ord(' '))
treescrn3.addch(6, 10, ord(' '))
# strng3
treescrn3.addch(7, 16, ord(' '))
treescrn3.addch(7, 14, ord(' '))
# strng4
treescrn3.addch(10, 13, ord(' '))
treescrn3.addch(10, 10, ord(' '))
treescrn3.addch(11, 8, ord(' '))
# strng5
treescrn3.addch(11, 18, ord(' '))
treescrn3.addch(12, 13, ord(' '))
# treescrn4
treescrn.overlay(treescrn4)
# balls
treescrn4.addch(3, 9, ord(' '))
treescrn4.addch(4, 16, ord(' '))
treescrn4.addch(7, 6, ord(' '))
treescrn4.addch(8, 19, ord(' '))
treescrn4.addch(11, 2, ord(' '))
treescrn4.addch(12, 23, ord(' '))
# star
treescrn4.standout()
treescrn4.addch(0, 12, ord('*'))
treescrn4.standend()
# strng1
treescrn4.addch(3, 13, ord(' '))
# strng2
# strng3
treescrn4.addch(7, 15, ord(' '))
treescrn4.addch(8, 11, ord(' '))
# strng4
treescrn4.addch(9, 16, ord(' '))
treescrn4.addch(10, 12, ord(' '))
treescrn4.addch(11, 8, ord(' '))
# strng5
treescrn4.addch(11, 18, ord(' '))
treescrn4.addch(12, 14, ord(' '))
# treescrn5
treescrn.overlay(treescrn5)
# balls
treescrn5.addch(3, 15, ord(' '))
treescrn5.addch(10, 20, ord(' '))
treescrn5.addch(12, 1, ord(' '))
# star
treescrn5.addch(0, 12, ord(' '))
# strng1
treescrn5.addch(3, 11, ord(' '))
# strng2
treescrn5.addch(5, 12, ord(' '))
# strng3
treescrn5.addch(7, 14, ord(' '))
treescrn5.addch(8, 10, ord(' '))
# strng4
treescrn5.addch(9, 15, ord(' '))
treescrn5.addch(10, 11, ord(' '))
treescrn5.addch(11, 7, ord(' '))
# strng5
treescrn5.addch(11, 17, ord(' '))
treescrn5.addch(12, 13, ord(' '))
# treescrn6
treescrn.overlay(treescrn6)
# balls
treescrn6.addch(6, 7, ord(' '))
treescrn6.addch(7, 18, ord(' '))
treescrn6.addch(10, 4, ord(' '))
treescrn6.addch(11, 23, ord(' '))
# star
treescrn6.standout()
treescrn6.addch(0, 12, ord('*'))
treescrn6.standend()
# strng1
# strng2
treescrn6.addch(5, 11, ord(' '))
# strng3
treescrn6.addch(7, 13, ord(' '))
treescrn6.addch(8, 9, ord(' '))
# strng4
treescrn6.addch(9, 14, ord(' '))
treescrn6.addch(10, 10, ord(' '))
treescrn6.addch(11, 6, ord(' '))
# strng5
treescrn6.addch(11, 16, ord(' '))
treescrn6.addch(12, 12, ord(' '))
# treescrn7
treescrn.overlay(treescrn7)
# balls
treescrn7.addch(3, 15, ord(' '))
treescrn7.addch(6, 7, ord(' '))
treescrn7.addch(7, 18, ord(' '))
treescrn7.addch(10, 4, ord(' '))
treescrn7.addch(11, 22, ord(' '))
# star
treescrn7.addch(0, 12, ord('*'))
# strng1
treescrn7.addch(3, 12, ord(' '))
# strng2
treescrn7.addch(5, 13, ord(' '))
treescrn7.addch(6, 9, ord(' '))
# strng3
treescrn7.addch(7, 15, ord(' '))
treescrn7.addch(8, 11, ord(' '))
# strng4
treescrn7.addch(9, 16, ord(' '))
treescrn7.addch(10, 12, ord(' '))
treescrn7.addch(11, 8, ord(' '))
# strng5
treescrn7.addch(11, 18, ord(' '))
treescrn7.addch(12, 14, ord(' '))
look_out(150)
reindeer()
w_holiday.touchwin()
w_holiday.refresh()
w_del_msg.refresh()
look_out(500)
for i in range(0, 20):
blinkit()
curses.wrapper(main)

View File

@@ -0,0 +1 @@
from main import main

View File

@@ -103,7 +103,7 @@ class BaseContent(object):
if isinstance(comment, praw.objects.MoreComments): if isinstance(comment, praw.objects.MoreComments):
data['type'] = 'MoreComments' data['type'] = 'MoreComments'
data['count'] = comment.count data['count'] = comment.count
data['body'] = 'More comments [{}]'.format(comment.count) data['body'] = 'More comments'.format(comment.count)
else: else:
data['type'] = 'Comment' data['type'] = 'Comment'
data['body'] = clean(comment.body) data['body'] = clean(comment.body)
@@ -112,6 +112,10 @@ class BaseContent(object):
data['author'] = (clean(comment.author.name) if data['author'] = (clean(comment.author.name) if
getattr(comment, 'author') else '[deleted]') getattr(comment, 'author') else '[deleted]')
sub_author = (clean(comment.submission.author.name) if
getattr(comment.submission, 'author') else '[deleted]')
data['is_author'] = (data['author'] == sub_author)
return data return data
@staticmethod @staticmethod
@@ -157,7 +161,7 @@ class SubmissionContent(BaseContent):
self.max_indent_level = max_indent_level self.max_indent_level = max_indent_level
self._loader = loader self._loader = loader
self._submissin = submission self._submission = submission
self._submission_data = self.strip_praw_submission(submission) self._submission_data = self.strip_praw_submission(submission)
self.name = self._submission_data['permalink'] self.name = self._submission_data['permalink']
with self._loader(): with self._loader():
@@ -184,7 +188,7 @@ class SubmissionContent(BaseContent):
def reset(self): def reset(self):
self._submissin.refresh() self._submission.refresh()
self._submission_data = self.strip_praw_submission(submission) self._submission_data = self.strip_praw_submission(submission)
self.name = self._submission_data['permalink'] self.name = self._submission_data['permalink']
comments = self.flatten_comments(submission.comments) comments = self.flatten_comments(submission.comments)

View File

@@ -10,12 +10,14 @@ from submission import SubmissionPage
parser = argparse.ArgumentParser(description='Reddit Terminal Viewer') parser = argparse.ArgumentParser(description='Reddit Terminal Viewer')
parser.add_argument('-s', dest='subreddit', default='front', help='subreddit name') parser.add_argument('-s', dest='subreddit', default='front', help='subreddit name')
parser.add_argument('-l', dest='link', help='full link to a submission') parser.add_argument('-l', dest='link', help='full link to a submission')
group = parser.add_argument_group('authentication (optional)') group = parser.add_argument_group('authentication (optional)')
group.add_argument('-u', dest='username', help='reddit username') group.add_argument('-u', dest='username', help='reddit username')
group.add_argument('-p', dest='password', help='reddit password') group.add_argument('-p', dest='password', help='reddit password')
group.add_argument('--debug', action='store_true')
def main(args): def main():
args = parser.parse_args()
try: try:
reddit = praw.Reddit(user_agent='reddit terminal viewer v0.0') reddit = praw.Reddit(user_agent='reddit terminal viewer v0.0')
@@ -46,13 +48,6 @@ def main(args):
except SubredditNameError as e: except SubredditNameError as e:
print 'Could not reach subreddit: {}'.format(e.name) print 'Could not reach subreddit: {}'.format(e.name)
# except Exception:
# if not args.debug:
# print 'Unhandled exception'
# else:
# raise
if __name__ == '__main__': if __name__ == '__main__':
main()
args = parser.parse_args()
main(args)

View File

@@ -1,5 +1,7 @@
import curses import curses
from utils import Color
class Navigator(object): class Navigator(object):
""" """
Handles math behind cursor movement and screen paging. Handles math behind cursor movement and screen paging.
@@ -139,7 +141,9 @@ class BasePage(object):
n_rows, n_cols = self._header_window.getmaxyx() n_rows, n_cols = self._header_window.getmaxyx()
self._header_window.erase() self._header_window.erase()
self._header_window.addnstr(0, 0, self.content.name, n_cols-1) attr = curses.A_REVERSE | curses.A_BOLD | Color.RED
self._header_window.addnstr(0, 0, self.content.name, n_cols-1, attr)
self._header_window.refresh()
def _draw_content(self): def _draw_content(self):
""" """
@@ -164,8 +168,8 @@ class BasePage(object):
start = current_row - window_rows if inverted else current_row start = current_row - window_rows if inverted else current_row
subwindow = self._content_window.derwin( subwindow = self._content_window.derwin(
window_rows, window_cols, start, data['offset']) window_rows, window_cols, start, data['offset'])
self.draw_item(subwindow, data, inverted) attr = self.draw_item(subwindow, data, inverted)
self._subwindows.append(subwindow) self._subwindows.append((subwindow, attr))
available_rows -= (window_rows + 1) # Add one for the blank line available_rows -= (window_rows + 1) # Add one for the blank line
current_row += step * (window_rows + 1) current_row += step * (window_rows + 1)
if available_rows <= 0: if available_rows <= 0:
@@ -188,13 +192,16 @@ class BasePage(object):
self.add_cursor() self.add_cursor()
def _edit_cursor(self, attribute): def _edit_cursor(self, attribute=None):
# Don't allow the cursor to go below page index 0 # Don't allow the cursor to go below page index 0
if self.nav.absolute_index < 0: if self.nav.absolute_index < 0:
return return
window = self._subwindows[self.nav.cursor_index] # TODO: attach attr to data[attr] or something
window, attr = self._subwindows[self.nav.cursor_index]
if attr is not None:
attribute |= attr
n_rows, _ = window.getmaxyx() n_rows, _ = window.getmaxyx()
for row in xrange(n_rows): for row in xrange(n_rows):

View File

@@ -3,7 +3,7 @@ import sys
from content import SubmissionContent from content import SubmissionContent
from page import BasePage from page import BasePage
from utils import LoadScreen from utils import LoadScreen, Color
class SubmissionPage(BasePage): class SubmissionPage(BasePage):
@@ -70,51 +70,64 @@ class SubmissionPage(BasePage):
def draw_item(self, win, data, inverted=False): def draw_item(self, win, data, inverted=False):
if data['type'] == 'MoreComments': if data['type'] == 'MoreComments':
self.draw_more_comments(win, data) return self.draw_more_comments(win, data)
elif data['type'] == 'HiddenComment': elif data['type'] == 'HiddenComment':
self.draw_more_comments(win, data) return self.draw_more_comments(win, data)
elif data['type'] == 'Comment': elif data['type'] == 'Comment':
self.draw_comment(win, data, inverted=inverted) return self.draw_comment(win, data, inverted=inverted)
else: else:
self.draw_submission(win, data) return self.draw_submission(win, data)
@staticmethod @staticmethod
def draw_comment(win, data, inverted=False): def draw_comment(win, data, inverted=False):
n_rows, n_cols = win.getmaxyx() n_rows, n_cols = win.getmaxyx()
n_cols -= 2 n_cols -= 1
# Handle the case where the window is not large enough to fit the data. # Handle the case where the window is not large enough to fit the data.
valid_rows = range(0, n_rows) valid_rows = range(0, n_rows)
offset = 0 if not inverted else -(data['n_rows'] - n_rows) offset = 0 if not inverted else -(data['n_rows'] - n_rows)
row = offset row = offset
text = '{} {} {}'.format(data['author'], data['score'], data['created'])
if row in valid_rows: if row in valid_rows:
win.addnstr(row, 1, text, n_cols) text = '{author}'.format(**data)
attr = curses.A_BOLD
attr |= (Color.BLUE if not data['is_author'] else Color.GREEN)
win.addnstr(row, 1, text, n_cols-1, attr)
text = ' {score} {created}'.format(**data)
win.addnstr(text, n_cols - win.getyx()[1])
n_body = len(data['split_body']) n_body = len(data['split_body'])
for row, text in enumerate(data['split_body'], start=offset+1): for row, text in enumerate(data['split_body'], start=offset+1):
if row in valid_rows: if row in valid_rows:
win.addnstr(row, 1, text, n_cols) win.addnstr(row, 1, text, n_cols-1)
# Vertical line, unfortunately vline() doesn't support custom color so # Vertical line, unfortunately vline() doesn't support custom color so
# we have to build it one chr at a time. # we have to build it one chr at a time.
attr = Color.get_level(data['level'])
for y in xrange(n_rows): for y in xrange(n_rows):
win.addch(y, 0, curses.ACS_VLINE) win.addch(y, 0, curses.ACS_VLINE, attr)
return attr | curses.ACS_VLINE
@staticmethod @staticmethod
def draw_more_comments(win, data): def draw_more_comments(win, data):
n_rows, n_cols = win.getmaxyx() n_rows, n_cols = win.getmaxyx()
n_cols -= 2 n_cols -= 1
win.addnstr(0, 1, data['body'], n_cols) win.addnstr(0, 1, data['body'], n_cols-1)
text = ' [{count}]'.format(**data)
attr = curses.A_BOLD
win.addnstr(text, n_cols - win.getyx()[1], attr)
attr = Color.get_level(data['level'])
for y in xrange(n_rows): for y in xrange(n_rows):
win.addch(y, 0, curses.ACS_VLINE) win.addch(y, 0, curses.ACS_VLINE, attr)
return attr | curses.ACS_VLINE
@staticmethod @staticmethod
def draw_submission(win, data): def draw_submission(win, data):

View File

@@ -5,7 +5,7 @@ from errors import SubredditNameError
from page import BasePage from page import BasePage
from submission import SubmissionPage from submission import SubmissionPage
from content import SubredditContent from content import SubredditContent
from utils import LoadScreen, text_input, display_message from utils import LoadScreen, text_input, display_message, Color
class SubredditPage(BasePage): class SubredditPage(BasePage):
@@ -108,11 +108,13 @@ class SubredditPage(BasePage):
n_title = len(data['split_title']) n_title = len(data['split_title'])
for row, text in enumerate(data['split_title'], start=offset): for row, text in enumerate(data['split_title'], start=offset):
if row in valid_rows: if row in valid_rows:
win.addstr(row, 1, text) attr = curses.A_BOLD
win.addstr(row, 1, text, attr)
row = n_title + offset row = n_title + offset
if row in valid_rows: if row in valid_rows:
win.addnstr(row, 1, '{url}'.format(**data), n_cols) attr = curses.A_UNDERLINE | Color.BLUE
win.addnstr(row, 1, '{url}'.format(**data), n_cols, attr)
row = n_title + offset + 1 row = n_title + offset + 1
if row in valid_rows: if row in valid_rows:

View File

@@ -7,6 +7,39 @@ from contextlib import contextmanager
from errors import EscapePressed from errors import EscapePressed
class Color(object):
COLORS = {
'RED': (curses.COLOR_RED, -1),
'GREEN': (curses.COLOR_GREEN, -1),
'YELLOW': (curses.COLOR_YELLOW, -1),
'BLUE': (curses.COLOR_BLUE, -1),
'MAGENTA': (curses.COLOR_MAGENTA, -1),
'CYAN': (curses.COLOR_CYAN, -1),
}
@classmethod
def get_level(cls, level):
levels = [cls.MAGENTA, cls.CYAN, cls.GREEN, cls.YELLOW]
return levels[level % len(levels)]
@classmethod
def init(cls):
"""
Initialize color pairs inside of curses using the default background.
This should be called once during the curses initial setup. Afterwards,
curses color pairs can be accessed directly through class attributes.
"""
# Assign the terminal's default (background) color to code -1
curses.use_default_colors()
for index, (attr, code) in enumerate(cls.COLORS.items(), start=1):
curses.init_pair(index, code[0], code[1])
setattr(cls, attr, curses.color_pair(index))
def text_input(window): def text_input(window):
""" """
Transform a window into a text box that will accept user input and loop Transform a window into a text box that will accept user input and loop
@@ -156,23 +189,14 @@ def curses_session():
# module -- the error return from C start_color() is ignorable. # module -- the error return from C start_color() is ignorable.
try: try:
curses.start_color() curses.start_color()
# Assign the terminal's default (background) color to code -1
curses.use_default_colors()
except: except:
pass pass
else:
Color.init()
# Hide blinking cursor # Hide blinking cursor
curses.curs_set(0) curses.curs_set(0)
# Initialize color pairs - colored text on the default background
curses.init_pair(1, curses.COLOR_RED, -1)
curses.init_pair(2, curses.COLOR_GREEN, -1)
curses.init_pair(3, curses.COLOR_YELLOW, -1)
curses.init_pair(4, curses.COLOR_BLUE, -1)
curses.init_pair(5, curses.COLOR_MAGENTA, -1)
curses.init_pair(6, curses.COLOR_CYAN, -1)
yield stdscr yield stdscr
finally: finally:

17
setup.py Normal file
View File

@@ -0,0 +1,17 @@
from setuptools import setup
setup(
name='rtv',
version='1.0a1',
description='A simple terminal viewer for Reddit (Reddit Terminal Viewer)',
url='http://TODO',
author='Michael Lazar',
author_email='lazar.michael22@gmail.com',
license='MIT',
keywords='reddit terminal praw',
packages=['rtv'],
install_requires=['praw'],
entry_points={'console_scripts': ['rtv=rtv:main']}
)
#python setup.py develop --user