aboutsummaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorArpit Chakladar <arpitchakladar+git@gmail.com>2026-08-16 19:59:48 +0530
committerArpit Chakladar <arpitchakladar+git@gmail.com>2026-08-29 03:50:26 +0530
commit2d482bcb7f1f36d8ea017f5fa8091a896faead49 (patch)
treeae694a0ebabd91d9781eaf1cd71a479853477f19 /modules
parent7a3b718c3196e0b0129bee4a2705c7f2fb5b206f (diff)
downloadhome-manager-config-2d482bcb7f1f36d8ea017f5fa8091a896faead49.tar.gz
home-manager-config-2d482bcb7f1f36d8ea017f5fa8091a896faead49.zip
feat: added auto-completion for usque-warp, fixed usque-warp disconnect
- Added zsh auto-completion for usque-warp - Fixed usque-warp disconnect
Diffstat (limited to 'modules')
-rw-r--r--modules/scripts/lib.nix59
-rw-r--r--modules/scripts/usque-warp/completion.zsh17
-rw-r--r--modules/scripts/usque-warp/default.nix1
-rw-r--r--modules/scripts/usque-warp/script.sh45
-rw-r--r--modules/web/chawan/default.nix2
5 files changed, 94 insertions, 30 deletions
diff --git a/modules/scripts/lib.nix b/modules/scripts/lib.nix
index 70affba..77c0a20 100644
--- a/modules/scripts/lib.nix
+++ b/modules/scripts/lib.nix
@@ -1,9 +1,7 @@
{ lib, pkgs }:
let
- shell = pkgs.runtimeShell;
-
mkScript =
- name: path: description: env: deps:
+ name: path: description: env: deps: completion:
let
descLines = lib.filter (s: s != "") (lib.splitString "\n" description);
descComment =
@@ -11,17 +9,35 @@ let
envVars = lib.concatStringsSep "\n" (
lib.mapAttrsToList (n: v: "export ${n}=${lib.escapeShellArg (toString v)}") env
);
+ base = pkgs.writeShellApplication {
+ inherit name;
+ runtimeInputs = deps;
+ text = ''
+ #!/usr/bin/env bash
+ ${descComment}${envVars}
+ ${builtins.readFile path}
+ '';
+ };
+ completionDrv =
+ pkgs.runCommand "${name}-completion"
+ {
+ nativeBuildInputs = [ pkgs.installShellFiles ];
+ }
+ ''
+ installShellCompletion --zsh --name _${name} ${pkgs.writeText "_${name}" completion}
+ '';
in
- pkgs.writeShellApplication {
- inherit name;
- runtimeInputs = deps;
- text = ''
- #!${shell}
- ${descComment}${envVars}
- ${builtins.readFile path}
- '';
- };
-
+ if completion == null then
+ base
+ else
+ pkgs.symlinkJoin {
+ name = name;
+ paths = [
+ base
+ completionDrv
+ ];
+ meta = base.meta or { };
+ };
mkScriptModule =
{
name,
@@ -32,9 +48,10 @@ let
extraLinks ? [ ],
config,
description ? "",
+ completion ? null,
}:
let
- scriptDrv = mkScript name path description env deps;
+ scriptDrv = mkScript name path description env deps completion;
in
{
options.scripts.${name} = {
@@ -48,6 +65,13 @@ let
readOnly = true;
description = "The derivation for the ${name} script.";
};
+ completion = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = completion != null;
+ description = "Whether to install a zsh completion for the ${name} script.";
+ };
+ };
desktop = {
enable = lib.mkOption {
type = lib.types.bool;
@@ -66,7 +90,6 @@ let
};
};
};
-
moduleConfig = {
scripts.${name} = lib.mkIf config.scripts.${name}.enable (
{
@@ -74,7 +97,6 @@ let
}
// lib.optionalAttrs (desktop != null) { inherit desktop; }
);
-
home.file = lib.mkIf config.scripts.${name}.enable (
builtins.listToAttrs (
map (linkPath: {
@@ -85,7 +107,6 @@ let
}) extraLinks
)
);
-
assertions = [
{
assertion =
@@ -94,6 +115,10 @@ let
|| config.terminal.kitty.enable;
message = "scripts.${name}.desktop.enable requires terminal.kitty.enable because desktop entries launch scripts in kitty.";
}
+ {
+ assertion = !config.scripts.${name}.completion.enable || completion != null;
+ message = "scripts.${name}.completion.enable is true but no completion text was provided to mkScriptModule.";
+ }
];
};
};
diff --git a/modules/scripts/usque-warp/completion.zsh b/modules/scripts/usque-warp/completion.zsh
new file mode 100644
index 0000000..fbb340e
--- /dev/null
+++ b/modules/scripts/usque-warp/completion.zsh
@@ -0,0 +1,17 @@
+#compdef usque-warp
+
+_arguments \
+ '1: :->cmds' \
+ '*::arg:->args'
+
+case $state in
+ cmds)
+ local -a commands
+ commands=(
+ 'connect:Connect to WARP'
+ 'disconnect:Disconnect from WARP'
+ 'status:Show connection status'
+ )
+ _describe 'command' commands
+ ;;
+esac
diff --git a/modules/scripts/usque-warp/default.nix b/modules/scripts/usque-warp/default.nix
index 77bf341..f5cb988 100644
--- a/modules/scripts/usque-warp/default.nix
+++ b/modules/scripts/usque-warp/default.nix
@@ -14,6 +14,7 @@ let
config.networking.usque.package
pkgs.bash
];
+ completion = builtins.readFile ./completion.zsh;
inherit config;
};
in
diff --git a/modules/scripts/usque-warp/script.sh b/modules/scripts/usque-warp/script.sh
index 01b298e..9d32872 100644
--- a/modules/scripts/usque-warp/script.sh
+++ b/modules/scripts/usque-warp/script.sh
@@ -50,6 +50,7 @@ remove_tun_default_routes() {
}
connect() {
+ sudo -v
ensure_config
if [[ -f "$PID_FILE" ]]; then
OLD_PID=$(cat "$PID_FILE")
@@ -133,6 +134,7 @@ connect() {
}
disconnect() {
+ sudo -v
echo "Disconnecting..."
local dev
if [[ -f "$IFACE_FILE" ]]; then
@@ -141,28 +143,49 @@ disconnect() {
dev=$(list_tun_ifaces | head -n1)
fi
+ # Kill usque FIRST so the kernel tears down tun0 (and every route
+ # bound to it) as a single atomic operation, instead of us racing
+ # it by pulling routes out from under a device that's still up.
+ if [[ -f "$PID_FILE" ]]; then
+ PID=$(cat "$PID_FILE")
+ if sudo kill -0 "$PID" 2>/dev/null; then
+ echo "Stopping usque..."
+ sudo kill "$PID" 2>/dev/null || true
+ for _ in {1..20}; do
+ sudo kill -0 "$PID" 2>/dev/null || break
+ sleep 0.2
+ done
+ fi
+ rm -f "$PID_FILE"
+ fi
+
+ # Belt-and-braces: if the interface (or any of its routes) somehow
+ # survived, clean them up explicitly. No-ops if tun0 is already gone.
if [[ -n "${dev:-}" ]]; then
- echo "Removing $dev routes..."
+ echo "Flushing $dev routes..."
+ sudo ip route flush dev "$dev" 2>/dev/null || true
remove_tun_default_routes "$dev"
fi
if [[ -f "$STATE_FILE" ]]; then
MASQUE_IP=$(grep -oP 'MASQUE_IP=\K[0-9.]+' "$STATE_FILE" || true)
if [[ -n "$MASQUE_IP" ]]; then
- echo "Removing MASQUE route: $MASQUE_IP"
- sudo ip route del "$MASQUE_IP" 2>/dev/null || true
+ echo "Removing MASQUE route: $MASQUE_IP"
+ sudo ip route del "$MASQUE_IP" 2>/dev/null || true
fi
- rm -f "$STATE_FILE"
- fi
- if [[ -f "$PID_FILE" ]]; then
- PID=$(cat "$PID_FILE")
- if sudo kill -0 "$PID" 2>/dev/null; then
- echo "Stopping usque..."
- sudo kill "$PID" 2>/dev/null || true
+ # Explicitly restore the pre-connect default route rather than
+ # assuming it's still intact. 'replace' is idempotent.
+ ORIGINAL_DEFAULT=$(head -n1 "$STATE_FILE")
+ if [[ "$ORIGINAL_DEFAULT" == default* ]]; then
+ echo "Restoring original default route..."
+ sudo ip route replace "$ORIGINAL_DEFAULT" \
+ || echo "Warning: could not restore original default route"
fi
- rm -f "$PID_FILE"
+
+ rm -f "$STATE_FILE"
fi
+
rm -f "$IFACE_FILE"
echo "Disconnected"
}
diff --git a/modules/web/chawan/default.nix b/modules/web/chawan/default.nix
index b1e0e9f..b71d902 100644
--- a/modules/web/chawan/default.nix
+++ b/modules/web/chawan/default.nix
@@ -67,8 +67,6 @@
};
page = {
o = ''() => pager.extern('xdg-open "$CHA_HOVER_URL"', {env: {CHA_HOVER_URL: pager.hoverLink}})'';
- ":q" = "() => pager.quit()";
- q = "";
};
};
};