Compare commits

...

5 Commits

Author SHA1 Message Date
Hektor Misplon d9603c543c Update git aliases 2024-12-14 15:57:23 +01:00
Hektor Misplon e29e6e808c Disable git commit gpgsign 2024-12-14 15:51:50 +01:00
Hektor Misplon 6b444e90e2
Add git worktree alias 2024-12-14 15:51:16 +01:00
Hektor Misplon 171d56150d
Migrate 'dmenu-trans' to rofi 2024-12-12 19:24:39 +01:00
Hektor Misplon fc08e2046b
Add 'taskdeps' script 2024-12-07 20:31:53 +01:00
4 changed files with 163 additions and 12 deletions

View File

@ -1,9 +0,0 @@
#!/usr/bin/env bash
options="nl:en\nen:nl\nnl:fr\nfr:nl\nen:fr\nfr:en\nnl:de\nde:nl"
selected=$(echo -e "$options" | dmenu -p "s?:t?" -i -l 0)
notify-send --app-name= -t 3000 "$(trans "$selected" -b "$(dmenu -p "$selected" &)" \
| tr -d '\n' \
| xclip -sel clip -f)"

13
.bin/rofi-trans Executable file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
options="nl:en\nen:nl\nnl:fr\nfr:nl\nen:fr\nfr:en\nnl:de\nde:nl"
selected=$(echo -en "$options" | rofi -dmenu -p "source?:target?" -i)
# notify-send --app-name= -t 3000 "$(trans "$selected" -b "$(rofi -dmenu -p "$selected" &)" \
# | tr -d '\n' \
# | xclip -sel clip -f)"
translation="$(trans "$selected" -b "$(rofi -dmenu -p "$selected" &)" | tr -d '\n')"
echo -e "Copy" | rofi -p "translation" -dmenu -i -mesg "$translation" | xargs -I{} echo -n "$translation" | xclip -selection clipboard

144
.bin/taskdeps Executable file
View File

@ -0,0 +1,144 @@
#!/usr/bin/python
import argparse
import json
import subprocess
from collections import defaultdict
def get_task_data():
command = (
"task +PENDING or +WAITING -COMPLETED -DELETED export | "
"jq '[.[] | {uuid: .uuid, id, depends: .depends, description: .description, status: .status }]'"
)
output = subprocess.check_output(command, shell=True)
return json.loads(output)
def parse_task_data(data):
dependency_graph = defaultdict(list)
task_details = {}
dependent_tasks = set()
for task in data:
task_id = task["uuid"]
task_details[task_id] = {
"id": task.get("id", "?"),
"description": task.get("description", "No description"),
"status": task.get("status", "Unknown status"),
}
if task["depends"]:
for dependency in task["depends"]:
dependency_graph[dependency].append(task_id)
dependent_tasks.add(task_id)
root_tasks = set(task_details.keys()) - dependent_tasks
return task_details, dependency_graph, root_tasks
def get_all_parents(task_id, dependency_graph):
return [
parent for parent, children in dependency_graph.items() if task_id in children
]
def build_ascii_dag(
task_id,
task_details,
dependency_graph,
prefix="",
is_last=True,
show_id=True,
visited=None,
):
if visited is None:
visited = set()
if task_id in visited:
return [f"{prefix}{'└── ' if is_last else '├── '}... (cycle detected)"]
visited.add(task_id)
task_info = task_details[task_id]
task_line = f"{prefix}{'└── ' if is_last else '├── '}{task_info['id'] + ': ' if show_id else ''}{task_info['description']} ({task_info['status']})"
lines = [task_line]
children = dependency_graph.get(task_id, [])
for idx, child in enumerate(children):
child_is_last = idx == len(children) - 1
child_prefix = prefix + (" " if is_last else "│ ")
lines.extend(
build_ascii_dag(
child,
task_details,
dependency_graph,
child_prefix,
child_is_last,
show_id,
visited.copy(),
)
)
return lines
def render_dependency_dag(task_details, dependency_graph, root_tasks, show_id):
dag_lines = []
global_visited = set()
def dfs(task_id, prefix="", is_last=True, visited=None):
if visited is None:
visited = set()
if task_id in visited:
return
visited.add(task_id)
global_visited.add(task_id)
task_info = task_details[task_id]
task_line = f"{prefix}{'└── ' if is_last else '├── '}{str(task_info['id']) + ': ' if show_id else ''}{task_info['description']} ({task_info['status']})"
dag_lines.append(task_line)
children = dependency_graph.get(task_id, [])
for idx, child in enumerate(children):
child_is_last = idx == len(children) - 1
child_prefix = prefix + (" " if is_last else "│ ")
dfs(child, child_prefix, child_is_last, visited.copy())
root_tasks_with_children = [
root for root in root_tasks if dependency_graph.get(root, [])
]
for root in sorted(
root_tasks_with_children,
key=lambda x: len(dependency_graph.get(x, [])),
reverse=True,
):
if root not in global_visited:
dfs(root)
dag_lines.append("")
return "\n".join(dag_lines).rstrip()
def main(args):
data = get_task_data()
task_details, dependency_graph, root_tasks = parse_task_data(data)
ascii_dag = render_dependency_dag(
task_details, dependency_graph, root_tasks, show_id=args.show_id
)
print(ascii_dag)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Generates a task dependency DAG for Taskwarrior tasks."
)
parser.add_argument(
"--show-id",
action="store_true",
default=False,
help="Include task IDs in the output.",
)
args = parser.parse_args()
main(args)

View File

@ -9,12 +9,14 @@
[alias]
d = diff
dc = diff --cached
ds = diff --staged
a = add
ap = add -p
c = commit
cm = commit -m
l = log --pretty=format:"(%an)\\ \\ %h\\ \\ %ad\\ \\ %s" --date=short
s = status -s
s = status --short
sv = status --verbose
co = checkout
cob = checkout -b
# Note these follow the naming convention of my `.bash_aliases`
@ -22,6 +24,7 @@
alf = "!git config -l | grep alias | cut -c 7- | fzf"
al- = "!git config --local --unset $(git config -l | grep alias | cut --delimiter="=" --fields=1 | fzf)"
rs = "restore --staged"
wt = "worktree"
[color]
ui = auto
@ -71,4 +74,4 @@
[diff]
colorMoved = zebra
[commit]
gpgsign = true
gpgsign = false