Commits

Ajay Roopakalu  committed d4a2307

Added tab-completion (yay) and updated README file.

  • Participants
  • Parent commits 9149ac3

Comments (0)

Files changed (3)

File README

-DESCRIPTION
-===========
-
-  This is a desktop client for Google Tasks that runs in the command line. It
-  provides a fast way to interface with all task lists of a user and make 
-  changes and updates very quickly. This program has been designed to make as
-  few API calls as possible in order to optimize performance.
- 
-DEPENDENCIES
-===========
-
-  Requires Python 2.7 and the Google API client for Python
-
-USAGE
-=====
-  
-  TODO
+DESCRIPTION
+===========
+
+> This is a desktop client for Google Tasks that runs in the command line. It
+provides a fast way to interface with all task lists of a user and make 
+changes and updates very quickly. This program has been designed to make as
+few API calls as possible in order to optimize performance.
+ 
+DEPENDENCIES
+===========
+
+> Requires Python 2.7, the GNU Readline library (`sudo easy_install readline`), 
+and the [Google API client for Python](http://code.google.com/p/google-api-python-client/).
+
+USAGE
+=====
+  
+> Quick Mode
+> ----------
+
+> > ### Common Operations ###
+
+> > + Adding a task (`a`):
+
+> >     `$` **`python tasky.py a --title "Title of task" --date "5/14/11" --note "This is a note."
+> >     --parent "Parent task name"`**
+
+> >     OR
+
+> >     `$` **`python tasky.py a -t "Title of task" -d "5/14/11" -n"This is a note." - "Parent task name"`**
+            
+> >     All of the above fields are optional except for the title and can appear
+> >     in any order.
+
+> > + Removing a task and its children (`r`):
+
+> >     `$` **`python tasky.py r --title "Title of task"`**
+
+> >     OR
+
+> >     `$` **`python tasky.py r -t "Title of task"`**
+            
+> > + Toggling a task and its children (`t`):
+
+> >     `$` **`python tasky.py t --title "Title of task"`**
+
+> >     OR
+
+> >     `$` **`python tasky.py t -t "Title of task"`**
+
+> > + Listing all tasks (`l`):
+
+> >     `$` **`python tasky.py l`**
+
+> > **Note:** The task list can be printed after the execution of the operation by 
+adding a (`--list`) or (`-l`) flag to the command.
+    
+> Normal Mode
+> -----------
+
+> > `$` **`python tasky.py`**
+
+> > ### Tab Completion ###
+
+> > Then follow the on-screen instruction. Tab-completion is supported, so you can 
+type the beginning of an existing task name. For example:
+
+> >     Name of task: Lea<TAB>
+
+> > If there is more than one match, all matches will be listed on the second tab:
+
+> >     Name of task: Lea<TAB><TAB>
+> >     Learn Java  Learn C++
+
+> > Otherwise, the task name will be filled in.
+
+> > ### Partial String Searching ###
+
+> > In addition, Tasky also support partial string searching, so you 
+can type just any consecutive portion of any task name when searching for it. 
+All of the matched results will be displayed and you can specify the number
+for the result you desire.

File src/tasky.py

 from string import find
 from collections import OrderedDict
 from argparse import ArgumentParser
+from operator import itemgetter
 
 import httplib2
 import sys
 import datetime as dt
 import time
+import os
+import readline
 
 parser = None
 arguments = False
 
 TaskLists = {}
 IDToTitle = {}
+TaskNames = []
 UNCHANGED = 0
 UPDATED = 1
 DELETED = 2
 bold = lambda x : '\x1b[1m' + x + '\x1b[0m'
 strike = lambda x : '\x1b[9m' + x + '\x1b[0m'
 
+class Completer():
+    def __init__(self):
+        self.matches = []
+        self.completions = []
+        self.DEBUG = False
+     
+    def complete_task_names(self, text, state):
+        self.completions = TaskNames
+        response = None
+       
+        if state is 0:
+            if text:
+                self.matches = [s for s in self.completions 
+                                if s and s.startswith(text)]
+            else:
+                self.matches = self.completions[:]
+
+        try:
+            response = self.matches[state]
+        except IndexError:
+            pass
+        
+        return response
+    
+    def complete_none(self, text, state):
+        return None
+
 def search_task(substr):
     length = len(substr)
     matches = {}
 
     # Update records
     IDToTitle[newTask['id']] = newTask['title']
+    TaskNames.append(newTask['title'])
     newTask['modified'] = UNCHANGED
 
 def remove_task(taskInfo):
     task['modified'] = DELETED
     # Tidy up
     del IDToTitle[task['id']]
+    TaskNames.remove(task['title'])
     
     # Also delete all children of deleted tasks
     for taskID in TaskLists[listID]:
             t['modified'] = DELETED
             if t['id'] in IDToTitle:
                 del IDToTitle[t['id']]
+                TaskNames.remove(t['title'])
 
 def toggle_task(taskInfo):
     global TaskLists
             continue
         # Over all tasks in a given list
         for task in tasks['items']:
+            TaskNames.append(task['title'])
             IDToTitle[task['id']] = task['title']
             # Set everything to be initially unmodified
             task['modified'] = UNCHANGED
             else:
                 (listID, parentTask) = ret
                 task['parent'] = parentTask['id']
-                print 'add_tasking task...'
+                print 'Adding task...'
                 add_task((listID, task))
                 return
-        print 'add_tasking task...'
+        print 'Adding task...'
         add_task((None, task))
     elif action is 'r':
         ret = search_task(''.join(argv['title']))
         print_all_tasks()
 
 def handle_input(c):
+    completer = Completer()
+    c_name = completer.complete_task_names
+    c_none = completer.complete_none
+    readline.set_completer(c_none)
+
     if c is 'a':
         t = dt.date.today()
 
         notes = raw_input("Notes: ")
         if notes is not '':
             task['notes'] = notes
-        
+    
+        readline.set_completer(c_name)
         parent = raw_input("Name of parent task: ")
+
         if parent is not '':
             ret = search_task(parent)
             if ret is None:
             else:
                 (listID, parentTask) = ret
                 task['parent'] = parentTask['id']
-                print 'add_tasking task...'
+                print 'Adding task...'
                 add_task((listID, task))
                 return
-        print 'add_tasking task...'
+        print 'Adding task...'
         add_task((None, task))
     elif c is 'l':
         print_all_tasks()
     elif c is 'r':
+        readline.set_completer(c_name)
         substr = raw_input("Name of task: ")
         ret = search_task(substr)
         if ret is None:
             print 'Removing task...'
             remove_task(ret)
     elif c is 't':
+        readline.set_completer(c_name)
         substr = raw_input("Name of task: ")
         ret = search_task(substr)
         if ret is None:
     if arguments:
         handle_input_args(argv)
     else:
+        readline.parse_and_bind('tab: complete')
+        readline.set_completer_delims(readline.get_completer_delims()[1:])
         print_all_tasks()
         while True:
             readIn = raw_input('[a]dd, [r]emove, [l]ist, [t]oggle, [q]uit: ')