7 Commits

11 changed files with 493 additions and 365 deletions

View File

@@ -1,7 +1,14 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e
set -o nounset
set -o pipefail
SCRIPTS=${SCRIPTS:-$HOME/.local/scripts}
THIS_FILE=${BASH_SOURCE[0]} THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE")
THIS=$(basename "$THIS_FILE") THIS=$(basename "$THIS_FILE")
LOG_FILE=${LOG_FILE:-"/tmp/$LOG_LABEL.log"}
usage() { usage() {
cat <<EOF cat <<EOF
@@ -52,7 +59,6 @@ launch_cmd=()
pattern="" pattern=""
special_flag="0" special_flag="0"
special="" special=""
SCRIPTS=${SCRIPTS:-$HOME/.local/scripts}
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
if [[ $1 == "-c" ]] || [[ $1 == "--or-close" ]]; then if [[ $1 == "-c" ]] || [[ $1 == "--or-close" ]]; then
@@ -114,7 +120,7 @@ launch_application() {
# Setup logging file and label # Setup logging file and label
source "$SCRIPTS/hypr/logging" source "$SCRIPTS/hypr/logging"
setup-logging "/tmp/$THIS.log" "$THIS" setup-logging "$LOG_FILE" "$LOG_LABEL"
if [[ -z $pattern ]]; then if [[ -z $pattern ]]; then
log --error "Must supply a pattern to match the window class." log --error "Must supply a pattern to match the window class."

View File

@@ -1,8 +1,11 @@
#! /usr/bin/env bash #! /usr/bin/env bash
# Adapted from https://github.com/basecamp/omarchy/tree/master?tab=readme-ov-file # Adapted from https://github.com/basecamp/omarchy/tree/master?tab=readme-ov-file
SCRIPTS="${SCRIPTS:-$HOME/.local/scripts}"
THIS_FILE=${BASH_SOURCE[0]} THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE")
THIS=$(basename "$THIS_FILE") THIS=$(basename "$THIS_FILE")
LOG_FILE=${LOG_FILE:-"/tmp/$LOG_LABEL.log"}
usage() { usage() {
cat <<EOF cat <<EOF
@@ -45,7 +48,6 @@ browser="chromium.desktop"
url="" url=""
launch_args=() launch_args=()
app_args="" app_args=""
SCRIPTS="${SCRIPTS:-$HOME/.local/scripts}"
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
if [[ $1 =~ ^--special ]] || [[ $1 =~ ^-s ]]; then if [[ $1 =~ ^--special ]] || [[ $1 =~ ^-s ]]; then
@@ -83,7 +85,7 @@ log() {
# setup logging file and label # setup logging file and label
source "$SCRIPTS/hypr/logging" source "$SCRIPTS/hypr/logging"
setup-logging "/tmp/$THIS.log" "$THIS" setup-logging "$LOG_FILE" "$LOG_LABEL"
if [[ -z $url ]]; then if [[ -z $url ]]; then
log --error "Must supply a url." && usage && exit 1 log --error "Must supply a url." && usage && exit 1

View File

@@ -27,10 +27,13 @@
# log --warning "My warning message." # log --warning "My warning message."
# log --error "My error message." # log --error "My error message."
# #
set -e
set -o nounset
set -o pipefail
LOG_FILE=(${LOG_FILE:-}) LOG_FILE=${LOG_FILE:-""}
LOG_INVOCATION_ID=${LOG_INVOCATION_ID:-} LOG_INVOCATION_ID=${LOG_INVOCATION_ID:-""}
LOG_LABEL=${LOG_LABEL:-()} LOG_LABEL=${LOG_LABEL:-""}
# Run in dry run mode, which just prints to the console and does # Run in dry run mode, which just prints to the console and does
# not log to the files. # not log to the files.
LOG_ENABLE_DRY_RUN=${LOG_ENABLE_DRY_RUN:-"0"} LOG_ENABLE_DRY_RUN=${LOG_ENABLE_DRY_RUN:-"0"}
@@ -104,14 +107,23 @@ logging() {
if [[ $LOG_ENABLE_DRY_RUN == "0" ]]; then if [[ $LOG_ENABLE_DRY_RUN == "0" ]]; then
# Loop over log files logging message to each file. # Loop over log files logging message to each file.
for i in "${!LOG_FILE[@]}"; do for i in "${!LOG_FILE[@]}"; do
prefix="[id: $LOG_INVOCATION_ID][time: $($SCRIPTS/isosec)][label: ${LOG_LABEL[i]}][source: $source_file] : " local file=${LOG_FILE[i]}
m="$prefix $msg" local id=$LOG_INVOCATION_ID
echo -e "$m" >>${LOG_FILE[i]} local label=${LOG_LABEL[i]:-"$LOG_LABEL"}
local time=$("$SCRIPTS/isosec")
if [[ -z $file ]] || [[ -z $id ]] || [[ -z $label ]]; then
echo "Loggging not properly setup."
exit 1
fi
local prefix="[id: $id][time: $time][source: \e[32m$source_file\e[0m][\e[34m$label\e[0m] :"
local m="$prefix $msg"
echo -e "$m" >>"$file"
done done
# Also log errors and warning messages to the console. # Also log errors and warning messages to the console.
if [[ $error_flag == "1" ]] || [[ $warn_flag == "1" ]]; then if [[ $error_flag == "1" ]] || [[ $warn_flag == "1" ]]; then
echo -e "[id: $LOG_INVOCATION_ID]$msg" echo -e "[id: $id]$msg"
fi fi
else else
# Dry run mode, so just log to the console # Dry run mode, so just log to the console
@@ -141,14 +153,19 @@ setup-logging() {
exit 1 exit 1
fi fi
# Only add files that aren't already in the LOG_FILE.
if [[ ! $LOG_FILE =~ $file ]]; then
LOG_FILE+=("$file") LOG_FILE+=("$file")
fi
LOG_INVOCATION_ID=${LOG_INVOCATION_ID:-$RANDOM} LOG_INVOCATION_ID=${LOG_INVOCATION_ID:-$RANDOM}
if [[ -n $LOG_LABEL ]]; then if [[ -n $LOG_LABEL ]] && [[ ! $LOG_LABEL =~ $label ]]; then
LOG_LABEL+=("${LOG_LABEL[@]}=>$label") LOG_LABEL+=("${LOG_LABEL[@]}=>$label")
else elif [[ ! $LOG_LABEL =~ $label ]]; then
LOG_LABEL+=("$label") LOG_LABEL+=("$label")
fi fi
export LOG_FILE export LOG_FILE
export LOG_LABEL export LOG_LABEL
export LOG_INVOCATION_ID export LOG_INVOCATION_ID

View File

@@ -1,7 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
THIS_FILE=${BASH_SOURCE[0]} THIS_FILE=${BASH_SOURCE[0]}
THIS=$(basename "$THIS_FILE") LOG_LABEL=$(basename $THIS_FILE)
LOG_FILE=${LOG_FILE:-/tmp/$LOG_LABEL.log}
THIS=${THIS:-$LOG_LABEL}
usage() { usage() {
cat <<EOF cat <<EOF
@@ -42,7 +44,7 @@ log() {
} }
source "$SCRIPTS/hypr/logging" source "$SCRIPTS/hypr/logging"
setup-logging "/tmp/$THIS.log" "$THIS" setup-logging "$LOG_FILE" "$LOG_LABEL"
if [[ -z target_workspace ]]; then if [[ -z target_workspace ]]; then
log --error "Must supply a workpsace to switch to." log --error "Must supply a workpsace to switch to."

View File

@@ -1,5 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e
set -o nounset
set -o pipefail
THIS_FILE=${BASH_SOURCE[0]} THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE") LOG_LABEL=$(basename "$THIS_FILE")
# Allows script name to be set when called from a parent script or defaults to filename. # Allows script name to be set when called from a parent script or defaults to filename.
@@ -98,6 +102,10 @@ close() {
fi fi
} }
################################################################################
# MAIN
################################################################################
# Setup logging file and label # Setup logging file and label
source "$SCRIPTS/hypr/logging" source "$SCRIPTS/hypr/logging"
setup-logging "$LOG_LABEL" setup-logging "$LOG_LABEL"

View File

@@ -0,0 +1,84 @@
#!/usr/bin/env bash
set -e
set -o nounset
set -o pipefail
SCRIPTS=${SCRIPTS:-$HOME/.local/scripts}
THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE")
THIS=${THIS:-$LOG_LABEL}
LOG_FILE=${LOG_FILE:-"/tmp/$LOG_LABEL.log"}
usage() {
cat <<EOF
Focuses a window, properly handling windows in special workspaces. If no address is supplied,
then we will read address from stdin.
USAGE:
$ $THIS <flags> <address>
FLAGS:
-h | --help: Show this help page.
EOF
}
# Logging utility function, use in place of echo.
log() {
logging log --source "$THIS_FILE" "$@"
}
# Prevent hyprctl dispatch calls from printing to the console.
hypr_dispatch() {
hyprctl dispatch "$@" >/dev/null 2>&1
return $?
}
focus_window() {
local address=$1
log "Focusing window, selection: $address"
local name=$(hyprctl clients -j | jq -r ".[] | select(.address == \"$address\") | .workspace.name")
local active_workspace=$(hyprctl activewindow -j | jq -r ".workspace.name")
log "Window workspace: '$name', active workspace: '$active_workspace'"
if [[ $name =~ ^special ]] && [[ ! $active_workspace == $name ]]; then
log "Toggling special workspace prior to focusing window."
name="${name#special:*}"
hypr_dispatch togglespecialworkspace $name
fi
hypr_dispatch focuswindow "address:$address"
}
################################################################################
# MAIN
################################################################################
# Setup logging file and label.
source "$SCRIPTS/hypr/logging"
setup-logging "$LOG_FILE" "$LOG_LABEL"
address=""
while [[ $# -gt 0 ]]; do
if [[ $1 == "-h" ]] || [[ $1 == "--help" ]]; then
usage && exit 0
else
address=$1
fi
shift
done
if [[ -z $address ]]; then
log "Reading address from stdin."
# If an address not supplied then read from stdin, which allows us to pipe the address into
# this command.
read -p "Window address: " address
fi
if [[ -z $address ]]; then
log --error "No address supplied." && exit 1
fi
focus_window $address && exit $?

View File

@@ -7,18 +7,18 @@ set -o pipefail
SCRIPTS=${SCRIPTS:-$HOME/.local/scripts} SCRIPTS=${SCRIPTS:-$HOME/.local/scripts}
THIS_FILE=${BASH_SOURCE[0]} THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE") LOG_LABEL=$(basename "$THIS_FILE")
LOG_FILE=${LOG_FILE:-"/tmp/$LOG_LABEL.log"}
THIS=${THIS:-$LOG_LABEL} THIS=${THIS:-$LOG_LABEL}
address="" address=""
move_silent_flag="0" move_silent_flag="0"
should_go_back="0"
if [[ $# == 1 ]]; then if [[ $# == 1 ]]; then
address="$1" address="$1"
else else
# If an address not supplied then read from stdin, which allows us to pipe into # If an address not supplied then read from stdin, which allows us to pipe the address into
# this command. # this command.
read -r address read -p "Window address: " address
fi fi
# Logging utility function, use in place of echo. # Logging utility function, use in place of echo.
@@ -42,19 +42,6 @@ hypr_dispatch() {
return $? return $?
} }
focus_window() {
log "Focusing window, selection: $address"
local name=$(hyprctl clients -j | jq -r ".[] | select(.address == \"$address\") | .workspace.name")
local active_workspace=$(hyprctl activewindow -j | jq -r ".workspace.name")
log "Window workspace: '$name', active workspace: '$active_workspace'"
if [[ $name =~ ^special ]] && [[ ! $active_workspace == $name ]]; then
log "Toggling special workspace prior to focusing window."
name="${name#special:*}"
hypr_dispatch togglespecialworkspace $name
fi
hypr_dispatch focuswindow "address:$address"
}
parse_workspace_id() { parse_workspace_id() {
local workspace_name="" local workspace_name=""
read -r workspace_name read -r workspace_name
@@ -91,25 +78,11 @@ move_to_workspace() {
xargs -I{} hyprctl dispatch "$action" "{},address:$address" >/dev/null 2>&1 xargs -I{} hyprctl dispatch "$action" "{},address:$address" >/dev/null 2>&1
return $? return $?
} }
################################################################################ make_selection() {
# MAIN
################################################################################
# Setup logging file and label.
source "$SCRIPTS/hypr/logging"
setup-logging "$LOG_LABEL"
if [[ -z $address ]]; then
log --error "Address not set."
exit 1
fi
log "Prompting for window action..." log "Prompting for window action..."
local choices=(
choices=(
"Focus the selected window.:Focus window" "Focus the selected window.:Focus window"
"Close the selected window.:Close window" "Close the selected window.:Close window"
"Close the selected window and go back to the window list.:Close window and back" "Close the selected window and go back to the window list.:Close window and back"
@@ -119,8 +92,8 @@ choices=(
"Move back to window picker and reload windows.:Back" "Move back to window picker and reload windows.:Back"
"Quit:Quit" "Quit:Quit"
) )
preview_action="$SCRIPTS/hypr/preview-stats window $address \"{title, workspace, address}\"" local preview_action="$SCRIPTS/hypr/preview-stats window $address \"{title, workspace, address}\""
choice=$( local choice=$(
printf "%s\n" "${choices[@]}" | printf "%s\n" "${choices[@]}" |
fzf --style=full --footer="$(action_footer)" \ fzf --style=full --footer="$(action_footer)" \
--delimiter=':' --with-nth=2 \ --delimiter=':' --with-nth=2 \
@@ -128,37 +101,60 @@ choice=$(
--preview-label="[ Description ]" \ --preview-label="[ Description ]" \
--preview="echo -e {1}; echo -e '\n\n\e[35mSelected Window:\e[0m'; $preview_action;" --preview="echo -e {1}; echo -e '\n\n\e[35mSelected Window:\e[0m'; $preview_action;"
) )
if [[ $? -gt 0 ]]; then # Exit if non-zero code returned from making selection.
log --error "Unexpected fzf status: $?" [[ $? -gt 0 ]] && log --error "Unexpected fzf status: $?" && exit $?
exit $?
fi
# Set choice to just the action portion. # Set choice to just the action portion.
choice="${choice#*:}" choice="${choice#*:}"
log "Action Choice: $choice" echo "$choice"
}
# Set appropriate flags based on the choice and perform the action on the window address. # Set appropriate flags based on the choice and perform the action on the window address.
handle_selection() {
local resp="done"
local choice=""
read -r choice
log "Action Choice: $choice"
if [[ $choice == "Quit" ]]; then if [[ $choice == "Quit" ]]; then
exit 0 log "Quitting..."
elif [[ $choice == "Close window" ]]; then elif [[ $choice == "Close window" ]]; then
log "Closing window..."
"$SCRIPTS/hypr/close-windows" "$address" "$SCRIPTS/hypr/close-windows" "$address"
elif [[ $choice == "Close window and back" ]]; then elif [[ $choice == "Close window and back" ]]; then
log "Closing window and setting should go back flag."
"$SCRIPTS/hypr/close-windows" "$address" "$SCRIPTS/hypr/close-windows" "$address"
should_go_back="1" resp="back:close"
elif [[ $choice == "Copy to clipboard" ]]; then elif [[ $choice == "Copy to clipboard" ]]; then
log "Copied window address to the clipboard."
echo $address | wl-copy echo $address | wl-copy
elif [[ $choice == "Focus window" ]]; then elif [[ $choice == "Focus window" ]]; then
focus_window "$SCRIPTS/hypr/utils/windows/focus-window" $address
elif [[ $choice == "Move to workspace" ]]; then elif [[ $choice == "Move to workspace" ]]; then
move_to_workspace move_to_workspace
elif [[ $choice == "Move to workspace - silent" ]]; then elif [[ $choice == "Move to workspace - silent" ]]; then
move_silent_flag="1" move_silent_flag="1"
move_to_workspace move_to_workspace
resp="back"
elif [[ $choice == "Back" ]]; then elif [[ $choice == "Back" ]]; then
should_go_back="1" resp="back"
fi fi
# TODO: Maybe we just echo out a 'back' message. echo "$resp"
if [[ $should_go_back == "1" ]]; then
exit 69 }
################################################################################
# MAIN
################################################################################
# Setup logging file and label.
source "$SCRIPTS/hypr/logging"
setup-logging "$LOG_FILE" "$LOG_LABEL"
if [[ -z $address ]]; then
log --error "Address not set."
exit 1
fi fi
res=$(make_selection | handle_selection)
log "Action result: $res"
echo "$res"

View File

@@ -0,0 +1,113 @@
#!/usr/bin/env bash
set -e
set -o nounset
set -o pipefail
SCRIPTS=${SCRIPTS:-$HOME/.local/scripts}
THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE")
THIS=${THIS:-$LOG_LABEL}
LOG_FILE=${LOG_FILE:-"/tmp/$LOG_LABEL.log"}
address=""
width=""
height=""
usage() {
cat <<EOF
Utility for toggling a windows floating property.
If no address is supplied and '--active' flag is not set, then we will read address from stdin.
USAGE:
$ $THIS <flags> <address>
FLAGS:
-a | --active: Toggles floating of the active window.
-w | --width <n>: Set a width of the floating window, can be pixels or percent (ex. 80%).
-h | --height <n>: Set a height of the floating window, can be pixels or percent (ex. 80%).
--help: Show this help page.
EOF
}
log() {
logging log --source "$THIS_FILE" "$@"
}
# Suppress output of hyprctl
hypr_dispatch() {
hyprctl dispatch "$@" >/dev/null 2>&1 && return $?
}
toggle_floating() {
hypr_dispatch togglefloating "address:$address"
}
resize_window() {
if [[ -n $width ]] && [[ -n $height ]]; then
log "Resizing window: width: $width, height: $height"
hypr_dispatch resizewindowpixel exact "$width $height,address:$address"
fi
echo "$address"
}
center_window() {
local address=""
read -r address
local activeaddress=$(hyprctl activewindow -j | jq -r '.address')
if [[ $address == $activeaddress ]]; then
log "Centering window..."
hypr_dispatch centerwindow
fi
}
################################################################################
# MAIN
################################################################################
# Setup logging
source "$SCRIPTS/hypr/logging"
setup-logging "$LOG_FILE" "$LOG_LABEL"
while [[ $# -gt 0 ]]; do
if [[ $1 == "--help" ]]; then
usage && exit 0
elif [[ $1 == "-w" ]] || [[ $1 == "--width" ]]; then
shift
width=$1
elif [[ $1 == "-h" ]] || [[ $1 == "--height" ]]; then
shift
height=$1
elif [[ $1 == "-a" ]] || [[ $1 == "--active" ]]; then
address=$(hyprctl activewindow -j | jq -r '.address')
else
address=$1
fi
shift
done
if [[ -z $address ]]; then
read -p "Window address: " address
fi
if [[ -z $address ]]; then
log --error "No address was supplied" && exit 1
fi
log "Begin toggling floating for: '$address'"
floating=$(hyprctl clients -j | jq ".[] | select(.address == \"$address\") | .floating")
log "Is currently floating: $floating"
toggle_floating
if [ ! "$floating" == "true" ]; then
resize_window | center_window
fi

View File

@@ -0,0 +1,97 @@
#!/usr/bin/env bash
set -e
set -o nounset
set -o pipefail
SCRIPTS=${SCRIPTS:-$HOME/.local/scripts}
THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE")
THIS=${THIS:-$LOG_LABEL}
LOG_FILE=${LOG_FILE:-"/tmp/$LOG_LABEL.log"}
usage() {
cat <<EOF
Shows a window picker and window details, then prompts for an action that can be
performed on the selected window.
USAGE:
$ $THIS <flags>
FLAGS:
-h | --help: Show this page.
EOF
}
# Logging utility function, use in place of echo.
log() {
logging log --source "$THIS_FILE" "$@"
}
handle_selected_value() {
local selection=""
read -r selection
if [[ -z $selection ]]; then
log "No selected value."
return 1
fi
log "Prompting for action, window: '$selection'"
local res=$(echo "$selection" | "$SCRIPTS/hypr/utils/windows/window-action-picker")
log "Action callback result: $res"
echo "$res"
}
prompt_for_window_selection() {
local selected_value=$("$SCRIPTS/hypr/window-picker")
local status=$?
if [[ $status -ne 0 ]]; then
exit $status
fi
echo "$selected_value"
}
################################################################################
# MAIN
################################################################################
# Setup logging file and label.
source "$SCRIPTS/hypr/logging"
setup-logging $LOG_FILE $LOG_LABEL
should_quit="0"
log "Starting $THIS..."
while [[ $# -gt 0 ]]; do
if [[ $1 == "-h" ]] || [[ $1 == "--help" ]]; then
usage && exit 0
elif [[ -n $1 ]]; then
address=$1
fi
shift
done
# Load colors if they haven't been loaded already.
[[ -z ${FZF_DEFAULT_OPTS} ]] &&
[[ -f $SCRIPTS/catppuccin-colors ]] &&
source $SCRIPTS/catppuccin-colors
trap 'log "Stoping..."; should_quit="1"' SIGINT
while [[ $should_quit -eq 0 ]]; do
res=$(prompt_for_window_selection | handle_selected_value)
if [[ ! $res =~ ^back ]]; then
should_quit=1
elif [[ $res == "back:close" ]]; then
sleep 0.3 # allow time for windows close, to prevent showing closed windows.
fi
log "Should quit: $should_quit"
done

View File

@@ -1,319 +1,117 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e
set -o nounset
set -o pipefail
THIS_FILE=${BASH_SOURCE[0]} THIS_FILE=${BASH_SOURCE[0]}
THIS=$(basename $THIS_FILE) THIS=$(basename $THIS_FILE)
LOG_LABEL=$(basename $THIS_FILE)
SCRIPTS=${SCRIPTS:-$HOME/.local/scripts} SCRIPTS=${SCRIPTS:-$HOME/.local/scripts}
LOG_FILE=${LOG_FILE:-"/tmp/$LOG_LABEL.log"}
usage() { usage() {
cat <<EOF cat <<EOF
Show a table with details about the currently active windows. You can choose a window and perform Utility for performing actions on windows.
an action. This script will prompt for what you would like to do depending on the options passed.
There are no required options for this script to work.
USAGE: USAGE:
$ $THIS [OPTIONS] $ $THIS <command> <flags>
OPTIONS: FLAGS:
--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 <address>: Close the selected window.
-f | --focus <address>: Focus the selected window, if optional address is supplied then we focus it.
-i | --ignore: Ignore the selected window.
-m | --move <address>: Move the selected window to another workspace and switch to that workspace.
-s | --silent-move <address>: Move the selected window to another workspace and remain on current workspace.
-t | --to-workspace <id>: Used with one of the move options to set which workspace to move to. If not supplied
then we will prompt for a workspace to move to.
-h | --help: Show this page. -h | --help: Show this page.
NOTES: COMMANDS:
close: Close window(s).
focus: Focuses a window, handling special workspaces properly.
launch: Launches an interactive picker in a new terminal.
picker: Window picker that prompts for an action to perform on the window.
toggle-floating: Toggles floating property of a window.
If using the 'launch' option then flags passed after the '--launch' flag will be passed into the Run "$THIS <command> --help" for more information on a command.
launched terminal, allowing you to launch with a specific mode turned on, any flags passed in prior to
'--launch' will be ignored.
EOF EOF
} }
if [[ "$1" == "close" ]]; then
shift
THIS="$THIS close" "$SCRIPTS/hypr/utils/windows/close-windows" "$@"
exit $?
fi
window_class="com.ghostty.$THIS" window_class="com.ghostty.$THIS"
window_padding_x="10" window_padding_x="10"
clipboard_flag="0"
close_flag="0"
focus_flag="0"
ignore_flag="0"
launch_flag="0"
move_flag="0"
move_silent_flag="0"
move_to_workspace_name=""
refresh_flag="0"
should_quit="0"
launch_args=()
selected_value=""
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"
selected_value=$2
shift
elif [[ $1 =~ ^-f ]] || [[ $1 =~ ^--focus ]]; then
focus_flag="1"
selected_value=$2
shift
elif [[ $1 =~ ^-h ]] || [[ $1 =~ ^--help ]]; then
usage && exit 0
elif [[ $1 =~ ^-i ]] || [[ $1 =~ ^--ignore ]]; then
ignore_flag="1"
elif [[ $1 =~ ^-m ]] || [[ $1 =~ ^--move ]]; then
move_flag="1"
selected_value=$2
shift
elif [[ $1 =~ ^-s ]] || [[ $1 =~ ^--silent-move ]]; then
move_flag="1"
move_silent_flag="1"
selected_value=$2
shift
elif [[ $1 =~ ^-t ]] || [[ $1 =~ ^--to-workspace ]]; then
shift
move_to_workspace_name=$1
elif [[ $1 =~ ^--launch ]]; then
launch_flag="1"
fi
fi
shift
done
action_footer() {
cat <<'EOF'
___ __ _
/ _ |____/ /_(_)__ ___
/ __ / __/ __/ / _ \/ _ \
/_/ |_\__/\__/_/\___/_//_/
EOF
}
log() { log() {
logging log --source "$THIS_FILE" "$@" logging log --source "$THIS_FILE" "$@"
} }
# Reset flags and selection. launch_usage() {
reset_flags() { cat <<EOF
selected_value=""
clipboard_flag="0" Launches an interactive picker in a new terminal window.
close_flag="0"
focus_flag="0" USAGE:
ignore_flag="0"
launch_flag="0" $ $THIS launch <flags>
move_flag="0"
move_silent_flag="0"
move_to_workspace_name="" FLAGS:
refresh_flag="0" -h | --help: Show this page.
should_quit="0"
EOF
} }
ask_what_to_do_with_selection() { # Launch in a new terminal window.
local choices=( launch() {
"Focus the selected window.:Focus window" if [[ $@ =~ ^-h ]] || [[ $@ =~ ^--help ]]; then
"Close the selected window.:Close window" launch_usage && exit 0
"Close the selected window and go back to the window list.:Close window and back"
"Move the selected window to another workspace, focusing the window.\n\nA workspace picker will be presented to choose which workspace to move to.:Move to workspace"
"Move the selected window to another workspace, without focusing the window.\n\nA workspace picker will be presented to choose which workspace to move to.:Move to workspace - silent"
"Copy the window address to the system clipboard:Copy to clipboard"
"Move back to window picker and reload windows.:Back"
"Quit:Quit"
)
choice=$(
printf "%s\n" "${choices[@]}" |
fzf --style=full --footer="$(action_footer)" \
--delimiter=':' --with-nth=2 \
--header="What should we do with the selected window?" \
--preview-label="[ Description ]" \
--preview="echo -e {1}; echo -e '\n\n\e[35mSelected Window:\e[0m'; $SCRIPTS/hypr/preview-stats window $selected_value \"{title, workspace, address}\";"
)
# Set choice to just the action portion.
choice="${choice#*:}"
log "Choice: $choice"
# Set appropriate flags based on the choice.
if [[ $choice == "Quit" ]]; then
exit 0
elif [[ $choice == "Close window" ]]; then
should_quit="1"
close_flag="1"
elif [[ $choice == "Close window and back" ]]; then
close_flag="1"
refresh_flag="1"
should_quit="0"
elif [[ $choice == "Copy to clipboard" ]]; then
should_quit="1"
clipboard_flag="1"
elif [[ $choice == "Focus window" ]]; then
should_quit="1"
focus_flag="1"
elif [[ $choice == "Move to workspace" ]]; then
should_quit="1"
move_flag="1"
elif [[ $choice == "Move to workspace - silent" ]]; then
should_quit="1"
move_silent_flag="1"
move_flag="1"
elif [[ $choice == "Refresh window list" ]]; then
refresh_flag="1"
should_quit="0"
fi fi
log "Launching terminal."
ghostty --class="$window_class" --window-padding-x="$window_padding_x" \
--keybind="ctrl+c=quit" \
-e "${BASH_SOURCE[0]}" "$@"
} }
# Prevent hyprctl dispatch calls from printing to the console. show_picker() {
hypr_dispatch() { log "Showing picker..."
hyprctl dispatch "$@" >/dev/null 2>&1 THIS="$THIS picker" "$SCRIPTS/hypr/utils/windows/windowctl-picker" "$@"
return $? return $?
} }
move_to_workspace() {
local workspace_id=""
if [[ -z $move_to_workspace_name ]]; then
move_to_workspace_name=$(
$SCRIPTS/hypr/workspace-picker --return-name-if-special \
--header="Select a workspace to move window to:"
)
fi
if [[ -z $move_to_workspace_name ]]; then
log --error "No workspace set to move window to."
exit 1
fi
# Check if moving to a special workspace to pass the appropriate args in to hyprctl.
if [[ $move_to_workspace_name =~ ^special ]]; then
workspace_id=$move_to_workspace_name
else
workspace_id=$(hyprctl workspaces -j | jq -r ".[] | select(.name | contains(\"$move_to_workspace_name\")) | .id")
fi
if [[ -z $workspace_id ]]; then
log --error "No workspace id found for: '$move_to_workspace_name'"
exit 1
fi
action="movetoworkspace"
if [[ $move_silent_flag == "1" ]]; then
action="movetoworkspacesilent"
fi
log "Moving window: '$selected_value' to workspace: '$workspace_id'"
hypr_dispatch $action "$workspace_id,address:$selected_value"
}
focus_window() {
log "Focusing window, selection: $selected_value"
local address="$selected_value"
local name=$(hyprctl clients -j | jq -r ".[] | select(.address == \"$address\") | .workspace.name")
local active_workspace=$(hyprctl activewindow -j | jq -r ".workspace.name")
log "Window workspace: '$name', active workspace: '$active_workspace'"
if [[ $name =~ ^special ]] && [[ ! $active_workspace == $name ]]; then
log "Toggling special workspace prior to focusing window."
name="${name#special:*}"
hypr_dispatch togglespecialworkspace $name
fi
hypr_dispatch focuswindow "address:$address"
}
handle_selected_value() {
if [[ $ignore_flag == "1" ]]; then
log "Ignore flag set, selection: '$selected_value'"
exit 0
elif [[ $clipboard_flag == "1" ]]; then
log "Copying to clipboard, selection: $selected_value"
wl-copy $selected_value
elif [[ $focus_flag == "1" ]]; then
focus_window
elif [[ $close_flag == "1" ]]; then
log "Closing window, selection: $selected_value"
hypr_dispatch closewindow "address:$selected_value"
if [[ $refresh_flag == "1" ]]; then
log "Refreshing windows..."
# Need to sleep here breifly otherwise recently closed windows will still show
# in the window picker.
reset_flags && sleep 0.3
fi
elif [[ $move_flag == "1" ]] || [[ $move_silent_flag == "1" ]]; then
move_to_workspace
# && exit 0
else
log "No flag set, selection: '$selected_value'"
fi
}
################################################## ##################################################
# MAIN # MAIN
################################################## ##################################################
# Setup logging file and label. # Setup logging file and label.
source "$SCRIPTS/hypr/logging" source "$SCRIPTS/hypr/logging"
setup-logging "/tmp/$THIS.log" "$THIS" setup-logging "$LOG_LABEL"
log "Starting with selected value: '$selected_value'" while [[ $# -gt 0 ]]; do
if [[ $1 == "close" ]]; then
if [[ $launch_flag == "1" ]]; then shift
ghostty --class="$window_class" --window-padding-x="$window_padding_x" \ THIS="$THIS close" "$SCRIPTS/hypr/utils/windows/close-windows" "$@"
--keybind="ctrl+c=quit" \ exit $?
-e "${BASH_SOURCE[0]}" "${launch_args[@]}" elif [[ $1 == "focus" ]]; then
shift
THIS="$THIS focus" "$SCRIPTS/hypr/utils/windows/focus-window" "$@"
exit $?
elif [[ $1 == "launch" ]]; then
shift
launch picker "$@" && exit 0
elif [[ $1 == "picker" ]]; then
shift
show_picker "$@"
exit $?
elif [[ $1 == "toggle-floating" ]]; then
shift
THIS="$THIS toggle-floating" "$SCRIPTS/hypr/utils/windows/window-toggle-floating" "$@"
exit $?
elif [[ $1 == "-h" ]] || [[ $1 == "--help" ]]; then
usage && exit 0
else else
log --error "Unhandled arg: $1"
# Load colors if they haven't been loaded already. exit 1
[[ -z ${FZF_DEFAULT_OPTS} ]] &&
[[ -f $SCRIPTS/catppuccin-colors ]] &&
source $SCRIPTS/catppuccin-colors
if [[ -n $selected_value ]]; then
# Handle value if it was passed in.
# TODO: This should probably ensure that flags were set.
handle_selected_value && exit 0
else
trap 'log "Stoping..."; should_quit="1"' SIGINT
while [[ $should_quit == "0" ]]; do
# not sure if this should be here or somewhere else, as it will
# cause any passed in flags to be ignored, but they're generally empty
# when using this interactive mode anyway.
reset_flags
selected_value=$("$SCRIPTS/hypr/window-picker")
status=$?
if [[ $status -ne 0 ]]; then
should_quit="1"
else
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.
log "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.
# log "Giving up without a selection."
fi
fi fi
shift
done done
fi
fi # If we've reached here then no commands were passed / handled.
usage && exit 1

7
gen
View File

@@ -74,10 +74,15 @@ generate_script() {
cat >"$dest" <<'EOF' cat >"$dest" <<'EOF'
#!/usr/bin/env bash #!/usr/bin/env bash
set -e
set -o nounset
set -o pipefail
SCRIPTS=${SCRIPTS:-$HOME/.local/scripts} SCRIPTS=${SCRIPTS:-$HOME/.local/scripts}
THIS_FILE=${BASH_SOURCE[0]} THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE") LOG_LABEL=$(basename "$THIS_FILE")
THIS=${THIS:-$LOG_LABEL} THIS=${THIS:-$LOG_LABEL}
LOG_FILE=${LOG_FILE:-"/tmp/$LOG_LABEL.log"}
# Logging utility function, use in place of echo. # Logging utility function, use in place of echo.
log() { log() {
@@ -90,7 +95,7 @@ log() {
# Setup logging file and label. # Setup logging file and label.
source "$SCRIPTS/hypr/logging" source "$SCRIPTS/hypr/logging"
setup-logging "$LOG_LABEL" setup-logging "$LOG_FILE" "$LOG_LABEL"
log "Starting $THIS..." log "Starting $THIS..."