diff --git a/dots/.config/task/.gitignore b/dots/.config/task/.gitignore deleted file mode 100644 index 52a7fce..0000000 --- a/dots/.config/task/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -taskrc.d/sync -taskrc.d/private diff --git a/dots/.config/task/taskrc b/dots/.config/task/taskrc deleted file mode 100644 index 2f5eb1f..0000000 --- a/dots/.config/task/taskrc +++ /dev/null @@ -1,13 +0,0 @@ -include ./taskrc.d/aliases -include ./taskrc.d/urgency -include ./taskrc.d/reports -include ./taskrc.d/contexts -include ./taskrc.d/colors -include ./taskrc.d/udas - -search.case.sensitive=no - -rc.json.array=on -rc.verbose=nothing -news.version=3.4.2 - diff --git a/dots/.config/task/taskrc.d/aliases b/dots/.config/task/taskrc.d/aliases deleted file mode 100644 index 6ee4c2a..0000000 --- a/dots/.config/task/taskrc.d/aliases +++ /dev/null @@ -1,4 +0,0 @@ -alias.burndown=burndown.daily -alias.a=add -alias.rm=delete -alias.e=modify diff --git a/dots/.config/task/taskrc.d/colors b/dots/.config/task/taskrc.d/colors deleted file mode 100644 index 968476f..0000000 --- a/dots/.config/task/taskrc.d/colors +++ /dev/null @@ -1,12 +0,0 @@ -color.active=bold white on black -color.alternate= -color.scheduled= -color.until= -color.blocking=bold -color.blocked=gray15 -color.uda.priority.H=bold -color.uda.priority.M= -color.uda.priority.L= -color.due= -color.due.today= -color.overdue= diff --git a/dots/.config/task/taskrc.d/contexts b/dots/.config/task/taskrc.d/contexts deleted file mode 100644 index 3cac65b..0000000 --- a/dots/.config/task/taskrc.d/contexts +++ /dev/null @@ -1,5 +0,0 @@ -context.home.read=project:home -context.work.read=tags:work -context.home.write=project:home -context.studies.read=project:studies -context.studies.write=project:studies diff --git a/dots/.config/task/taskrc.d/desktop-arch b/dots/.config/task/taskrc.d/desktop-arch deleted file mode 100644 index de94d88..0000000 --- a/dots/.config/task/taskrc.d/desktop-arch +++ /dev/null @@ -1,4 +0,0 @@ -include /usr/share/doc/task/rc/light-256.theme - -include ./locations -include ./sync diff --git a/dots/.config/task/taskrc.d/locations b/dots/.config/task/taskrc.d/locations deleted file mode 100644 index 7bd7e99..0000000 --- a/dots/.config/task/taskrc.d/locations +++ /dev/null @@ -1,2 +0,0 @@ -data.location=$XDG_DATA_HOME/task/ -hooks.location=$XDG_DATA_HOME/task/hooks diff --git a/dots/.config/task/taskrc.d/reports b/dots/.config/task/taskrc.d/reports deleted file mode 100644 index 3dc27b9..0000000 --- a/dots/.config/task/taskrc.d/reports +++ /dev/null @@ -1,24 +0,0 @@ -# The default report is `next`, to obtain details on a report -# (e.g. the columns used), the following command can be used: -# -# `task _get rc.report..columns` - -report.next.columns=id,start.age,entry.age,depends,project,tags,scheduled.countdown,due.relative,until.remaining,description -report.next.labels=ID,Active,Age,Deps,Project,Tag,S,Due,Until,Description -report.next.filter=status:pending -WAITING -BLOCKED limit:page - -report.in.columns=id,description -report.in.labels=ID,Description -report.in.description=Inbox (untagged) -report.in.filter=status:pending tags.none: -report.in.sort=entry+ - -report.recent.columns=id,description,entry -report.recent.labels=ID,Description,Age -report.recent.description=Recently added -report.recent.sort=entry+ - -report.minimal.columns=id,description -report.minimal.labels=, - -# verbose=blank,header,footnote,label,new-id,affected,edit,special,project,unwait diff --git a/dots/.config/task/taskrc.d/sync.example b/dots/.config/task/taskrc.d/sync.example deleted file mode 100644 index 5653579..0000000 --- a/dots/.config/task/taskrc.d/sync.example +++ /dev/null @@ -1,3 +0,0 @@ -sync.server.url= -sync.server.client_id= -sync.encryption_secret= diff --git a/dots/.config/task/taskrc.d/udas b/dots/.config/task/taskrc.d/udas deleted file mode 100644 index 0482cac..0000000 --- a/dots/.config/task/taskrc.d/udas +++ /dev/null @@ -1,2 +0,0 @@ -uda.url.type=string -uda.url.label=URL diff --git a/dots/.config/task/taskrc.d/urgency b/dots/.config/task/taskrc.d/urgency deleted file mode 100644 index f4695e1..0000000 --- a/dots/.config/task/taskrc.d/urgency +++ /dev/null @@ -1,9 +0,0 @@ -urgency.uda.priority.L.coefficient=-1.0 - -urgency.user.project.studies.coefficient=1.0 -urgency.user.project.admin.coefficient=1.0 -urgency.user.project.personal.coefficient=0.5 -urgency.user.project.groceries.coefficient=0.5 -urgency.user.project.home.coefficient=0.2 -urgency.user.project.creative.coefficient=0.0 -urgency.user.project.side.coefficient=0.0 diff --git a/dots/.local/share/task/hooks/on-exit.sync.py b/dots/.local/share/task/hooks/on-exit.sync.py deleted file mode 100755 index 807b60c..0000000 --- a/dots/.local/share/task/hooks/on-exit.sync.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 - -# Source: - -# This hooks script syncs task warrior to the configured task server without blocking. -# The on-exit event is triggered once, after all processing is complete. - -# Make sure hooks are enabled and this hook script is executable. -# Run `task diag` for diagnostics on the hook. - -import json -import subprocess -import sys - -try: - tasks = json.loads(sys.stdin.readline()) -except: - # No input - pass - -# Call the `sync` command -# hooks=0 ensures that the sync command doesn't call the on-exit hook -# verbose=nothing sets the verbosity to print nothing at all - -ps_1 = subprocess.Popen( - ["task", "rc.hooks=0", "sync"], - stdin=subprocess.PIPE, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, -) - -sys.exit(0) diff --git a/dots/.local/share/task/scripts/sync-and-notify.sh b/dots/.local/share/task/scripts/sync-and-notify.sh deleted file mode 100755 index 247297c..0000000 --- a/dots/.local/share/task/scripts/sync-and-notify.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -# Redirect both stdout and stderr to notify-send as is, but set -# urgency to critical if the command fails -output="$(task rc.hooks=0 sync 2>&1)" -ret=$? -if [ $ret -ne 0 ]; then - urgency=critical -else - urgency=normal -fi -notify-send -u $urgency "Taskwarrior sync" "$output" diff --git a/home/modules/taskwarrior/default.nix b/home/modules/taskwarrior/default.nix index da5880e..959fa4f 100644 --- a/home/modules/taskwarrior/default.nix +++ b/home/modules/taskwarrior/default.nix @@ -2,7 +2,6 @@ config, lib, pkgs, - dotsPath, myUtils, osConfig ? null, inputs ? null, @@ -13,6 +12,52 @@ let cfg = config.taskwarrior; sops = myUtils.sopsAvailability config osConfig; standalone = osConfig == null; + + syncHook = pkgs.writers.writePython3 "on-exit.sync.py" { flakeIgnore = [ "E501" ]; } '' + # Source: + + # This hook syncs Taskwarrior to the configured task server without blocking. + # The on-exit event is triggered once, after all processing is complete. + + import json + import subprocess + import sys + + try: + json.loads(sys.stdin.readline()) + except json.JSONDecodeError: + # No input + pass + + # hooks=0 ensures that the sync command doesn't call the on-exit hook. + # verbose=nothing sets the verbosity to print nothing at all. + subprocess.Popen( + ["${lib.getExe pkgs.taskwarrior3}", "rc.hooks=0", "sync"], + stdin=subprocess.PIPE, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + + sys.exit(0) + ''; + + syncAndNotify = pkgs.writeShellApplication { + name = "sync-and-notify"; + runtimeInputs = [ + pkgs.libnotify + pkgs.taskwarrior3 + ]; + text = '' + # Redirect both stdout and stderr to notify-send as is, but set + # urgency to critical if the command fails. + if output="$(task rc.hooks=0 sync 2>&1)"; then + urgency=normal + else + urgency=critical + fi + notify-send -u "$urgency" "Taskwarrior sync" "$output" + ''; + }; in { options.taskwarrior.enable = lib.mkEnableOption "taskwarrior"; @@ -42,39 +87,85 @@ in lib.optional (!sops.available) "taskwarrior is enabled, but sops templates are not available. taskwarrior sync will not be configured."; - home.packages = with pkgs; [ - libnotify - taskopen - python3 - ]; - + home.packages = [ pkgs.taskopen ]; home.file = { - ".config/task/taskrc" = { - force = true; - source = dotsPath + "/.config/task/taskrc"; - }; - ".config/task/taskrc.d/aliases".source = dotsPath + "/.config/task/taskrc.d/aliases"; - ".config/task/taskrc.d/colors".source = dotsPath + "/.config/task/taskrc.d/colors"; - ".config/task/taskrc.d/contexts".source = dotsPath + "/.config/task/taskrc.d/contexts"; - ".config/task/taskrc.d/reports".source = dotsPath + "/.config/task/taskrc.d/reports"; - ".config/task/taskrc.d/udas".source = dotsPath + "/.config/task/taskrc.d/udas"; - ".config/task/taskrc.d/urgency".source = dotsPath + "/.config/task/taskrc.d/urgency"; - ".local/share/task/hooks/on-exit.sync.py" = { - source = dotsPath + "/.local/share/task/hooks/on-exit.sync.py"; - }; - ".local/share/task/scripts/sync-and-notify.sh" = { - source = dotsPath + "/.local/share/task/scripts/sync-and-notify.sh"; - executable = true; - }; + ".config/task/taskrc".text = '' + include ${config.xdg.configHome}/task/home-manager-taskrc + ''; + ".local/share/task/hooks/on-exit.sync.py".source = syncHook; + ".local/share/task/scripts/sync-and-notify.sh".source = lib.getExe syncAndNotify; }; - programs.taskwarrior = with pkgs; { + programs.taskwarrior = { enable = true; - package = taskwarrior3; + package = pkgs.taskwarrior3; colorTheme = "dark-256"; config = { - recurrence = "off"; - reserved.lines = 3; + # taskrc.d/aliases + "alias.a" = "add"; + "alias.burndown" = "burndown.daily"; + "alias.e" = "modify"; + "alias.rm" = "delete"; + + # taskrc.d/colors + "color.active" = "bold white on black"; + "color.alternate" = ""; + "color.blocked" = "gray15"; + "color.blocking" = "bold"; + "color.due" = ""; + "color.due.today" = ""; + "color.overdue" = ""; + "color.scheduled" = ""; + "color.uda.priority.H" = "bold"; + "color.uda.priority.L" = ""; + "color.uda.priority.M" = ""; + "color.until" = ""; + + # taskrc.d/contexts + "context.home.read" = "project:home"; + "context.home.write" = "project:home"; + "context.studies.read" = "project:studies"; + "context.studies.write" = "project:studies"; + "context.work.read" = "tags:work"; + + # taskrc.d/reports + "report.in.columns" = "id,description"; + "report.in.description" = "Inbox (untagged)"; + "report.in.filter" = "status:pending tags.none:"; + "report.in.labels" = "ID,Description"; + "report.in.sort" = "entry+"; + "report.minimal.columns" = "id,description"; + "report.minimal.labels" = ","; + "report.next.columns" = + "id,start.age,entry.age,depends,project,tags,scheduled.countdown,due.relative,until.remaining,description"; + "report.next.filter" = "status:pending -WAITING -BLOCKED limit:page"; + "report.next.labels" = "ID,Active,Age,Deps,Project,Tag,S,Due,Until,Description"; + "report.recent.columns" = "id,description,entry"; + "report.recent.description" = "Recently added"; + "report.recent.labels" = "ID,Description,Age"; + "report.recent.sort" = "entry+"; + + # taskrc.d/udas + "uda.url.label" = "URL"; + "uda.url.type" = "string"; + + # taskrc.d/urgency + "urgency.uda.priority.L.coefficient" = "-1.0"; + "urgency.user.project.admin.coefficient" = "1.0"; + "urgency.user.project.creative.coefficient" = "0.0"; + "urgency.user.project.groceries.coefficient" = "0.5"; + "urgency.user.project.home.coefficient" = "0.2"; + "urgency.user.project.personal.coefficient" = "0.5"; + "urgency.user.project.side.coefficient" = "0.0"; + "urgency.user.project.studies.coefficient" = "1.0"; + + # misc + "news.version" = "3.4.2"; + "rc.json.array" = "on"; + "rc.verbose" = "nothing"; + "search.case.sensitive" = "no"; + "recurrence" = "off"; + "reserved.lines" = "3"; }; extraConfig = lib.optionalString sops.available '' include ${sops.templates."taskrc.d/sync".path}