From 0734bee219d097683b37a59fa274b1fdc2051b7a Mon Sep 17 00:00:00 2001 From: djairoh Date: Tue, 6 Oct 2026 22:34:05 +0200 Subject: [PATCH] scripts reorganize --- modules/apps/default.nix | 1 + modules/apps/mpv.nix | 2 +- modules/base.nix | 5 + modules/desktop/hypr.nix | 4 +- modules/dev/default.nix | 2 +- modules/dev/uv.nix | 11 ++ modules/terminal/fish.nix | 2 +- scripts/WMScripts/backlight-notif.sh | 11 ++ scripts/WMScripts/changewall.fish | 19 +++ scripts/WMScripts/dunst.sh | 27 +++++ scripts/WMScripts/dunst_bar.py | 42 +++++++ scripts/WMScripts/exit.sh | 78 ++++++++++++ scripts/WMScripts/kitty_window.sh | 21 ++++ scripts/WMScripts/microphone.sh | 18 +++ scripts/WMScripts/microphone_bar.sh | 41 +++++++ scripts/WMScripts/murder.sh | 28 +++++ scripts/WMScripts/mute_active.sh | 73 ++++++++++++ scripts/WMScripts/record.sh | 75 ++++++++++++ scripts/WMScripts/screenshot_float.sh | 47 ++++++++ scripts/WMScripts/tess.sh | 36 ++++++ scripts/WMScripts/toggle_audiocables.sh | 38 ++++++ scripts/WMScripts/toggle_audiocables_bar.sh | 112 ++++++++++++++++++ .../fish-functions/bulkpaste.fish | 0 .../fish-functions/copy.fish | 0 .../fish-functions/files.fish | 0 .../fish-functions/fmf.fish | 0 .../fish-functions/histdelete.fish | 0 .../fish-functions/move.fish | 0 .../fish-functions/nshell.fish | 0 .../fish-functions/run.fish | 0 .../fish-functions/runl.fish | 0 .../fish-functions/secret.fish | 0 .../fish-functions/show_colour.fish | 0 .../fish-functions/sudo.fish | 0 .../fish-functions/tmux-updater.fish | 0 .../fish-functions/yazi.fish | 0 .../scripts => scripts/hypr-scripts}/bg.fish | 0 .../hypr-scripts}/gamemode_hypr.sh | 0 .../hypr-scripts}/gamemode_power.sh | 0 .../hypr-scripts}/keybinds.sh | 0 .../hypr-scripts}/screenshot_float.sh | 0 .../hypr-scripts}/shader_picker.sh | 0 .../hypr-scripts}/shader_picker_window.sh | 0 .../hypr-scripts}/toggle_focus_floating.sh | 0 .../hypr-scripts}/toggle_touchpad.sh | 0 .../hypr-scripts}/waybar.sh | 0 .../shaders => scripts/hypr-shaders}/crt.frag | 0 .../shaders => scripts/hypr-shaders}/dim.frag | 0 .../hypr-shaders}/grey.frag | 0 .../hypr-shaders}/horror.frag | 0 .../hypr-shaders}/invert.frag | 0 .../hypr-shaders}/noblue.frag | 0 .../hypr-shaders}/nogreen.frag | 0 .../hypr-shaders}/nored.frag | 0 .../hypr-shaders}/rainbow.frag | 0 .../hypr-shaders}/rbinvert.frag | 0 {modules/apps => scripts}/mpv-visualizer.lua | 0 scripts/sanitize/autoSanitize.sh | 42 +++++++ scripts/sanitize/sanitize.sh | 41 +++++++ scripts/sanitize/sanitize_hist.fish | 53 +++++++++ 60 files changed, 824 insertions(+), 5 deletions(-) create mode 100644 modules/dev/uv.nix create mode 100755 scripts/WMScripts/backlight-notif.sh create mode 100755 scripts/WMScripts/changewall.fish create mode 100755 scripts/WMScripts/dunst.sh create mode 100755 scripts/WMScripts/dunst_bar.py create mode 100755 scripts/WMScripts/exit.sh create mode 100755 scripts/WMScripts/kitty_window.sh create mode 100755 scripts/WMScripts/microphone.sh create mode 100755 scripts/WMScripts/microphone_bar.sh create mode 100755 scripts/WMScripts/murder.sh create mode 100755 scripts/WMScripts/mute_active.sh create mode 100755 scripts/WMScripts/record.sh create mode 100755 scripts/WMScripts/screenshot_float.sh create mode 100755 scripts/WMScripts/tess.sh create mode 100755 scripts/WMScripts/toggle_audiocables.sh create mode 100755 scripts/WMScripts/toggle_audiocables_bar.sh rename {modules/terminal => scripts}/fish-functions/bulkpaste.fish (100%) rename {modules/terminal => scripts}/fish-functions/copy.fish (100%) rename {modules/terminal => scripts}/fish-functions/files.fish (100%) rename {modules/terminal => scripts}/fish-functions/fmf.fish (100%) rename {modules/terminal => scripts}/fish-functions/histdelete.fish (100%) rename {modules/terminal => scripts}/fish-functions/move.fish (100%) rename {modules/terminal => scripts}/fish-functions/nshell.fish (100%) rename {modules/terminal => scripts}/fish-functions/run.fish (100%) rename {modules/terminal => scripts}/fish-functions/runl.fish (100%) rename {modules/terminal => scripts}/fish-functions/secret.fish (100%) rename {modules/terminal => scripts}/fish-functions/show_colour.fish (100%) rename {modules/terminal => scripts}/fish-functions/sudo.fish (100%) rename {modules/terminal => scripts}/fish-functions/tmux-updater.fish (100%) rename {modules/terminal => scripts}/fish-functions/yazi.fish (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/bg.fish (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/gamemode_hypr.sh (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/gamemode_power.sh (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/keybinds.sh (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/screenshot_float.sh (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/shader_picker.sh (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/shader_picker_window.sh (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/toggle_focus_floating.sh (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/toggle_touchpad.sh (100%) rename {modules/desktop/scripts => scripts/hypr-scripts}/waybar.sh (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/crt.frag (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/dim.frag (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/grey.frag (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/horror.frag (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/invert.frag (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/noblue.frag (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/nogreen.frag (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/nored.frag (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/rainbow.frag (100%) rename {modules/desktop/shaders => scripts/hypr-shaders}/rbinvert.frag (100%) rename {modules/apps => scripts}/mpv-visualizer.lua (100%) create mode 100755 scripts/sanitize/autoSanitize.sh create mode 100755 scripts/sanitize/sanitize.sh create mode 100755 scripts/sanitize/sanitize_hist.fish diff --git a/modules/apps/default.nix b/modules/apps/default.nix index 0064ff8..fba78cf 100644 --- a/modules/apps/default.nix +++ b/modules/apps/default.nix @@ -28,6 +28,7 @@ home-manager.users.djai.programs.w3m.enable = true; home-manager.users.djai.programs.zathura.enable = true; home-manager.users.djai.programs.yt-dlp.enable = true; + home-manager.users.djai.services.flameshot.enable = true; # TODO: switch to home manager users.users.djai.packages = with pkgs; [ diff --git a/modules/apps/mpv.nix b/modules/apps/mpv.nix index bb5754c..72ef013 100644 --- a/modules/apps/mpv.nix +++ b/modules/apps/mpv.nix @@ -40,5 +40,5 @@ ]; }; - home-manager.users."djai".home.file.".config/mpv/scripts/visualizer.lua".source = ./mpv-visualizer.lua; + home-manager.users."djai".home.file.".config/mpv/scripts/visualizer.lua".source = ../../scripts/mpv-visualizer.lua; } diff --git a/modules/base.nix b/modules/base.nix index 62bf5d7..daa9495 100644 --- a/modules/base.nix +++ b/modules/base.nix @@ -77,6 +77,11 @@ "$HOME/Scripts" ]; + file = { + ".config/WMScripts".source = ../scripts/WMScripts; + ".config/sanitize".source = ../scripts/sanitize; + }; + sessionVariables = { # TODO: add rest of .config/uwms/env.bck here NEWT_COLORS_FILE = "$HOME/.newtColours"; BROWSER = "librewolf"; diff --git a/modules/desktop/hypr.nix b/modules/desktop/hypr.nix index df9bfd5..7b94a47 100644 --- a/modules/desktop/hypr.nix +++ b/modules/desktop/hypr.nix @@ -37,8 +37,8 @@ in }; }; - home-manager.users."djai".home.file.".config/hypr/scripts".source = ./scripts; - home-manager.users."djai".home.file.".config/hypr/shaders".source = ./shaders; + home-manager.users."djai".home.file.".config/hypr/scripts".source = ../../scripts/hypr-scripts; + home-manager.users."djai".home.file.".config/hypr/shaders".source = ../../scripts/hypr-shaders; home-manager.users."djai".xdg.configFile."uwsm/env-hyprland".text = '' export AQ_ARM_DEVICES="/dev/dri/card1:/dev/dri/card2" export AQ_NO_HARDWARE_CUSRORS="1" diff --git a/modules/dev/default.nix b/modules/dev/default.nix index 2a5cb96..b0bae5d 100644 --- a/modules/dev/default.nix +++ b/modules/dev/default.nix @@ -10,6 +10,7 @@ in { imports = [ ./git.nix + ./uv.nix ]; programs.java.enable = true; @@ -57,7 +58,6 @@ in openssl python3 rustc - uv stdenv.cc.cc.lib # containers / secrets diff --git a/modules/dev/uv.nix b/modules/dev/uv.nix new file mode 100644 index 0000000..1c15ea3 --- /dev/null +++ b/modules/dev/uv.nix @@ -0,0 +1,11 @@ +{ ... }: + +{ + home-manager.users.djai.programs.uv = { + enable = true; + tool.packages = [ + "ruff" + "ipython" + ]; + }; +} diff --git a/modules/terminal/fish.nix b/modules/terminal/fish.nix index 7fae89e..13753bd 100644 --- a/modules/terminal/fish.nix +++ b/modules/terminal/fish.nix @@ -2,7 +2,7 @@ let # automatically discover functions in the relative fish functions directory - fishFuncDir = ./fish-functions; + fishFuncDir = ../../scripts/fish-functions; fishFuncs = lib.attrsets.mapAttrs' (name: _: lib.nameValuePair (lib.strings.removeSuffix ".fish" "${name}") ({ body = builtins.readFile (fishFuncDir + "/${name}"); diff --git a/scripts/WMScripts/backlight-notif.sh b/scripts/WMScripts/backlight-notif.sh new file mode 100755 index 0000000..1b5b5ea --- /dev/null +++ b/scripts/WMScripts/backlight-notif.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# This script sends a quick notification through dunst, informing the user about the backlight of their screen + +brightness=$(brightnessctl -m | awk -F, '{print $4}') + +dunstify -u low \ + -a Backlight \ + -r 88 \ + -i ~/.icons/candy-icons/apps/scalable/lightbeat.svg \ + "Screen brightness is $brightness" diff --git a/scripts/WMScripts/changewall.fish b/scripts/WMScripts/changewall.fish new file mode 100755 index 0000000..0c9edf7 --- /dev/null +++ b/scripts/WMScripts/changewall.fish @@ -0,0 +1,19 @@ +#!/usr/bin/env fish + +# This script switches the wallpaper to a random image found under ~/Pictures/wallpapers +# Supports i3, Hyprland, and Sway. + + +switch "$XDG_CURRENT_DESKTOP" + case i3 + feh --bg-fill (find ~/Pictures/wallpapers -type f -regextype posix-extended -iregex "/(.*/)*[^\.]*\.(png|jpe?g|webp)" | sort -R | head -n1) + case sway Hyprland + swaybg -i (find ~/Pictures/wallpapers -type f | sort -R | head -n1) & + set newpid $last_pid + sleep 0.2 + for pid in (pgrep -x swaybg) + if test $pid -ne $last_pid + kill $pid + end + end +end diff --git a/scripts/WMScripts/dunst.sh b/scripts/WMScripts/dunst.sh new file mode 100755 index 0000000..a18bc2e --- /dev/null +++ b/scripts/WMScripts/dunst.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# toggles dunstctl + sends a message (thru dounst ironically) + +lvl=$(dunstctl get-pause-level) + +send_msg() { + dunstify -u low \ + -a Backlight \ + -r 92 \ + -i ~/.icons/candy-icons/apps/scalable/cliq.svg \ + "Toggled dunst $1" +} + + +if [[ $lvl == "0" ]]; then + # dunst is currently enabled; send message first then disable + dunstctl close-all + # send_msg "off" + # sleep 2 + dunstctl set-paused toggle +else + # dunst is currently disabled; enable then send message + dunstctl set-paused toggle + # send_msg "on" +fi + diff --git a/scripts/WMScripts/dunst_bar.py b/scripts/WMScripts/dunst_bar.py new file mode 100755 index 0000000..cb2df93 --- /dev/null +++ b/scripts/WMScripts/dunst_bar.py @@ -0,0 +1,42 @@ +#!/usr/bin/env nix-shell +#! nix-shell -i python3 --packages python314Packages.dbus-fast + +from asyncio import run, Event +from json import dumps +from dbus_fast.aio import MessageBus +from dbus_fast.proxy_object import BaseProxyInterface, BaseProxyObject + +def update_dbus_state(interface, changed, _) -> None: + if interface != 'org.dunstproject.cmd0': + return + + if 'paused' in changed: + update_output(changed['paused'].value) + +def update_output(paused: bool) -> None: + print(dumps({ + "text": "󱙍" if paused else "󰍡", + "alt": "", + "tooltip": "", + "class": "muted-notifs" if paused else "unmuted-notifs", + "percentage": 0 + }, ensure_ascii=False)) + +async def main() -> None: + bus = await MessageBus().connect() + + introspection = await bus.introspect('org.freedesktop.Notifications', '/org/freedesktop/Notifications') + notifications: BaseProxyObject = bus.get_proxy_object('org.freedesktop.Notifications', '/org/freedesktop/Notifications', introspection) + + properties = notifications.get_interface('org.freedesktop.DBus.Properties') + dunst = notifications.get_interface('org.dunstproject.cmd0') + + properties.on_properties_changed(update_dbus_state) + + update_output(await dunst.get_paused()) + + await Event().wait() + +if __name__ == "__main__": + run(main()) + diff --git a/scripts/WMScripts/exit.sh b/scripts/WMScripts/exit.sh new file mode 100755 index 0000000..4fb9bb6 --- /dev/null +++ b/scripts/WMScripts/exit.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env sh + +# This script cleanly exits a variety of window managers, depending on the given parameters +# Also checks no windows exist on the scratchpad (as I tend to forget about those) + + +case "$XDG_CURRENT_DESKTOP" in + "Hyprland") + lock="hyprlock" + cmd="hyprctl clients -j | jq . | grep -E 'special' -c" + ctl="hyprctl dispatch" + logout="uwsm stop" + ;; + "sway") + lock="swaylock --screenshots --clock --indicator --indicator-radius 100 --indicator-thickness 7 --effect-pixelate 25 -- effect-vignette 0.5:0.5 --ring-color 244273a --key-hl-color c6a0f6 --line-color 00000000 --inside-color 00000000 --separator-color 00000000" + cmd="swaymsg -rt get_tree | jq . | grep -E 'scratchpad_state\": \"(changed|fresh)' -c" + ctl="swaymsg" + logout="swaymsg exit" + ;; + "i3") + lock='i3lock -n -c 18192666 -k --radius 180 --inside-color=24273a --layout-color=cad3f5 --time-color=cad3f5 --date-color=cad3f5 --greeter-color=cad3f5 --verif-color=cad3f5 --wrong-color=cad3f5 --modif-color=cad3f5 --ring-color=c6a0f6 --insidever-color=24273a --ringver-color=8aadf4 --insidewrong-color=24273a --ringwrong-color=ed8796 --keyhl-color=a6da95 --bshl-color=f5a97f --separator-color=24273a --date-str="%A, %d %B %Y"' + cmd="i3-msg -t get_tree | jq . | grep -E 'scratchpad_state\": \"(changed|fresh)' -c" + ctl="i3-msg" + logout="i3-msg exit" + ;; + *) + dunstify -u low -t 2000 -i ~/.icons/candy-icons/apps/scalable/system-shutdown.svg "This desktop is not supported." + exit + ;; +esac + +spec_exist() { + n=$(eval "$cmd") + + if [ "$n" -gt 0 ]; then + [ "$n" -gt 1 ] && msg="$n windows" || msg="window" + dunstify -t 3000 \ + -u low \ + -i ~/.icons/candy-icons/apps/scalable/system-shutdown.svg \ + -a i3exit \ + "Close the $msg in the scratchpad first." + exit 0 + fi +} + +lock() { + dunstctl set-paused true + bash -c "$lock" + dunstctl set-paused false +} + +case "$1" in + lock) + lock + ;; + logout) + eval "$logout" + ;; + suspend) + systemctl suspend && lock + ;; + hibernate) + systemctl hibernate && lock + ;; + reboot) + spec_exist + systemctl reboot + ;; + shutdown) + spec_exist + systemctl poweroff + ;; + *) + echo "Usage: $0 {lock|logout|suspend|hibernate|reboot|shutdown}" + exit 2 +esac + +exit 0 diff --git a/scripts/WMScripts/kitty_window.sh b/scripts/WMScripts/kitty_window.sh new file mode 100755 index 0000000..0104617 --- /dev/null +++ b/scripts/WMScripts/kitty_window.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env sh + +# launch a new kitty window. +# If a kitty window is active, sets the new CWD to the current one. +# Else just launch a new one. + +case "$XDG_CURRENT_DESKTOP" in + "Hyprland") + pid=$(hyprctl activewindow -j | jq '. | if .initialTitle == "kitty" then .pid else -1 end') + ;; + *) + pid="-1" + ;; +esac + +if [[ "$pid" == "-1" ]]; then + kitty & +else + kitten @ --to unix:@kitty-$pid launch --cwd current --type os-window & +fi + diff --git a/scripts/WMScripts/microphone.sh b/scripts/WMScripts/microphone.sh new file mode 100755 index 0000000..249f4dc --- /dev/null +++ b/scripts/WMScripts/microphone.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# This script updates the microphone custom module of my specific polybar setup + +case "$XDG_CURRENT_DESKTOP" in + "sway"|"Hyprland") + "$(dirname "$0")/microphone_bar.sh" mute + kill -n36 $(pgrep waybar) + ;; + "i3") + polybar-msg -p "$(xdotool search --name polybar-default getwindowpid)" action "#microphone.hook.0" + polybar-msg -p "$(xdotool search --name polybar-secondary getwindowpid)" action "#microphone.hook.1" + ;; + *) + dunstify -u low -t 2000 -i ~/.icons/candy-icons/apps/scalable/pavucontrol.svg "Current desktop is not supported by microphone.sh" + exit + ;; +esac diff --git a/scripts/WMScripts/microphone_bar.sh b/scripts/WMScripts/microphone_bar.sh new file mode 100755 index 0000000..09cba0e --- /dev/null +++ b/scripts/WMScripts/microphone_bar.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +MUTE=" " +NORMAL="" + +output () { + case "$XDG_CURRENT_DESKTOP" in + "sway"|"Hyprland") + if [[ -n "$1" ]]; then + echo "{\"text\": \"$NORMAL\", \"alt\": \"\", \"tooltip\": \"\", \"class\": \"unmuted-mike\", \"percentage\": 0}" + else + echo "{\"text\": \"$MUTE\", \"alt\": \"\", \"tooltip\": \"\", \"class\": \"muted-mike\", \"percentage\": 0}" + fi + ;; + "i3") + if [[ -n "$1" ]]; then + echo "$NORMAL" + else + echo "%{F#707880}$MUTE%{T- F-}" + fi + ;; + *) + dunstify -t 2000 -u low -i ~/.icons/candy-icons/apps/scalable/noisetorch.svg "This desktop is not supported." + exit + ;; + esac +} + +if [[ "$1" == "mute" ]]; then + amixer sset Capture toggle > /dev/null +fi + +STATUS=$(amixer get Capture | tail -n1 | awk '{print $5}' -) +case $STATUS in + "[on]") + output "yes" + ;; + *) + output + ;; +esac diff --git a/scripts/WMScripts/murder.sh b/scripts/WMScripts/murder.sh new file mode 100755 index 0000000..2eceb5d --- /dev/null +++ b/scripts/WMScripts/murder.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# This script allows the user to select a window +# then nicely asks it to shut down (SIGTERM). +# if the window does not shut down, it is murdered instead (SIGKILL) + +case "$XDG_CURRENT_DESKTOP" in + "Hyprland") + id=$(hyprprop | jq '.pid') + ;; + "sway") + id=$(wlprop | jq '.pid') + ;; + "i3") + id=$(xprop _NET_WM_PID | awk '{print $3}') + ;; + *) + dunstify -u low -t 2000 -i ~/.icons/candy-icons/apps/scalable/clamav.svg "This session type is not supported by murder.sh" + exit +esac + +[[ ! "$id" =~ [0-9]+ ]] && exit + +kill "$id" +sleep 2 +if [[ $(ps -p "$id" 2>&1 > /dev/null) -ne 0 ]]; then + kill -s 9 "$id" +fi diff --git a/scripts/WMScripts/mute_active.sh b/scripts/WMScripts/mute_active.sh new file mode 100755 index 0000000..fa00232 --- /dev/null +++ b/scripts/WMScripts/mute_active.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash + +# mutes the pipewire sink of the active window, if we can find it. +# $1: if non-empty, applies the specified shader + +# 1: get activewindow pid +# 2 match to pactl source +# 2a: try directly against pid +# 2b: if fails: run through fallbacks for specific windows +# 3 toggle pactl source mute +# 4 set window tag for custom shading + + +# Toggle mute a pactl sink +# $1 int: id of sink to toggle +function toggle_sink { + pactl set-sink-input-mute "$1" toggle +} + +# Toggle mute for an array of pactl sinks +# $1 string: space separated list of sink ids +function toggle_multiple { + for i in $1; do + toggle_sink "$i" + done +} + + +case "$XDG_CURRENT_DESKTOP" in + "Hyprland") + activePid=$(hyprctl activewindow -j | jq ".pid") + tagCmd="hyprctl dispatch 'hl.dsp.window.tag({ tag = \"shader/$1\" })'" + class=$(hyprctl activewindow -j | jq ".class") + ;; + *) + dunstify -u low -t 2000 -i ~/.icons/candy-icons/apps/scalable/yast-sound.svg "muteActive does not support the current desktop." + exit + ;; +esac + + +sinks=$(pactl -f json list sink-inputs) +binary=$(ps -q "$activePid" -o comm=) + +mutableSinks=$(printf "%s" "$sinks" | jq -r ".[] | select(.properties.\"application.process.id\" == \"$activePid\") | .index") + +# fallbacks +[[ -z "$mutableSinks" ]] && mutableSinks=$(printf "%s" "$sinks" | jq -r ".[] | select(.properties.\"application.process.binary\" == \"$binary\") | .index") # Feishin +[[ -z "$mutableSinks" ]] && mutableSinks=$(printf "%s" "$sinks" | jq -r ".[] | select(.properties.\"application.id\" == \"$binary\") | .index") # mpv +[[ -z "$mutableSinks" && "$class" = \"tf_linux64\" ]] && mutableSinks=$(printf "%s" "$sinks" | jq -r ".[] | select(.properties.\"application.name\" == \"tf_linux64\" ) .index") # tf2 + + + +if [[ -z "$mutableSinks" ]]; then + # still no matched sink; give up + printf "Couldn't match activeWindow to any pipewire sinks!\n" + dunstify -u low \ + -a Mute \ + -r 35 \ + -i ~/.icons/candy-icons/apps/scalable/yast-sound.svg \ + "Could not match active window to pipewire input" + exit 1 +else + printf "Matched activeWindow | class | %s\n |binary| %s\n | sink | %s | to pipewire sink" "$class" "$binary" "$mutableSinks" | column -ts '|' + dunstify -u low \ + -a Mute \ + -r 35 \ + -i ~/.icons/candy-icons/apps/scalable/yast-sound.svg \ + "Toggled mute on active window" +fi + +toggle_multiple "$mutableSinks" +[ -n "$1" ] && eval "$tagCmd" diff --git a/scripts/WMScripts/record.sh b/scripts/WMScripts/record.sh new file mode 100755 index 0000000..3dea265 --- /dev/null +++ b/scripts/WMScripts/record.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# This script allows one to record a slected area of the screen. +# Calling the script again will end recording, and save the file to +# ~/Videos/screen captures/$(date +%F_%T).mp4 + +# create directory if necessary +mkdir -p ~/Videos/screen\ captures + +# variables +record_file="/tmp/record_file" +now="$(date +%F_%T)" +file="$HOME/Videos/screen captures/$now.mp4" + + +stop_recording () { + kill -2 "$(head -1 $record_file)" + kill -KILL "$(head -2 $record_file | tail -n1 )" + old_date="$(cat $record_file | tail -n1)" + rm "$record_file" + + # notif + dunstify -u low \ + -a Record \ + -r 8827 \ + -i ~/.icons/candy-icons/apps/scalable/simplescreenrecorder.svg \ + "Saved recording to $old_date.mp4" + echo "Saved recording to $old_date.mp4" +} + + +start_recording () { + case "$XDG_SESSION_TYPE" in + x11) + # get coordinates + slop=$(slop -f "%x %y %w %h %g %i") || exit 1 + read -r X Y W H G ID <<< "$slop" + + # record screen + ffmpeg -v 1 -r 30 -f x11grab -s "$W"x"$H" -i :0.0+"$X","$Y" -show_region 1 -vf "scale=2*trunc(iw/2):2*trunc(ih/2)" -vcodec libx264 -pix_fmt yuv420p -preset ultrafast -crf 18 -threads 0 "$file" -y & + ;; + wayland) + # get coordinates + if ! slurp="$(slurp)"; then + exit + fi + wf-recorder -g "$slurp" -f "$file" --framerate 30 & + ;; + *) + dunstify -t 2000 -u low -i ~/.icons/candy-icons/apps/scalable/camorama.svg "This session type is not supported by record.sh" + exit + ;; + esac + + # print metadata to tmp file + echo $! > "$record_file" + echo $$ >> "$record_file" + echo "$now" >> "$record_file" + + + # loop notif + i=0 + while :; do + i=$(($i + 1)) + dunstify -u low \ + -a Record \ + -r 8827 \ + -i ~/.icons/candy-icons/apps/scalable/simplescreenrecorder.svg \ + "Recording for $(date -d@$i -u +%H:%M:%S)" + sleep 1 + done +} + + +[[ -e "$record_file" ]] && stop_recording || start_recording diff --git a/scripts/WMScripts/screenshot_float.sh b/scripts/WMScripts/screenshot_float.sh new file mode 100755 index 0000000..7f6c63a --- /dev/null +++ b/scripts/WMScripts/screenshot_float.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# This script allows the user to make a screenshot (through flameshot) +# and will then open said screenshot from the clipboard into feh +# it will also make the feh window floating + +case "$XDG_CURRENT_DESKTOP" in + "Hyprland") + paste="wl-paste -t image/png" + move () { + bash -c "hyprctl dispatch 'hl.dsp.window.move({ x = \"$1\", y = \"$2\", relative = false})'" + } + ;; + "sway") + paste="wl-paste -t image/png" + move () { + bash -c "swaymsg move absolute position $1 $2" + } + ;; + "i3") + paste="xclip -selection clipboard -t image/png -o" + move () { + bash -c "i3-msg move position $1 $2" + } + ;; + *) + dunstify -t 2000 -u low -i ~/.icons/candy-icons/apps/scalable/image-viewer.svg "Current desktop is not supported by floatshot." + exit + ;; +esac + +out=$(flameshot gui -g) +# If the capture was cancelled, out will be empty +if [[ -n "$out" ]]; then + # get x,y of selection + x=$(echo "$out" | awk -F'+' '{print $2}') + y=$(echo "$out" | awk -F'+' '{print $3}') + + bash -c "$paste" | feh - -T notitle --class 'floatme' & + pid="$!" + + while [[ -z $(wmctrl -lp | awk -vpid=$pid '$3==pid {print $1; exit}') ]]; do + sleep 0.05 + done + move "$x" "$y" +fi + diff --git a/scripts/WMScripts/tess.sh b/scripts/WMScripts/tess.sh new file mode 100755 index 0000000..33fc44e --- /dev/null +++ b/scripts/WMScripts/tess.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# This script allows the user to make a selection, then runs that selection through OCR and copies the result to clipboard + +case "$XDG_SESSION_TYPE" in + "wayland") + copy="wl-copy" + screenshot="grim -g" + slop=$(slurp -f "%x,%y %wx%h") || exit 1 + ;; + "x11") + copy="xclip -selection c" + screenshot="import -window root -crop " + slop=$(slop -f "%G") || exit 1 + ;; + *) + dunstify -t 2000 -u low -i ~/.icons/candy-icons/apps/scalable/code.svg "Current session type not supported by tess.sh" + exit + ;; +esac + +# files +imagefile="/tmp/tesseract.$RANDOM.png" +text="/tmp/translation" + +# get screenshot +read -r G <<< "$slop" +bash -c "$screenshot \"$G\" $imagefile" + +# OCR, save to clipboard +tesseract $imagefile $text 2>/dev/null +cat "$text.txt" | bash -c "$copy" + +# cleanup +rm $text".txt" +rm "$imagefile" diff --git a/scripts/WMScripts/toggle_audiocables.sh b/scripts/WMScripts/toggle_audiocables.sh new file mode 100755 index 0000000..bc1c399 --- /dev/null +++ b/scripts/WMScripts/toggle_audiocables.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# This script updates the clementine and combine toggle custom modules of my specific polybar setup +case "$XDG_CURRENT_DESKTOP" in + "sway"|"Hyprland") + case "$1" in + "clementine") + "$(dirname "$0")/toggle_audiocables_bar.sh" toggle clementine + kill -37 $(pgrep waybar) + ;; + "combine") + "$(dirname "$0")/toggle_audiocables_bar.sh" toggle combine + kill -37 $(pgrep waybar) + ;; + *) + echo "Unknown sink specified." + ;; + esac + ;; + "i3") + case "$1" in + "clementine") + polybar-msg -p "$(xdotool search --name polybar-default getwindowpid)" action "#audiocables.hook.0" + ;; + "combine") + polybar-msg -p "$(xdotool search --name polybar-default getwindowpid)" action "#audiocables.hook.1" + ;; + *) + echo "unknown sink specified." + ;; + esac + ;; + *) + dunstify -u low -t 2000 -i ~/.icons/candy-icons/apps/scalable/pavucontrol.svg "Current desktop is not supported by audiocables.sh" + exit + ;; +esac + diff --git a/scripts/WMScripts/toggle_audiocables_bar.sh b/scripts/WMScripts/toggle_audiocables_bar.sh new file mode 100755 index 0000000..6b52bc7 --- /dev/null +++ b/scripts/WMScripts/toggle_audiocables_bar.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash + +# This script toggles state between a few of my audio cables: +# combine sink -> default_output | hyperx_output +# clementine sink -> combine sink | default_output +# The script also outputs a symbol indicating which configuration is active. +# Usecase: My USB-C headset is a different sink than the one in the laptop; sometimes I want to have audio over the headset, sometimes through the laptop. + +# Output symbols +# SYMBOLS=("neither" "co^!cl" "cl^!co" "both") +SYMBOLS=("󰴸 " "󰝚 " "󰓃 " "󰋋 ") + +# The sinks to test against +DEFAULT_SINKS=("bluez_output_internal.0A_E6_E0_F9_F1_BE.1" "alsa_output.pci-0000_06_00.6.analog-stereo" "bluez_output.20_18_5B_F0_FC_4A.1" "bluez_output.0A_E6_E0_F9_F1_BE.1" "bluez_output.0A_E6_E0_F9_F1_BE" "bluez_output.0A:E6:E0:F9:F1:BE") +USB_C_SINK="alsa_output.usb-HP__Inc_HyperX_Cloud_III_Wireless_0000000000000000-00.analog-stereo" +COMBINE_SINK="combine" + +# awkcommand - a little complicated, but basically tests if the DEFAULT_SINK is connected to the clementine sink (adding +2 if so) or the combine sink (adding +1). This gives a numerical mapping for all 4 states im interested in: +# 0: neither combine,clementine are attached to usb_c_sink +# 1: only combine is attached to usb_c_sink +# 2: only clementine is attached to usb_c_sink +# 3: both combine,clementine are attached to usb_c_sink +read -r -d "" awkcommand << EOF +/$USB_C_SINK:playback_FL/,/$USB_C_SINK:playback_FR/ { + if (\$2 == "combine:monitor_FL") { + state += 1 + } +} + +/$COMBINE_SINK:playback_FL/,/$COMBINE_SINK:playback_FR/ { + if (\$2 == "clementine:monitor_FL") { + state += 2 + } +} + +END { + printf "%d\n", state +} +EOF + +# Attaches a single sink to a specific source +function attach() { + echo "attaching $1 to $2" + pw-link "$1":monitor_FL "$2":playback_FL + pw-link "$1":monitor_FR "$2":playback_FR +} + +# Attaches an array of sinks to a specific source. +# $1 = source (pw monitor) +# $2 = list of sinks to attach +function attachArray() { + name=$2[@] + a=("${!name}") + for sink in "${a[@]}"; do + attach "$1" "$sink" + done +} + +# Detaches a single sink from a specific source +function detach() { + echo "detaching $1 from $2" + pw-link -d "$1":monitor_FL "$2":playback_FL + pw-link -d "$1":monitor_FR "$2":playback_FR +} + +# Detaches an array of sinks to a specific source. +# $1 = source (pw monitor) +# $2 = list of sinks to attach +function detachArray() { + name=$2[@] + a=("${!name}") + for sink in "${a[@]}"; do + detach "$1" "$sink" + done +} + + +state=$(pw-link -li | awk "$awkcommand") +IFS=$'\n' + +# actually toggle iff we have a $1 telling us to +if [[ "$1" == "toggle" ]];then + case "$2" in + "clementine") + if [[ $state -eq 2 || $state -eq 3 ]]; then + detach "clementine" "$COMBINE_SINK" + attachArray "clementine" "DEFAULT_SINKS" + state=$((state-2)) + else + detachArray "clementine" "DEFAULT_SINKS" + attach "clementine" "$COMBINE_SINK" + state=$((state+2)) + fi + ;; + "combine") + if [[ $state -eq 1 || $state -eq 3 ]]; then + detach "combine" "$USB_C_SINK" + attachArray "combine" "DEFAULT_SINKS" + state=$((state-1)) + else + detachArray "combine" "DEFAULT_SINKS" + attach "combine" "$USB_C_SINK" + state=$((state+1)) + fi + ;; + *) + echo "Unknown option: '$2'" + ;; + esac +fi + +echo "${SYMBOLS[$state]}" diff --git a/modules/terminal/fish-functions/bulkpaste.fish b/scripts/fish-functions/bulkpaste.fish similarity index 100% rename from modules/terminal/fish-functions/bulkpaste.fish rename to scripts/fish-functions/bulkpaste.fish diff --git a/modules/terminal/fish-functions/copy.fish b/scripts/fish-functions/copy.fish similarity index 100% rename from modules/terminal/fish-functions/copy.fish rename to scripts/fish-functions/copy.fish diff --git a/modules/terminal/fish-functions/files.fish b/scripts/fish-functions/files.fish similarity index 100% rename from modules/terminal/fish-functions/files.fish rename to scripts/fish-functions/files.fish diff --git a/modules/terminal/fish-functions/fmf.fish b/scripts/fish-functions/fmf.fish similarity index 100% rename from modules/terminal/fish-functions/fmf.fish rename to scripts/fish-functions/fmf.fish diff --git a/modules/terminal/fish-functions/histdelete.fish b/scripts/fish-functions/histdelete.fish similarity index 100% rename from modules/terminal/fish-functions/histdelete.fish rename to scripts/fish-functions/histdelete.fish diff --git a/modules/terminal/fish-functions/move.fish b/scripts/fish-functions/move.fish similarity index 100% rename from modules/terminal/fish-functions/move.fish rename to scripts/fish-functions/move.fish diff --git a/modules/terminal/fish-functions/nshell.fish b/scripts/fish-functions/nshell.fish similarity index 100% rename from modules/terminal/fish-functions/nshell.fish rename to scripts/fish-functions/nshell.fish diff --git a/modules/terminal/fish-functions/run.fish b/scripts/fish-functions/run.fish similarity index 100% rename from modules/terminal/fish-functions/run.fish rename to scripts/fish-functions/run.fish diff --git a/modules/terminal/fish-functions/runl.fish b/scripts/fish-functions/runl.fish similarity index 100% rename from modules/terminal/fish-functions/runl.fish rename to scripts/fish-functions/runl.fish diff --git a/modules/terminal/fish-functions/secret.fish b/scripts/fish-functions/secret.fish similarity index 100% rename from modules/terminal/fish-functions/secret.fish rename to scripts/fish-functions/secret.fish diff --git a/modules/terminal/fish-functions/show_colour.fish b/scripts/fish-functions/show_colour.fish similarity index 100% rename from modules/terminal/fish-functions/show_colour.fish rename to scripts/fish-functions/show_colour.fish diff --git a/modules/terminal/fish-functions/sudo.fish b/scripts/fish-functions/sudo.fish similarity index 100% rename from modules/terminal/fish-functions/sudo.fish rename to scripts/fish-functions/sudo.fish diff --git a/modules/terminal/fish-functions/tmux-updater.fish b/scripts/fish-functions/tmux-updater.fish similarity index 100% rename from modules/terminal/fish-functions/tmux-updater.fish rename to scripts/fish-functions/tmux-updater.fish diff --git a/modules/terminal/fish-functions/yazi.fish b/scripts/fish-functions/yazi.fish similarity index 100% rename from modules/terminal/fish-functions/yazi.fish rename to scripts/fish-functions/yazi.fish diff --git a/modules/desktop/scripts/bg.fish b/scripts/hypr-scripts/bg.fish similarity index 100% rename from modules/desktop/scripts/bg.fish rename to scripts/hypr-scripts/bg.fish diff --git a/modules/desktop/scripts/gamemode_hypr.sh b/scripts/hypr-scripts/gamemode_hypr.sh similarity index 100% rename from modules/desktop/scripts/gamemode_hypr.sh rename to scripts/hypr-scripts/gamemode_hypr.sh diff --git a/modules/desktop/scripts/gamemode_power.sh b/scripts/hypr-scripts/gamemode_power.sh similarity index 100% rename from modules/desktop/scripts/gamemode_power.sh rename to scripts/hypr-scripts/gamemode_power.sh diff --git a/modules/desktop/scripts/keybinds.sh b/scripts/hypr-scripts/keybinds.sh similarity index 100% rename from modules/desktop/scripts/keybinds.sh rename to scripts/hypr-scripts/keybinds.sh diff --git a/modules/desktop/scripts/screenshot_float.sh b/scripts/hypr-scripts/screenshot_float.sh similarity index 100% rename from modules/desktop/scripts/screenshot_float.sh rename to scripts/hypr-scripts/screenshot_float.sh diff --git a/modules/desktop/scripts/shader_picker.sh b/scripts/hypr-scripts/shader_picker.sh similarity index 100% rename from modules/desktop/scripts/shader_picker.sh rename to scripts/hypr-scripts/shader_picker.sh diff --git a/modules/desktop/scripts/shader_picker_window.sh b/scripts/hypr-scripts/shader_picker_window.sh similarity index 100% rename from modules/desktop/scripts/shader_picker_window.sh rename to scripts/hypr-scripts/shader_picker_window.sh diff --git a/modules/desktop/scripts/toggle_focus_floating.sh b/scripts/hypr-scripts/toggle_focus_floating.sh similarity index 100% rename from modules/desktop/scripts/toggle_focus_floating.sh rename to scripts/hypr-scripts/toggle_focus_floating.sh diff --git a/modules/desktop/scripts/toggle_touchpad.sh b/scripts/hypr-scripts/toggle_touchpad.sh similarity index 100% rename from modules/desktop/scripts/toggle_touchpad.sh rename to scripts/hypr-scripts/toggle_touchpad.sh diff --git a/modules/desktop/scripts/waybar.sh b/scripts/hypr-scripts/waybar.sh similarity index 100% rename from modules/desktop/scripts/waybar.sh rename to scripts/hypr-scripts/waybar.sh diff --git a/modules/desktop/shaders/crt.frag b/scripts/hypr-shaders/crt.frag similarity index 100% rename from modules/desktop/shaders/crt.frag rename to scripts/hypr-shaders/crt.frag diff --git a/modules/desktop/shaders/dim.frag b/scripts/hypr-shaders/dim.frag similarity index 100% rename from modules/desktop/shaders/dim.frag rename to scripts/hypr-shaders/dim.frag diff --git a/modules/desktop/shaders/grey.frag b/scripts/hypr-shaders/grey.frag similarity index 100% rename from modules/desktop/shaders/grey.frag rename to scripts/hypr-shaders/grey.frag diff --git a/modules/desktop/shaders/horror.frag b/scripts/hypr-shaders/horror.frag similarity index 100% rename from modules/desktop/shaders/horror.frag rename to scripts/hypr-shaders/horror.frag diff --git a/modules/desktop/shaders/invert.frag b/scripts/hypr-shaders/invert.frag similarity index 100% rename from modules/desktop/shaders/invert.frag rename to scripts/hypr-shaders/invert.frag diff --git a/modules/desktop/shaders/noblue.frag b/scripts/hypr-shaders/noblue.frag similarity index 100% rename from modules/desktop/shaders/noblue.frag rename to scripts/hypr-shaders/noblue.frag diff --git a/modules/desktop/shaders/nogreen.frag b/scripts/hypr-shaders/nogreen.frag similarity index 100% rename from modules/desktop/shaders/nogreen.frag rename to scripts/hypr-shaders/nogreen.frag diff --git a/modules/desktop/shaders/nored.frag b/scripts/hypr-shaders/nored.frag similarity index 100% rename from modules/desktop/shaders/nored.frag rename to scripts/hypr-shaders/nored.frag diff --git a/modules/desktop/shaders/rainbow.frag b/scripts/hypr-shaders/rainbow.frag similarity index 100% rename from modules/desktop/shaders/rainbow.frag rename to scripts/hypr-shaders/rainbow.frag diff --git a/modules/desktop/shaders/rbinvert.frag b/scripts/hypr-shaders/rbinvert.frag similarity index 100% rename from modules/desktop/shaders/rbinvert.frag rename to scripts/hypr-shaders/rbinvert.frag diff --git a/modules/apps/mpv-visualizer.lua b/scripts/mpv-visualizer.lua similarity index 100% rename from modules/apps/mpv-visualizer.lua rename to scripts/mpv-visualizer.lua diff --git a/scripts/sanitize/autoSanitize.sh b/scripts/sanitize/autoSanitize.sh new file mode 100755 index 0000000..03dc09a --- /dev/null +++ b/scripts/sanitize/autoSanitize.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +on_exit() { + (ccrypt -K "$now" -d "$file.cpt") + + # prepare regex pattern + shopt -s extglob + readarray -t removeArray < <(grep -ve '^$\|^#' "$file") + IFS='|' eval 'PATTERN="(${removeArray[*]})"' + PATTERN="(^|[^a-zA-Z])$PATTERN([^a-zA-Z]|$)" + + case $shell in + *fish) + printf "sanitizing fish history!\n" + "$(dirname "$0")/sanitize_hist.fish" "$PATTERN" "/home/$(whoami)/.local/share/fish/fish_history" + ;; + *bash) + printf "sanitizing bash history!\n" + "$(dirname "$0")/sanitize.sh" "$PATTERN" "/home/$(whoami)/.bash_history" 1 + ;; + *) + printf "autosanitize has no implementation for %s\n" "$shell" + ;; + esac + + rm -r ~/.cache/thumbnails/* + rm "$file" +} + +trap 'on_exit' EXIT +now=$(date +%s.%N) +folder=/run/media/$(whoami)/P/Scripts +file=/tmp/tags +shell=$(grep "$(whoami)" < /etc/passwd | awk -F':' '{print $NF}' ) + +echo "copying tags to temp file..." +cat "$folder/tags2" "$folder/tags" > "$file" +(sed -i '/^$/d;/^\#.*$/d' "$file") +(ccrypt -K "$now" "$file") +while :; do + sleep 600 +done diff --git a/scripts/sanitize/sanitize.sh b/scripts/sanitize/sanitize.sh new file mode 100755 index 0000000..ff8a42f --- /dev/null +++ b/scripts/sanitize/sanitize.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +#This script sanitizes a file in the following manner: +#it reads a pattern and a destFile +#then, all lines in destFILE that can be regexp'd to pattern are removed. +#optionally, a confirm variable is also specified; if so, the script does not prompt the user before overwriting destFILE + +#this script takes the following input: +#sanitize.sh pattern destFile [confirm] + +#make sure input is valid +[[ "$1" == "" || "$2" == "" ]] && printf "Incorrect input format.\nUse: \t sanitize.sh pattern destFile [confirm]\n" && exit +[[ ! -f "$2" ]] && printf 'destFile - %s - does not exist!\n' "$2" && exit + + +PATTERN=$1 +destFile=$2 +saveArray=() +discardArray=() +[[ "$3" =~ [yY][eE][sS]|[yY]|1|[tT][rR][uU][eE] ]] && confirm=0 || confirm=1 + +#go through each line, adding to either SAVE or DISCARD as necessary +while read -r line; do + [[ ! $line =~ $PATTERN ]] && saveArray+=("$line") || discardArray+=("$line") +done < "$destFile" + +#confirm output +if [[ $confirm -eq 1 ]]; then + printf "Discarding the following:\n" + printf '%s\n' "${discardArray[@]}" +else + printf 'Discarding %d line(s).\n' "${#discardArray[@]}" +fi + +#confirm the user is ok with this +response="y" +[[ $confirm -eq 1 ]] && read -r -p "Proceed? (y/N): " response +if [[ "$response" =~ [yY][eE][sS]|[yY] ]]; then + echo "Removing unwanted lines..." + printf '%s\n' "${saveArray[@]}" > "$destFile" +fi diff --git a/scripts/sanitize/sanitize_hist.fish b/scripts/sanitize/sanitize_hist.fish new file mode 100755 index 0000000..06d59ae --- /dev/null +++ b/scripts/sanitize/sanitize_hist.fish @@ -0,0 +1,53 @@ +#!/usr/bin/env fish + +# This script filters a file on a given regex, deleting all entries that match. +# it is intended to be used with yaml-like files (namely, the fish shell history file) +# and will delete entries, not individual lines. To give an example: +# - cmd: "cd ~/Documents" +# when: 128301283 +# - paths: +# /usr/bin +# - cmd: "mv file file2" +# when: 1928321 +# with the regex "(^|[^a-z])(Documents)($|[^a-z])" will result in: +# - cmd: "mv file file2" +# when: 1928321 +# (note how it deletes not only the line containing the matched regex, but also the 'when' and 'paths' components). +# +# the input for this script is: +# script.fish Regex File +# where: +# Regex is the pattern to be matched, and +# File is the file to be filtered. + +# error handling +if not test -f "$argv[2]" + printf 'Wrong syntax!\nUse:\t%s\tRegex\tFile' "$(basename (status -f))" + exit +end + +# setup +set -f is_writing "false" +set -f tempFile (mktemp -p '' fish_hist.XXXXX) +set -f num_deleted 0 + +# loop through the file +while read -lad ' ' line + if string match -qri "^- cmd:" -- "$line" + if string match -qri "$argv[1]" -- "$line" + set is_writing "false" + set num_deleted (math $num_deleted + 1) + else + printf '%s\n' "$line" >> "$tempFile" + set is_writing "true" + end + else if string match -q "true" -- "$is_writing" + printf '%s\n' "$line" >> "$tempFile" + end +end < "$argv[2]" + +printf 'Discarding %d line(s).\n ' "$num_deleted" + +# replace files +rm "$argv[2]" +cp "$tempFile" "$argv[2]"