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