--- a/alexandria.py Fri Jun 13 14:55:43 2008 -0400
+++ b/alexandria.py Mon Jun 30 07:44:01 2008 -0400
@@ -33,6 +33,7 @@
return (True, os.path.join(directory, db_filename))
def add(args, options):
+ """add a paper to the database"""
path = args[0]
if not os.path.exists(path):
print _colorize_string('error', "Path %s does not exist. Cannot add paper." % path)
@@ -61,12 +62,14 @@
_show_paper(p)
def update(args, options):
+ """update paper by hash"""
p = Paper.query.filter(Paper.md5.startswith(args[0])).one()
_set_options(p, options)
session.flush()
_show_paper(p)
def view(args, options):
+ """view paper by hash"""
if len(args) < 1: return
p = Paper.query.filter(Paper.md5.startswith(args[0])).one()
if not p: return
@@ -75,6 +78,7 @@
os.system('%s %s' % (viewer, os.path.join(options.commonpath, p.path.strip('/'))))
def remove(args, options):
+ """remove paper by hash"""
if len(args) < 1: return
p = Paper.query.filter(Paper.md5.startswith(args[0])).one()
if not p: return
@@ -84,6 +88,7 @@
session.flush()
def list(args, options):
+ """list papers in the database"""
papers = Paper.query
# Refactor with _set_options()
@@ -109,6 +114,7 @@
print
def alias(args, options):
+ """add or list author nicknames"""
if len(args) > 1:
a = Author.get_by_or_init(name = unicode(args[1]))
an = AuthorNickname.get_by_or_init(name = unicode(args[0]))
@@ -118,10 +124,17 @@
_show_nicknames()
def labels(args, options):
+ """rename and/or list labels"""
if len(args) >= 2:
t = Tag.get_by(name = unicode(args[0]))
- if t:
+ t2 = Tag.get_by(name = unicode(args[1]))
+ if t and not t2:
t.name = unicode(args[1])
+ elif t and t2:
+ for p in t.papers:
+ t2.papers.append(p)
+ t.papers.remove(p)
+ t.delete()
session.flush()
print "Labels:"
@@ -133,6 +146,7 @@
session.flush()
def ralias(args, options):
+ """remove alias"""
if len(args) == 0:
print _colorize_string('error', 'Need alias to remove as an argument.')
@@ -143,6 +157,23 @@
_show_nicknames()
+def info(args, options):
+ """Show information about a path"""
+
+ if len(args) == 0:
+ print _colorize_string('error', 'Need path to check as an argument.')
+
+ path = os.path.abspath(args[0])
+ commonpath = os.path.commonprefix([options.commonpath, path])
+ path = path[len(commonpath):]
+ path = path.strip('/')
+ paper = Paper.get_by(path = path)
+
+ if paper:
+ _show_paper(paper)
+ else:
+ print "No such path %s found" % _colorize_string('path', path)
+
def _set_options(p, options, required = []):
title = options.title or ('title' in required) and raw_input("Enter title: ")
if title:
@@ -198,23 +229,33 @@
def _colorize_string(clr, str):
return '%s%s%s' % (color[clr], str, color['normal'])
-commands = [
- (add, 'add a paper to the database'),
- (list, 'list papers in the database'),
- (alias, 'add or list author nicknames'),
- (update, 'update paper by hash'),
- (view, 'view paper by hash'),
- (remove, 'remove paper by hash'),
- (labels, 'rename and/or list labels'),
- (ralias, 'remove alias'),
- ]
+def _find_command(args, commands):
+ if len(args) == 0: return None
+ candidates = []
+ for cmd in commands:
+ func = cmd
+ if func.__name__.startswith(args[0]):
+ candidates += [func]
+
+ if len(candidates) > 1:
+ print "Ambiguous choices:",
+ for c in candidates: print c.__name__,
+ print
+
+ if len(candidates) == 1:
+ return candidates[0]
+ else:
+ return None
+
+
+commands = [add, list, alias, update, view, remove, labels, ralias, info]
if __name__ == "__main__":
- usage = '%s COMMAND OPTIONS\n' % sys.argv[0]
+ usage = '%prog COMMAND OPTIONS\n'
usage += 'Commands:\n'
for cmd in commands:
- func, description = cmd
+ func, description = cmd, cmd.__doc__.split('\n')[0]
usage += ' %-10s - %s\n' % (func.__name__, description)
# Parse config
@@ -224,13 +265,25 @@
commonpath = os.path.expanduser(config.get('paths', 'common'))
# Parse options
- parser = OptionParser(usage = usage)
- parser.add_option('-a', '--author', action='append', dest='authors', help='author')
- parser.add_option('-t', '--title', dest='title', help='title')
- parser.add_option('-l', '--label', action='append', dest='labels', help='label')
- parser.add_option('-D', '--database', dest='database', help='directory with the database')
+ parser = OptionParser(usage = usage, add_help_option = False)
+ parser.add_option('-a', '--author', action='append', dest='authors')
+ parser.add_option('-t', '--title', dest='title')
+ parser.add_option('-l', '--label', action='append', dest='labels', help='"label" to add a label or "-label" to remove a label')
+ parser.add_option('-D', '--database', dest='database', help='directory with the database')
+ parser.add_option('-h', '--help', action='store_true', dest='show_help', help='show help message')
(options, args) = parser.parse_args()
+ # Find command
+ cmd = _find_command(args, commands)
+
+ # Show help if requested
+ if options.show_help:
+ if cmd:
+ print cmd.__doc__
+ else:
+ parser.print_help()
+ sys.exit()
+
# Find database
found, path = find_database(options.database or dbpath)
initDatabase(path, not found)
@@ -239,16 +292,5 @@
options.dbpath = path
options.commonpath = commonpath
- # Find and execute the command
- if len(args) == 0: sys.exit()
- candidates = []
- for cmd in commands:
- func, description = cmd
- if func.__name__.startswith(args[0]):
- candidates += [func]
- if len(candidates) > 1:
- print "Ambiguous choices:",
- for c in candidates: print c.__name__,
- print
- else:
- candidates[0](args[1:], options)
+ # Execute command if found
+ if cmd: cmd(args[1:], options)