Browse Source

lazygit

main
Gregory Leeman 6 months ago
parent
commit
7bc33d8713
  1. 334
      wf/script.py

334
wf/script.py

@ -12,12 +12,41 @@ from rich.console import Console
from rich.theme import Theme from rich.theme import Theme
STORAGE_FILE = os.path.join(os.path.expanduser('~'), '.workflowy_data.json') STORAGE_FILE = os.path.join(os.path.expanduser('~'), '.workflowy_data.json')
INBOX_ID = "f5cf6b0b-2931-4a59-9301-0a52813e51e3" INBOX_ID = "f5cf6b0b-2931-4a59-9301-0a52813e51e3"
PLANNER_ID = "d0162605-db2d-7f97-f451-4408da2bb5df" TASKS_ID = "4f5fca00-8141-3f33-ac7a-b732f37515f4"
PLANNER_IDS = {
"life": "d0162605-db2d-7f97-f451-4408da2bb5df",
"admin": "3af78fcf-71d1-c020-26f1-a230b2403683",
"art": "d33c5cd2-6183-776f-33e8-c0714c8c5d63",
"health": "ab0ed672-7868-f38d-06c1-86c6464cd85b",
"mind": "09e9a2c7-954d-9178-7bca-de54d6f6680d",
"social": "2be5c4e5-ebfe-a462-3389-5b83aa86d016",
"church": "c69aa1a1-26a3-2ab7-a125-fe6b61d108bd",
"work": "f6306ec9-9243-a249-3af7-aa7d64963e2b"
}
solarized_theme = Theme({ solarized_theme = Theme({
"orange": "#cb4b16", "base03": "bright_black",
"violet": "#6c71c4", "base02": "black",
"base01": "bright_green",
"base00": "bright_yellow",
"base0": "bright_blue",
"base1": "bright_cyan",
"base2": "white",
"base3": "bright_white",
"orange": "bright_red",
"violet": "bright_magenta",
"underline base03": "underline bright_black",
"underline base02": "underline black",
"underline base01": "underline bright_green",
"underline base00": "underline bright_yellow",
"underline base0": "underline bright_blue",
"underline base1": "underline bright_cyan",
"underline base2": "underline white",
"underline base3": "underline bright_white",
"underline orange": "bright_red underline",
"underline violet": "bright_magenta underline",
}) })
console = Console(highlight=False, theme=solarized_theme) console = Console(highlight=False, theme=solarized_theme)
@ -239,16 +268,36 @@ def clip_to_workflowy(name, description, parent_id): # {{{
# }}} # }}}
def simplify_project(project_data): # {{{ def simplify_project(project_data, full_data, follow_mirrors=False): # {{{
simplified_project = { if project_data.get("metadata", {}).get("mirror", {}).get("originalId"):
"name": project_data.get("nm", ""), if follow_mirrors:
"description": project_data.get("no", ""), # Assuming 'no' contains description/URL if present originalId = project_data["metadata"]["mirror"]["originalId"]
"children": [] project_data, full_data = find_project_by_id(full_data, full_data, originalId)
} else:
children = project_data.get("ch", []) return None, full_data
for child in children: if project_data.get("metadata", {}).get("isReferencesRoot"):
simplified_project["children"].append(simplify_project(child)) if project_data.get("ch"):
return simplified_project if len(project_data["ch"]) > 0:
project_data["nm"] = "backlinks"
project_data["metadata"]["layoutMode"] = "h1"
else:
return None, full_data
else:
return None, full_data
if project_data:
simplified_project = {
"name": project_data.get("nm", ""),
"id": project_data.get("id", ""),
"children": [],
"format": project_data.get("metadata", {}).get("layoutMode", None)
}
children = project_data.get("ch", [])
for child in children:
simplified_child, full_data = simplify_project(child, full_data, follow_mirrors=follow_mirrors)
if simplified_child:
simplified_project["children"].append(simplified_child)
return simplified_project, full_data
return None, full_data
# }}} # }}}
@ -256,8 +305,14 @@ def simplify_project(project_data): # {{{
def flatten(children): # {{{ def flatten(children): # {{{
flattened = [] flattened = []
for child in children: for child in children:
try:
grand_children = child.get("children", [])
except Exception as e:
print(f"child: {child} {e}")
grand_children = []
child["children"] = []
flattened.append(child) flattened.append(child)
flattened.extend(flatten(child.get("children", []))) flattened.extend(flatten(grand_children))
return flattened return flattened
# }}} # }}}
@ -269,32 +324,90 @@ def flatten_project(project_data): # {{{
# }}} # }}}
def filter_project_any(project_data, filters): # {{{ # def filter_project_any(project_data, filters): # {{{
filtered_project = { # filtered_project = {
"name": project_data["name"], # "name": project_data["name"],
"children": [] # "id": project_data.get("id", ""),
} # # "description": project_data["description"],
children = project_data.get("children", []) # "children": [],
for child in children: # "format": project_data["format"]
include = False # }
for filter_text in filters: # children = project_data.get("children", [])
if filter_text.lower() in child["name"].lower(): # for child in children:
include = True # include = False
break # for filter_text in filters:
if include: # if filter_text.lower() in child["name"].lower():
filtered_project["children"].append(filter_project_any(child, filters)) # include = True
return filtered_project # break
# if include:
# filtered_project["children"].append(filter_project_any(child, filters))
# return filtered_project
def filter_project_any(project_data, filters, include_headers=False):
include = False
if include_headers:
if project_data["format"] == "h1" or project_data["format"] == "h2":
include = True
for filter_text in filters:
if filter_text in project_data["name"]:
include = True
break
children = []
for child in project_data.get("children", []):
child = filter_project_any(child, filters, include_headers=include_headers)
if child:
children.append(child)
project_data["children"] = children
if include or children:
return project_data
else:
return None
# }}} # }}}
def filter_project_all(project_data, filters): # {{{
include = True
for filter_text in filters:
if filter_text not in project_data["name"]:
include = False
break
children = []
for child in project_data.get("children", []):
child = filter_project_all(child, filters)
if child:
children.append(child)
project_data["children"] = children
if include or children:
return project_data
else:
return None
def strip(project_data, regex): # {{{ def strip(project_data, regex): # {{{
project_data["name"] = re.sub(regex, "", project_data["name"]) project_data["name"] = re.sub(regex, "", project_data["name"])
children = project_data.get("children", []) children = project_data.get("children", [])
for child in children: for child in children:
strip(child, regex) strip(child, regex)
return project_data return project_data
# }}}
def rstrip(project_data): # {{{
project_data["name"] = project_data["name"].rstrip()
children = project_data.get("children", [])
for child in children:
rstrip(child)
return project_data
# }}} # }}}
@ -311,7 +424,16 @@ highlights = {
"@a": "red", "@a": "red",
"@b": "blue", "@b": "blue",
"@c": "green", "@c": "green",
"@d": "violet" "@d": "violet",
"@done": "green",
"@missed": "red",
"@na": "blue",
"@one": "base01",
"@two": "base01",
"@three": "base01",
"@five": "base01",
"@eight": "base01",
"@thirteen": "base01",
} }
@ -326,45 +448,108 @@ def highlight(project_data): # {{{
# }}} # }}}
colors1 = {
"xnext": "blue",
"xtimed": "orange",
"xwhenever": "orange",
"xwaiting": "cyan",
"xmaybe": "violet",
"xrepeat": "green",
"xscheduled": "red",
"xblocked": "red",
"xvisualisation": "red",
"xactive": "underline magenta",
"xhold": "underline orange",
"xsprint": "violet",
"xstory": "cyan",
"xfuture": "yellow",
"xarchive": "underline base01",
"xsomeday": "underline violet"
}
colors2 = {
"@done": "strike base01",
"@missed": "strike base01",
"@na": "strike base01",
}
colors3 = {
# "xactive": "underline",
# "xhold": "underline",
# "xarchive": "underline",
# "xsomeday": "underline",
# "@done": "strike",
# "@missed": "strike",
# "@na": "strike",
}
def recolor(project_data, colors):
for key, value in colors.items():
if key in project_data["name"]:
if key.startswith("x"):
project_data["name"] = f"[{value}]{project_data['name']} [/][base01]{key}[/]"
else:
project_data["name"] = f"[{value}]{project_data['name']}[/]"
break
children = project_data.get("children", [])
for child in children:
recolor(child, colors)
return project_data
# }}}
def print_pretty(data, indent=0, color="grey"): # {{{ def print_pretty(data, indent=0, color="grey"): # {{{
for item in data["children"]: try:
console.print(" " * indent + f"[white]•[/] [{color}]{item['name']}[/]") # href = f"https://workflowy.com/#/{data['id'].split('-')[4]}"
if item["children"]: for item in data["children"]:
print_pretty(item["children"], indent + 1) if item["format"] == "h1" or item["format"] == "h2":
console.print("")
console.print(" " * indent + f"[base3]•[/] [base3][underline]{item['name']}[/][/]")
else:
console.print(" " * indent + f"[base3]•[/] [{color}]{item['name']}[/]")
if item["children"]:
print_pretty(item, indent + 1, color)
except Exception as e:
console.log(f"data: {data} {e}")
# }}} # }}}
def find_project_by_id(project_data, target_id): # {{{ def find_project_by_id(project_data, full_data, target_id): # {{{
if project_data.get("id") == target_id: if project_data.get("id") == target_id:
return project_data return project_data, full_data
for child in project_data.get("ch", []): for child in project_data.get("ch", []):
result = find_project_by_id(child, target_id) result, full_data = find_project_by_id(child, full_data, target_id)
if result: if result:
return result return result, full_data
return None return None, full_data
# }}} # }}}
def show(parent_id, flat=False, filter_all=None, filter_any=None, color="grey"): # {{{ def show(parent_id, flat=False, filter_all=None, filter_any=None, color="grey", follow_mirrors=False, include_headers=False): # {{{
root_data = load_from_storage("root") root_data = load_from_storage("root")
project_data = find_project_by_id(root_data, parent_id) project_data, root_data = find_project_by_id(root_data, root_data, parent_id)
project_data = simplify_project(project_data) project_data, root_data = simplify_project(project_data, root_data, follow_mirrors=follow_mirrors)
if flat: if flat:
project_data = flatten_project(project_data) project_data = flatten_project(project_data)
if filter_all is not None: if filter_all is not None:
pass pass
if filter_any is not None: if filter_any is not None:
project_data = filter_project_any(project_data, filter_any) project_data = filter_project_any(project_data, filter_any, include_headers=include_headers)
project_data = rstrip(project_data)
project_data = recolor(project_data, colors2)
project_data = recolor(project_data, colors3)
project_data = recolor(project_data, colors1)
project_data = strip(project_data, r"<a href=\".*\">.*</a>") project_data = strip(project_data, r"<a href=\".*\">.*</a>")
project_data = strip(project_data, r"<time .*</time>") project_data = strip(project_data, r"<time .*</time>")
project_data = strip(project_data, r"<span[^>]*>") project_data = strip(project_data, r"<[^>]*>")
project_data = strip(project_data, r"</span>") project_data = strip(project_data, r"</[^>]*>")
project_data = remove_double_spaces(project_data)
project_data = highlight(project_data) project_data = highlight(project_data)
console.print(f"\n[white][bold]{project_data['name']}[/][/]\n") project_data = remove_double_spaces(project_data)
console.print(f"\n[base3][bold]{project_data['name']}[/][/]\n")
print_pretty(project_data, color=color) print_pretty(project_data, color=color)
console.print("") console.print("")
return True return True
@ -386,19 +571,18 @@ def main(): # {{{
subparsers = parser.add_subparsers(dest="command", required=True) subparsers = parser.add_subparsers(dest="command", required=True)
subparsers.add_parser("dump", help="Dump storage")
inbox_parser = subparsers.add_parser("inbox", help="Inbox commands") inbox_parser = subparsers.add_parser("inbox", help="Inbox commands")
inbox_parser.add_argument("name", help="Item text", nargs="*") inbox_parser.add_argument("name", help="Item text", nargs="*")
subparsers.add_parser("vis", help="Visualisations") tasks_parser = subparsers.add_parser("tasks", help="Tasks commands")
subparsers.add_parser("active", help="Active projects") tasks_parser.add_argument("filter", help="Filter text", nargs="*", default=None)
subparsers.add_parser("hold", help="Hold projects")
subparsers.add_parser("sprint", help="Sprint goals") subparsers.add_parser("dump", help="Dump storage")
subparsers.add_parser("today", help="Today's tasks")
subparsers.add_parser("habit", help="Habits") for planner_name, planner_id in PLANNER_IDS.items():
subparsers.add_parser("story", help="Stories") planner_parser = subparsers.add_parser(planner_name, help=f"{planner_name.capitalize()} commands")
subparsers.add_parser("future", help="Futures") planner_parser.add_argument("filter", help="Filter text", nargs="*", default=None)
args = parser.parse_args() args = parser.parse_args()
@ -416,32 +600,24 @@ def main(): # {{{
else: else:
show(INBOX_ID) show(INBOX_ID)
if args.command == "vis": if args.command == "tasks":
show(PLANNER_ID, flat=True, filter_any=["xvisualisation"], color="red") if args.filter:
if args.filter == "today":
if args.command == "active": show(TASKS_ID, filter_any=[get_today()], flat=True, follow_mirrors=True, include_headers=True)
show(PLANNER_ID, flat=True, filter_any=["xactive"], color="magenta") else:
show(TASKS_ID, filter_any=args.filter, flat=True, follow_mirrors=True, include_headers=True)
if args.command == "hold": else:
show(PLANNER_ID, flat=True, filter_any=["xhold"], color="orange") show(TASKS_ID, follow_mirrors=True)
if args.command == "sprint":
show(PLANNER_ID, flat=True, filter_any=["xsprint"], color="violet")
if args.command == "today":
today = get_today()
show(PLANNER_ID, flat=True, filter_any=[today], color="blue")
if args.command == "habits":
show(PLANNER_ID, flat=True, filter_any=["xtimed", "xwhenever"], color="orange")
if args.command == "story":
show(PLANNER_ID, flat=True, filter_any=["xstory"], color="cyan")
if args.command == "future": for planner_name, PLANNER_ID in PLANNER_IDS.items():
show(PLANNER_ID, flat=True, filter_any=["xfuture"], color="yellow") if args.command == planner_name:
if args.filter:
show(PLANNER_ID, filter_any=args.filter)
else:
show(PLANNER_ID)
# }}} # }}}
if __name__ == "__main__": if __name__ == "__main__":
main() main()

Loading…
Cancel
Save