4 Commits

22 changed files with 291 additions and 227 deletions

21
dev-env
View File

@@ -43,7 +43,11 @@ update_dirs() {
pushd $1 &>/dev/null
(
# Copy everything except systemd, share, and zsh folders, they need treated differently.
configs=$(find . -mindepth 1 -maxdepth 1 -type d \( -name "systemd" -o -name "zsh" -o -name "share" \) -prune -o -type d -print)
configs=$(
find . -mindepth 1 -maxdepth 1 -type d \
\( -name "systemd" -o -name "zsh" -o -name "share" -o -name "scripts" \) \
-prune -o -type d -print
)
for c in $configs; do
directory=${2%/}/${c#./}
log " removing: rm -rf $directory"
@@ -102,6 +106,11 @@ copy_files() {
update_dirs $DEV_ENV/env/.config $XDG_CONFIG_HOME
update_dirs $DEV_ENV/env/.local $HOME/.local
# SCRIPTS
mkdir -p ~/.local/scripts >/dev/null 2>&1
update_dirs $DEV_ENV/env/.local/scripts $HOME/.local/scripts
copy_files $DEV_ENV/env/.local/scripts $HOME/.local/scripts
# SYSTEMD
mkdir -p $XDG_CONFIG_HOME/systemd/user >/dev/null 2>&1
copy_files $DEV_ENV/env/.config/systemd/user $XDG_CONFIG_HOME/systemd/user
@@ -134,7 +143,9 @@ mkdir -p $XDG_DATA_HOME/applications/icons
copy_files $DEV_ENV/env/.local/share/applications $XDG_DATA_HOME/applications
copy_files $DEV_ENV/env/.local/share/applications/icons $XDG_DATA_HOME/applications/icons
systemctl --user daemon-reload
hyprctl reload
espanso service restart
exec zsh -l
if [[ $dry_run == "0" ]]; then
systemctl --user daemon-reload
hyprctl reload
espanso service restart
exec zsh -l
fi

View File

@@ -14,9 +14,9 @@ $browser = uwsm app -- zen-browser
$fileManager = $terminal -e yazi
$fileBrowser = uwsm app -- nautilus
$menu = uwsm app -- walker
$scripts = ~/.local/scripts
$scripts = ~/.local/scripts/hypr
$pwa = $scripts/launch-webapp
$tmuxSessionator = $scripts/tmux-sessionator
$tmuxSessionator = ~/.local/scripts/tmux-sessionator
$clipboardHistory = com.ghostty.clipse $terminal --class=com.ghostty.clipse -e clipse
$uninstallDesktop = $terminal --class=com.ghostty.float -e $scripts/uninstall-desktop-app
$housecallPro = https://pro.housecallpro.com/app/calendar_new
@@ -35,16 +35,16 @@ bindd = $mainMod, SPACE, Application launcher, exec,
bindd = $mainMod, RETURN, New terminal, exec, $terminal
bindd = $mainMod SHIFT, RETURN, New floating terminal, exec, $terminal --class=com.ghostty.float
bindd = $mainMod, TAB, Focus previous workspace, workspace, previous
bindd = $mainMod, A, [A]i - launch / focus, exec, $pwa --focus "https://chatgpt.com"
bindd = $mainMod, A, [A]i - launch / focus, exec, $pwa --or-focus "https://chatgpt.com"
bindd = $mainMod SHIFT, A, [A]i - new window, exec, $pwa "https://chatgpt.com"
bindd = $mainMod, B, New [b]rowser, exec, $browser
bindd = $mainMod SHIFT, B, New private [b]rowser, exec, $browser --private-window
bindd = $mainMod, C, [C]alendar, exec, $pwa --focus "https://www.icloud.com/calendar"
bindd = $mainMod, C, [C]alendar, exec, $pwa --or-focus "https://www.icloud.com/calendar"
bindd = $mainMod SHIFT, C, [C]onfig folder in tmux session, exec, $terminal -e $tmuxSessionator ~/.config
bindd = $mainMod, D, [D]ispatch app - special workspace, exec, $pwa --special dispatch $housecallPro
bindd = $mainMod SHIFT, D, [D]ispatch app - new window, exec, $pwa $housecallPro
bindd = $mainMod, E, [E]mail - personal, exec, $pwa --focus "https://mail.proton.me"
bindd = $mainMod SHIFT, E, [E]mail - work, exec, $scripts/launch-or --focus thunderbird uwsm app -- thunderbird
bindd = $mainMod, E, [E]mail - personal, exec, $pwa --or-focus "https://mail.proton.me"
bindd = $mainMod SHIFT, E, [E]mail - work, exec, $scripts/launch --or-focus thunderbird uwsm app -- thunderbird
bindd = $mainMod, F, [F]ile manager - terminal, exec, $fileManager
bindd = $mainMod SHIFT, F, [F]ile manager - application, exec, $fileBrowser
bindd = $mainMod, G, [G]itea, exec, $pwa "https://git.housh.dev"
@@ -61,10 +61,10 @@ bindd = $mainMod, P, [P]assword manager, exec,
bindd = $mainMod SHIFT, P, Toggle [p]seudo window mode, pseudo, # dwindle
bindd = $mainMod SHIFT, R, [R]estart menu bar, exec, $scripts/waybar-restart
bindd = $mainMod, S, Toggle [s]pecial workspace, togglespecialworkspace, magic # use $windowMod S to send window to the special workspace
bindd = $mainMod, Y, [Y]ouTube, exec, $pwa --focus "https://youtube.com"
bindd = $mainMod, Y, [Y]ouTube, exec, $pwa --or-focus "https://youtube.com"
bindd = $mainMod, U, [U]nifi, exec, $pwa "https://unifi.ui.com"
bindd = $mainMod SHIFT, U, [U]ninstall desktop app, exec, $uninstallDesktop
bindd = $mainMod, V, Clipboard history, exec, $scripts/launch-or --close $clipboardHistory
bindd = $mainMod, V, Clipboard history, exec, $scripts/launch --or-close $clipboardHistory
bindd = $mainMod, W, Close current window, killactive,
bindd = $mainMod SHIFT, W, Close all windows in active workspace, exec, $scripts/close-windows --active-workspace

View File

@@ -4,5 +4,5 @@ After=graphical-session.target
[Service]
Type=oneshot
ExecStart=%h/.local/scripts/battery-monitor
ExecStart=%h/.local/scripts/hypr/battery-monitor
Environment=DISPLAY=:0

View File

@@ -5,7 +5,7 @@ Before=exit.target
[Service]
Type=oneshot
ExecStart=%h/.local/scripts/clear-clipboard-history
ExecStart=%h/.local/scripts/hypr/clear-clipboard-history
[Install]
WantedBy=exit.target

View File

@@ -65,6 +65,7 @@ path_prepend \
"$XDG_DATA_HOME/bin" \
"$HOME/.local/bin" \
"$SCRIPTS" \
"$SCRIPTS/hypr" \
"$HOME/.local/pnpm" \
"$CARGO_HOME/bin" \
"$HOME/.local/bin"

View File

@@ -160,7 +160,7 @@ fi
if [[ -n $CUSTOM_EXEC ]] && [[ ! $CUSTOM_EXEC == "null" ]]; then
EXEC_COMMAND="$CUSTOM_EXEC"
else
EXEC_COMMAND="${SCRIPTS:-$HOME/.local/scripts}/launch-webapp $APP_URL"
EXEC_COMMAND="${SCRIPTS:-$HOME/.local/scripts}/hypr/launch-webapp $APP_URL"
fi
# Create application .desktop file

165
env/.local/scripts/hypr/launch vendored Executable file
View File

@@ -0,0 +1,165 @@
#!/usr/bin/env bash
usage() {
cat <<EOF
Launch or focus / close a window based on pattern contained within the window
class name. (Default is to focus the window).
This is used in keybinds and by other scripts as a general entrypoint for managing applications.
USAGE:
$ $(basename ${BASH_SOURCE[0]}) [OPTIONS] PATTERN [LAUNCH_CMD...]
OPTIONS:
-f | --or-focus: Focus the window matching the pattern, if it exists.
-c | --or-close: Close the window matching the pattern, if it exists.
-o | --focus-active-only: Focus only if window is on active workspace, otherwise launch a new
instance.
-x | --close-active-only: Close only windows on active workspace matching the pattern.
-s | --special <name>: Launch or toggle a special workspace.
-h | --help: Show this help page.
NOTES:
In general only one flag should be passed to determine the action mode.
Passing both any of the close or focus flags together will result in an error if a window is found matching
the pattern, if no window is found then one will still be launched without any errors.
If the special option is passed then we will not attempt to close a window. If the script is
invoked with the special option set, we check if there is a window matching the pattern, if there
is and the currently active window is on the same workspace passed in to the special option, then
we toggle the workspace closed. This allows the same keybind to be used to launch an application
in a special workspace as well as toggle the workspace closed.
EOF
}
action="focuswindow"
close_flag="0"
close_active_only_flag="0"
focus_flag="0"
focus_active_only_flag="0"
launch_cmd=()
pattern=""
special_flag="0"
special=""
while [[ $# -gt 0 ]]; do
if [[ $1 == "-c" ]] || [[ $1 == "--or-close" ]]; then
close_flag="1"
action="closewindow"
elif [[ $1 == "-f" ]] || [[ $1 == "--or-focus" ]]; then
focus_flag="1"
action="focuswindow"
elif [[ $1 == "-s" ]] || [[ $1 == "--special" ]]; then
shift
special_flag="1"
special=$1
elif [[ $1 == "-o" ]] || [[ $1 == "--focus-active-only" ]]; then
focus_flag="1"
focus_active_only_flag="1"
action="focuswindow"
elif [[ $1 == "-x" ]] || [[ $1 == "--close-active-only" ]]; then
close_flag="1"
close_active_only_flag="1"
action="closewindow"
elif [[ $1 == "-h" ]] || [[ $1 == "--help" ]]; then
usage && exit 0
elif [[ -z $pattern ]]; then
pattern=$1
else
launch_cmd+=("$1")
fi
shift
done
toggle_special() {
if [[ -z $special ]]; then
echo "[ERROR]: No name supplied for special workspace."
exit 1
fi
hyprctl dispatch togglespecialworkspace $special
}
launch_application() {
echo "Launching..."
echo "'${launch_cmd[@]}'"
eval exec ${launch_cmd[@]}
}
################################################################################
# MAIN
################################################################################
if [[ -z $pattern ]]; then
echo "[ERROR]: Must supply a pattern to match the window class."
usage && exit 1
elif [[ -z $launch_cmd ]]; then
echo "[ERROR]: Must supply a launch command to match the window class."
usage && exit 1
fi
echo "Pattern: $pattern"
addresses=$(hyprctl clients -j | jq ".[] | select(.class | contains(\"$pattern\")) | .address")
# If no addresses, then launch the application.
if [[ -z $addresses ]]; then
# Toggle special workspace if applicable.
if [[ $special_flag == "1" ]]; then
toggle_special
fi
launch_application && exit 0
fi
active_window_workspace=$(hyprctl activewindow -j | jq -r '.workspace.name')
# Check if we have special flag and active window is on the special workspace. If so
# we just toggle the special workspace. This keeps "special" apps alive, but closes and / opens
# the special workspace when invoked.
if [[ $special_flag == "1" ]] && [[ $active_window_workspace =~ $special ]]; then
toggle_special && exit 0
fi
# Check if both close and focus flags were passed, so we don't do the
# wrong thing.
if [[ $focus_flag == "1" ]] && [[ $close_flag == "1" ]]; then
echo "[ERROR]: Both focus and close flag were passed."
exit 1
fi
for address in ${addresses[@]}; do
# Clean the address of quotes.
address=${address//\"/}
echo "Handling address: '$address'"
if [[ $focus_active_only_flag == "1" ]] || [[ $close_active_only_flag == "1" ]]; then
# get the workspace name for the address.
workspace=$(hyprctl clients -j | jq -r ".[] | select(.address == \"$address\") | .workspace.name")
# check that the window is on the active workspace.
if [[ $active_window_workspace == $workspace ]]; then
echo "Performing action: '$action', on window: '$address'"
hyprctl dispatch $action "address:$address"
# early out if focusing a window.
[[ $focus_active_only_flag ]] && exit 0
else
# the window is not on the active workspace, so skip it.
echo "Skipping window: $address"
fi
else
# We don't have the focus_active_only_flag or close_active_only_flag set, so we perform
# the action on the window.
echo "Performing action: '$action', on window: '$address'"
hyprctl dispatch $action "address:$address"
fi
done
# If we made it here and focus_active_only_flag was set, then we did not
# find a window on the active workspace, so we launch a new window.
if [[ $focus_active_only_flag == "1" ]]; then
launch_application
fi

96
env/.local/scripts/hypr/launch-webapp vendored Executable file
View File

@@ -0,0 +1,96 @@
# /usr/bin/env bash
# Adapted from https://github.com/basecamp/omarchy/tree/master?tab=readme-ov-file
usage() {
cat <<EOF
Launches a url as a web application. This script relys on the 'launch' script. This
essentially just generates the pattern and launch command to pass into that script.
USAGE:
$ launch-webapp [OPTIONS] <url> [ARGS...]
OPTIONS:
-f | --or-focus: If a window exists matching the url's domain, focus it
instead of launching new window.
-s | --special <name>: Launch in the special workspace name, or toggle the special
workspace.
-h | --help: Show this help page.
NOTES:
Any extra arguments after '--' get passed directly to the browser invocation.
$ launch-webapp https://example.com -- --some-random-flag-for-browser=1
Any options passed in prior to the '--' get sent to the 'launch-or' script, so you can pass
options that are not specifically shown here, but the ones shown would be the most commonly
used, so they are documented here.
Using the '--special' flag is useful for apps that you want to have a "summoning" like behavior.
Upon first launch the application will be opened and the special workspace will be shown.
Calling it again will keep the application open in the special workspace but hide the workspace.
Further calls will not open another instance of the application, but will toggle the visiblity
of the special workspace.
EOF
}
browser="chromium.desktop"
url=""
launch_args=()
app_args=""
SCRIPTS="${SCRIPTS}"
if [[ -z $SCRIPTS ]]; then
echo "scripts directory not set"
echo "using ~/.local/scripts"
SCRIPTS=~/.local/scripts
fi
while [[ $# -gt 0 ]]; do
if [[ $1 =~ ^--special ]] || [[ $1 =~ ^-s ]]; then
launch_args+=("$1")
launch_args+=("$2")
shift # Second shift get's handled below
elif [[ $1 =~ ^--help ]] || [[ $1 =~ ^-h ]]; then
usage && exit 0
elif [[ -z $url ]] && [[ ! $1 =~ ^- ]]; then
url=$1
elif [[ $1 == "--" ]]; then
shift
break
else
launch_args+=("$1")
fi
shift
done
# Strips url down to just the domain, so that we can match window classes.
pattern() {
pattern=${url/#https:\/\//}
pattern=${pattern/#http:\/\//}
pattern=${pattern%%/*}
echo $pattern
}
##################################################
# MAIN
##################################################
if [[ -z $url ]]; then
echo "[ERROR]: Must supply a url." && usage && exit 1
fi
# Any left over args after "--"
app_args="$@"
echo "URL: $url"
echo "Launch args: ${launch_args[@]}"
echo "App args: ${app_args}"
$SCRIPTS/hypr/launch "${launch_args[@]}" "$(pattern)" \
setsid uwsm app -- $(sed -n 's/^Exec=\([^ ]*\).*/\1/p' {~/.local,~/.nix-profile,/usr}/share/applications/$browser 2>/dev/null | head -1) --app="$url" "$app_args"

View File

@@ -1,61 +0,0 @@
#!/usr/bin/env bash
usage() {
cat <<EOF
Launch or focus / close a window based on pattern contained within the window
class name. (Default is to focus the window).
USAGE:
$ $(basename ${BASH_SOURCE[0]}) [OPTIONS] PATTERN [LAUNCH_CMD...]
OPTIONS:
-f | --focus: Focus the window matching the pattern, if it exists.
-c | --close: Close the window matching the pattern, if it exists.
-h | --help: Show this help page.
EOF
}
action="focuswindow"
pattern=""
launch_cmd=()
while [[ $# -gt 0 ]]; do
if [[ $1 == "-c" ]] || [[ $1 == "--close" ]]; then
action="closewindow"
elif [[ $1 == "-f" ]] || [[ $1 == "--focus" ]]; then
action="focuswindow"
elif [[ $1 == "-h" ]] || [[ $1 == "--help" ]]; then
usage && exit 0
elif [[ -z $pattern ]]; then
pattern=$1
else
launch_cmd+=("$1")
fi
shift
done
if [[ -z $pattern ]]; then
echo "[ERROR]: Must supply a pattern to match the window class."
usage && exit 1
elif [[ -z $launch_cmd ]]; then
echo "[ERROR]: Must supply a launch command to match the window class."
usage && exit 1
fi
address=$(hyprctl clients -j | jq -r ".[] | select(.class | contains(\"$pattern\")) | .address")
echo "Pattern: $pattern"
echo "Address: $address"
if [[ -n $address ]]; then
echo "Found window, dispatching action: $action"
hyprctl dispatch $action "address:$address"
else
echo "Launching..."
echo "'${launch_cmd[@]}'"
eval exec ${launch_cmd[@]}
fi

View File

@@ -1,148 +0,0 @@
#!/usr/bin/env bash
# Adapted from https://github.com/basecamp/omarchy/tree/master?tab=readme-ov-file
usage() {
cat <<EOF
Launches a url as a web application.
USAGE:
$ launch-webapp [OPTIONS] <url> [ARGS...]
OPTIONS:
-f | --focus: If a window exists matching the url's domain, focus it
instead of launching new window.
-s | --special <name>: Launch in the special workspace name, or toggle the special
workspace.
-h | --help: Show this help page.
NOTES:
Any extra arguments after the url get passed directly to the browser invocation.
Using the '--special' flag is useful for apps that you want to have a "summoning" like behavior.
Upon first launch the application will be opened and the special workspace will be shown.
Calling it again will keep the application open in the special workspace but hide the workspace.
Further calls will not open another instance of the application, but will toggle the visiblity
of the special workspace.
EOF
}
browser="chromium.desktop"
special=""
special_flag="0"
focus_flag="0"
help_flag="0"
url=""
args=()
SCRIPTS="${SCRIPTS}"
if [[ -z $SCRIPTS ]]; then
echo "scripts directory not set"
echo "using ~/.local/scripts"
SCRIPTS=~/.local/scripts
fi
while [[ $# -gt 0 ]]; do
if [[ $1 =~ ^--special ]] || [[ $1 =~ ^-s ]]; then
shift
special_flag="1"
special=$1
elif [[ $1 =~ ^--focus ]] || [[ $1 =~ ^-f ]]; then
focus_flag="1"
elif [[ $1 =~ ^--help ]] || [[ $1 =~ ^-h ]]; then
help_flag="1"
elif [[ -z $url ]]; then
url=$1
else
args+=($1)
fi
shift
done
# Early out if help flag was supplied.
if [[ $help_flag == "1" ]]; then
usage && exit 0
fi
launch() {
exec setsid uwsm app -- $(sed -n 's/^Exec=\([^ ]*\).*/\1/p' {~/.local,~/.nix-profile,/usr}/share/applications/$browser 2>/dev/null | head -1) --app="$1" "$2"
}
# Strips url down to just the domain, so that we can match window classes.
pattern() {
pattern=${url/#https:\/\//}
pattern=${pattern/#http:\/\//}
pattern=${pattern%%/*}
echo $pattern
}
getWindowProp() {
echo $(hyprctl clients -j | jq -r ".[] | select((.class | contains(\"$(pattern)\"))) | .$1" | head -n 1)
}
log() {
echo "[$($SCRIPTS/isosec)] - $1" >>/tmp/launch-webapp.log
}
fail() {
echo -e "\n\e[31m[Error]: $1\e[0m"
log "[Error]: $1"
}
handleSpecial() {
local window_addr=$(getWindowProp address)
local window_workspace=$(getWindowProp workspace.id)
local active_workspace=$(hyprctl activeworkspace -j | jq -r ".id")
local special_workspace_id=$(hyprctl workspaces -j | jq -r ".[] | select(.name | contains(\"$special\")) | .id")
log "Window: address: $window_addr workspace: $window_workspace"
log "Special workspace: $special id: $special_workspace_id"
log "Active workspace: $active_workspace"
# Check if we don't have a window address, or if the window is not on the expected special workspace.
if [[ -z $window_addr ]] || ([[ -n $window_workspace ]] && [[ $window_workspace != $special_workspace_id ]]); then
log "No window, launching..."
hyprctl dispatch togglespecialworkspace $special
launch $url $args
else
log "We have a window, toggling special workspace"
hyprctl dispatch togglespecialworkspace $special
fi
}
##################################################
# MAIN
##################################################
if [[ -z $url ]]; then
fail "Must supply a url." && usage && exit 1
fi
if [[ $special_flag == "1" ]]; then
log "Handling special workspace..."
if [[ -z $special ]]; then
fail "Must supply special workspace name." && exit 1
fi
handleSpecial && exit 0
fi
window_addr=""
if [[ $focus_flag == "1" ]]; then
log "Received focus flag, checking for window address."
window_addr=$(getWindowProp address)
log "Window address: $window_addr"
fi
if [[ -n $window_addr ]]; then
log "No window address launching..."
hyprctl dispatch focuswindow "address:$window_addr"
exit 0
fi
launch $url $args

4
webapp
View File

@@ -45,7 +45,7 @@ log() {
install() {
local file=$DEV_ENV/env/webapps/$(basename $1)
local script="$DEV_ENV/env/.local/scripts/install-webapp"
local script="$DEV_ENV/env/.local/scripts/hypr/install-webapp"
if [[ ! -x $script ]]; then
log "Failed to find install web app script."
@@ -69,7 +69,7 @@ install() {
uninstall() {
local file=$DEV_ENV/env/webapps/$(basename $1)
local script="$DEV_ENV/env/.local/scripts/uninstall-desktop-app"
local script="$DEV_ENV/env/.local/scripts/hypr/uninstall-desktop-app"
if [[ ! -x $script ]]; then
log "Failed to find uninstall web app script."