Last active
February 12, 2020 20:43
-
-
Save simonbru/c06cd9e6e2286a9b6df3c389d62cce22 to your computer and use it in GitHub Desktop.
Sort todo.txt file according to multiple critera.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
Sort todo.txt file according to multiple critera. | |
Depends on todotxt-machine | |
""" | |
import argparse | |
import datetime | |
import sys | |
from dataclasses import dataclass | |
from pathlib import Path | |
from todotxt_machine.todo import Todo, Todos | |
@dataclass | |
class Criterion: | |
value: str | |
after: bool = False | |
def key(self, todo): | |
if self.value.startswith("+"): | |
does_match = self.value in todo.projects | |
elif self.value.startswith("@"): | |
does_match = self.value in todo.contexts | |
return int(does_match if self.after else not does_match) | |
@dataclass | |
class Priority: | |
ascending: bool = False | |
def key(self, todo): | |
value = ord(todo.priority if todo.priority else "Z") | |
return value if self.ascending else -value | |
@dataclass | |
class Done: | |
after: bool = False | |
def key(self, todo): | |
value = todo.is_complete() | |
if not self.after: | |
value = not value | |
return int(value) | |
@dataclass | |
class CompletionDate: | |
ascending: bool = False | |
null_after: bool = False | |
def key(self, todo): | |
try: | |
value = datetime.date.fromisoformat(todo.completed_date).toordinal() | |
except (TypeError, ValueError): | |
value = math.inf if self.null_after else 0 | |
return value if self.ascending else -value | |
ORDERING = ( | |
Done(after=False), | |
CompletionDate(ascending=True, null_after=False), | |
Criterion("+y"), | |
Criterion("+m"), | |
Criterion("+w"), | |
Criterion("+wait"), | |
Priority(), | |
) | |
def sort_key(todo): | |
return tuple(predicate.key(todo) for predicate in ORDERING) | |
def main(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument("todo_file") | |
parser.add_argument("-s", "--save", action="store_true") | |
parser.add_argument("-q", "--quiet", action="store_true") | |
args = parser.parse_args() | |
todos_path = Path(args.todo_file) | |
todos = Todos(todos_path.read_text().split("\n"), str(todos_path), None) | |
todos.todo_items.sort(key=sort_key) | |
if args.save: | |
todos.save() | |
if not args.quiet: | |
todos_raw = "\n".join(todo.raw for todo in todos) | |
print(todos_raw) | |
if __name__ == "__main__": | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment