diff --git a/scripts/mel b/scripts/mel index 96113ca..037e345 100755 --- a/scripts/mel +++ b/scripts/mel @@ -7,12 +7,14 @@ to become a fully-functional extremly-opinonated mail client. """ # TODO Features + # TODO Implement initial command set # TODO Lockfiles for write operations on mail files (mbsync, tags→maildir operations) # TODO OPTI Lockfile per account and process everything in parallel (if implemented, this # should be optional since while it may speed up the mail fetching process, its multi-threading # nature would cause a lot of cache flushes and be not very efficient on battery) # TODO Handle true character width # TODO IMAP IDLE watches? + # TODO GPG # TODO (only then) Refactor # TODO OOP-based # TODO Merge file with melConf @@ -58,17 +60,49 @@ ALIASES = set() db = None config = None +def notmuch_new(): + close_database() + log.info("Indexing mails") + notmuchConfigPath = os.path.expanduser("~/.notmuchrc") # TODO Better + cmd = ["notmuch", "--config", notmuchConfigPath, "new"] + log.debug(" ".join(cmd)) + subprocess.run(cmd) + +def list_folders(): + storagePath = os.path.realpath(os.path.expanduser(config["GENERAL"]["storage"])) + folders = list() + for account in ACCOUNTS.keys(): + storagePathAccount = os.path.join(storagePath, account) + for root, dirs, files in os.walk(storagePathAccount): + if "cur" not in dirs or "new" not in dirs or "tmp" not in dirs: + continue + assert root.startswith(storagePath) + path = root[len(storagePath):] + pathSplit = path.split('/') + if pathSplit[0] == '': + pathSplit = pathSplit[1:] + folders.append(tuple(pathSplit)) + return folders def open_database(write=False): global db mode = notmuch.Database.MODE.READ_WRITE if write else notmuch.Database.MODE.READ_ONLY + if db: + if db.mode == mode: + return + else: + log.info("Current database not in required mode, closing") + close_database() + log.info("Opening database in mode {}".format(mode)) dbPath = os.path.realpath(os.path.expanduser(config["GENERAL"]["storage"])) db = notmuch.Database(mode=mode, path=dbPath) def close_database(): global db - db.close() - db = None + if db: + log.info("Closing database") + db.close() + db = None def generate_aliases(): for name in config.sections(): @@ -252,9 +286,7 @@ def extract_email(field): return field def applyMsgs(queryStr, action, *args, showProgress=False, write=False, closeDb=True, **kwargs): - # TODO Verify it's open in the correct mode - if db is None: - open_database(write=write) + open_database(write=write) log.info("Querying {}".format(queryStr)) query = notmuch.Query(db, queryStr) @@ -377,6 +409,8 @@ def sizeof_fmt(num, suffix='B'): num /= 1024.0 return "%.1f %s%s" % (num, 'Yi', suffix) +PART_MULTI_FORMAT = colorama.Fore.BLUE + '{nb} {indent}+ {typ}' + colorama.Style.RESET_ALL +PART_LEAF_FORMAT = colorama.Fore.BLUE + '{nb} {indent}→ {desc} ({typ}; {size})' + colorama.Style.RESET_ALL def show_parts_tree(part, lvl=0, nb=1): indent = lvl * '\t' typ = part.get_content_type() @@ -395,8 +429,6 @@ def show_parts_tree(part, lvl=0, nb=1): INTERESTING_HEADERS = ["Date", "From", "Subject", "To", "Cc", "Message-Id"] HEADER_FORMAT = colorama.Fore.BLUE + colorama.Style.BRIGHT + '{}:' + colorama.Style.NORMAL + ' {}' + colorama.Style.RESET_ALL -PART_MULTI_FORMAT = colorama.Fore.BLUE + '{nb} {indent}+ {typ}' + colorama.Style.RESET_ALL -PART_LEAF_FORMAT = colorama.Fore.BLUE + '{nb} {indent}→ {desc} ({typ}; {size})' + colorama.Style.RESET_ALL def read_msg(msg): # Parse filename = msg.get_filename() @@ -524,12 +556,7 @@ if __name__ == "__main__": subprocess.run(cmd) # Index new mails - log.info("Indexing mails") - log.error("TODO Can't `notmuch new` when database is already open!") - notmuchConfigPath = os.path.expanduser("~/.notmuchrc") # TODO Better - cmd = ["notmuch", "--config", notmuchConfigPath, "new"] - log.debug(" ".join(cmd)) - subprocess.run(cmd) + notmuch_new() # Notify notify_all() @@ -550,9 +577,12 @@ if __name__ == "__main__": global msg msg = a applyMsgs('tag:tuidyviU45m6flff', expose_msg, closeDb=False) + def func_debug(args): + from pprint import pprint + pprint(list_folders()) parserDebug = subparsers.add_parser("debug", help="Who know what this holds...") parserDebug.set_defaults(verbosity='DEBUG') - parserDebug.set_defaults(func=func_expose) + parserDebug.set_defaults(func=func_debug) # retag (all or unprocessed) def func_retag(args):