]> git.notmuchmail.org Git - notmuch/blob - notmuch
notmuch: implement tag command
[notmuch] / notmuch
1 #!/usr/bin/env python
2 """This is a notmuch implementation in python. It's goal is to allow running the test suite on the cnotmuch python bindings."""
3 import sys, os, re, logging
4 from cnotmuch.notmuch import Database, Query
5 PREFIX=re.compile('(\w+):(.*$)')
6 #TODO Handle variable: NOTMUCH-CONFIG
7
8 #-------------------------------------------------------------------------
9 HELPTEXT="""The notmuch mail system.
10
11 Usage: notmuch <command> [args...]
12
13 Where <command> and [args...] are as follows:
14
15         setup   Interactively setup notmuch for first use.
16
17         new     [--verbose]
18
19                 Find and import new messages to the notmuch database.
20
21         search  [options...] <search-terms> [...]
22
23                 Search for messages matching the given search terms.
24
25         show    <search-terms> [...]
26
27                 Show all messages matching the search terms.
28
29         count   <search-terms> [...]
30
31                 Count messages matching the search terms.
32
33         reply   [options...] <search-terms> [...]
34
35                 Construct a reply template for a set of messages.
36
37         tag     +<tag>|-<tag> [...] [--] <search-terms> [...]
38
39                 Add/remove tags for all messages matching the search terms.
40
41         dump    [<filename>]
42
43                 Create a plain-text dump of the tags for each message.
44
45         restore <filename>
46
47                 Restore the tags from the given dump file (see 'dump').
48
49         search-tags     [<search-terms> [...] ]
50
51                 List all tags found in the database or matching messages.
52
53         help    [<command>]
54
55                 This message, or more detailed help for the named command.
56
57 Use "notmuch help <command>" for more details on each command.
58 And "notmuch help search-terms" for the common search-terms syntax.
59 """
60 #-------------------------------------------------------------------------
61 #TODO: replace the dynamic pieces
62 USAGE="""Notmuch is configured and appears to have a database. Excellent!
63
64 At this point you can start exploring the functionality of notmuch by
65 using commands such as:
66
67         notmuch search tag:inbox
68
69         notmuch search to:"Sebastian Spaeth"
70
71         notmuch search from:"Sebastian@SSpaeth.de"
72
73         notmuch search subject:"my favorite things"
74
75 See "notmuch help search" for more details.
76
77 You can also use "notmuch show" with any of the thread IDs resulting
78 from a search. Finally, you may want to explore using a more sophisticated
79 interface to notmuch such as the emacs interface implemented in notmuch.el
80 or any other interface described at http://notmuchmail.org
81
82 And don't forget to run "notmuch new" whenever new mail arrives.
83
84 Have fun, and may your inbox never have much mail.
85 """
86 #-------------------------------------------------------------------------
87 def quote_query_line(argv):
88    #mangle arguments wrapping terms with spaces in quotes
89    for i in xrange(0,len(argv)):
90       if argv[i].find(' ') >= 0:
91          #if we use prefix:termWithSpaces, put quotes around term
92          m = PREFIX.match(argv[i])
93          if m:
94             argv[i] = '%s:"%s"' % (m.group(1), m.group(2))
95          else:
96             argv[i] = '"'+argv[i]+'"'
97    return ' '.join(argv)
98
99 if __name__ == '__main__':
100
101    # Handle command line options
102    # No option 
103    #-------------------------------------
104    if len(sys.argv) == 1:
105       print USAGE
106    #-------------------------------------
107    elif sys.argv[1] == 'setup':
108        """ Interactively setup notmuch for first use. """
109        print "Not implemented."
110    #-------------------------------------
111    elif sys.argv[1] == 'help':
112        if len(sys.argv) == 2: print HELPTEXT
113        else: print "Not implemented"
114    #-------------------------------------
115    elif sys.argv[1] == 'show':
116       db = Database()
117       if len(sys.argv) == 2:
118          #no further search term
119          querystr=''
120       else:
121          #mangle arguments wrapping terms with spaces in quotes
122          querystr = quote_query_line(sys.argv[2:])
123       logging.debug("show "+querystr)
124       m = Query(db,querystr).search_messages()
125       for msg in m:
126          print(msg.format_as_text())
127    #-------------------------------------
128    elif sys.argv[1] == 'new':
129        #TODO: handle --verbose
130        print "Not implemented."
131    #-------------------------------------
132    elif sys.argv[1] == 'count':
133       db = Database()
134       if len(sys.argv) == 2:
135          #no further search term
136          querystr=''
137       else:
138          #mangle arguments wrapping terms with spaces in quotes
139          querystr = quote_query_line(sys.argv[2:])
140       logging.debug("count "+querystr)
141       print(len(Query(db,querystr).search_messages()))
142    #-------------------------------------
143    elif sys.argv[1] == 'tag':
144       #build lists of tags to be added and removed
145       add, remove = [], []
146       while not sys.argv[2]=='--' and \
147             (sys.argv[2].startswith('+') or sys.argv[2].startswith('-')):
148          if sys.argv[2].startswith('+'):
149             #append to add list without initial +
150             add.append(sys.argv.pop(2)[1:])
151          else:
152             #append to remove list without initial -
153             remove.append(sys.argv.pop(2)[1:])
154       #skip eventual '--'
155       if sys.argv[2]=='--': sys.argv.pop(2)
156       #the rest is search terms
157       querystr = quote_query_line(sys.argv[2:])
158       logging.warning("tag search-term "+querystr)
159       db = Database(mode=Database.MODE.READ_WRITE)
160       m  = Query(db,querystr).search_messages()
161       for msg in m:
162          #actually add and remove all tags
163          map(msg.add_tag, add)
164          map(msg.remove_tag, remove)
165    #-------------------------------------
166    elif sys.argv[1] == 'search-tags':
167       if len(sys.argv) == 2:
168          #no further search term
169          print("\n".join(Database().get_all_tags()))
170       else:
171          #mangle arguments wrapping terms with spaces in quotes
172          querystr = quote_query_line(sys.argv[2:])
173          logging.debug("search-term "+querystr)
174          db = Database()
175          m  = Query(db,querystr).search_messages()
176          print("\n".join([t for t in m.collect_tags()]))
177    #-------------------------------------
178    elif sys.argv[1] == 'dump':
179       #TODO: implement "dump <filename>"
180       db = Database()
181       q = Query(db,'')
182       q.set_sort(Query.SORT.MESSAGE_ID)
183       m = q.search_messages()
184       for msg in m:
185          print("%s (%s)" % (msg.get_message_id(), msg.get_tags()))
186    #-------------------------------------
187    else:
188        # unknown command
189        print "Error: Unknown command '%s' (see \"notmuch help\")" % sys.argv[1]
190
191
192    #TODO: implement
193    """
194 setup
195 new
196 search  [options...] <search-terms> [...]
197 show    <search-terms> [...]
198 reply   [options...] <search-terms> [...]
199 restore <filename>
200    """