mirror of
https://github.com/arthur-pbty/arthur-os.git
synced 2026-08-01 20:28:16 +02:00
Download the current page's video with yt-dlp via Alt+Shift+D or a click on the toolbar icon. A native-messaging host runs the download, shows live progress on the Quickshell OSD, and posts a clickable "Download complete" toast that opens the file in mpv. - Extension: pinned key for a stable id, green download-video icon, keyboard command + toolbar action (reads the active tab URL). - Native host (omarchy-chromium-ytdlp-host): verifies the URL with yt-dlp --simulate (else "No video found"), streams progress to the OSD (time-throttled to ~4/s), saves to ~/Videos, opens mpv on click. - Installer (omarchy-install-chromium-ytdlp) writes the native-messaging manifest into installed Chromium/Chrome/Brave/Edge profiles; wired into browser install and chromium refresh, with a migration for existing users. - omarchy-osd: add -d/--duration so the OSD can persist during a download. - Add yt-dlp to base packages, load the extension via --load-extension, and document the Alt+Shift+D binding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
614 lines
17 KiB
Bash
Executable File
614 lines
17 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Display Hyprland keybindings defined in your configuration using an interactive search menu.
|
|
|
|
declare -A KEYCODE_SYM_MAP
|
|
# Hyprland reports XKB keycodes for code: bindings. Keep a small fallback for
|
|
# common keys so the menu remains readable if xkbcli cannot resolve a symbol.
|
|
declare -A FALLBACK_KEYCODE_SYM_MAP=(
|
|
[10]="1"
|
|
[11]="2"
|
|
[12]="3"
|
|
[13]="4"
|
|
[14]="5"
|
|
[15]="6"
|
|
[16]="7"
|
|
[17]="8"
|
|
[18]="9"
|
|
[19]="0"
|
|
[20]="MINUS"
|
|
[21]="EQUAL"
|
|
[59]="COMMA"
|
|
[60]="PERIOD"
|
|
[61]="SLASH"
|
|
)
|
|
|
|
# Hyprland's Lua config provider currently reports Lua binds as dispatcher
|
|
# __lua and code:... binds from hl.bind() as key="" and keycode=0 in
|
|
# `hyprctl -j binds`. Keep a lightweight source-derived cache so the menu can
|
|
# still show and dispatch those bindings.
|
|
declare -A LUA_BIND_KEY_MAP
|
|
declare -A LUA_BIND_DISPATCHER_MAP
|
|
declare -A LUA_BIND_ARG_MAP
|
|
|
|
build_keymap_cache() {
|
|
local keymap
|
|
keymap="$(xkbcli compile-keymap)" || {
|
|
echo "Failed to compile keymap" >&2
|
|
return 1
|
|
}
|
|
|
|
while IFS=, read -r code sym; do
|
|
[[ -z $code || -z $sym ]] && continue
|
|
KEYCODE_SYM_MAP["$code"]="$sym"
|
|
done < <(
|
|
awk '
|
|
BEGIN { sec = "" }
|
|
/xkb_keycodes/ { sec = "codes"; next }
|
|
/xkb_symbols/ { sec = "syms"; next }
|
|
sec == "codes" {
|
|
if (match($0, /<([A-Za-z0-9_]+)>\s*=\s*([0-9]+)\s*;/, m)) code_by_name[m[1]] = m[2]
|
|
}
|
|
sec == "syms" {
|
|
if (match($0, /key\s*<([A-Za-z0-9_]+)>\s*\{\s*\[\s*([^, \]]+)/, m)) sym_by_name[m[1]] = m[2]
|
|
}
|
|
END {
|
|
for (k in code_by_name) {
|
|
c = code_by_name[k]
|
|
s = sym_by_name[k]
|
|
if (c != "" && s != "" && s != "NoSymbol") print c "," s
|
|
}
|
|
}
|
|
' <<<"$keymap"
|
|
)
|
|
}
|
|
|
|
lookup_keycode_cached() {
|
|
local symbol
|
|
symbol="${KEYCODE_SYM_MAP[$1]}"
|
|
|
|
if [[ -z $symbol ]]; then
|
|
symbol="${FALLBACK_KEYCODE_SYM_MAP[$1]}"
|
|
fi
|
|
|
|
if [[ -z $symbol ]]; then
|
|
symbol="code:$1"
|
|
fi
|
|
|
|
printf '%s\n' "${symbol^^}"
|
|
}
|
|
|
|
parse_keycodes() {
|
|
local start end elapsed
|
|
[[ ${DEBUG:-0} == "1" ]] && start=$(date +%s.%N)
|
|
while IFS= read -r line; do
|
|
if [[ $line =~ code:([0-9]+) ]]; then
|
|
code="${BASH_REMATCH[1]}"
|
|
if [[ $code == "201" ]]; then
|
|
echo "${line/SUPER SHIFT,code:201/,COPILOT KEY}"
|
|
else
|
|
symbol=$(lookup_keycode_cached "$code" "$XKB_KEYMAP_CACHE")
|
|
echo "${line/code:${code}/$symbol}"
|
|
fi
|
|
elif [[ $line =~ mouse:([0-9]+) ]]; then
|
|
code="${BASH_REMATCH[1]}"
|
|
|
|
case "$code" in
|
|
272) symbol="LEFT MOUSE BUTTON" ;;
|
|
273) symbol="RIGHT MOUSE BUTTON" ;;
|
|
274) symbol="MIDDLE MOUSE BUTTON" ;;
|
|
*) symbol="mouse:${code}" ;;
|
|
esac
|
|
|
|
echo "${line/mouse:${code}/$symbol}"
|
|
else
|
|
echo "$line"
|
|
fi
|
|
done
|
|
|
|
if [[ $DEBUG == "1" ]]; then
|
|
end=$(date +%s.%N)
|
|
# fall back to awk if bc is missing
|
|
if command -v bc >/dev/null 2>&1; then
|
|
elapsed=$(echo "$end - $start" | bc)
|
|
else
|
|
elapsed=$(awk -v s="$start" -v e="$end" 'BEGIN{printf "%.6f", (e - s)}')
|
|
fi
|
|
echo "[DEBUG] parse_keycodes elapsed: ${elapsed}s" >&2
|
|
fi
|
|
}
|
|
|
|
# Supplement `hyprctl -j binds` for Lua-only binds that Hyprland currently
|
|
# reports as dispatcher __lua and without their original key for code: binds.
|
|
build_lua_bind_cache() {
|
|
local modmask description key dispatcher arg cache_key
|
|
|
|
omarchy-cmd-present lua || return 0
|
|
|
|
while IFS=$'\t' read -r modmask description key dispatcher arg; do
|
|
[[ -z $modmask || -z $description || -z $key ]] && continue
|
|
|
|
LUA_BIND_KEY_MAP["$modmask,$description"]="$key"
|
|
cache_key="$modmask,$description,$key"
|
|
LUA_BIND_DISPATCHER_MAP["$cache_key"]="$dispatcher"
|
|
LUA_BIND_ARG_MAP["$cache_key"]="$arg"
|
|
done < <(
|
|
lua <<'LUA'
|
|
local modifiers = { SHIFT = 1, CTRL = 4, CONTROL = 4, ALT = 8, SUPER = 64 }
|
|
|
|
local function split_keys(keys)
|
|
local modmask = 0
|
|
local key = ""
|
|
|
|
for part in string.gmatch(tostring(keys or ""), "[^+]+") do
|
|
local value = part:gsub("^%s+", ""):gsub("%s+$", "")
|
|
local modifier = modifiers[string.upper(value)]
|
|
|
|
if modifier then
|
|
modmask = modmask + modifier
|
|
else
|
|
key = value
|
|
end
|
|
end
|
|
|
|
return modmask, key
|
|
end
|
|
|
|
local function lua_literal(value)
|
|
local value_type = type(value)
|
|
|
|
if value_type == "string" then
|
|
return string.format("%q", value)
|
|
elseif value_type == "number" or value_type == "boolean" then
|
|
return tostring(value)
|
|
elseif value_type == "table" then
|
|
local parts = {}
|
|
local keys = {}
|
|
local array_length = #value
|
|
|
|
for index = 1, array_length do
|
|
parts[#parts + 1] = lua_literal(value[index])
|
|
end
|
|
|
|
for key in pairs(value) do
|
|
if not (type(key) == "number" and key >= 1 and key <= array_length and math.floor(key) == key) then
|
|
keys[#keys + 1] = key
|
|
end
|
|
end
|
|
|
|
table.sort(keys, function(left, right)
|
|
return tostring(left) < tostring(right)
|
|
end)
|
|
|
|
for _, key in ipairs(keys) do
|
|
local key_prefix
|
|
if type(key) == "string" and key:match("^[%a_][%w_]*$") then
|
|
key_prefix = key .. " = "
|
|
else
|
|
key_prefix = "[" .. lua_literal(key) .. "] = "
|
|
end
|
|
|
|
parts[#parts + 1] = key_prefix .. lua_literal(value[key])
|
|
end
|
|
|
|
return "{ " .. table.concat(parts, ", ") .. " }"
|
|
elseif value_type == "nil" then
|
|
return "nil"
|
|
else
|
|
return "nil"
|
|
end
|
|
end
|
|
|
|
local function call_expression(path, ...)
|
|
local args = {}
|
|
|
|
for index = 1, select("#", ...) do
|
|
args[index] = lua_literal(select(index, ...))
|
|
end
|
|
|
|
return path .. "(" .. table.concat(args, ", ") .. ")"
|
|
end
|
|
|
|
local function dispatcher(kind, arg, expr)
|
|
return {
|
|
__omarchy_dispatcher = true,
|
|
kind = kind or "",
|
|
arg = arg or "",
|
|
expr = expr or "",
|
|
}
|
|
end
|
|
|
|
local function dsp_proxy(path)
|
|
return setmetatable({ path = path }, {
|
|
__index = function(self, key)
|
|
return dsp_proxy(self.path .. "." .. tostring(key))
|
|
end,
|
|
__call = function(self, ...)
|
|
local first_arg = ...
|
|
local expr = call_expression(self.path, ...)
|
|
|
|
if self.path == "hl.dsp.exec_cmd" and type(first_arg) == "string" then
|
|
return dispatcher("exec", first_arg, expr)
|
|
end
|
|
|
|
return dispatcher("lua", expr, expr)
|
|
end,
|
|
})
|
|
end
|
|
|
|
local noop
|
|
noop = setmetatable({}, {
|
|
__index = function()
|
|
return noop
|
|
end,
|
|
__call = function()
|
|
return noop
|
|
end,
|
|
})
|
|
|
|
local function noop_fn()
|
|
return noop
|
|
end
|
|
|
|
hl = setmetatable({
|
|
dsp = dsp_proxy("hl.dsp"),
|
|
bind = function(keys, bind_dispatcher, opts)
|
|
opts = opts or {}
|
|
|
|
if opts.description and opts.description ~= "" then
|
|
local modmask, key = split_keys(keys)
|
|
local kind = ""
|
|
local arg = ""
|
|
|
|
if type(bind_dispatcher) == "table" and bind_dispatcher.__omarchy_dispatcher then
|
|
kind = bind_dispatcher.kind or ""
|
|
arg = bind_dispatcher.arg or bind_dispatcher.expr or ""
|
|
elseif type(bind_dispatcher) == "string" and bind_dispatcher ~= "" then
|
|
kind = "exec"
|
|
arg = bind_dispatcher
|
|
end
|
|
|
|
print(table.concat({ tostring(modmask), opts.description, key, kind, arg }, "\t"))
|
|
end
|
|
|
|
return noop
|
|
end,
|
|
unbind = noop_fn,
|
|
config = noop_fn,
|
|
env = noop_fn,
|
|
monitor = noop_fn,
|
|
window_rule = noop_fn,
|
|
workspace_rule = noop_fn,
|
|
layer_rule = noop_fn,
|
|
gesture = noop_fn,
|
|
animation = noop_fn,
|
|
curve = noop_fn,
|
|
exec_cmd = noop_fn,
|
|
dispatch = noop_fn,
|
|
on = noop_fn,
|
|
timer = noop_fn,
|
|
get_config = function()
|
|
return nil
|
|
end,
|
|
}, {
|
|
__index = function()
|
|
return noop
|
|
end,
|
|
})
|
|
|
|
local config = os.getenv("HOME") .. "/.config/hypr/hyprland.lua"
|
|
local file = io.open(config, "r")
|
|
|
|
if file then
|
|
file:close()
|
|
local ok, err = pcall(dofile, config)
|
|
if not ok and os.getenv("DEBUG") == "1" then
|
|
io.stderr:write("[DEBUG] lua bind scan failed: " .. tostring(err) .. "\n")
|
|
end
|
|
end
|
|
LUA
|
|
)
|
|
}
|
|
|
|
modmask_to_text() {
|
|
case "$1" in
|
|
0) printf '' ;;
|
|
1) printf 'SHIFT' ;;
|
|
4) printf 'CTRL' ;;
|
|
5) printf 'SHIFT CTRL' ;;
|
|
8) printf 'ALT' ;;
|
|
9) printf 'SHIFT ALT' ;;
|
|
12) printf 'CTRL ALT' ;;
|
|
13) printf 'SHIFT CTRL ALT' ;;
|
|
64) printf 'SUPER' ;;
|
|
65) printf 'SUPER SHIFT' ;;
|
|
68) printf 'SUPER CTRL' ;;
|
|
69) printf 'SUPER SHIFT CTRL' ;;
|
|
72) printf 'SUPER ALT' ;;
|
|
73) printf 'SUPER SHIFT ALT' ;;
|
|
76) printf 'SUPER CTRL ALT' ;;
|
|
77) printf 'SUPER SHIFT CTRL ALT' ;;
|
|
*) printf '%s' "$1" ;;
|
|
esac
|
|
}
|
|
|
|
# Fetch dynamic keybindings from Hyprland.
|
|
#
|
|
# Also do some pre-processing:
|
|
# - Fill missing Lua code:... keys and __lua dispatch metadata from the Lua source cache
|
|
# - Remove standard Omarchy bin path prefix
|
|
# - Map numeric modifier key mask to a textual rendition
|
|
# - Output comma-separated values that the parser can understand
|
|
dynamic_bindings() {
|
|
local modmask key keycode description dispatcher arg modifiers cache_key
|
|
|
|
hyprctl -j binds |
|
|
jq -r '.[] | [.modmask, (.key // ""), (.keycode // 0), (.description // ""), (.dispatcher // ""), (.arg // "") | tostring] | join("\u001f")' |
|
|
while IFS=$'\x1f' read -r modmask key keycode description dispatcher arg; do
|
|
if [[ -z $key && $keycode != "0" ]]; then
|
|
key="code:$keycode"
|
|
fi
|
|
|
|
if [[ -z $key && -n $description ]]; then
|
|
key="${LUA_BIND_KEY_MAP["$modmask,$description"]}"
|
|
fi
|
|
|
|
if [[ $dispatcher == "__lua" && -n $description && -n $key ]]; then
|
|
cache_key="$modmask,$description,$key"
|
|
dispatcher="${LUA_BIND_DISPATCHER_MAP["$cache_key"]}"
|
|
arg="${LUA_BIND_ARG_MAP["$cache_key"]}"
|
|
fi
|
|
|
|
[[ -z $description && $dispatcher == "__lua" ]] && continue
|
|
|
|
case "$key" in
|
|
comma) key="COMMA" ;;
|
|
period) key="PERIOD" ;;
|
|
minus) key="MINUS" ;;
|
|
equal) key="EQUAL" ;;
|
|
slash) key="SLASH" ;;
|
|
esac
|
|
|
|
modifiers=$(modmask_to_text "$modmask")
|
|
arg="${arg//~\/.local\/share\/omarchy\/bin\//}"
|
|
|
|
printf '%s,%s,%s,%s,%s\n' "$modifiers" "$key" "$description" "$dispatcher" "$arg"
|
|
done
|
|
}
|
|
|
|
# Hardcoded bindings, like the copy-url extension and such
|
|
static_bindings() {
|
|
echo "SHIFT ALT,L,Copy URL from Web App,sendshortcut,SHIFT ALT,L,"
|
|
echo "SHIFT ALT,D,Download Video from Web App,sendshortcut,SHIFT ALT,D,"
|
|
}
|
|
|
|
# Parse and format keybindings
|
|
#
|
|
# `awk` does the heavy lifting:
|
|
# - Set the field separator to a comma ','.
|
|
# - Joins the key combination (e.g., "SUPER + Q").
|
|
# - Joins the command that the key executes.
|
|
# - Prints display text and dispatch metadata as tab-separated fields.
|
|
parse_binding_records() {
|
|
awk -F, '
|
|
{
|
|
# Combine the modifier and key (first two fields)
|
|
key_combo = $1 " + " $2;
|
|
|
|
# Clean up: strip leading "+" if present, trim spaces
|
|
gsub(/^[ \t]*\+?[ \t]*/, "", key_combo);
|
|
gsub(/[ \t]+$/, "", key_combo);
|
|
|
|
# Use description, if set
|
|
action = $3;
|
|
dispatcher = $4;
|
|
|
|
# Reconstruct the dispatcher arg from the remaining fields
|
|
arg = "";
|
|
for (i = 5; i <= NF; i++) {
|
|
arg = arg $i (i < NF ? "," : "");
|
|
}
|
|
|
|
if (action == "") {
|
|
# Reconstruct the command from the remaining fields
|
|
for (i = 4; i <= NF; i++) {
|
|
action = action $i (i < NF ? "," : "");
|
|
}
|
|
|
|
# Clean up trailing commas, remove leading "exec, ", and trim
|
|
sub(/,$/, "", action);
|
|
gsub(/(^|,)[[:space:]]*exec[[:space:]]*,?/, "", action);
|
|
gsub(/(^|[[:space:]])uwsm(-app| app)[[:space:]]+--[[:space:]]+/, "", action);
|
|
gsub(/^[ \t]+|[ \t]+$/, "", action);
|
|
gsub(/[ \t]+/, " ", key_combo); # Collapse multiple spaces to one
|
|
|
|
# Escape XML entities
|
|
gsub(/&/, "\\&", action);
|
|
gsub(/</, "\\<", action);
|
|
gsub(/>/, "\\>", action);
|
|
gsub(/"/, "\\"", action);
|
|
gsub(/'"'"'/, "\\'", action);
|
|
}
|
|
|
|
if (action != "") {
|
|
printf "%-35s → %s\t%s\t%s\n", key_combo, action, dispatcher, arg;
|
|
}
|
|
}'
|
|
}
|
|
|
|
prioritize_entries() {
|
|
awk -F '\t' '
|
|
{
|
|
line = $1
|
|
prio = 50
|
|
if (match(line, /Terminal/)) prio = 0
|
|
if (match(line, /Tmux/)) prio = 1
|
|
if (match(line, /Browser/) && !match(line, /Browser[[:space:]]*\(/) && !match(line, /SUPER SHIFT.*\+.*B.*→.*Browser/)) prio = 2
|
|
if (match(line, /File manager/) && !match(line, /File manager \(cwd\)/)) prio = 3
|
|
if (match(line, /Launch apps/)) prio = 4
|
|
if (match(line, /Omarchy menu/)) prio = 5
|
|
if (match(line, /System menu/)) prio = 6
|
|
if (match(line, /Theme menu/)) prio = 7
|
|
if (match(line, /Full screen/)) prio = 8
|
|
if (match(line, /Full width/)) prio = 9
|
|
if (match(line, /Close window/)) prio = 10
|
|
if (match(line, /Close all windows/)) prio = 11
|
|
if (match(line, /Lock system/)) prio = 12
|
|
if (match(line, /Toggle window floating/)) prio = 13
|
|
if (match(line, /Toggle window split/)) prio = 14
|
|
if (match(line, /Pop window/)) prio = 15
|
|
if (match(line, /Universal/)) prio = 16
|
|
if (match(line, /Clipboard/)) prio = 17
|
|
if (match(line, /Audio controls/)) prio = 18
|
|
if (match(line, /Bluetooth controls/)) prio = 19
|
|
if (match(line, /Wifi controls/)) prio = 20
|
|
if (match(line, /Emojis/)) prio = 21
|
|
if (match(line, /Color picker/)) prio = 22
|
|
if (match(line, /Screenshot/)) prio = 23
|
|
if (match(line, /Screenrecording/)) prio = 24
|
|
if (match(line, /SUPER SHIFT.*\+.*B.*→.*Browser/)) prio = 25
|
|
if (match(line, /File manager \(cwd\)/)) prio = 26
|
|
if (match(line, /(Switch|Next|Former|Previous).*workspace/)) prio = 27
|
|
if (match(line, /Move window to workspace/)) prio = 28
|
|
if (match(line, /Move window silently to workspace/)) prio = 29
|
|
if (match(line, /Swap window/)) prio = 30
|
|
if (match(line, /Focus/)) prio = 31
|
|
if (match(line, /Move window$/)) prio = 32
|
|
if (match(line, /Resize window/)) prio = 33
|
|
if (match(line, /Expand window/)) prio = 34
|
|
if (match(line, /Shrink window/)) prio = 35
|
|
if (match(line, /scratchpad/)) prio = 36
|
|
if (match(line, /notification/)) prio = 37
|
|
if (match(line, /Toggle window transparency/)) prio = 38
|
|
if (match(line, /Toggle workspace gaps/)) prio = 39
|
|
if (match(line, /Toggle nightlight/)) prio = 40
|
|
if (match(line, /Toggle locking/)) prio = 41
|
|
if (match(line, /group/)) prio = 94
|
|
if (match(line, /Scroll active workspace/)) prio = 95
|
|
if (match(line, /Cycle to/)) prio = 96
|
|
if (match(line, /Reveal active/)) prio = 97
|
|
if (match(line, /Apple Display/)) prio = 98
|
|
if (match(line, /XF86/)) prio = 99
|
|
|
|
# print "priority<TAB>record"
|
|
printf "%d\t%s\n", prio, $0
|
|
}' |
|
|
sort -k1,1n -k2,2 |
|
|
cut -f2-
|
|
}
|
|
|
|
output_binding_records() {
|
|
build_keymap_cache
|
|
build_lua_bind_cache
|
|
|
|
{
|
|
dynamic_bindings
|
|
static_bindings
|
|
} |
|
|
sort -u |
|
|
parse_keycodes |
|
|
parse_binding_records |
|
|
prioritize_entries
|
|
}
|
|
|
|
output_keybindings() {
|
|
output_binding_records | cut -f1
|
|
}
|
|
|
|
trim() {
|
|
local value="$1"
|
|
|
|
value="${value#"${value%%[![:space:]]*}"}"
|
|
value="${value%"${value##*[![:space:]]}"}"
|
|
|
|
printf '%s\n' "$value"
|
|
}
|
|
|
|
lua_string() {
|
|
jq -Rnr --arg value "$1" '$value | @json'
|
|
}
|
|
|
|
dispatch_lua_expression() {
|
|
local expression="$1"
|
|
local output status
|
|
|
|
output=$(hyprctl dispatch "$expression" 2>&1)
|
|
status=$?
|
|
|
|
if (( status == 0 )) && [[ -z $output || $output == "ok" ]]; then
|
|
[[ -n $output ]] && printf '%s\n' "$output"
|
|
return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
dispatch_exec_binding() {
|
|
local command="$1"
|
|
|
|
dispatch_lua_expression "hl.dsp.exec_cmd($(lua_string "$command"))" || hyprctl dispatch exec "$command"
|
|
}
|
|
|
|
dispatch_sendshortcut_binding() {
|
|
local arg="$1"
|
|
local mods key window rest
|
|
|
|
IFS=, read -r mods key window rest <<<"$arg"
|
|
mods=$(trim "$mods")
|
|
key=$(trim "$key")
|
|
window=$(trim "$window")
|
|
|
|
[[ -z $window ]] && window="activewindow"
|
|
|
|
if [[ -n $key ]] && dispatch_lua_expression "hl.dsp.send_key_state({ mods = $(lua_string "$mods"), key = $(lua_string "$key"), state = \"down\", window = $(lua_string "$window") })"; then
|
|
sleep 0.05
|
|
dispatch_lua_expression "hl.dsp.send_key_state({ mods = $(lua_string "$mods"), key = $(lua_string "$key"), state = \"up\", window = $(lua_string "$window") })"
|
|
return
|
|
fi
|
|
|
|
hyprctl dispatch sendshortcut "$arg"
|
|
}
|
|
|
|
dispatch_binding() {
|
|
local dispatcher="$1"
|
|
local arg="$2"
|
|
|
|
case "$dispatcher" in
|
|
exec)
|
|
[[ -n $arg ]] && dispatch_exec_binding "$arg"
|
|
;;
|
|
sendshortcut)
|
|
[[ -n $arg ]] && dispatch_sendshortcut_binding "$arg"
|
|
;;
|
|
lua)
|
|
[[ -n $arg ]] && hyprctl dispatch "$arg"
|
|
;;
|
|
"") return 1 ;;
|
|
*)
|
|
if [[ -n $arg ]]; then
|
|
hyprctl dispatch "$dispatcher" "$arg"
|
|
else
|
|
hyprctl dispatch "$dispatcher"
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
if [[ $1 == "--print" || $1 == "-p" ]]; then
|
|
output_keybindings
|
|
else
|
|
records=$(output_binding_records)
|
|
monitor_height=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .height')
|
|
menu_height=$((monitor_height * 40 / 100))
|
|
selection=$(cut -f1 <<<"$records" |
|
|
omarchy-menu-select 'Keybindings' -- --width 800 --height "$menu_height")
|
|
|
|
if [[ -n $selection ]]; then
|
|
record=$(awk -F '\t' -v selection="$selection" '$1 == selection { print; exit }' <<<"$records")
|
|
dispatcher=$(cut -f2 <<<"$record")
|
|
arg=$(cut -f3- <<<"$record")
|
|
|
|
dispatch_binding "$dispatcher" "$arg"
|
|
fi
|
|
fi
|