|
|
@ -23,7 +23,9 @@ PLANNER_IDS = { |
|
|
|
"mind": "09e9a2c7-954d-9178-7bca-de54d6f6680d", |
|
|
|
"social": "2be5c4e5-ebfe-a462-3389-5b83aa86d016", |
|
|
|
"church": "c69aa1a1-26a3-2ab7-a125-fe6b61d108bd", |
|
|
|
"work": "f6306ec9-9243-a249-3af7-aa7d64963e2b" |
|
|
|
"work": "f6306ec9-9243-a249-3af7-aa7d64963e2b", |
|
|
|
"affirm": "a1412d52-c72c-0612-f5b1-48874ef03943", |
|
|
|
"tabs": "63aa4d3a-4db3-9b8c-cbae-a49fca975c1e", |
|
|
|
} |
|
|
|
|
|
|
|
solarized_theme = Theme({ |
|
|
@ -289,6 +291,7 @@ def simplify_project(project_data, full_data, follow_mirrors=False): # {{{ |
|
|
|
"name": project_data.get("nm", ""), |
|
|
|
"id": project_data.get("id", ""), |
|
|
|
"children": [], |
|
|
|
"description": project_data.get("no", ""), |
|
|
|
"format": project_data.get("metadata", {}).get("layoutMode", None) |
|
|
|
} |
|
|
|
children = project_data.get("ch", []) |
|
|
@ -369,16 +372,18 @@ def filter_project_any(project_data, filters, include_headers=False): |
|
|
|
# }}} |
|
|
|
|
|
|
|
|
|
|
|
def filter_project_all(project_data, filters): # {{{ |
|
|
|
def filter_project_all(project_data, filters, include_headers=False): # {{{ |
|
|
|
include = True |
|
|
|
if include_headers and (project_data["format"] == "h1" or project_data["format"] == "h2"): |
|
|
|
pass |
|
|
|
else: |
|
|
|
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) |
|
|
|
child = filter_project_all(child, filters, include_headers=include_headers) |
|
|
|
if child: |
|
|
|
children.append(child) |
|
|
|
|
|
|
@ -389,23 +394,24 @@ def filter_project_all(project_data, filters): # {{{ |
|
|
|
else: |
|
|
|
return None |
|
|
|
|
|
|
|
# }}} |
|
|
|
|
|
|
|
|
|
|
|
def strip(project_data, regex): # {{{ |
|
|
|
project_data["name"] = re.sub(regex, "", project_data["name"]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def replace(project_data, regex, replacement): # {{{ |
|
|
|
project_data["name"] = re.sub(regex, replacement, project_data["name"]) |
|
|
|
children = project_data.get("children", []) |
|
|
|
for child in children: |
|
|
|
strip(child, regex) |
|
|
|
replace(child, regex, replacement) |
|
|
|
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) |
|
|
|
def strip(project_data, regex): # {{{ |
|
|
|
project_data = replace(project_data, regex, "") |
|
|
|
return project_data |
|
|
|
|
|
|
|
# }}} |
|
|
@ -468,19 +474,9 @@ colors1 = { |
|
|
|
} |
|
|
|
|
|
|
|
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", |
|
|
|
"@done": "strike", |
|
|
|
"@missed": "strike", |
|
|
|
"@na": "strike", |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -488,9 +484,9 @@ 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}[/]" |
|
|
|
project_data["name"] = f"[{value}]{project_data['name'].strip(" ")}[/] [base01]{key}[/]" |
|
|
|
else: |
|
|
|
project_data["name"] = f"[{value}]{project_data['name']}[/]" |
|
|
|
project_data["name"] = f"[{value}]{project_data['name'].strip()}[/]" |
|
|
|
break |
|
|
|
children = project_data.get("children", []) |
|
|
|
for child in children: |
|
|
@ -499,27 +495,37 @@ def recolor(project_data, colors): |
|
|
|
# }}} |
|
|
|
|
|
|
|
|
|
|
|
def print_pretty(data, indent=0, color="grey"): # {{{ |
|
|
|
def print_pretty(data, indent=0, color="grey", show_description=True, show_id=False): # {{{ |
|
|
|
try: |
|
|
|
# href = f"https://workflowy.com/#/{data['id'].split('-')[4]}" |
|
|
|
for item in data["children"]: |
|
|
|
if item["format"] == "h1" or item["format"] == "h2": |
|
|
|
|
|
|
|
if item["format"] == "h1": |
|
|
|
console.print("") |
|
|
|
console.print(" " * indent + f"[base3]•[/] [base3][underline]{item['name']}[/][/]") |
|
|
|
console.print(" " * indent + f"[base3]•[/] [base3][underline]{item['name']}[/][/][base01]{' ' + item['id'].split('-')[4] if show_id else ''}[/]") |
|
|
|
elif item["format"] == "h2": |
|
|
|
console.print(" " * indent + f"[base3]•[/] [base1][underline]{item['name']}[/][/][base01]{' ' + item['id'].split('-')[4] if show_id else ''}[/]") |
|
|
|
|
|
|
|
else: |
|
|
|
console.print(" " * indent + f"[base3]•[/] [{color}]{item['name']}[/]") |
|
|
|
console.print(" " * indent + f"[base3]•[/] [{color}]{item['name']}[/][base01]{' ' + item['id'].split('-')[4] if show_id else ''}[/]") |
|
|
|
|
|
|
|
|
|
|
|
if item["description"] and show_description: |
|
|
|
console.print(" " * (indent + 1) + f"[base01]{item['description'].replace('\n', '\n' + ' ' * (indent + 1))}[/]") |
|
|
|
|
|
|
|
if item["children"]: |
|
|
|
print_pretty(item, indent + 1, color) |
|
|
|
print_pretty(item, indent + 1, color, show_description=show_description, show_id=show_id) |
|
|
|
|
|
|
|
except Exception as e: |
|
|
|
console.log(f"data: {data} {e}") |
|
|
|
console.log(f"Error: {e}") |
|
|
|
|
|
|
|
# }}} |
|
|
|
|
|
|
|
|
|
|
|
def find_project_by_id(project_data, full_data, target_id): # {{{ |
|
|
|
if project_data.get("id") == target_id: |
|
|
|
if project_data.get("id"): |
|
|
|
if target_id in project_data.get("id"): |
|
|
|
return project_data, full_data |
|
|
|
|
|
|
|
for child in project_data.get("ch", []): |
|
|
|
result, full_data = find_project_by_id(child, full_data, target_id) |
|
|
|
if result: |
|
|
@ -529,19 +535,17 @@ def find_project_by_id(project_data, full_data, target_id): # {{{ |
|
|
|
# }}} |
|
|
|
|
|
|
|
|
|
|
|
def show(parent_id, flat=False, filter_all=None, filter_any=None, color="grey", follow_mirrors=False, include_headers=False): # {{{ |
|
|
|
def show(parent_id, flat=False, filters=None, color="grey", follow_mirrors=False, include_headers=False, show_description=True, show_id=False): # {{{ |
|
|
|
root_data = load_from_storage("root") |
|
|
|
project_data, root_data = find_project_by_id(root_data, root_data, parent_id) |
|
|
|
project_data, root_data = simplify_project(project_data, root_data, follow_mirrors=follow_mirrors) |
|
|
|
if flat: |
|
|
|
project_data = flatten_project(project_data) |
|
|
|
if filter_all is not None: |
|
|
|
pass |
|
|
|
if filter_any is not None: |
|
|
|
project_data = filter_project_any(project_data, filter_any, include_headers=include_headers) |
|
|
|
project_data = rstrip(project_data) |
|
|
|
if filters is not None: |
|
|
|
project_data = filter_project_all(project_data, filters, include_headers=include_headers) |
|
|
|
project_data = replace(project_data, r" *<", "<") |
|
|
|
project_data = replace(project_data, r" *$", "") |
|
|
|
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"<time .*</time>") |
|
|
@ -549,8 +553,10 @@ def show(parent_id, flat=False, filter_all=None, filter_any=None, color="grey", |
|
|
|
project_data = strip(project_data, r"</[^>]*>") |
|
|
|
project_data = highlight(project_data) |
|
|
|
project_data = remove_double_spaces(project_data) |
|
|
|
console.print(f"\n[base3][bold]{project_data['name']}[/][/]\n") |
|
|
|
print_pretty(project_data, color=color) |
|
|
|
console.print(f"\n[base3][bold]{project_data['name']}[/][/]") |
|
|
|
if project_data.get("description") and show_description: |
|
|
|
console.print(f"[base01]{project_data['description']}[/]") |
|
|
|
print_pretty(project_data, color=color, show_description=show_description, show_id=show_id) |
|
|
|
console.print("") |
|
|
|
return True |
|
|
|
|
|
|
@ -567,11 +573,9 @@ def dump(): # {{{ |
|
|
|
def main(): # {{{ |
|
|
|
import argparse |
|
|
|
parser = argparse.ArgumentParser(description="Workdlowy CLI") |
|
|
|
parser.add_argument("--refresh", action="store_true", help="Refresh session cookie and Workflowy data") |
|
|
|
|
|
|
|
subparsers = parser.add_subparsers(dest="command", required=True) |
|
|
|
|
|
|
|
|
|
|
|
inbox_parser = subparsers.add_parser("inbox", help="Inbox commands") |
|
|
|
inbox_parser.add_argument("name", help="Item text", nargs="*") |
|
|
|
|
|
|
@ -579,14 +583,26 @@ def main(): # {{{ |
|
|
|
tasks_parser.add_argument("filter", help="Filter text", nargs="*", default=None) |
|
|
|
|
|
|
|
subparsers.add_parser("dump", help="Dump storage") |
|
|
|
subparsers.add_parser("refresh", help="Refresh session cookie and Workflowy data") |
|
|
|
|
|
|
|
for planner_name, planner_id in PLANNER_IDS.items(): |
|
|
|
planner_parser = subparsers.add_parser(planner_name, help=f"{planner_name.capitalize()} commands") |
|
|
|
planner_parser.add_argument("filter", help="Filter text", nargs="*", default=None) |
|
|
|
planner_parser.add_argument("--hide-comments", action="store_true", help="Do not show comments") |
|
|
|
planner_parser.add_argument("--flat", action="store_true", help="Show flat list") |
|
|
|
planner_parser.add_argument("--hide-headers", action="store_true", help="Hide headers") |
|
|
|
planner_parser.add_argument("--show-id", action="store_true", help="Show item id") |
|
|
|
|
|
|
|
focus_parser = subparsers.add_parser("focus", help="Focus commands") |
|
|
|
focus_parser.add_argument("id", help="Item id", nargs=1) |
|
|
|
focus_parser.add_argument("--hide-comments", action="store_true", help="Do not show comments") |
|
|
|
focus_parser.add_argument("--flat", action="store_true", help="Show flat list") |
|
|
|
focus_parser.add_argument("--hide-headers", action="store_true", help="Hide headers") |
|
|
|
focus_parser.add_argument("--show-id", action="store_true", help="Show item id") |
|
|
|
|
|
|
|
args = parser.parse_args() |
|
|
|
|
|
|
|
if args.refresh: |
|
|
|
if args.command == "refresh": |
|
|
|
refresh_cookie() |
|
|
|
refresh_workflowy_data() |
|
|
|
|
|
|
@ -602,19 +618,24 @@ def main(): # {{{ |
|
|
|
|
|
|
|
if args.command == "tasks": |
|
|
|
if args.filter: |
|
|
|
if args.filter == "today": |
|
|
|
show(TASKS_ID, filter_any=[get_today()], flat=True, follow_mirrors=True, include_headers=True) |
|
|
|
if args.filter == ["today"]: |
|
|
|
t = get_today() |
|
|
|
show(TASKS_ID, filters=[t], flat=True, follow_mirrors=True, include_headers=True, show_description=not args.hide_comments, show_id=args.show_id) |
|
|
|
else: |
|
|
|
show(TASKS_ID, filter_any=args.filter, flat=True, follow_mirrors=True, include_headers=True) |
|
|
|
show(TASKS_ID, filters=args.filter, flat=True, follow_mirrors=True, include_headers=True, show_description=not args.hide_comments, show_id=args.show_id) |
|
|
|
else: |
|
|
|
show(TASKS_ID, follow_mirrors=True) |
|
|
|
show(TASKS_ID, follow_mirrors=True, show_description=not args.hide_comments, show_id=args.show_id) |
|
|
|
|
|
|
|
for planner_name, PLANNER_ID in PLANNER_IDS.items(): |
|
|
|
if args.command == planner_name: |
|
|
|
if args.filter: |
|
|
|
show(PLANNER_ID, filter_any=args.filter) |
|
|
|
show(PLANNER_ID, filters=args.filter, show_description=not args.hide_comments, flat=args.flat, include_headers=not args.hide_headers, show_id=args.show_id) |
|
|
|
else: |
|
|
|
show(PLANNER_ID) |
|
|
|
show(PLANNER_ID, show_description=not args.hide_comments, flat=args.flat, include_headers=not args.hide_headers, show_id=args.show_id) |
|
|
|
|
|
|
|
if args.command == "focus": |
|
|
|
show(args.id[0], follow_mirrors=True, show_description=not args.hide_comments, flat=args.flat, include_headers=not args.hide_headers, show_id=args.show_id) |
|
|
|
|
|
|
|
|
|
|
|
# }}} |
|
|
|
|
|
|
|