PTW
git-svn-id: http://photonzero.com/dotfiles/trunk@88 23f722f6-122a-0410-8cef-c75bd312dd78
This commit is contained in:
parent
d749c5905d
commit
ed0869cb88
1 changed files with 238 additions and 0 deletions
238
bin/ptw
Executable file
238
bin/ptw
Executable file
|
|
@ -0,0 +1,238 @@
|
|||
#!/usr/bin/env python
|
||||
import json
|
||||
import os.path
|
||||
import time
|
||||
from optparse import OptionParser
|
||||
from operator import itemgetter
|
||||
|
||||
# Start Parser I grabbed from http://pyparsing.wikispaces.com/UnderDevelopment#toc0
|
||||
from datetime import datetime, timedelta
|
||||
from pyparsing import *
|
||||
import calendar
|
||||
|
||||
# string conversion parse actions
|
||||
def convertToTimedelta(toks):
|
||||
unit = toks.timeunit.lower().rstrip("s")
|
||||
td = {
|
||||
'week' : timedelta(7),
|
||||
'day' : timedelta(1),
|
||||
'hour' : timedelta(0,0,0,0,0,1),
|
||||
'minute' : timedelta(0,0,0,0,1),
|
||||
'second' : timedelta(0,1),
|
||||
}[unit]
|
||||
if toks.qty:
|
||||
td *= int(toks.qty)
|
||||
x = 0
|
||||
if toks.dir == "":
|
||||
x = 1
|
||||
else:
|
||||
x = toks.dir
|
||||
if x > 0:
|
||||
td *= -x
|
||||
else:
|
||||
td *= x
|
||||
toks["timeOffset"] = td
|
||||
|
||||
def convertToDay(toks):
|
||||
now = datetime.now()
|
||||
if "wkdayRef" in toks:
|
||||
todaynum = now.weekday()
|
||||
daynames = [n.lower() for n in calendar.day_name]
|
||||
nameddaynum = daynames.index(toks.wkdayRef.day.lower())
|
||||
if toks.wkdayRef.dir > 0:
|
||||
daydiff = (nameddaynum + 7 - todaynum) % 7
|
||||
else:
|
||||
daydiff = -((todaynum + 7 - nameddaynum) % 7)
|
||||
toks["absTime"] = datetime(now.year, now.month, now.day)+timedelta(daydiff)
|
||||
else:
|
||||
name = toks.name.lower()
|
||||
toks["absTime"] = {
|
||||
"now" : now,
|
||||
"today" : datetime(now.year, now.month, now.day),
|
||||
"yesterday" : datetime(now.year, now.month, now.day)+timedelta(-1),
|
||||
"tomorrow" : datetime(now.year, now.month, now.day)+timedelta(+1),
|
||||
}[name]
|
||||
|
||||
def convertToAbsTime(toks):
|
||||
now = datetime.now()
|
||||
if "dayRef" in toks:
|
||||
day = toks.dayRef.absTime
|
||||
day = datetime(day.year, day.month, day.day)
|
||||
else:
|
||||
day = datetime(now.year, now.month, now.day)
|
||||
if "timeOfDay" in toks:
|
||||
if isinstance(toks.timeOfDay,basestring):
|
||||
timeOfDay = {
|
||||
"now" : timedelta(0, (now.hour*60+now.minute)*60+now.second, now.microsecond),
|
||||
"noon" : timedelta(0,0,0,0,0,12),
|
||||
"midnight" : timedelta(),
|
||||
}[toks.timeOfDay]
|
||||
else:
|
||||
hhmmss = toks.timeparts
|
||||
if hhmmss.miltime:
|
||||
hh,mm = hhmmss.miltime
|
||||
ss = 0
|
||||
else:
|
||||
hh,mm,ss = (hhmmss.HH % 12), hhmmss.MM, hhmmss.SS
|
||||
if not mm: mm = 0
|
||||
if not ss: ss = 0
|
||||
if toks.timeOfDay.ampm == 'pm':
|
||||
hh += 12
|
||||
timeOfDay = timedelta(0, (hh*60+mm)*60+ss, 0)
|
||||
else:
|
||||
timeOfDay = timedelta(0, (now.hour*60+now.minute)*60+now.second, now.microsecond)
|
||||
toks["absTime"] = day + timeOfDay
|
||||
|
||||
def calculateTime(toks):
|
||||
if toks.absTime:
|
||||
absTime = toks.absTime
|
||||
else:
|
||||
absTime = datetime.now()
|
||||
if toks.timeOffset:
|
||||
absTime += toks.timeOffset
|
||||
toks["calculatedTime"] = absTime
|
||||
|
||||
# grammar definitions
|
||||
CL = CaselessLiteral
|
||||
today, tomorrow, yesterday, noon, midnight, now = map( CL,
|
||||
"today tomorrow yesterday noon midnight now".split())
|
||||
plural = lambda s : Combine(CL(s) + Optional(CL("s")))
|
||||
week, day, hour, minute, second = map( plural,
|
||||
"week day hour minute second".split())
|
||||
am = CL("am")
|
||||
pm = CL("pm")
|
||||
COLON = Suppress(':')
|
||||
|
||||
# are these actually operators?
|
||||
in_ = CL("in").setParseAction(replaceWith(1))
|
||||
from_ = CL("from").setParseAction(replaceWith(1))
|
||||
before = CL("before").setParseAction(replaceWith(-1))
|
||||
after = CL("after").setParseAction(replaceWith(1))
|
||||
ago = CL("ago").setParseAction(replaceWith(-1))
|
||||
next_ = CL("next").setParseAction(replaceWith(1))
|
||||
last_ = CL("last").setParseAction(replaceWith(-1))
|
||||
|
||||
couple = (Optional(CL("a")) + CL("couple") + Optional(CL("of"))).setParseAction(replaceWith(2))
|
||||
a_qty = CL("a").setParseAction(replaceWith(1))
|
||||
integer = Word(nums).setParseAction(lambda t:int(t[0]))
|
||||
int4 = Group(Word(nums,exact=4).setParseAction(lambda t: [int(t[0][:2]),int(t[0][2:])] ))
|
||||
qty = integer | couple | a_qty
|
||||
dayName = oneOf( list(calendar.day_name) )
|
||||
|
||||
dayOffset = (qty("qty") + (week | day)("timeunit"))
|
||||
dayFwdBack = (from_ + now.suppress() | ago)("dir")
|
||||
weekdayRef = (Optional(next_ | last_,-1)("dir") + dayName("day"))
|
||||
dayRef = Optional( (dayOffset + (before | after | from_)("dir") ).setParseAction(convertToTimedelta) ) + \
|
||||
((yesterday | today | tomorrow)("name")|
|
||||
weekdayRef("wkdayRef")).setParseAction(convertToDay)
|
||||
todayRef = (dayOffset + dayFwdBack).setParseAction(convertToTimedelta) | \
|
||||
(in_("dir") + qty("qty") + day("timeunit")).setParseAction(convertToTimedelta)
|
||||
|
||||
dayTimeSpec = dayRef | todayRef
|
||||
dayTimeSpec.setParseAction(calculateTime)
|
||||
|
||||
hourMinuteOrSecond = (hour | minute | second)
|
||||
|
||||
timespec = Group(int4("miltime") |
|
||||
integer("HH") +
|
||||
Optional(COLON + integer("MM")) +
|
||||
Optional(COLON + integer("SS")) + (am | pm)("ampm")
|
||||
)
|
||||
absTimeSpec = ((noon | midnight | now | timespec("timeparts"))("timeOfDay") +
|
||||
Optional(dayRef)("dayRef"))
|
||||
absTimeSpec.setParseAction(convertToAbsTime,calculateTime)
|
||||
|
||||
relTimeSpec = qty("qty") + hourMinuteOrSecond("timeunit") + \
|
||||
(from_ | before | after)("dir") + \
|
||||
absTimeSpec("absTime") | \
|
||||
qty("qty") + hourMinuteOrSecond("timeunit") + ago("dir") | \
|
||||
in_ + qty("qty") + hourMinuteOrSecond("timeunit") | \
|
||||
qty("qty") + hourMinuteOrSecond("timeunit")
|
||||
relTimeSpec.setParseAction(convertToTimedelta,calculateTime)
|
||||
|
||||
nlTimeExpression = (absTimeSpec | dayTimeSpec | relTimeSpec)
|
||||
|
||||
# End parser
|
||||
|
||||
def db_append(data):
|
||||
db_file = open(os.path.expanduser("~/.ptwdb"), "r")
|
||||
db = json.load(db_file)
|
||||
db_file.close()
|
||||
db.append(data)
|
||||
db_file = open(os.path.expanduser("~/.ptwdb"), "w")
|
||||
json.dump(db, db_file)
|
||||
db_file.close()
|
||||
|
||||
def db_new():
|
||||
db_file = open(os.path.expanduser("~/.ptwdb"), "w")
|
||||
json.dump([], db_file)
|
||||
db_file.close()
|
||||
|
||||
def db_get(count=None, since=None):
|
||||
if count is None and since is None:
|
||||
count = 10
|
||||
if count is None and since is not None:
|
||||
count = 500000
|
||||
out = []
|
||||
db_file = open(os.path.expanduser("~/.ptwdb"), "r")
|
||||
db = json.load(db_file)
|
||||
db_file.close()
|
||||
db.sort(key=itemgetter(u"timestamp"))
|
||||
while count != 0:
|
||||
if len(db) == 0:
|
||||
break
|
||||
x = db.pop()
|
||||
if since is not None and x["timestamp"] < since:
|
||||
break
|
||||
out.append(x)
|
||||
count -= 1
|
||||
return out
|
||||
|
||||
|
||||
def format(l):
|
||||
out = []
|
||||
for x in l:
|
||||
timestr = time.strftime("%a %b %d %Y @ %I:%M%p",
|
||||
time.localtime(x["timestamp"]))
|
||||
out.append("%s: %s" % (timestr, x["text"]))
|
||||
|
||||
return out
|
||||
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option("--host", dest="hostname", help="Hostname from post",
|
||||
metavar="HOSTNAME", default="localhost")
|
||||
|
||||
parser.add_option("--client", dest="client", help="Client for post",
|
||||
default="Command Line", metavar="CLIENT")
|
||||
parser.add_option("-n", dest="num", help="Number of posts to show",
|
||||
default=None, metavar="N")
|
||||
parser.add_option("-s", "--since", dest="since", help="Number of posts to show",
|
||||
default=None, metavar="SINCE")
|
||||
parser.add_option("-v", "--verbose", dest="verbose", help="Debug output",
|
||||
default=False, action="store_true")
|
||||
(options, args) = parser.parse_args()
|
||||
if len(args) < 2:
|
||||
parser.print_help()
|
||||
exit()
|
||||
command = args[0]
|
||||
text = " ".join(args[1:])
|
||||
if command == "post":
|
||||
data = {"timestamp" : time.time(), "text" : text, "client" : options.client,
|
||||
"hostname" : options.hostname }
|
||||
if not os.path.exists(os.path.expanduser("~/.ptwdb")):
|
||||
db_new()
|
||||
db_append(data)
|
||||
elif command == "get":
|
||||
if options.since is not None:
|
||||
p = nlTimeExpression.parseString(options.since)
|
||||
if "calculatedTime" in p:
|
||||
options.since = time.mktime(p.calculatedTime.timetuple())
|
||||
if options.verbose:
|
||||
print p.calculatedTime.isoformat()
|
||||
else:
|
||||
options.since = None
|
||||
for x in format(db_get(options.num, options.since)):
|
||||
print x
|
||||
else:
|
||||
print "Invalid Command"
|
||||
Loading…
Add table
Add a link
Reference in a new issue