New command location + docstring help + info command
authorDmitriy Morozov <morozov@cs.duke.edu>
Mon, 30 Jun 2008 07:44:01 -0400
changeset 8 0c241cd7c989
parent 7 d0e3cd42a3af
child 9 f7462be0b274
New command location + docstring help + info command
alexandria.py
--- 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)