143 lines
4 KiB
Python
143 lines
4 KiB
Python
from typing import Dict, Optional
|
|
import webbrowser
|
|
from talon import ctrl, ui, Module, Context, actions, clip, app
|
|
from dataclasses import dataclass
|
|
from things3.things3 import Things3
|
|
from ...code.create_spoken_forms import create_spoken_forms
|
|
import io
|
|
import csv
|
|
|
|
ctx = Context()
|
|
mod = Module()
|
|
apps = mod.apps
|
|
apps.things3 = """
|
|
app.name: Things
|
|
"""
|
|
ctx.matches = r"""
|
|
app: things3
|
|
"""
|
|
|
|
mod.list("things_tag", desc="Tags in Things")
|
|
mod.list("things_tag_with_shortcut", desc="Tags in Things within an assigned shortcut")
|
|
mod.list("things_project", desc="Areas and projects in Things")
|
|
|
|
things = Things3()
|
|
|
|
|
|
@dataclass
|
|
class Tag:
|
|
uuid: str
|
|
title: str
|
|
shortcut: Optional[str]
|
|
|
|
|
|
@dataclass
|
|
class Project:
|
|
uuid: str
|
|
title: str
|
|
|
|
|
|
raw_areas = things.get_areas()
|
|
raw_projects = things.get_projects()
|
|
sql_query = f"""
|
|
SELECT TAG.title, TAG.shortcut, TAG.uuid
|
|
FROM {things.TABLE_TAG} AS TAG
|
|
"""
|
|
tags = [Tag(**raw_tag) for raw_tag in things.execute_query(sql_query)]
|
|
projects = [
|
|
Project(uuid=raw_project["uuid"], title=raw_project["title"])
|
|
for raw_project in raw_areas + raw_projects
|
|
]
|
|
|
|
tag_map: Dict[str, Tag] = {tag.uuid: tag for tag in tags}
|
|
project_map = {project.uuid: project for project in projects}
|
|
|
|
ctx.lists["self.things_tag"] = {
|
|
spoken_form: tag.uuid
|
|
for tag in tags
|
|
for spoken_form in create_spoken_forms(tag.title)
|
|
}
|
|
ctx.lists["self.things_tag_with_shortcut"] = {
|
|
spoken_form: tag.uuid
|
|
for tag in tags
|
|
if tag.shortcut is not None
|
|
for spoken_form in create_spoken_forms(tag.title)
|
|
}
|
|
things_projects = {
|
|
spoken_form: project.uuid
|
|
for project in projects
|
|
for spoken_form in create_spoken_forms(project.title)
|
|
}
|
|
print(things_projects)
|
|
ctx.lists["self.things_project"] = things_projects
|
|
|
|
|
|
@mod.action_class
|
|
class Actions:
|
|
def tag_todo(things_tags: str):
|
|
"""Tag todo with a list of tags"""
|
|
tag_list = [tag_map[tag_uuid] for tag_uuid in things_tags.split(",")]
|
|
tags_with_shortcuts = [tag for tag in tag_list if tag.shortcut is not None]
|
|
tags_without_shortcuts = [tag for tag in tag_list if tag.shortcut is None]
|
|
|
|
for tag in tags_with_shortcuts:
|
|
actions.key(f"ctrl-{tag.shortcut}")
|
|
|
|
for tag in tags_without_shortcuts:
|
|
actions.key(f"cmd-shift-t")
|
|
actions.insert(tag.title)
|
|
actions.key("enter")
|
|
|
|
def filter_by_tag(things_tags: str):
|
|
"""Tag todo with a list of tags"""
|
|
tag_list = [tag_map[tag_uuid] for tag_uuid in things_tags.split(",")]
|
|
|
|
for tag in tag_list:
|
|
if tag.shortcut is None:
|
|
raise Exception("Can only filter by tags with assigned shortcuts")
|
|
actions.key(f"ctrl-alt-{tag.shortcut}")
|
|
|
|
def show_tag(things_tag: str):
|
|
"""Show a particular tag in things"""
|
|
tag = tag_map[things_tag]
|
|
webbrowser.open(f"things:///show?id={tag.uuid}")
|
|
|
|
def show_things_list(things_project: str):
|
|
"""Show a list in things"""
|
|
project = project_map[things_project]
|
|
webbrowser.open(f"things:///show?id={project.uuid}")
|
|
|
|
def move_todo(project: str):
|
|
"""Move todo to a particular list"""
|
|
try:
|
|
project = project_map[project].title
|
|
except KeyError:
|
|
pass
|
|
actions.key("cmd-shift-m")
|
|
actions.insert(project)
|
|
actions.key("enter")
|
|
|
|
|
|
@mod.capture(rule="{self.things_tag}+")
|
|
def things_tags(m) -> str:
|
|
"One or more Things tags"
|
|
return ",".join(m.things_tag_list)
|
|
|
|
|
|
@mod.capture(rule="{self.things_tag_with_shortcut}+")
|
|
def things_tags_with_shortcut(m) -> str:
|
|
"One or more Things tags"
|
|
return ",".join(m.things_tag_with_shortcut_list)
|
|
|
|
|
|
@mod.capture(rule="{self.things_project}+")
|
|
def things_projects(m) -> str:
|
|
"One or more Things projects"
|
|
return to_csv_row_string(m.things_project_list)
|
|
|
|
|
|
def to_csv_row_string(row_elements: str) -> str:
|
|
output = io.StringIO()
|
|
writer = csv.writer(output, quoting=csv.QUOTE_MINIMAL)
|
|
writer.writerow(row_elements)
|
|
return output.getvalue()
|