feat: Moves hyprland scripts into it's own directory.

This commit is contained in:
2025-10-03 23:43:29 -04:00
parent 1def0356d7
commit d32d0cf64f
16 changed files with 26 additions and 14 deletions

132
env/.local/scripts/hypr/close-windows vendored Executable file
View File

@@ -0,0 +1,132 @@
#!/usr/bin/env bash
usage() {
cat <<EOF
Close window(s) by address or pattern mode.
USAGE:
$ $(basename ${BASH_SOURCE[0]}) [OPTIONS] [MODE] [ARG...]
MODE:
--all: Close all windows in all workspaces, any arguments are ignored.
-a | --active-workspace: Close all windows in the active workspace, any arguments are ignored.
-c | --class: Close all windows whose class contains one of the passed arguments.
-s | --special: Close all windows in special workspaces whose name matches on of the
passed in arguments, or if no arguments are supplied then it will close
all windows in all special workspaces.
OPTIONS:
--dry-run
-h | --help: Show this help page.
NOTES:
If a mode is selected all arguments are treated for that mode, meaning only one mode
runs. It does not work to mix modes / arguments.
If no modes are supplied then arguments are assumed to be window addresses and we will
close all supplied window addresses.
EOF
}
active_workspace_flag="0"
all_flag="0"
class_flag="0"
dry_run_flag="0"
special_flag="0"
args=()
addresses=()
while [[ $# -gt 0 ]]; do
if [[ $1 =~ ^-a ]] || [[ $1 =~ ^--active-workspace ]]; then
active_workspace_flag="1"
elif [[ $1 =~ ^--all ]]; then
all_flag="1"
elif [[ $1 =~ ^-c ]] || [[ $1 =~ ^--class ]]; then
class_flag="1"
elif [[ $1 =~ ^--dry-run ]]; then
dry_run_flag="1"
elif [[ $1 =~ ^-h ]] || [[ $1 =~ ^--help ]]; then
usage && exit 0
elif [[ $1 =~ ^-s ]] || [[ $1 =~ ^--special ]]; then
special_flag="1"
else
args+=($1)
fi
shift
done
log() {
if [[ $dry_run_flag == "1" ]]; then
echo "[DRY RUN]: $1"
else
echo "$1"
fi
}
_select_addresses() {
local property=$1
local pattern=$2
addresses+=("$(hyprctl clients -j | jq -r ".[] | select($property | contains(\"$pattern\")) | .address")")
}
get_special_addresses() {
# If no arguments, then we add the "special" to the pattern args, which will
# match all windows in any special workspace.
if [[ ${#args} == 0 ]]; then
args+=("special")
fi
for name in ${args[@]}; do
log "Fetching addresses for special: $name"
_select_addresses .workspace.name $name
done
}
close() {
log "Closing window address: $1"
if [[ $dry_run_flag == "0" ]]; then
hyprctl dispatch closewindow "address:$1"
fi
}
if [[ $active_workspace_flag == "1" ]]; then
# Set addresses to active workspace windows.
id=$(hyprctl activeworkspace -j | jq -r '.id')
log "Fetching addresses for active workspace: $id"
addresses+=("$(hyprctl clients -j | jq -r ".[] | select(.workspace.id == $id) | .address")")
elif [[ $all_flag == "1" ]]; then
# Set addresses to all window addresses.
addresses+=("$(hyprctl clients -j | jq -r ".[] | .address")")
elif [[ $class_flag == "1" ]]; then
# Set addresses to all windows containing the passed in classes.
for c in ${args[@]}; do
_select_addresses .class $c
done
elif [[ $special_flag == "1" ]]; then
# Set addresses to all windows in the passed in special workspaces.
get_special_addresses
else
# If no modes selected, then assume there were addresses passed in
# as args.
addresses=("$args")
fi
if [[ ${#addresses} == 0 ]]; then
log "No windows found."
exit 0
fi
for address in ${addresses[@]}; do
close $address
done

190
env/.local/scripts/hypr/install-webapp vendored Executable file
View File

@@ -0,0 +1,190 @@
#!/bin/zsh
# Adapted from https://github.com/basecamp/omarchy/tree/master?tab=readme-ov-file
function usage() {
cat <<EOF
Generates a '.desktop' file for a web application, so that it
can act as a stand alone application and launched from an application
launcher.
USAGE: install-webapp [-n <name>] [-u <url>] [-i <icon>] [-e <exec-cmd>] [-m <mime-types>] [-f <file>] [-h] [args...]
OPTIONS:
-n | --name: The name of the application.
-u | --url: The url used to launch the application.
-i | --icon: The icon for the application.
-e | --exec: Custom execution command (optional).
-m | --mime-types: MIME-types for the application (optional).
-f | --file: Install from a spec in a json file.
-h | --help: Show usage information.
EXAMPLES:
If no options or arguments are supplied, then it will start an interactive session that prompts for the
values.
$ install-webapp
Calling the app with named arguments:
$ install-webapp \\
--name "My Awesome App" \\
--url "https://awesome.com" \\
--icon "https://awesome.com/assets/icon.png"
Using a json file as input:
$ install-webapp --file myapp.json
It is also possible to use only positional arguments with out their key. They can be passed in the order as
they're listed.
$ install-webapp "My Awesome App" \\
"https://awesome.com" \\
"https://awesome.com/assets/icon.png"
NOTES:
The icon option can either be a url where we will download a png from or a local file. Local files
can either be the full path to the file or a file name of an icon located in '~/.local/share/applications/icons/'.
Interactive sessions do not give the option to use a custom execution command or supply the
MIME types, which are less frequently used options.
If using a json spec file, all keys are the same as their option name, except for mime-types use 'mime_types' as the
key in the json object. Although the 'exec' and 'mime_types' are not required in the spec file. An common json spec
file example would look like:
{
"name": "My Awesome App",
"url": "https://awesome.com",
"icon: "https://awesome.com/assets/icon.png"
}
EOF
}
declare -a app_name
declare -a app_url
declare -a icon_ref
declare -a custom_exec # Optional custom exec command
declare -a mime_types # Optional mime types
declare -a help_flag
declare -a file_mode
declare INTERACTIVE_MODE=false
SCRIPTS="${SCRIPTS}"
if [[ -z "$SCRIPTS" ]]; then
echo "SCRIPTS not set"
echo "using ~/.local/scripts"
SCRIPTS=$HOME/.local/scripts
fi
zparseopts -D -F -K -- \
{n,-name}:=app_name \
{u,-url}:=app_url \
{i,-icon}:=icon_ref \
{e,-exec}:=custom_exec \
{m,-mime-types}:=mime_types \
{f,-file}:=file_mode \
{h,-help}=help_flag
[ ${#help_flag[@]} -gt 0 ] && usage && exit 0
# If passed in as positional arguments, without flags.
[ -n "$1" ] && app_name+=("$1")
[ -n "$2" ] && app_url+=("$2")
[ -n "$3" ] && icon_ref+=("$3")
[ -n "$4" ] && custom_exec+=("$4")
[ -n "$5" ] && mime_types+=("$5")
# If passed in a json spec file.
if [[ -n "$file_mode" ]]; then
file=$(cat ${file_mode[-1]})
app_name+=$(echo $file | jq -r '.name')
app_url+=$(echo $file | jq -r '.url')
icon_ref+=$(echo $file | jq -r '.icon')
custom_exec+=$(echo $file | jq -r '.exec')
mime_types+=$(echo $file | jq -r '.mime_types')
fi
# Check if proper arguments were passed in. Start interactive mode if not.
if [[ -z "$app_name[-1]" || -z "$app_url[-1]" || -z "$icon_ref[-1]" ]]; then
echo -e "\e[32mLet's create a new web app you can start with the app launcher.\n\e[0m"
app_name+=($(gum input --prompt "Name> " --placeholder "My favorite web app"))
app_url+=($(gum input --prompt "URL> " --placeholder "https://example.com"))
icon_ref+=($(gum input --prompt "Icon URL> " --placeholder "See https://dashboardicons.com (must use PNG!)"))
INTERACTIVE_MODE=true
else
INTERACTIVE_MODE=false
fi
# Ensure valid execution
if [[ -z "$app_name[-1]" || "$app_name[-1]" == "null" ||
-z "$app_url[-1]" || "$app_url[-1]" == "null" ||
-z "$icon_ref[-1]" || "$icon_ref[-1]" == "null" ]]; then
echo "You must set app name, app URL, and icon URL!"
exit 1
fi
APP_NAME=$app_name[-1]
APP_URL=$app_url[-1]
ICON_REF=$icon_ref[-1]
CUSTOM_EXEC=$custom_exec[-1]
MIME_TYPES=$mime_types[-1]
# Refer to local icon or fetch remotely from URL
ICON_DIR="$HOME/.local/share/applications/icons"
# Ensure the icon directory exists (useful if it's the first run.)
[ ! -d $ICON_DIR ] && mkdir -p $ICON_DIR
if [[ $ICON_REF == https://* ]]; then
ICON_PATH="$ICON_DIR/$APP_NAME.png"
if curl -sL -o "$ICON_PATH" "$ICON_REF"; then
ICON_PATH="$ICON_DIR/$APP_NAME.png"
else
echo "Error: Failed to download icon."
exit 1
fi
else
# Check if the icon path is a file.
if [ -f $ICON_REF ]; then
ICON_PATH=$ICON_REF
else
ICON_PATH="$ICON_DIR/$ICON_REF"
fi
fi
# Use custom exec if provided, otherwise default behavior
if [[ -n $CUSTOM_EXEC ]] && [[ ! $CUSTOM_EXEC == "null" ]]; then
EXEC_COMMAND="$CUSTOM_EXEC"
else
EXEC_COMMAND="${SCRIPTS:-$HOME/.local/scripts}/hypr/launch-webapp $APP_URL"
fi
# Create application .desktop file
DESKTOP_FILE="$HOME/.local/share/applications/$APP_NAME.desktop"
cat >"$DESKTOP_FILE" <<EOF
[Desktop Entry]
Version=1.0
Name=$APP_NAME
Comment=$APP_NAME
Exec=$EXEC_COMMAND
Terminal=false
Type=Application
Icon=$ICON_PATH
StartupNotify=true
EOF
# Add mime types if provided
if [[ -n $MIME_TYPES ]] && [[ ! $MIME_TYPES == "null" ]]; then
echo "MimeType=$MIME_TYPES" >>"$DESKTOP_FILE"
fi
chmod +x "$DESKTOP_FILE"
if [[ $INTERACTIVE_MODE == true ]]; then
echo -e "You can now find $APP_NAME using the app launcher (SUPER + SPACE)\n"
fi

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

@@ -0,0 +1,15 @@
#!/bin/bash
# Moves all workspaces to the passed in monitor id, which can be useful when
# connecting or disconnecting from a monitor.
MONITOR=$1
if [ ! $# = 1 ]; then
echo "Usage: mv-all-workspaces-to-monitor <monitor-id>"
exit 1
fi
hyprctl workspaces -j |
jq '.[] | select(.monitorID != "$MONITOR") | .id' |
xargs -I{} hyprctl dispatch moveworkspacetomonitor {} "$MONITOR" >/dev/null 2>&1

29
env/.local/scripts/hypr/toggle-desktop vendored Executable file
View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# Workspace to hide everything in
HIDE_WS="special:hidden"
# File to store original workspace ID
STATE_FILE="/tmp/hypr_hide_state"
# Get current workspace ID
CUR_WS=$(hyprctl -j activeworkspace | jq -r '.id')
# Check if we're currently hidden
if [[ -f "$STATE_FILE" ]]; then
# Restore windows
ORIG_WS=$(cat "$STATE_FILE")
for win in $(hyprctl -j clients | jq -r ".[] | select(.workspace.name | contains(\"$HIDE_WS\")) | .address"); do
hyprctl dispatch movetoworkspace "$ORIG_WS,address:$win"
hyprctl dispatch workspace "$ORIG_WS"
done
rm "$STATE_FILE"
else
# Hide all windows (move to special hidden workspace)
for win in $(hyprctl -j clients | jq -r ".[] | select(.workspace.id == $CUR_WS) | .address"); do
hyprctl dispatch movetoworkspace "$HIDE_WS,address:$win"
hyprctl dispatch togglespecialworkspace "$HIDE_WS"
done
rm "$STATE_FILE"
echo "$CUR_WS" >"$STATE_FILE"
fi

View File

@@ -0,0 +1,12 @@
#!/bin/zsh
#
# Toggles the state of the internal laptop monitor, which is useful
# when I'm connected to an external monitor / docks.
monitor="eDP-1"
if hyprctl monitors | grep -q "$monitor"; then
hyprctl keyword monitor "$monitor,disable" 1>/dev/null
else
hyprctl keyword monitor "$monitor,enable" 1>/dev/null
fi

119
env/.local/scripts/hypr/uninstall-desktop-app vendored Executable file
View File

@@ -0,0 +1,119 @@
#!/usr/bin/env bash
# Uninstalls '.desktop' applications, including their icon.
#
# This is primarily used for uninstalling web app's, if a
# desktop app was installed via the package manager, then the
# package manager should be used to uninstall the application.
usage() {
cat <<EOF
Uninstalls '.desktop' files, including their icons. Most commonly
used for web applications, if an application was installed by a
package manager, then it should be used to uninstall the application.
Usage:
uninstall-desktop-app [OPTIONS] [FILE...]
OPTIONS:
--dry-run: Perform but don't actually remove anything.
-h | --help: Show the help page.
If no files are supplied, then an interactive session will be
started that allows you to choose the applications to remove.
EOF
}
declare -a files
interactive_mode="0"
dry_run="0"
help_flag="0"
XDG_DATA_HOME=${XDG_DATA_HOME}
while [[ $# -gt 0 ]]; do
if [[ $1 =~ ^--dry ]]; then
dry_run="1"
elif [[ $1 =~ ^-h ]] || [[ $1 =~ ^--h ]]; then
help_flag="1"
else
files+=("$1")
fi
shift
done
# Early out for help option.
if [[ $help_flag == "1" ]]; then
usage
exit 0
fi
if [[ -z $XDG_DATA_HOME ]]; then
echo "xdg data home is not set"
echo "using: ~/.local/share"
XDG_DATA_HOME=$HOME/.local/share
fi
if [[ ${#files} == 0 ]]; then
interactive_mode="1"
files+=(
$(find $XDG_DATA_HOME/applications -mindepth 1 -maxdepth 1 -type f -name "*.desktop" -printf "%f\n" |
gum choose --no-limit --padding "2 4" --header "Choose desktop apps to remove:" --selected-prefix="✗ ")
)
fi
log() {
if [[ $dry_run == "1" ]]; then
echo "[DRY RUN]: $1"
else
echo "$1"
fi
}
############################## MAIN ##############################
for f in ${files[@]}; do
icon=""
log "ARG: $f"
# Handle a passed in webapp spec file.
if [[ $f =~ \.json$ ]]; then
name=$(jq -r ".name" $f)
f="$name.desktop"
fi
fname=${f##*/}
log "Uninstalling Desktop: $fname"
file="$XDG_DATA_HOME/applications/$fname"
if [[ ! -f $file ]]; then
log "[WARNING]: File didn't exist, skipping!"
else
# get the line in file that has the icon path.
icon_line=$(cat $file | grep "Icon")
# get just the file path.
icon=${icon_line/#Icon=/}
log " removing icon: rm -rf $icon"
log " removing desktop: rm -rf $file"
if [[ $dry_run == "0" ]]; then
rm -rf $icon
rm -rf $file
fi
fi
done
if [[ ${#files} -gt 0 ]]; then
# Refresh the database so that applcation luanchers, etc
# don't show the app still exists.
update-desktop-database $XDG_DATA_HOME/applications
if [[ $interactive_mode == "1" ]]; then
log "Done!"
fi
fi

4
env/.local/scripts/hypr/waybar-restart vendored Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/zsh
pkill -x waybar
setsid uwsm app -- waybar >/dev/null 2>&1 &

166
env/.local/scripts/hypr/window-table vendored Executable file
View File

@@ -0,0 +1,166 @@
#!/usr/bin/env bash
usage() {
cat <<EOF
Show a table with details about the currently active windows. You can choose a window and perform
an action depending on the option passed in.
USAGE:
$ $(basename ${BASH_SOURCE[0]}) [OPTIONS]
OPTIONS:
--launch: Launch in a new terminal window, user will be prompted what to do with selected window.
-c | --clip: Copy selected window's address to the system clipboard.
-x | --close: Close the selected window.
-f | --focus: Focus the selected window.
-i | --ignore: Ignore the selected window.
--show-window-class: Include window class in the table.
-h | --help: Show this page.
NOTES:
If using the 'launch' option then flags passed after the '--launch' flag will be passed into the
launched terminal, allowing you to launch with a specific mode turned on, any flags passed in prior to
'--launch' will be ignored.
EOF
}
window_class="com.ghostty.window-table"
window_padding_x="10"
clipboard_flag="0"
close_flag="0"
focus_flag="0"
ignore_flag="0"
launch_flag="0"
show_window_class_flag="0"
launch_args=()
rows=()
selected_value=""
window_data=$(hyprctl clients -j | jq 'sort_by(.workspace.name)')
while [[ $# -gt 0 ]]; do
if [[ $launch_flag == "1" ]]; then
launch_args+=("$1")
else
if [[ $1 =~ ^-c ]] || [[ $1 =~ ^--clip ]]; then
clipboard_flag="1"
elif [[ $1 =~ ^-x ]] || [[ $1 =~ ^--close ]]; then
close_flag="1"
elif [[ $1 =~ ^-f ]] || [[ $1 =~ ^--focus ]]; then
focus_flag="1"
elif [[ $1 =~ ^-h ]] || [[ $1 =~ ^--help ]]; then
usage && exit 0
elif [[ $1 =~ ^-i ]] || [[ $1 =~ ^--ignore ]]; then
ignore_flag="1"
elif [[ $1 =~ ^--launch ]]; then
launch_flag="1"
elif [[ $1 =~ ^--show-window-class ]]; then
show_window_class_flag="1"
fi
fi
shift
done
generate_rows() {
readarray -t addresses <<<"$(echo "$window_data" | jq -r '.[] | .address')"
readarray -t classes <<<$(echo "$window_data" | jq -r '.[] | .class')
readarray -t titles <<<$(echo "$window_data" | jq -r '.[] | .title')
readarray -t workspaces <<<$(echo "$window_data" | jq -r '.[] | .workspace.name')
# Zip into a new comma separated values
for i in "${!addresses[@]}"; do
if [[ $show_window_class_flag == "1" ]]; then
rows+=("${workspaces[i]}, ${titles[i]}, ${classes[i]}, ${addresses[i]}")
else
rows+=("${workspaces[i]}, ${titles[i]}, ${addresses[i]}")
fi
done
}
show_table_return_choice() {
local columns="Workspace, Title, Address"
local ret_column=3
if [[ $show_window_class_flag == "1" ]]; then
columns="Workspace, Title, Class, Address"
ret_column=4
fi
local ret=$(
printf '%s\n' "${rows[@]}" |
fzf --footer="Workspace - Title - Address" --footer-label-pos=center
# gum table --columns "$columns" --return-column $ret_column
)
# remove spaces and quotes from result.
ret=${ret//\"/}
ret=${ret// /}
echo "$ret"
}
ask_what_to_do_with_selection() {
choice=$(gum choose "Focus window" "Copy to clipboard" "Refresh" "Close window" "Quit")
echo "Choice: $choice"
if [[ $choice == "Quit" ]]; then
exit 0
elif [[ $choice == "Close window" ]]; then
close_flag="1"
elif [[ $choice == "Copy to clipboard" ]]; then
clipboard_flag="1"
elif [[ $choice == "Focus window" ]]; then
focus_flag="1"
elif [[ $choice == "Refresh" ]]; then
eval exec ${BASH_SOURCE[0]}
exit 0
fi
}
handle_selected_value() {
if [[ $ignore_flag == "1" ]]; then
echo "Ignore flag set, selection: '$selected_value'"
exit 0
elif [[ $clipboard_flag == "1" ]]; then
echo "Copying to clipboard, selection: $selected_value"
wl-copy $selected_value
exit 0
elif [[ $focus_flag == "1" ]]; then
echo "Focusing window, selection: $selected_value"
hyprctl dispatch focuswindow "address:$selected_value"
exit 0
elif [[ $close_flag == "1" ]]; then
echo "Closing window, selection: $selected_value"
hyprctl dispatch closewindow "address:$selected_value"
exit 0
fi
# TODO: Choose from list of what to do with the selected_value.
echo "No flag set, selection: '$selected_value'"
}
##################################################
# MAIN
##################################################
if [[ $launch_flag == "1" ]]; then
ghostty --class="$window_class" --window-padding-x="$window_padding_x" \
--keybind="q=quit" \
-e "${BASH_SOURCE[0]}" "${launch_args[@]}"
else
generate_rows
selected_value=$(show_table_return_choice)
if [[ -n $selected_value ]]; then
handle_selected_value
# If we got here then no flag was passed in initially on how to handle the
# selected window, so ask what they'd like to do. Then handle it.
echo "Asking what to do with selction."
ask_what_to_do_with_selection
[[ -n $selected_value ]] && handle_selected_value
# If you make it here, We just give up... Don't start an endless loop.
fi
fi

View File

@@ -0,0 +1,27 @@
#!/bin/bash
#
# Float's a window, setting it's height and width and centering.
# The percentage of the screen size for the floating window.
WIDTH_PERCENT=80
HEIGHT_PERCENT=40
floating=$(hyprctl activewindow -j | jq '.floating')
if [ "$floating" = "true" ]; then
hyprctl dispatch togglefloating
else
monitor=$(hyprctl monitors -j | jq '.[] | select(.focused == true)')
mw=$(echo "$monitor" | jq '.width')
mh=$(echo "$monitor" | jq '.height')
ms=$(echo "$monitor" | jq '.scale')
echo "scale: $ms"
neww=$(echo "scale=6; (($mw / $ms) * $WIDTH_PERCENT / 100)" | bc)
newh=$(echo "scale=6; (($mh / $ms) * $HEIGHT_PERCENT / 100)" | bc)
hyprctl dispatch togglefloating &&
hyprctl dispatch resizeactive exact $neww $newh &&
hyprctl dispatch centerwindow
fi