about summary refs log tree commit diff stats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--modules/by-name/ts/tskm/module.nix130
-rwxr-xr-xmodules/by-name/ts/tskm/taskwarrior_hooks/enforce-projects.sh12
-rw-r--r--modules/common/default.nix4
3 files changed, 146 insertions, 0 deletions
diff --git a/modules/by-name/ts/tskm/module.nix b/modules/by-name/ts/tskm/module.nix
new file mode 100644
index 00000000..fa61bf7a
--- /dev/null
+++ b/modules/by-name/ts/tskm/module.nix
@@ -0,0 +1,130 @@
+{
+  lib,
+  config,
+  pkgs,
+  baseLib,
+  ...
+}: let
+  cfg = config.soispha.programs.tskm;
+
+  allProjectNames = lib.lists.flatten (lib.attrsets.mapAttrsToList mkProject cfg.projects);
+
+  projectList = builtins.concatStringsSep "\n" allProjectNames;
+  mkProject = name: value: let
+    subprojects = lib.attrsets.mapAttrsToList (newName: mkProject "${name}.${newName}") value.subprojects;
+  in
+    [name] ++ subprojects;
+
+  firefoxProfiles = builtins.listToAttrs (builtins.map (name:
+    lib.attrsets.nameValuePair name {
+      inherit name;
+      # We use the hash-based function here, so that we can avoid an id change if a new
+      # profile is added (i.e., simply using it index.)
+      # TODO: However, I do not know what this id is for and if it would be bad if it changed? <2025-04-02>
+      id = baseLib.idFromString name;
+    })
+  allProjectNames);
+
+  contexts =
+    builtins.concatStringsSep "\n"
+    (lib.lists.flatten
+      (lib.attrsets.mapAttrsToList mkContext cfg.projects));
+  mkContext = name: value: let
+    subprojects =
+      lib.attrsets.mapAttrsToList
+      (newName: newValue: let
+        finalValue =
+          if newValue.prefix == ""
+          then newValue // {inherit (value) prefix;}
+          else newValue;
+      in
+        mkContext "${name}.${newName}" finalValue)
+      value.subprojects;
+    contextName = builtins.replaceStrings ["."] ["_"] name;
+  in
+    [
+      ''
+        context.${contextName}.rc.neorg_path=${value.prefix}/index.norg
+        context.${contextName}.read=project:${name}
+        context.${contextName}.write=project:${name}
+      ''
+    ]
+    ++ subprojects;
+
+  contextsFile =
+    pkgs.writeText "contexts-file" contexts;
+
+  projectType = lib.types.submodule {
+    options = {
+      name = lib.mkOption {
+        type = lib.types.str;
+        example = "timesinks";
+        description = "The name of this project";
+      };
+
+      prefix = lib.mkOption {
+        type = lib.types.str;
+        default = "";
+        example = "programming/zig";
+        description = ''
+          A prefix to append to the project neorg path.
+          This can be used to group similar project's neorg directories together. '
+        '';
+      };
+
+      subprojects = lib.mkOption {
+        type = lib.types.attrsOf projectType;
+        description = ''
+          A list of subprojects.
+          These can also contain subprojects.
+        '';
+        default = {};
+      };
+    };
+  };
+in {
+  options.soispha.programs.tskm = {
+    enable = lib.mkEnableOption "tskm";
+
+    projects = lib.mkOption {
+      type = lib.types.attrsOf projectType;
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    soispha.programs = {
+      firefox.profiles = firefoxProfiles;
+      taskwarrior = {
+        includeFiles = {
+          tskm-contexts = contextsFile;
+        };
+        hooks = {
+          enforce-projects =
+            config.lib.taskwarrior.mkHook "on-add" [
+              pkgs.jq
+              pkgs.gnugrep
+              pkgs.neorg
+            ]
+            ./taskwarrior_hooks/enforce-projects.sh;
+        };
+      };
+    };
+
+    home-manager.users.soispha = {
+      home.sessionVariables = {
+        # TODO: Remove this hard-coded path with a reference. <2025-04-04>
+        "TSKM_PROJECT_FILE" = "/home/soispha/repos/nix/config/modules/common/projects.json";
+      };
+
+      programs.nixvim = {
+        plugins.neorg.settings.load."core.dirman".config.workspaces = {
+          tskm = "~/.local/share/tskm/notes";
+        };
+      };
+
+      xdg.configFile."tskm/projects.list" = {
+        text = projectList;
+      };
+    };
+  };
+}
diff --git a/modules/by-name/ts/tskm/taskwarrior_hooks/enforce-projects.sh b/modules/by-name/ts/tskm/taskwarrior_hooks/enforce-projects.sh
new file mode 100755
index 00000000..d65f786a
--- /dev/null
+++ b/modules/by-name/ts/tskm/taskwarrior_hooks/enforce-projects.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env sh
+
+new_task="$1"
+
+project="$(echo "$new_task" | jq '.project' --raw-output)"
+[ "$project" = "null" ] && die "No project supplied!"
+
+if ! neorg list | grep -q "^$project$"; then
+    die "The project '$project' is not (yet) registered, registered projects: $(neorg list | tr '\n' ',')"
+fi
+
+# vim: ft=sh
diff --git a/modules/common/default.nix b/modules/common/default.nix
index 7b3713d0..7db33d09 100644
--- a/modules/common/default.nix
+++ b/modules/common/default.nix
@@ -189,6 +189,10 @@
         enable = true;
         hooks = import ./hooks {inherit pkgs lib config;};
       };
+      tskm = {
+        enable = true;
+        projects = builtins.fromJSON (builtins.readFile ./projects.nix);
+      };
       yambar.enable = true;
       yt.enable = true;
       zathura.enable = true;