#! /usr/bin/env python # This software carries the following license: # # Modified BSD license # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Steinar Knutsen """NB 1.1 """ import DCLMatcher, LineInterpreter, tempfile, cPickle, sys, string, time, os class commands: def __init__(self, database): self.database = database datafile = open(database, 'r') self.notes = cPickle.load(datafile) datafile.close() def exit(self, interp, args): """Save database and exit. Use ^D to exit without save. """ self.save(interp, args) interp.writeline("Exiting.\n") raise EOFError def list(self, interp, args): """List notes in database. """ output = ["Notes:"] output.append(string.join(self.notes.keys(), ', ')) output = interp.formatlines(output) interp.writelines(output) def delete(self, interp, args): """Delete note(s) in database. """ for arg in args: del self.notes[arg] def read(self, interp, args): """Read note(s) in database. """ for arg in args: try: interp.writelines(self.notes[arg].text) LineInterpreter.KeyPressWait() except DCLMatcher.AmbiguiousQuery: interp.writeline("Error: Ambiguious key %s.\n" % arg) except (DCLMatcher.KeyMismatch, KeyError): interp.writeline("Error: No note matching %s.\n" % arg) def save(self, interp, args): """Save database to disk. """ interp.writeline("Saving database.\n") datafile = open(self.database, 'w') cPickle.dump(self.notes, datafile) datafile.close() def jot(self, interp, args): """Add or overwrite note(s) to/in database. """ for arg in args: note = [] line = raw_input(': ')+'\n' while string.strip(line) != '.': note.append(line) line = raw_input(': ')+'\n' interp.writeline("Adding/Overwriting note.\n") try: self.notes[arg] = Note(note) except DCLMatcher.AmbiguiousKeytable: interp.writeline( "Error: Would make keytable ambiguious.\n") except DCLMatcher.AmbiguiousQuery: interp.writeline("Error: Ambiguious key.\n") def help(self, interp, args): """Show help texts for commands. """ if len(args) == 0: functions = interp.functiontable.keys() interp.writeline(string.join(functions, ', ')+'\n') else: for arg in args: doc = interp.functiontable[arg].__doc__ doc = map(lambda x: x+'\n', string.split(doc, '\n')[:-1]) interp.writelines(doc) def time(self, interp, args): """Show the timestamp(s) of (a) note(s). """ for arg in args: t = self.notes[arg].timestamp key = self.notes.findref(arg).realkey t = time.strftime('%A, %Y-%m-%d %H:%M:%S', time.localtime(t)) interp.writeline("%s: %s\n" % (key, t)) def vim(self, interp, args): """Edit an existing note with Vim. New notes must be made with jot. """ for arg in args: interp.writeline("Editing %s\n" % self.notes.findref(arg).realkey) buffer = self.notes[arg] tmpname = tempfile.mktemp() tmp = open(tmpname, 'w') tmp.writelines(buffer.text) tmp.close() os.system("vim %s" % tmpname) tmp = open(tmpname, 'r') buffer.text = tmp.readlines() buffer.newtime() tmp.close() os.unlink(tmpname) class Note: def __init__(self, text): self.text = text self.timestamp = time.time() def newtime(self): self.timestamp = time.time() AmbiguiousCommand = "Error: Ambiguious command." UnknownCommand = "Error: Unknown command." def main(commanddict): commandtable = DCLMatcher.DCLMatcher(commanddict) interp = LineInterpreter.LineInterpreter(commandtable) nouserexit = 1 while nouserexit: try: interp.mainloop() except EOFError: nouserexit = 0 except DCLMatcher.AmbiguiousQuery: print AmbiguiousCommand except (DCLMatcher.KeyMismatch, KeyError): print UnknownCommand else: nouserexit = 0 if __name__ == '__main__': if len(sys.argv) > 1 and string.lower(sys.argv[1]) == 'init': if len(sys.argv) == 3: filename = sys.argv[2] else: filename = '.journal' datafile = open(filename, 'w') cPickle.dump(DCLMatcher.DCLMatcher({}), datafile) datafile.close() elif len(sys.argv) == 2 or len(sys.argv) == 1: if len(sys.argv) == 2: filename == sys.argv[1] else: filename = '.journal' engine = commands(filename) commanddict = { "exit": engine.exit, "list": engine.list, "delete": engine.delete, "read": engine.read, "save": engine.save, "jot": engine.jot, "help": engine.help, "time": engine.time, "vim": engine.vim } main(commanddict)