diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fcf7246 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.pre-commit-config.yaml diff --git a/.woodpecker/check.yml b/.woodpecker/check.yml new file mode 100644 index 0000000..4197230 --- /dev/null +++ b/.woodpecker/check.yml @@ -0,0 +1,31 @@ +labels: + backend: local + +pipeline: +- name: flake check + image: bash + commands: + - nix flake check + +- name: package check + image: bash + commands: + - nix build + +- name: notify + image: bash + secrets: + - source: matrix_roomid + target: room + - source: matrix_username + target: user + - source: matrix_password + target: pass + - source: matrix_homeserver + target: address + commands: + - nix run github:ambroisie/matrix-notifier + when: + status: + - failure + - success diff --git a/README.md b/README.md new file mode 100644 index 0000000..cc34cec --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ +# `zsh-done` + +This is a Zshell plug-in to automatically receive notifications after a +long-running process ends. + +## Dependencies + +* If you want notifications with icons on macOS, install `terminal-notifier`. +* If you are using `swaywm`, install `jq`. + +## Settings + +### Command duration threshold + +```zsh +DONE_MIN_CMD_DURATION=15 # Default: 5 +``` + +### Command deny-list regex + +Uses `grep -P` (Perl syntax) to filter out commands that should never notify. + +```zsh +DONE_MIN_CMD_DURATION='^\sgit (?!push|pull|fetch)' # Default: '' +``` + +### Play a sound when sending notification + +When using `terminal-notifier`, play a sound when sending the notification, +otherwise ring the terminal bell. + +```zsh +DONE_NOTIFY_SOUND=1 # Default: 0 +``` + +### Notification levels + +When using `notify-send` or `notify-desktop`, use a specific urgency level for +your notifications. + +```zsh +DONE_NOTIFICATION_URGENCY_LEVEL=low # Default: normal +DONE_NOTIFICATION_URGENCY_LEVEL_FAILURE=normal # Default: critical +``` + +### Do not show notification for visible windows (`sway` only) + +```zsh +DONE_SWAY_IGNORE_VISIBLE=1 # Default: 0 +``` + +### Allow sending notifications on non-graphical systems + +This also requires you to define the `done_send_notification` function. + +```zsh +DONE_ALLOW_NONGRAPHICAL=1 # Default: 0 + +done_send_notification() { + local exit_status="$1" + local title="$2" + local message="$3" + # Use OSC-777 to send a notification (only with compatible terminals) + echo -ne "\e]777;notify;$title;$message\e\\" +} +``` + +### Customize the notification texts + +You can define `done_format_title` and `done_format_message` to customize the +title and message of your notifications. + +```zsh +done_format_title() { + local exit_status="$1" + local cmd_duration="$2" + local last_command="$3" + + if [ "$exit_status" -eq 0 ]; then + echo "SUCCESS (__done_humanize_duration "$cmd_duration")" + else + echo "FAIL (__done_humanize_duration "$cmd_duration")" + fi +} + +done_format_message() { + local exit_status="$1" + local cmd_duration="$2" + local last_command="$3" + + printf '%s (%s)' "$last_command" "$exit_status" +} +``` + +## More information and alternatives + +This plug-in was largely inspired by [the fish package of the same +name](https://github.com/franciscolourenco/done), and steals much of the "is the +shell focused" logic from it. + +Unlike the `fish` plug-in, this one does not have support for Windows wired in. + +Alternative plug-ins: +* [`zsh-notify`](https://github.com/marzocchi/zsh-notify) +* [`zsh-background-notify`](https://github.com/t413/zsh-background-notify) diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..ab15c24 --- /dev/null +++ b/flake.lock @@ -0,0 +1,129 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "futils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "main", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1691853136, + "narHash": "sha256-wTzDsRV4HN8A2Sl0SVQY0q8ILs90CD43Ha//7gNZE+E=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f0451844bbdf545f696f029d1448de4906c7f753", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": [ + "futils" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1691747570, + "narHash": "sha256-J3fnIwJtHVQ0tK2JMBv4oAmII+1mCdXdpeCxtIsrL2A=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "c5ac3aa3324bd8aebe8622a3fc92eeb3975d317a", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "master", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "futils": "futils", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..1e94953 --- /dev/null +++ b/flake.nix @@ -0,0 +1,102 @@ +{ + description = "A zsh plug-in to receive notifications when long processes finish"; + + inputs = { + futils = { + type = "github"; + owner = "numtide"; + repo = "flake-utils"; + ref = "main"; + }; + + nixpkgs = { + type = "github"; + owner = "NixOS"; + repo = "nixpkgs"; + ref = "nixpkgs-unstable"; + }; + + pre-commit-hooks = { + type = "github"; + owner = "cachix"; + repo = "pre-commit-hooks.nix"; + ref = "master"; + inputs = { + flake-utils.follows = "futils"; + nixpkgs.follows = "nixpkgs"; + nixpkgs-stable.follows = "nixpkgs"; + }; + }; + }; + + outputs = { self, futils, nixpkgs, pre-commit-hooks } @ inputs: + futils.lib.eachDefaultSystem (system: + let + inherit (nixpkgs) lib; + pkgs = nixpkgs.legacyPackages.${system}; + in + rec { + checks = { + pre-commit = pre-commit-hooks.lib.${system}.run { + src = ./.; + + hooks = { + nixpkgs-fmt = { + enable = true; + }; + + shellcheck = { + enable = true; + }; + }; + }; + }; + + devShells = { + default = pkgs.mkShell { + name = "zsh-done"; + + inputsFrom = with self.packages.${system}; [ + zsh-done + ]; + + inherit (self.checks.${system}.pre-commit) shellHook; + }; + }; + + packages = { + default = packages.zsh-done; + + zsh-done = pkgs.stdenvNoCC.mkDerivation rec { + pname = "zsh-done"; + version = "0.1.0"; + + src = ./done.plugin.zsh; + + dontUnpack = true; + + dontConfigure = true; + + dontBuild = true; + + installPhase = '' + plugindir="$out/share/zsh/site-functions" + + mkdir -p $plugindir + cp $src $plugindir/done.plugin.zsh + ''; + + meta = with pkgs.lib; { + description = '' + A zsh plug-in to receive notifications when long processes finish + ''; + homepage = "https://gitea.belanyi.fr/ambroisie/zsh-done"; + license = licenses.mit; + platforms = platforms.unix; + maintainers = with maintainers; [ ambroisie ]; + }; + }; + }; + } + ); +}