Compare commits

...
18 changed files with 2526 additions and 857 deletions
+228
View File
@@ -0,0 +1,228 @@
#!/bin/bash
# omarchy:summary=Measure Quickshell Omarchy menu response times
# omarchy:args=[--repeat=<count>] [--no-ui]
# omarchy:examples=omarchy dev benchmark menu | omarchy dev benchmark menu --repeat=10
set -euo pipefail
OMARCHY_BIN_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
OMARCHY_PATH=${OMARCHY_PATH:-$(cd -- "$OMARCHY_BIN_DIR/.." && pwd)}
REPEAT=5
NO_UI=false
show_help() {
cat <<'EOF'
Usage:
omarchy dev benchmark menu [--repeat=<count>] [--no-ui]
Measure the Omarchy menu startup path:
- static JSONC menu parsing
- Quickshell socket startup
- cold open/close roundtrip (unless --no-ui)
- warm open/close roundtrip against the resident Quickshell process
Options:
--repeat=<count> Number of UI open/close runs to measure (default: 5)
--no-ui Skip cases that briefly open the menu
EOF
}
now_us() {
local now="${EPOCHREALTIME/./}"
printf '%s' "$now"
}
format_ms() {
local us="$1"
printf '%d.%03d' "$(( us / 1000 ))" "$(( us % 1000 ))"
}
measure_once() {
local start_us end_us
start_us=$(now_us)
"$@" >/dev/null
end_us=$(now_us)
printf '%s' "$(( end_us - start_us ))"
}
run_case() {
local label="$1"
shift
local total_us=0
local min_us=0
local max_us=0
local elapsed_us=0
for (( i = 1; i <= REPEAT; i++ )); do
elapsed_us=$(measure_once "$@")
total_us=$(( total_us + elapsed_us ))
if (( i == 1 || elapsed_us < min_us )); then
min_us=$elapsed_us
fi
if (( elapsed_us > max_us )); then
max_us=$elapsed_us
fi
done
printf '%-34s avg %8s ms min %8s ms max %8s ms\n' \
"$label" \
"$(format_ms "$(( total_us / REPEAT ))")" \
"$(format_ms "$min_us")" \
"$(format_ms "$max_us")"
}
socket_path() {
printf '%s/omarchy-menu.sock' "${XDG_RUNTIME_DIR:-/run/user/$UID}"
}
menu_qml() {
printf '%s/default/quickshell/menu.qml' "$OMARCHY_PATH"
}
kill_menu_shell() {
quickshell kill -p "$(menu_qml)" >/dev/null 2>&1 || true
for (( i = 0; i < 200; i++ )); do
if ! pgrep -f "[q]uickshell .*$(menu_qml)" >/dev/null 2>&1; then
break
fi
sleep 0.01
done
rm -f "$(socket_path)" "${XDG_RUNTIME_DIR:-/run/user/$UID}/omarchy-menu.state" "${XDG_RUNTIME_DIR:-/run/user/$UID}/omarchy-menu.lock"
}
build_menu_json() {
env OMARCHY_PATH="$OMARCHY_PATH" PATH="$OMARCHY_BIN_DIR:$PATH" \
"$OMARCHY_BIN_DIR/omarchy-menu" --json
}
start_quickshell_socket() {
local menu_file
local selection_file
local done_file
kill_menu_shell
menu_file=$(mktemp)
selection_file=$(mktemp)
done_file=$(mktemp)
printf '{"items":[]}' >"$menu_file"
rm -f "$done_file"
env \
OMARCHY_PATH="$OMARCHY_PATH" \
OMARCHY_MENU_JSON_FILE="$menu_file" \
OMARCHY_MENU_INITIAL_MENU="root" \
OMARCHY_MENU_SELECTION_FILE="$selection_file" \
OMARCHY_MENU_DONE_FILE="$done_file" \
quickshell -n -d -p "$(menu_qml)" >/dev/null
for (( i = 0; i < 200; i++ )); do
[[ -S $(socket_path) ]] && break
sleep 0.01
done
[[ -S $(socket_path) ]]
kill_menu_shell
rm -f "$menu_file" "$selection_file" "$done_file"
}
menu_layer_visible() {
hyprctl layers -j 2>/dev/null | jq -e '.. | objects | select(.namespace? == "omarchy-menu")' >/dev/null
}
open_close_menu() {
local pid
env OMARCHY_PATH="$OMARCHY_PATH" PATH="$OMARCHY_BIN_DIR:$PATH" \
"$OMARCHY_BIN_DIR/omarchy-menu" >/dev/null &
pid=$!
for (( i = 0; i < 300; i++ )); do
if menu_layer_visible && [[ -S $(socket_path) ]]; then
break
fi
sleep 0.01
done
if [[ ! -S $(socket_path) ]]; then
kill "$pid" 2>/dev/null || true
kill_menu_shell
return 1
fi
printf 'close\n' | socat -u - "UNIX-CONNECT:$(socket_path)" >/dev/null 2>&1 || true
for (( i = 0; i < 500; i++ )); do
if ! kill -0 "$pid" 2>/dev/null; then
break
fi
sleep 0.01
done
if kill -0 "$pid" 2>/dev/null; then
kill "$pid" 2>/dev/null || true
kill_menu_shell
return 1
fi
wait "$pid" || true
}
cold_open_close_menu() {
kill_menu_shell
open_close_menu
kill_menu_shell
}
warm_open_close_menu() {
open_close_menu
}
while (( $# > 0 )); do
case "$1" in
--repeat=*) REPEAT="${1#*=}" ;;
--no-ui) NO_UI=true ;;
--help | -h)
show_help
exit 0
;;
*)
echo "Unknown option: $1" >&2
show_help >&2
exit 2
;;
esac
shift
done
if [[ ! $REPEAT =~ ^[0-9]+$ ]] || (( REPEAT < 1 )); then
echo "--repeat must be a positive integer" >&2
exit 2
fi
cleanup() {
kill_menu_shell
}
trap cleanup EXIT
run_label="runs"
(( REPEAT == 1 )) && run_label="run"
printf 'Omarchy menu benchmark (%d %s each)\n\n' "$REPEAT" "$run_label"
run_case "menu JSON build" build_menu_json
if [[ $NO_UI != true ]]; then
if omarchy-cmd-present quickshell socat hyprctl jq && [[ -n ${WAYLAND_DISPLAY:-} ]]; then
printf '%-34s %s ms\n' "quickshell socket startup" "$(format_ms "$(measure_once start_quickshell_socket)")"
run_case "cold open/close" cold_open_close_menu
kill_menu_shell
open_close_menu >/dev/null
run_case "warm open/close" warm_open_close_menu
else
printf 'Skipping UI cases: quickshell/socat/hyprctl/jq/Wayland unavailable\n'
fi
fi
+933 -828
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -1,6 +1,6 @@
#!/bin/bash
# omarchy:summary=Set Hyprland, Hyprlock, Mako, and Walker corners to sharp or round
# omarchy:summary=Set Hyprland, Hyprlock, Mako, Walker, and Quickshell corners to sharp or round
# omarchy:args=<sharp|round>
# omarchy:examples=omarchy style corners round | omarchy style corners sharp
@@ -13,6 +13,7 @@ omarchy-style-corners-hyprland "$1"
omarchy-style-corners-hyprlock "$1"
omarchy-style-corners-mako "$1"
omarchy-style-corners-walker "$1"
omarchy-style-corners-quickshell "$1"
case $1 in
sharp) omarchy-notification-send "Sharp corners enabled" -g 󰝣 ;;
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# omarchy:summary=Set Quickshell Omarchy menu corners
# omarchy:args=<sharp|round>
# omarchy:examples=omarchy style corners quickshell round | omarchy style corners quickshell sharp
set_radius() {
local radius="$1"
local toggles_dir="$HOME/.local/state/omarchy/toggles"
mkdir -p "$toggles_dir"
printf '{ "radius": %s }\n' "$radius" >"$toggles_dir/quickshell-menu.json"
}
case "${1:-}" in
sharp) set_radius 0 ;;
round) set_radius 6 ;;
*)
echo "Usage: omarchy-style-corners-quickshell <sharp|round>"
exit 1
;;
esac
-20
View File
@@ -1,20 +0,0 @@
# Overwrite parts of the omarchy-menu with user-specific submenus.
# See $OMARCHY_PATH/bin/omarchy-menu for functions that can be overwritten.
#
# WARNING: Overwritten functions will obviously not be updated when Omarchy changes.
#
# Example of minimal system menu:
#
# show_system_menu() {
# case $(menu "System" " Lock\n󰐥 Shutdown") in
# *Lock*) omarchy-system-lock ;;
# *Shutdown*) omarchy-system-shutdown ;;
# *) back_to show_main_menu ;;
# esac
# }
#
# Example of overriding just the about menu action: (Using zsh instead of bash (default))
#
# show_about() {
# exec omarchy-launch-or-focus-tui "zsh -c 'fastfetch; read -k 1'"
# }
@@ -0,0 +1,31 @@
{
// Extend the Quickshell Omarchy menu with JSONC.
//
// IDs are object keys. The parent is inferred from the dotted id, so
// "personal.notes" appears under "personal", and "personal" appears on the
// root menu. Reuse an existing id to override/extend it.
//
// Fields:
// icon Nerd Font glyph shown in the icon column.
// label Visible row title.
// action Shell command to run. If omitted, the row is a submenu.
// target Existing submenu id to open. Use for links/aliases.
// provider Runtime provider function/command returning JSON rows.
// aliases Alternate `omarchy-menu <name>` routes; also searchable.
// keywords Extra search terms beyond id/label/aliases.
// description Optional subtitle and extra search text.
// when Shell condition; hide row when it fails.
// checked Shell condition; append ✓ when it succeeds.
//
// Examples:
// "personal": {"icon":"","label":"Personal","keywords":"notes projects"},
// "personal.notes": {"icon":"󰎞","label":"Notes","action":"omarchy-launch-editor ~/notes","keywords":"notes"},
// "personal.files": {"icon":"","label":"Files","action":"uwsm-app -- nautilus ~/Documents","keywords":"files documents"},
//
// Only use provider when a provider_name function or command named "name"
// returns JSON rows. Static submenus only need dotted ids.
//
// Example: replace the default About action by reusing the same id. Existing
// fields are kept unless overridden.
// "about": {"icon":"","label":"About","action":"omarchy-launch-or-focus-tui \"zsh -c 'fastfetch; read -k 1'\""},
}
+1 -1
View File
@@ -1,2 +1,2 @@
-- Remove 1px border around hyprshot screenshots.
hl.layer_rule({ match = { namespace = "selection" }, no_anim = true })
hl.layer_rule({ match = { namespace = "selection" }, no_anim = true, animation = "none" })
+2
View File
@@ -0,0 +1,2 @@
-- Keep the menu instant: no layer-shell fade/slide animation.
hl.layer_rule({ match = { namespace = "omarchy-menu" }, no_anim = true, animation = "none" })
+1 -1
View File
@@ -15,4 +15,4 @@ o.window({ tag = "pop" }, { rounding = 8 })
o.window({ tag = "noidle" }, { idle_inhibit = "always" })
-- Disable animations for image selector overlay.
hl.layer_rule({ match = { namespace = "omarchy-image-selector" }, no_anim = true })
hl.layer_rule({ match = { namespace = "omarchy-image-selector" }, no_anim = true, animation = "none" })
+1 -1
View File
@@ -1,2 +1,2 @@
-- Application-specific animation.
hl.layer_rule({ match = { namespace = "walker" }, no_anim = true })
hl.layer_rule({ match = { namespace = "walker" }, no_anim = true, animation = "none" })
@@ -1,4 +0,0 @@
decoration {
rounding = 6
rounding_power = 3
}
+7
View File
@@ -0,0 +1,7 @@
-- Use round window corners.
hl.config({
decoration = {
rounding = 6,
rounding_power = 3,
},
})
+333
View File
@@ -0,0 +1,333 @@
{
// Omarchy menu definition.
// JSONC is used for Neovim-friendly highlighting, comments, and trailing commas.
// IDs are object keys. Dotted IDs imply hierarchy: trigger.share.file belongs
// under trigger.share.
// Kind is inferred: action -> action, target -> link, otherwise submenu.
// Dotted IDs define the tree. Use provider:"name" only when the submenu
// calls provider_name() or a command named "name" to return JSON rows.
// Optional fields:
// aliases alternate `omarchy-menu <name>` routes; also searchable
// keywords extra search terms beyond id/label/aliases
// when shell condition; hide row when it fails
// checked shell condition; append ✓ when it succeeds
// Root Menu
"apps": {"icon":"󰀻","label":"Apps","aliases":["app","applications"],"keywords":"launch launcher","action":"omarchy-launch-walker -p 'Launch…'"},
"learn": {"icon":"󰧑","label":"Learn","keywords":"manual docs help reference"},
"trigger": {"icon":"󱓞","label":"Trigger","keywords":"actions capture share toggle hardware reminder"},
"style": {"icon":"","label":"Style","keywords":"theme background font waybar hyprland appearance"},
"setup": {"icon":"","label":"Setup","aliases":["settings"],"keywords":"configure defaults wifi bluetooth audio"},
"install": {"icon":"󰉉","label":"Install","keywords":"package app service browser editor terminal development gaming"},
"remove": {"icon":"󰭌","label":"Remove","aliases":["uninstall"],"keywords":"package app browser development gaming"},
"update": {"icon":"","label":"Update","aliases":["restart","refresh"],"keywords":"upgrade channel firmware timezone"},
"about": {"icon":"","label":"About","keywords":"omarchy system information","action":"omarchy-launch-about"},
"system": {"icon":"","label":"System","aliases":["power-menu"],"keywords":"lock logout restart shutdown suspend hibernate"},
// System
"system.screensaver": {"icon":"󱄄","label":"Screensaver","action":"omarchy-launch-screensaver force"},
"system.lock": {"icon":"","label":"Lock","keywords":"screen","action":"omarchy-system-lock"},
"system.suspend": {"icon":"󰒲","label":"Suspend","keywords":"sleep","when":"! omarchy-toggle-enabled suspend-off","action":"systemctl suspend"},
"system.hibernate": {"icon":"󰤁","label":"Hibernate","keywords":"sleep","when":"omarchy-hibernation-available","action":"systemctl hibernate"},
"system.logout": {"icon":"󰍃","label":"Logout","keywords":"sign out","action":"omarchy-system-logout"},
"system.restart": {"icon":"󰜉","label":"Restart","keywords":"reboot","action":"omarchy-system-reboot"},
"system.shutdown": {"icon":"󰐥","label":"Shutdown","keywords":"power off","action":"omarchy-system-shutdown"},
// Learn
"learn.keybindings": {"icon":"","label":"Keybindings","keywords":"keyboard shortcuts bindings","action":"omarchy-menu-keybindings"},
"learn.tmux-keybindings": {"icon":"","label":"Tmux keybindings","keywords":"keyboard shortcuts bindings terminal","action":"omarchy-menu-tmux-keybindings"},
"learn.omarchy": {"icon":"","label":"Omarchy","keywords":"manual documentation","action":"omarchy-launch-webapp 'https://learn.omacom.io/2/the-omarchy-manual'"},
"learn.hyprland": {"icon":"","label":"Hyprland","keywords":"wiki docs","action":"omarchy-launch-webapp 'https://wiki.hypr.land/'"},
"learn.arch": {"icon":"󰣇","label":"Arch","keywords":"linux wiki docs","action":"omarchy-launch-webapp 'https://wiki.archlinux.org/title/Main_page'"},
"learn.neovim": {"icon":"","label":"Neovim","keywords":"lazyvim keymaps docs","action":"omarchy-launch-webapp 'https://www.lazyvim.org/keymaps'"},
"learn.bash": {"icon":"󱆃","label":"Bash","keywords":"shell cheatsheet","action":"omarchy-launch-webapp 'https://devhints.io/bash'"},
// Trigger
"trigger.reminder": {"icon":"󰔛","label":"Reminder","aliases":["reminder"],"keywords":"timer notification remind"},
"trigger.capture": {"icon":"","label":"Capture","aliases":["capture","screenshot","screenrecord","screen-record","screenrecording"],"keywords":"color text extraction"},
"trigger.capture.screenshot": {"icon":"","label":"Screenshot","keywords":"picture","action":"omarchy-capture-screenshot"},
"trigger.capture.screenrecord.stop": {"icon":"","label":"Stop Screenrecording","keywords":"recording video","when":"pgrep -f '^gpu-screen-recorder' >/dev/null","action":"stop_active_screenrecording"},
"trigger.capture.screenrecord": {"icon":"","label":"Screenrecord","keywords":"record screen video"},
"trigger.capture.text": {"icon":"󰴑","label":"Text Extraction","keywords":"ocr","action":"omarchy-capture-text-extraction"},
"trigger.capture.color": {"icon":"󰃉","label":"Color","keywords":"picker hyprpicker","action":"pkill hyprpicker || hyprpicker -a"},
"trigger.capture.screenrecord.no-audio": {"icon":"","label":"With no audio","action":"omarchy-capture-screenrecording"},
"trigger.capture.screenrecord.desktop-audio": {"icon":"","label":"With desktop audio","action":"omarchy-capture-screenrecording --with-desktop-audio"},
"trigger.capture.screenrecord.microphone": {"icon":"","label":"With desktop + microphone audio","keywords":"mic","action":"omarchy-capture-screenrecording --with-desktop-audio --with-microphone-audio"},
"trigger.capture.screenrecord.webcam": {"icon":"","label":"With desktop + microphone audio + webcam","keywords":"camera","action":"screenrecord_with_webcam"},
"trigger.transcode": {"icon":"󰧸","label":"Transcode","keywords":"convert image video","action":"omarchy-transcode"},
"trigger.share": {"icon":"","label":"Share","aliases":["share"],"keywords":"clipboard file folder localsend"},
"trigger.toggle": {"icon":"󰔎","label":"Toggle","aliases":["toggle","toggles"],"keywords":"screensaver nightlight idle notifications waybar"},
"trigger.hardware": {"icon":"","label":"Hardware","aliases":["hardware","hw"],"keywords":"monitor touchpad touchscreen gpu"},
"trigger.hardware.laptop-display": {"icon":"󰛧","label":"Laptop Display","keywords":"monitor","action":"omarchy-hyprland-monitor-internal toggle"},
"trigger.hardware.mirror-display": {"icon":"󰍹","label":"Mirror Display","keywords":"monitor","action":"omarchy-hyprland-monitor-internal-mirror toggle"},
"trigger.hardware.hybrid-gpu": {"icon":"","label":"Hybrid GPU","keywords":"graphics","when":"omarchy-hw-hybrid-gpu >/dev/null","action":"present_terminal omarchy-toggle-hybrid-gpu"},
"trigger.hardware.touchpad": {"icon":"󰟸","label":"Touchpad","keywords":"trackpad","when":"omarchy-hw-touchpad >/dev/null","action":"omarchy-toggle-touchpad"},
"trigger.hardware.touchpad-haptics": {"icon":"󰌌","label":"Touchpad Haptics","when":"omarchy-hw-dell-xps-haptic-touchpad >/dev/null && omarchy-cmd-present dell-xps-touchpad-haptics"},
"trigger.hardware.touchpad-haptics.low": {"icon":"󰌌","label":"low","when":"omarchy-hw-dell-xps-haptic-touchpad >/dev/null && omarchy-cmd-present dell-xps-touchpad-haptics","checked":"haptic_touchpad_is low","action":"dell-xps-touchpad-haptics set low"},
"trigger.hardware.touchpad-haptics.mid": {"icon":"󰌌","label":"mid","keywords":"medium","when":"omarchy-hw-dell-xps-haptic-touchpad >/dev/null && omarchy-cmd-present dell-xps-touchpad-haptics","checked":"haptic_touchpad_is mid","action":"dell-xps-touchpad-haptics set mid"},
"trigger.hardware.touchpad-haptics.high": {"icon":"󰌌","label":"high","when":"omarchy-hw-dell-xps-haptic-touchpad >/dev/null && omarchy-cmd-present dell-xps-touchpad-haptics","checked":"haptic_touchpad_is high","action":"dell-xps-touchpad-haptics set high"},
"trigger.hardware.touchscreen": {"icon":"󰆽","label":"Touchscreen","keywords":"tablet","when":"omarchy-hw-touchscreen >/dev/null","action":"omarchy-toggle-touchscreen"},
"trigger.reminder.set": {"icon":"󰔛","label":"Set one","aliases":["reminder-set","remind"],"keywords":"timer","action":"show_custom_reminder_input"},
"trigger.reminder.show": {"icon":"󰔛","label":"Show all","keywords":"list","action":"omarchy-reminder show"},
"trigger.reminder.clear": {"icon":"󰔛","label":"Clear all","keywords":"delete","action":"omarchy-reminder clear"},
"trigger.share.clipboard": {"icon":"","label":"Clipboard","action":"omarchy-menu-share clipboard"},
"trigger.share.file": {"icon":"","label":"File","action":"terminal bash -c 'omarchy-menu-share file'"},
"trigger.share.folder": {"icon":"","label":"Folder","keywords":"directory","action":"terminal bash -c 'omarchy-menu-share folder'"},
"trigger.share.receive": {"icon":"󰥦","label":"Receive","keywords":"localsend","action":"uwsm-app -- localsend"},
"trigger.toggle.screensaver": {"icon":"󱄄","label":"Screensaver","action":"omarchy-toggle-screensaver"},
"trigger.toggle.nightlight": {"icon":"󰔎","label":"Nightlight","keywords":"night light hyprsunset","action":"omarchy-toggle-nightlight"},
"trigger.toggle.idle-lock": {"icon":"󱫖","label":"Idle Lock","keywords":"hypridle","action":"omarchy-toggle-idle"},
"trigger.toggle.notifications": {"icon":"󰂛","label":"Notifications","keywords":"mako silence","action":"omarchy-toggle-notification-silencing"},
"trigger.toggle.top-bar": {"icon":"󰍜","label":"Top Bar","keywords":"waybar","action":"omarchy-toggle-waybar"},
"trigger.toggle.workspace-layout": {"icon":"󱂬","label":"Workspace Layout","action":"omarchy-hyprland-workspace-layout-toggle"},
"trigger.toggle.window-gaps": {"icon":"","label":"Window Gaps","action":"omarchy-hyprland-window-gaps-toggle"},
"trigger.toggle.one-window-ratio": {"icon":"","label":"1-Window Ratio","keywords":"square","action":"omarchy-hyprland-window-single-square-aspect-toggle"},
"trigger.toggle.monitor-scaling": {"icon":"󰍹","label":"Monitor Scaling","keywords":"display","action":"omarchy-hyprland-monitor-scaling-cycle"},
"trigger.toggle.direct-boot": {"icon":"","label":"Direct Boot","action":"present_terminal omarchy-config-direct-boot"},
"trigger.toggle.passwordless-sudo": {"icon":"󰟵","label":"Passwordless Sudo","action":"present_terminal omarchy-sudo-passwordless"},
// Style
"style.theme": {"icon":"󰸌","label":"Theme","aliases":["theme","themes"],"keywords":"colors","action":"theme=$(omarchy-theme-switcher); [[ -n $theme ]] && omarchy-theme-set \"$theme\""},
"style.unlock": {"icon":"󰟵","label":"Unlock","keywords":"themes","action":"omarchy-launch-walker -m menus:omarchyunlocks --width 800 --minheight 400"},
"style.font": {"icon":"","label":"Font","keywords":"typeface","provider":"fonts"},
"style.background": {"icon":"","label":"Background","aliases":["background","wallpaper"],"action":"background=$(omarchy-theme-bg-switcher); [[ -n $background ]] && omarchy-theme-bg-set \"$background\""},
"style.waybar": {"icon":"󰍜","label":"Waybar","keywords":"bar top bottom left right"},
"style.corners": {"icon":"󰘇","label":"Corners","keywords":"sharp round rounded"},
"style.hyprland": {"icon":"","label":"Hyprland","keywords":"look feel","action":"open_in_editor \"$(hypr_config_file looknfeel)\""},
"style.screensaver": {"icon":"󱄄","label":"Screensaver","keywords":"branding"},
"style.about": {"icon":"","label":"About","keywords":"branding"},
"style.install": {"icon":"󰉉","label":"Install","keywords":"theme background font"},
"style.waybar.top": {"icon":"󰁝","label":"Top","keywords":"position","action":"omarchy-style-waybar-position top"},
"style.waybar.bottom": {"icon":"󰁅","label":"Bottom","keywords":"position","action":"omarchy-style-waybar-position bottom"},
"style.waybar.left": {"icon":"󰁍","label":"Left","keywords":"position","action":"omarchy-style-waybar-position left"},
"style.waybar.right": {"icon":"󰁔","label":"Right","keywords":"position","action":"omarchy-style-waybar-position right"},
"style.corners.sharp": {"icon":"󰝣","label":"Sharp","keywords":"square","action":"omarchy-style-corners sharp"},
"style.corners.round": {"icon":"󰘇","label":"Round","keywords":"rounded","action":"omarchy-style-corners round"},
"style.about.text": {"icon":"","label":"Edit Text","keywords":"branding","action":"omarchy-branding-about text"},
"style.about.image": {"icon":"","label":"Set From Image","keywords":"branding","action":"omarchy-branding-about image"},
"style.about.default": {"icon":"","label":"Restore Default","keywords":"branding","action":"omarchy-branding-about reset"},
"style.screensaver.text": {"icon":"","label":"Edit Text","keywords":"branding","action":"omarchy-branding-screensaver text"},
"style.screensaver.image": {"icon":"","label":"Set From Image","keywords":"branding","action":"omarchy-branding-screensaver image"},
"style.screensaver.default": {"icon":"","label":"Restore Default","keywords":"branding","action":"omarchy-branding-screensaver reset"},
"style.install.theme": {"icon":"󰸌","label":"Theme","action":"present_terminal omarchy-theme-install"},
"style.install.background": {"icon":"","label":"Background","keywords":"wallpaper","action":"omarchy-theme-bg-install"},
"style.install.font": {"icon":"","label":"Font"},
"style.install.font.cascadia": {"icon":"","label":"Cascadia Mono","action":"install_font 'Cascadia Mono' ttf-cascadia-mono-nerd 'CaskaydiaMono Nerd Font'"},
"style.install.font.meslo": {"icon":"","label":"Meslo LG Mono","action":"install_font 'Meslo LG Mono' ttf-meslo-nerd 'MesloLGL Nerd Font'"},
"style.install.font.fira": {"icon":"","label":"Fira Code","action":"install_font 'Fira Code' ttf-firacode-nerd 'FiraCode Nerd Font'"},
"style.install.font.victor": {"icon":"","label":"Victor Code","action":"install_font 'Victor Code' ttf-victor-mono-nerd 'VictorMono Nerd Font'"},
"style.install.font.bitstream": {"icon":"","label":"Bitstream Vera Mono","action":"install_font 'Bitstream Vera Code' ttf-bitstream-vera-mono-nerd 'BitstromWera Nerd Font'"},
"style.install.font.iosevka": {"icon":"","label":"Iosevka","action":"install_font Iosevka ttf-iosevka-nerd 'Iosevka Nerd Font Mono'"},
// Setup
"setup.audio": {"icon":"","label":"Audio","keywords":"sound","action":"omarchy-launch-audio"},
"setup.wifi": {"icon":"","label":"Wifi","keywords":"wireless network","action":"omarchy-launch-wifi"},
"setup.bluetooth": {"icon":"󰂯","label":"Bluetooth","action":"omarchy-launch-bluetooth"},
"setup.power": {"icon":"󱐋","label":"Power Profile","aliases":["power","power-profile","power-profiles"],"keywords":"performance battery","provider":"power-profiles"},
"setup.sleep": {"icon":"","label":"System Sleep","keywords":"suspend hibernate"},
"setup.sleep.suspend-enable": {"icon":"󰒲","label":"Enable Suspend","when":"omarchy-toggle-enabled suspend-off","action":"omarchy-toggle-suspend"},
"setup.sleep.suspend-disable": {"icon":"󰒲","label":"Disable Suspend","when":"! omarchy-toggle-enabled suspend-off","action":"omarchy-toggle-suspend"},
"setup.sleep.hibernate-enable": {"icon":"󰤁","label":"Enable Hibernate","when":"! omarchy-hibernation-available","action":"present_terminal omarchy-hibernation-setup"},
"setup.sleep.hibernate-disable": {"icon":"󰤁","label":"Disable Hibernate","when":"omarchy-hibernation-available","action":"present_terminal omarchy-hibernation-remove"},
"setup.monitors": {"icon":"󰍹","label":"Monitors","keywords":"monitor display hyprland","action":"open_in_editor \"$(hypr_config_file monitors)\""},
"setup.keybindings": {"icon":"","label":"Keybindings","keywords":"keyboard shortcuts","when":"[[ -f $(hypr_config_file bindings) ]]","action":"open_in_editor \"$(hypr_config_file bindings)\""},
"setup.input": {"icon":"","label":"Input","keywords":"keyboard touchpad mouse","when":"[[ -f $(hypr_config_file input) ]]","action":"open_in_editor \"$(hypr_config_file input)\""},
"setup.default": {"icon":"","label":"Defaults","aliases":["default","defaults"],"keywords":"browser terminal editor"},
"setup.default.browser": {"icon":"","label":"Browser"},
"setup.default.browser.chromium": {"icon":"","label":"Chromium","when":"omarchy-cmd-present chromium","checked":"default_browser_is chromium","action":"omarchy-default-browser chromium"},
"setup.default.browser.chrome": {"icon":"󰊯","label":"Chrome","keywords":"google","when":"omarchy-cmd-present google-chrome-stable","checked":"default_browser_is chrome","action":"omarchy-default-browser chrome"},
"setup.default.browser.brave": {"icon":"󰖟","label":"Brave","when":"omarchy-cmd-present brave","checked":"default_browser_is brave","action":"omarchy-default-browser brave"},
"setup.default.browser.brave-origin": {"icon":"󰖟","label":"Brave Origin","when":"omarchy-cmd-present brave-origin-beta","checked":"default_browser_is brave-origin","action":"omarchy-default-browser brave-origin"},
"setup.default.browser.edge": {"icon":"󰇩","label":"Edge","when":"omarchy-cmd-present microsoft-edge-stable","checked":"default_browser_is edge","action":"omarchy-default-browser edge"},
"setup.default.browser.firefox": {"icon":"󰈹","label":"Firefox","when":"omarchy-cmd-present firefox","checked":"default_browser_is firefox","action":"omarchy-default-browser firefox"},
"setup.default.browser.zen": {"icon":"󰖟","label":"Zen","when":"omarchy-cmd-present zen-browser","checked":"default_browser_is zen","action":"omarchy-default-browser zen"},
"setup.default.terminal": {"icon":"","label":"Terminal"},
"setup.default.terminal.alacritty": {"icon":"","label":"Alacritty","when":"omarchy-cmd-present alacritty","checked":"default_terminal_is alacritty","action":"omarchy-default-terminal alacritty"},
"setup.default.terminal.foot": {"icon":"","label":"Foot","when":"omarchy-cmd-present foot","checked":"default_terminal_is foot","action":"omarchy-default-terminal foot"},
"setup.default.terminal.ghostty": {"icon":"","label":"Ghostty","when":"omarchy-cmd-present ghostty","checked":"default_terminal_is ghostty","action":"omarchy-default-terminal ghostty"},
"setup.default.terminal.kitty": {"icon":"","label":"Kitty","when":"omarchy-cmd-present kitty","checked":"default_terminal_is kitty","action":"omarchy-default-terminal kitty"},
"setup.default.editor": {"icon":"","label":"Editor"},
"setup.default.editor.neovim": {"icon":"","label":"Neovim","keywords":"nvim","when":"omarchy-cmd-present nvim","checked":"default_editor_is nvim","action":"omarchy-default-editor nvim"},
"setup.default.editor.vscode": {"icon":"","label":"VSCode","keywords":"code","when":"omarchy-cmd-present code","checked":"default_editor_is code","action":"omarchy-default-editor code"},
"setup.default.editor.cursor": {"icon":"","label":"Cursor","when":"omarchy-cmd-present cursor","checked":"default_editor_is cursor","action":"omarchy-default-editor cursor"},
"setup.default.editor.zed": {"icon":"","label":"Zed","when":"omarchy-cmd-present zeditor","checked":"default_editor_is zeditor","action":"omarchy-default-editor zed"},
"setup.default.editor.sublime": {"icon":"","label":"Sublime Text","when":"omarchy-cmd-present sublime_text","checked":"default_editor_is sublime_text","action":"omarchy-default-editor sublime_text"},
"setup.default.editor.helix": {"icon":"","label":"Helix","when":"omarchy-cmd-present helix","checked":"default_editor_is helix","action":"omarchy-default-editor helix"},
"setup.default.editor.vim": {"icon":"","label":"Vim","when":"omarchy-cmd-present vim","checked":"default_editor_is vim","action":"omarchy-default-editor vim"},
"setup.default.editor.emacs": {"icon":"","label":"Emacs","when":"omarchy-cmd-present emacs","checked":"default_editor_is emacs","action":"omarchy-default-editor emacs"},
"setup.dns": {"icon":"󰱔","label":"DNS","keywords":"network","action":"present_terminal omarchy-setup-dns"},
"setup.security": {"icon":"","label":"Security","keywords":"fingerprint fido2"},
"setup.config": {"icon":"","label":"Config","keywords":"files hyprland waybar walker"},
"setup.security.fingerprint": {"icon":"󰈷","label":"Fingerprint","action":"present_terminal omarchy-setup-security-fingerprint"},
"setup.security.fido2": {"icon":"","label":"Fido2","keywords":"key","action":"present_terminal omarchy-setup-security-fido2"},
"setup.config.hyprland": {"icon":"","label":"Hyprland","action":"open_in_editor \"$(hypr_config_file hyprland)\""},
"setup.config.hypridle": {"icon":"","label":"Hypridle","keywords":"idle","action":"open_in_editor ~/.config/hypr/hypridle.conf && omarchy-restart-hypridle"},
"setup.config.hyprlock": {"icon":"","label":"Hyprlock","keywords":"lock","action":"open_in_editor ~/.config/hypr/hyprlock.conf"},
"setup.config.hyprsunset": {"icon":"","label":"Hyprsunset","keywords":"night light","action":"open_in_editor ~/.config/hypr/hyprsunset.conf && omarchy-restart-hyprsunset"},
"setup.config.swayosd": {"icon":"","label":"Swayosd","action":"open_in_editor ~/.config/swayosd/config.toml && omarchy-restart-swayosd"},
"setup.config.walker": {"icon":"󰌧","label":"Walker","keywords":"launcher","action":"open_in_editor ~/.config/walker/config.toml && omarchy-restart-walker"},
"setup.config.waybar": {"icon":"󰍜","label":"Waybar","keywords":"bar","action":"open_in_editor ~/.config/waybar/config.jsonc && omarchy-restart-waybar"},
"setup.config.xcompose": {"icon":"󰞅","label":"XCompose","keywords":"compose key","action":"open_in_editor ~/.XCompose && omarchy-restart-xcompose"},
// Install
"install.package": {"icon":"󰣇","label":"Package","keywords":"pacman aur","action":"terminal omarchy-pkg-install"},
"install.aur": {"icon":"󰣇","label":"AUR","keywords":"package","action":"terminal omarchy-pkg-aur-install"},
"install.webapp": {"icon":"","label":"Web App","keywords":"pwa","action":"present_terminal omarchy-webapp-install"},
"install.tui": {"icon":"","label":"TUI","keywords":"terminal app","action":"present_terminal omarchy-tui-install"},
"install.service": {"icon":"","label":"Service","keywords":"dropbox tailscale vpn"},
"install.style": {"icon":"","label":"Style","keywords":"theme background font","target":"style.install"},
"install.development": {"icon":"󰵮","label":"Development","keywords":"languages programming"},
"install.editor": {"icon":"","label":"Editor","keywords":"ide"},
"install.terminal": {"icon":"","label":"Terminal","keywords":"emulator"},
"install.browser": {"icon":"","label":"Browser","keywords":"web"},
"install.ai": {"icon":"󱚤","label":"AI","keywords":"dictation ollama lm studio crush"},
"install.gaming": {"icon":"","label":"Gaming","keywords":"steam retroarch minecraft lutris heroic"},
"install.windows": {"icon":"󰍲","label":"Windows","keywords":"vm","action":"present_terminal 'omarchy-windows-vm install'"},
"install.browser.chrome": {"icon":"","label":"Chrome","action":"present_terminal 'omarchy-install-browser chrome'"},
"install.browser.edge": {"icon":"","label":"Edge","action":"present_terminal 'omarchy-install-browser edge'"},
"install.browser.brave": {"icon":"","label":"Brave","action":"present_terminal 'omarchy-install-browser brave'"},
"install.browser.brave-origin": {"icon":"","label":"Brave Origin","action":"present_terminal 'omarchy-install-browser brave-origin'"},
"install.browser.firefox": {"icon":"","label":"Firefox","action":"present_terminal 'omarchy-install-browser firefox'"},
"install.browser.zen": {"icon":"󰖟","label":"Zen","action":"present_terminal 'omarchy-install-browser zen'"},
"install.service.dropbox": {"icon":"","label":"Dropbox","action":"present_terminal omarchy-install-dropbox"},
"install.service.tailscale": {"icon":"","label":"Tailscale","keywords":"vpn","action":"present_terminal omarchy-install-tailscale"},
"install.service.nordvpn": {"icon":"󱇱","label":"NordVPN [AUR]","keywords":"vpn","action":"present_terminal omarchy-install-nordvpn"},
"install.service.once": {"icon":"󰏖","label":"ONCE","action":"present_terminal omarchy-install-once"},
"install.service.bitwarden": {"icon":"󰟵","label":"Bitwarden","keywords":"password","action":"install_and_launch Bitwarden 'bitwarden bitwarden-cli' bitwarden"},
"install.service.chromium-account": {"icon":"","label":"Chromium Account","keywords":"google","action":"present_terminal omarchy-install-chromium-google-account"},
"install.editor.vscode": {"icon":"","label":"VSCode","keywords":"code","action":"present_terminal omarchy-install-vscode"},
"install.editor.cursor": {"icon":"","label":"Cursor","action":"install_and_launch Cursor cursor-bin cursor"},
"install.editor.zed": {"icon":"","label":"Zed","action":"present_terminal omarchy-install-zed"},
"install.editor.sublime": {"icon":"","label":"Sublime Text","action":"install_and_launch 'Sublime Text' sublime-text-4 sublime_text"},
"install.editor.helix": {"icon":"","label":"Helix","action":"present_terminal omarchy-install-helix"},
"install.editor.vim": {"icon":"","label":"Vim","action":"install Vim vim"},
"install.editor.emacs": {"icon":"","label":"Emacs","action":"install Emacs emacs-wayland && systemctl --user enable --now emacs.service"},
"install.terminal.alacritty": {"icon":"","label":"Alacritty","action":"install_terminal alacritty"},
"install.terminal.foot": {"icon":"","label":"Foot","action":"install_terminal foot"},
"install.terminal.ghostty": {"icon":"","label":"Ghostty","action":"install_terminal ghostty"},
"install.terminal.kitty": {"icon":"","label":"Kitty","action":"install_terminal kitty"},
"install.ai.dictation": {"icon":"","label":"Dictation","keywords":"voice","action":"present_terminal omarchy-voxtype-install"},
"install.ai.lm-studio": {"icon":"󱚤","label":"LM Studio","action":"install 'LM Studio' lmstudio-bin"},
"install.ai.ollama": {"icon":"󱚤","label":"Ollama","action":"if omarchy-cmd-present nvidia-smi; then ollama_pkg=ollama-cuda; elif omarchy-cmd-present rocminfo; then ollama_pkg=ollama-rocm; else ollama_pkg=ollama; fi; install Ollama \"$ollama_pkg\""},
"install.ai.crush": {"icon":"󱚤","label":"Crush","action":"install Crush crush-bin"},
"install.gaming.steam": {"icon":"","label":"Steam","action":"present_terminal omarchy-install-gaming-steam"},
"install.gaming.retroarch": {"icon":"󰯉","label":"RetroArch","action":"present_terminal omarchy-install-gaming-retroarch"},
"install.gaming.minecraft": {"icon":"󰍳","label":"Minecraft","action":"install_and_launch Minecraft minecraft-launcher minecraft-launcher"},
"install.gaming.geforce-now": {"icon":"󰢹","label":"NVIDIA GeForce NOW","action":"present_terminal omarchy-install-gaming-geforce-now"},
"install.gaming.xbox-cloud": {"icon":"","label":"Xbox Cloud Gaming","action":"present_terminal omarchy-install-gaming-xbox-cloud"},
"install.gaming.xbox-controller": {"icon":"󰂯","label":"Xbox Controller","action":"present_terminal omarchy-install-gaming-xbox-controllers"},
"install.gaming.moonlight": {"icon":"󰍹","label":"Moonlight (GameStream)","action":"present_terminal omarchy-install-gaming-moonlight"},
"install.gaming.lutris": {"icon":"","label":"Lutris (Battle.net)","action":"present_terminal omarchy-install-gaming-lutris"},
"install.gaming.heroic": {"icon":"󱓟","label":"Heroic (Epic Games)","action":"present_terminal omarchy-install-gaming-heroic"},
"install.gaming.retro-launcher": {"icon":"󰯉","label":"RetroArch Game Launcher","action":"omarchy-games-retro-install"},
"install.development.rails": {"icon":"󰫏","label":"Ruby on Rails","action":"present_terminal 'omarchy-install-dev-env ruby'"},
"install.development.docker-dbs": {"icon":"","label":"Docker DB","keywords":"databases","action":"present_terminal omarchy-install-docker-dbs"},
"install.development.javascript": {"icon":"","label":"JavaScript","keywords":"node bun deno"},
"install.development.go": {"icon":"","label":"Go","keywords":"golang","action":"present_terminal 'omarchy-install-dev-env go'"},
"install.development.php": {"icon":"","label":"PHP","keywords":"laravel symfony"},
"install.development.python": {"icon":"","label":"Python","action":"present_terminal 'omarchy-install-dev-env python'"},
"install.development.elixir": {"icon":"","label":"Elixir","keywords":"phoenix"},
"install.development.zig": {"icon":"","label":"Zig","action":"present_terminal 'omarchy-install-dev-env zig'"},
"install.development.rust": {"icon":"","label":"Rust","action":"present_terminal 'omarchy-install-dev-env rust'"},
"install.development.java": {"icon":"","label":"Java","action":"present_terminal 'omarchy-install-dev-env java'"},
"install.development.dotnet": {"icon":"","label":".NET","action":"present_terminal 'omarchy-install-dev-env dotnet'"},
"install.development.ocaml": {"icon":"","label":"OCaml","action":"present_terminal 'omarchy-install-dev-env ocaml'"},
"install.development.clojure": {"icon":"","label":"Clojure","action":"present_terminal 'omarchy-install-dev-env clojure'"},
"install.development.scala": {"icon":"","label":"Scala","action":"present_terminal 'omarchy-install-dev-env scala'"},
"install.development.javascript.node": {"icon":"","label":"Node.js","action":"present_terminal 'omarchy-install-dev-env node'"},
"install.development.javascript.bun": {"icon":"","label":"Bun","action":"present_terminal 'omarchy-install-dev-env bun'"},
"install.development.javascript.deno": {"icon":"","label":"Deno","action":"present_terminal 'omarchy-install-dev-env deno'"},
"install.development.php.php": {"icon":"","label":"PHP","action":"present_terminal 'omarchy-install-dev-env php'"},
"install.development.php.laravel": {"icon":"","label":"Laravel","action":"present_terminal 'omarchy-install-dev-env laravel'"},
"install.development.php.symfony": {"icon":"","label":"Symfony","action":"present_terminal 'omarchy-install-dev-env symfony'"},
"install.development.elixir.elixir": {"icon":"","label":"Elixir","action":"present_terminal 'omarchy-install-dev-env elixir'"},
"install.development.elixir.phoenix": {"icon":"","label":"Phoenix","action":"present_terminal 'omarchy-install-dev-env phoenix'"},
// Remove
"remove.package": {"icon":"󰣇","label":"Package","keywords":"uninstall","action":"terminal omarchy-pkg-remove"},
"remove.webapp": {"icon":"","label":"Web App","keywords":"uninstall","action":"present_terminal omarchy-webapp-remove"},
"remove.tui": {"icon":"","label":"TUI","keywords":"uninstall terminal app","action":"present_terminal omarchy-tui-remove"},
"remove.development": {"icon":"󰵮","label":"Development","keywords":"uninstall languages"},
"remove.theme": {"icon":"󰸌","label":"Theme","keywords":"uninstall","action":"present_terminal omarchy-theme-remove"},
"remove.browser": {"icon":"","label":"Browser","keywords":"uninstall"},
"remove.dictation": {"icon":"","label":"Dictation","keywords":"uninstall voice","action":"present_terminal omarchy-voxtype-remove"},
"remove.gaming": {"icon":"","label":"Gaming","keywords":"uninstall steam retroarch minecraft"},
"remove.windows": {"icon":"󰍲","label":"Windows","keywords":"uninstall vm","action":"present_terminal 'omarchy-windows-vm remove'"},
"remove.preinstalls": {"icon":"󰏓","label":"Preinstalls","action":"present_terminal omarchy-remove-preinstalls"},
"remove.security": {"icon":"","label":"Security","keywords":"fingerprint fido2"},
"remove.security.fingerprint": {"icon":"󰈷","label":"Fingerprint","action":"present_terminal omarchy-remove-security-fingerprint"},
"remove.security.fido2": {"icon":"","label":"Fido2","action":"present_terminal omarchy-remove-security-fido2"},
"remove.browser.chrome": {"icon":"","label":"Chrome","action":"present_terminal 'omarchy-remove-browser chrome'"},
"remove.browser.edge": {"icon":"","label":"Edge","action":"present_terminal 'omarchy-remove-browser edge'"},
"remove.browser.brave": {"icon":"","label":"Brave","action":"present_terminal 'omarchy-remove-browser brave'"},
"remove.browser.brave-origin": {"icon":"","label":"Brave Origin","action":"present_terminal 'omarchy-remove-browser brave-origin'"},
"remove.browser.firefox": {"icon":"","label":"Firefox","action":"present_terminal 'omarchy-remove-browser firefox'"},
"remove.browser.zen": {"icon":"","label":"Zen","action":"present_terminal 'omarchy-remove-browser zen'"},
"remove.gaming.steam": {"icon":"","label":"Steam","action":"present_terminal omarchy-remove-gaming-steam"},
"remove.gaming.retroarch": {"icon":"","label":"RetroArch","action":"present_terminal omarchy-remove-gaming-retroarch"},
"remove.gaming.minecraft": {"icon":"󰍳","label":"Minecraft","action":"present_terminal omarchy-remove-gaming-minecraft"},
"remove.gaming.geforce-now": {"icon":"󰢹","label":"NVIDIA GeForce NOW","action":"present_terminal omarchy-remove-gaming-geforce-now"},
"remove.gaming.xbox-cloud": {"icon":"","label":"Xbox Cloud Gaming","action":"present_terminal omarchy-remove-gaming-xbox-cloud"},
"remove.gaming.xbox-controller": {"icon":"󰖺","label":"Xbox Controller (󰂯)","action":"present_terminal omarchy-remove-gaming-xbox-controllers"},
"remove.gaming.moonlight": {"icon":"󰍹","label":"Moonlight (GameStream)","action":"present_terminal omarchy-remove-gaming-moonlight"},
"remove.gaming.lutris": {"icon":"","label":"Lutris (Battle.net)","action":"present_terminal omarchy-remove-gaming-lutris"},
"remove.gaming.heroic": {"icon":"󱓟","label":"Heroic (Epic Games)","action":"present_terminal omarchy-remove-gaming-heroic"},
"remove.development.rails": {"icon":"󰫏","label":"Ruby on Rails","action":"present_terminal 'omarchy-remove-dev-env ruby'"},
"remove.development.javascript": {"icon":"","label":"JavaScript","keywords":"node bun deno"},
"remove.development.go": {"icon":"","label":"Go","keywords":"golang","action":"present_terminal 'omarchy-remove-dev-env go'"},
"remove.development.php": {"icon":"","label":"PHP","keywords":"laravel symfony"},
"remove.development.python": {"icon":"","label":"Python","action":"present_terminal 'omarchy-remove-dev-env python'"},
"remove.development.elixir": {"icon":"","label":"Elixir","keywords":"phoenix"},
"remove.development.zig": {"icon":"","label":"Zig","action":"present_terminal 'omarchy-remove-dev-env zig'"},
"remove.development.rust": {"icon":"","label":"Rust","action":"present_terminal 'omarchy-remove-dev-env rust'"},
"remove.development.java": {"icon":"","label":"Java","action":"present_terminal 'omarchy-remove-dev-env java'"},
"remove.development.dotnet": {"icon":"","label":".NET","action":"present_terminal 'omarchy-remove-dev-env dotnet'"},
"remove.development.ocaml": {"icon":"","label":"OCaml","action":"present_terminal 'omarchy-remove-dev-env ocaml'"},
"remove.development.clojure": {"icon":"","label":"Clojure","action":"present_terminal 'omarchy-remove-dev-env clojure'"},
"remove.development.scala": {"icon":"","label":"Scala","action":"present_terminal 'omarchy-remove-dev-env scala'"},
"remove.development.javascript.node": {"icon":"","label":"Node.js","action":"present_terminal 'omarchy-remove-dev-env node'"},
"remove.development.javascript.bun": {"icon":"","label":"Bun","action":"present_terminal 'omarchy-remove-dev-env bun'"},
"remove.development.javascript.deno": {"icon":"","label":"Deno","action":"present_terminal 'omarchy-remove-dev-env deno'"},
"remove.development.php.php": {"icon":"","label":"PHP","action":"present_terminal 'omarchy-remove-dev-env php'"},
"remove.development.php.laravel": {"icon":"","label":"Laravel","action":"present_terminal 'omarchy-remove-dev-env laravel'"},
"remove.development.php.symfony": {"icon":"","label":"Symfony","action":"present_terminal 'omarchy-remove-dev-env symfony'"},
"remove.development.elixir.elixir": {"icon":"","label":"Elixir","action":"present_terminal 'omarchy-remove-dev-env elixir'"},
"remove.development.elixir.phoenix": {"icon":"","label":"Phoenix","action":"present_terminal 'omarchy-remove-dev-env phoenix'"},
// Update
"update.omarchy": {"icon":"","label":"Omarchy","keywords":"system","action":"present_terminal omarchy-update"},
"update.channel": {"icon":"󰔫","label":"Channel","keywords":"stable rc edge dev"},
"update.config": {"icon":"","label":"Config","keywords":"refresh default"},
"update.themes": {"icon":"󰸌","label":"Extra Themes","action":"present_terminal omarchy-theme-update"},
"update.process": {"icon":"","label":"Process","keywords":"restart services"},
"update.hardware": {"icon":"󰇅","label":"Hardware","keywords":"restart audio wifi bluetooth trackpad"},
"update.firmware": {"icon":"","label":"Firmware","keywords":"fwupd","action":"present_terminal omarchy-update-firmware"},
"update.password": {"icon":"","label":"Password","keywords":"drive user"},
"update.timezone": {"icon":"","label":"Timezone","keywords":"time zone","action":"present_terminal omarchy-tz-select"},
"update.time": {"icon":"","label":"Time","keywords":"clock ntp","action":"present_terminal omarchy-update-time"},
"update.channel.stable": {"icon":"🟢","label":"Stable","action":"present_terminal 'omarchy-channel-set stable'"},
"update.channel.rc": {"icon":"🟡","label":"RC","keywords":"release candidate","action":"present_terminal 'omarchy-channel-set rc'"},
"update.channel.edge": {"icon":"🟠","label":"Edge","action":"present_terminal 'omarchy-channel-set edge'"},
"update.channel.dev": {"icon":"🔴","label":"Dev","keywords":"development","action":"present_terminal 'omarchy-channel-set dev'"},
"update.process.hypridle": {"icon":"","label":"Hypridle","keywords":"restart","action":"omarchy-restart-hypridle"},
"update.process.hyprsunset": {"icon":"","label":"Hyprsunset","keywords":"restart","action":"omarchy-restart-hyprsunset"},
"update.process.mako": {"icon":"󰎟","label":"Mako","keywords":"restart notifications","action":"omarchy-restart-mako"},
"update.process.swayosd": {"icon":"","label":"Swayosd","keywords":"restart","action":"omarchy-restart-swayosd"},
"update.process.walker": {"icon":"󰌧","label":"Walker","keywords":"restart launcher","action":"omarchy-restart-walker"},
"update.process.waybar": {"icon":"󰍜","label":"Waybar","keywords":"restart","action":"omarchy-restart-waybar"},
"update.config.hyprland": {"icon":"","label":"Hyprland","keywords":"refresh","action":"present_terminal omarchy-refresh-hyprland"},
"update.config.hypridle": {"icon":"","label":"Hypridle","keywords":"refresh","action":"present_terminal omarchy-refresh-hypridle"},
"update.config.hyprlock": {"icon":"","label":"Hyprlock","keywords":"refresh","action":"present_terminal omarchy-refresh-hyprlock"},
"update.config.hyprsunset": {"icon":"","label":"Hyprsunset","keywords":"refresh","action":"present_terminal omarchy-refresh-hyprsunset"},
"update.config.plymouth": {"icon":"󱣴","label":"Plymouth","keywords":"refresh","action":"present_terminal omarchy-refresh-plymouth"},
"update.config.swayosd": {"icon":"","label":"Swayosd","keywords":"refresh","action":"present_terminal omarchy-refresh-swayosd"},
"update.config.tmux": {"icon":"","label":"Tmux","keywords":"refresh","action":"present_terminal omarchy-refresh-tmux"},
"update.config.walker": {"icon":"󰌧","label":"Walker","keywords":"refresh","action":"present_terminal omarchy-refresh-walker"},
"update.config.waybar": {"icon":"󰍜","label":"Waybar","keywords":"refresh","action":"present_terminal omarchy-refresh-waybar"},
"update.hardware.audio": {"icon":"","label":"Audio","keywords":"restart pipewire","action":"present_terminal omarchy-restart-pipewire"},
"update.hardware.wifi": {"icon":"󱚾","label":"Wi-Fi","keywords":"restart wireless","action":"present_terminal omarchy-restart-wifi"},
"update.hardware.bluetooth": {"icon":"󰂯","label":"Bluetooth","keywords":"restart","action":"present_terminal omarchy-restart-bluetooth"},
"update.hardware.trackpad": {"icon":"󰟸","label":"Trackpad","keywords":"restart touchpad","action":"present_terminal omarchy-restart-trackpad"},
"update.password.drive": {"icon":"","label":"Drive Encryption","action":"present_terminal omarchy-drive-password"},
"update.password.user": {"icon":"","label":"User","keywords":"passwd","action":"present_terminal passwd"},
}
+892
View File
@@ -0,0 +1,892 @@
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import QtQuick
ShellRoot {
id: root
property string socketPath: (Quickshell.env("XDG_RUNTIME_DIR") || ("/run/user/" + Quickshell.env("UID"))) + "/omarchy-menu.sock"
property string startupMenuJsonFile: Quickshell.env("OMARCHY_MENU_JSON_FILE") || ""
property string menuBin: Quickshell.env("OMARCHY_MENU_BIN") || "omarchy-menu"
property string startupInitialMenu: Quickshell.env("OMARCHY_MENU_INITIAL_MENU") || "root"
property string startupSelectionFile: Quickshell.env("OMARCHY_MENU_SELECTION_FILE") || ""
property string startupDoneFile: Quickshell.env("OMARCHY_MENU_DONE_FILE") || ""
property string startupColorsRaw: Quickshell.env("OMARCHY_MENU_COLORS_RAW") || ""
property string fontFamily: Quickshell.env("OMARCHY_MENU_FONT") || "monospace"
property string colorsFile: Quickshell.env("OMARCHY_MENU_COLORS_FILE") || (Quickshell.env("HOME") + "/.config/omarchy/current/theme/menu.json")
property string styleFile: Quickshell.env("OMARCHY_MENU_STYLE_FILE") || (Quickshell.env("HOME") + "/.local/state/omarchy/toggles/quickshell-menu.json")
property string selectionFile: ""
property string doneFile: ""
property bool requestActive: false
property bool opened: false
property bool rowsLoaded: false
property string activeMenu: "root"
property string filterText: ""
property int selectedIndex: 0
property int requestSerial: 0
property int applySerial: 0
property var items: ({})
property var itemOrder: []
property var navStack: []
property var providersLoaded: ({})
property var providerQueue: []
property var doneFilesToRelease: []
property color accent: "#89b4fa"
property color background: "#101315"
property color foreground: "#cacccc"
property color border: foreground
property int cornerRadius: 0
property int contentMargin: 18
property int headerHeight: 34
property int contentSpacing: 6
property int baseRowHeight: 50
property int detailRowHeight: 58
property int rowSpacing: 3
property int dividerHeight: 17
property bool searchDivider: false
property int layoutSerial: 0
property int cardWidth: Math.min(300, panel.width - 48)
property int visibleRowsHeight: rowListHeight(layoutSerial, displayModel.count, filterText, searchDivider)
property int cardHeight: Math.min(Math.max(220, contentMargin * 2 + headerHeight + contentSpacing + visibleRowsHeight), panel.height - 48)
function shellQuote(value) {
return "'" + String(value).replace(/'/g, "'\\''") + "'"
}
function decodeField(value) {
return String(value || "").replace(/\v/g, "\n").replace(/\f/g, "\t")
}
function withAlpha(color, alpha) {
return Qt.rgba(color.r, color.g, color.b, alpha)
}
function rowHeightForDetail(detail) {
return root.filterText && detail ? root.detailRowHeight : root.baseRowHeight
}
function rowListHeight(_serial, _count, _filter, _divider) {
if (displayModel.count === 0) return root.baseRowHeight
var count = Math.min(displayModel.count, 10)
var total = 0
var previousSection = ""
for (var i = 0; i < count; i++) {
var row = displayModel.get(i)
if (i > 0) total += root.rowSpacing
if (row.section === "drilldown" && previousSection !== "drilldown") total += root.dividerHeight
total += root.rowHeightForDetail(row.detail)
previousSection = row.section
}
return total
}
function item(id) {
return root.items[id] || null
}
function loadMenuJson(raw) {
var nextItems = ({})
var nextOrder = []
var payload = JSON.parse(raw || "{}")
var rows = payload.items || []
for (var i = 0; i < rows.length; i++) {
var entry = rows[i]
var id = entry.id || ""
if (!id) continue
var order = nextItems[id] ? nextItems[id].order : nextOrder.length
if (!nextItems[id]) nextOrder.push(id)
nextItems[id] = {
id: id,
parent: entry.parent || "",
kind: entry.kind || "action",
icon: entry.icon || "",
label: entry.label || id,
target: entry.target || "",
keywords: entry.keywords || "",
description: entry.description || "",
action: entry.action || "",
provider: entry.provider || "",
order: order
}
}
if (!nextItems.root) {
nextItems.root = { id: "root", parent: "", kind: "menu", icon: "", label: "Go", target: "", keywords: "", description: "", order: -1 }
}
root.items = nextItems
root.itemOrder = nextOrder
root.rowsLoaded = true
}
function mergeProviderJson(raw, menuId) {
var payload = ({})
try {
payload = JSON.parse(raw || "{}")
} catch (e) {
return
}
var rows = payload.items || []
var changed = false
for (var i = 0; i < rows.length; i++) {
var entry = rows[i]
var id = entry.id || ""
if (!id) continue
if (!root.items[id]) root.itemOrder.push(id)
root.items[id] = {
id: id,
parent: entry.parent || menuId,
kind: entry.kind || "action",
icon: entry.icon || "",
label: entry.label || id,
target: entry.target || "",
keywords: entry.keywords || "",
description: entry.description || "",
action: entry.action || "",
provider: entry.provider || "",
order: root.itemOrder.indexOf(id)
}
changed = true
}
if (changed) root.rebuildDisplay()
}
function startProviderForMenu(id) {
var entry = root.item(id)
if (!entry || !entry.provider || root.providersLoaded[id]) return
root.providersLoaded[id] = true
providerProc.menuId = id
providerProc.output = ""
providerProc.command = [root.menuBin, "--provider", entry.provider, id]
providerProc.running = true
}
function startNextProvider() {
if (providerProc.running) return
while (root.providerQueue.length > 0) {
var id = root.providerQueue.shift()
var entry = root.item(id)
if (!entry || !entry.provider || root.providersLoaded[id]) continue
root.startProviderForMenu(id)
return
}
}
function loadProviderForMenu(id) {
var entry = root.item(id)
if (!entry || !entry.provider || root.providersLoaded[id]) return
if (providerProc.running) {
if (root.providerQueue.indexOf(id) < 0) root.providerQueue = root.providerQueue.concat([id])
return
}
root.startProviderForMenu(id)
}
function loadProvidersForSearch() {
var active = root.item(root.activeMenu) ? root.activeMenu : "root"
for (var i = 0; i < root.itemOrder.length; i++) {
var entry = root.item(root.itemOrder[i])
if (!entry || !entry.provider || root.providersLoaded[entry.id]) continue
if (active !== "root" && entry.id !== active && !root.isDescendantOf(entry.id, active)) continue
root.loadProviderForMenu(entry.id)
}
}
function depthFor(id) {
var depth = 0
var current = root.item(id)
var guard = 0
while (current && current.parent && current.parent !== "root" && guard < 32) {
depth += 1
current = root.item(current.parent)
guard += 1
}
return depth
}
function pathFor(id) {
var labels = []
var current = root.item(id)
var guard = 0
while (current && current.id !== "root" && guard < 32) {
labels.unshift(current.label)
current = root.item(current.parent)
guard += 1
}
return labels.join(" ")
}
function parentPathFor(id) {
var entry = root.item(id)
if (!entry || !entry.parent || entry.parent === "root") return ""
return root.pathFor(entry.parent)
}
function breadcrumbFor(id) {
var path = root.pathFor(id)
return path ? ("Go " + path) : "Go"
}
function isDescendantOf(id, ancestorId) {
if (ancestorId === "root") return id !== "root"
var current = root.item(id)
var guard = 0
while (current && current.parent && guard < 32) {
if (current.parent === ancestorId) return true
current = root.item(current.parent)
guard += 1
}
return false
}
function childCount(id) {
var count = 0
for (var i = 0; i < root.itemOrder.length; i++) {
var entry = root.item(root.itemOrder[i])
if (entry && entry.parent === id) count += 1
}
return count
}
function matchesQuery(entry, query) {
if (!entry || entry.id === "root") return false
var haystack = (entry.label + " " + root.pathFor(entry.id) + " " + entry.keywords + " " + entry.description).toLowerCase()
var terms = query.toLowerCase().trim().split(/\s+/)
for (var i = 0; i < terms.length; i++) {
if (terms[i] && haystack.indexOf(terms[i]) === -1) return false
}
return true
}
function searchScore(entry, query) {
var needle = query.toLowerCase().trim()
var label = entry.label.toLowerCase()
var path = root.pathFor(entry.id).toLowerCase()
var keywords = entry.keywords.toLowerCase()
var parent = root.item(entry.parent)
var parentLabel = parent ? parent.label.toLowerCase() : ""
var score = 80
if (label === needle) score = entry.parent === "root" ? 2 : 0
else if (label.indexOf(needle) === 0) score = 10
else if (path.indexOf(needle) === 0) score = entry.kind === "action" ? 12 : 14
else if (parentLabel === needle) score = entry.kind === "action" ? 18 : 20
else if (label.indexOf(needle) >= 0) score = 30
else if (path.indexOf(needle) >= 0) score = 40
else if (keywords.indexOf(needle) >= 0) score = 50
if (entry.kind === "menu" || entry.kind === "link") score -= 2
return score * 1000 + root.depthFor(entry.id) * 25 + entry.order
}
function displayRow(entry, detail, score, section) {
var target = entry.kind === "link" ? entry.target : entry.id
return {
itemId: entry.id,
kind: entry.kind,
icon: entry.icon,
label: entry.label,
target: target,
detail: detail || "",
path: root.pathFor(entry.id),
childCount: (entry.kind === "menu" || entry.kind === "link") ? root.childCount(target) : 0,
action: entry.action || "",
provider: entry.provider || "",
score: score || 0,
section: section || ""
}
}
function rebuildDisplay() {
displayModel.clear()
if (!root.rowsLoaded) return
var active = root.item(root.activeMenu) ? root.activeMenu : "root"
root.activeMenu = active
var rows = []
var query = root.filterText.trim()
root.searchDivider = false
if (query) {
var currentRows = []
var drilldownRows = []
for (var i = 0; i < root.itemOrder.length; i++) {
var entry = root.item(root.itemOrder[i])
if (!entry || entry.id === "root") continue
if (!root.isDescendantOf(entry.id, active)) continue
if (!root.matchesQuery(entry, query)) continue
var detail = root.parentPathFor(entry.id)
var row = root.displayRow(entry, detail, root.searchScore(entry, query))
if (entry.parent === active) currentRows.push(row)
else drilldownRows.push(row)
}
var searchSort = function(a, b) {
if (a.score !== b.score) return a.score - b.score
return a.path.localeCompare(b.path)
}
currentRows.sort(searchSort)
drilldownRows.sort(searchSort)
root.searchDivider = currentRows.length > 0 && drilldownRows.length > 0
if (root.searchDivider) {
for (var d = 0; d < drilldownRows.length; d++) drilldownRows[d].section = "drilldown"
}
rows = currentRows.concat(drilldownRows)
} else {
if (active !== "root") {
var parentTarget = root.item(active).parent || "root"
var backTarget = root.navStack.length > 0 ? root.navStack[root.navStack.length - 1] : parentTarget
rows.push({ itemId: "__back", kind: "back", icon: "", label: "Back", target: backTarget, detail: root.breadcrumbFor(backTarget), path: "", childCount: 0, action: "", score: -1, section: "" })
}
for (var j = 0; j < root.itemOrder.length; j++) {
var child = root.item(root.itemOrder[j])
if (!child || child.parent !== active) continue
rows.push(root.displayRow(child, child.description, child.order))
}
}
for (var k = 0; k < rows.length; k++) displayModel.append(rows[k])
layoutSerial += 1
if (displayModel.count === 0) selectedIndex = 0
else if (selectedIndex >= displayModel.count) selectedIndex = displayModel.count - 1
else if (selectedIndex < 0) selectedIndex = 0
Qt.callLater(function() {
if (displayModel.count > 0) resultList.positionViewAtIndex(root.selectedIndex, ListView.Contain)
})
}
function select(delta) {
if (displayModel.count === 0) return
selectedIndex += delta
if (selectedIndex < 0) selectedIndex = 0
if (selectedIndex >= displayModel.count) selectedIndex = displayModel.count - 1
resultList.positionViewAtIndex(selectedIndex, ListView.Contain)
}
function setFilter(nextFilter) {
root.filterText = nextFilter
root.selectedIndex = 0
if (root.filterText.trim()) root.loadProvidersForSearch()
root.rebuildDisplay()
}
function setActiveMenu(id, pushHistory) {
if (!root.item(id)) id = "root"
if (pushHistory && id !== root.activeMenu) root.navStack = root.navStack.concat([root.activeMenu])
root.activeMenu = id
root.filterText = ""
root.selectedIndex = 0
root.rebuildDisplay()
root.loadProviderForMenu(id)
}
function goBack() {
if (root.activeMenu === "root") return false
if (root.navStack.length > 0) {
var previous = root.navStack[root.navStack.length - 1]
root.navStack = root.navStack.slice(0, root.navStack.length - 1)
root.setActiveMenu(previous, false)
return true
}
var active = root.item(root.activeMenu)
root.setActiveMenu((active && active.parent) ? active.parent : "root", false)
return true
}
function activateIndex(index) {
if (index < 0 || index >= displayModel.count) return
var row = displayModel.get(index)
if (row.kind === "back") {
root.goBack()
} else if (row.kind === "menu" || row.kind === "link") {
root.setActiveMenu(row.target || row.itemId, true)
} else {
root.applySelected(row.itemId, row.action)
}
}
function releaseNextDoneFile() {
if (releaseProc.running || doneFilesToRelease.length === 0) return
var path = doneFilesToRelease.shift()
releaseProc.command = ["bash", "-lc", ": > " + shellQuote(path)]
releaseProc.running = true
}
function finishDoneFile(path) {
if (!path) return
doneFilesToRelease.push(path)
releaseNextDoneFile()
}
function resetRequest() {
requestActive = false
selectionFile = ""
doneFile = ""
}
function applySelected(id, action) {
if (!id || !selectionFile || !doneFile) {
cancel()
return
}
var activeSelectionFile = selectionFile
var activeDoneFile = doneFile
applySerial = requestSerial
resetRequest()
opened = false
applyProc.command = ["bash", "-lc", "printf '%s\\t%s\\n' " + shellQuote(id) + " " + shellQuote(action || "") + " > " + shellQuote(activeSelectionFile) + "; : > " + shellQuote(activeDoneFile)]
applyProc.running = true
}
function cancel() {
if (requestActive) finishDoneFile(doneFile)
resetRequest()
opened = false
filterText = ""
}
function closeMenu(nextDoneFile) {
requestSerial += 1
if (requestActive) finishDoneFile(doneFile)
if (nextDoneFile && nextDoneFile !== doneFile) finishDoneFile(nextDoneFile)
resetRequest()
opened = false
filterText = ""
}
function openExistingMenu(initialMenu, nextSelectionFile, nextDoneFile) {
requestSerial += 1
if (requestActive && doneFile && doneFile !== nextDoneFile) finishDoneFile(doneFile)
selectionFile = nextSelectionFile
doneFile = nextDoneFile
requestActive = !!doneFile
activeMenu = root.item(initialMenu) ? initialMenu : "root"
navStack = []
filterText = ""
selectedIndex = 0
opened = true
rebuildDisplay()
loadProviderForMenu(activeMenu)
Qt.callLater(function() { keyCatcher.forceActiveFocus() })
}
function openMenu(menuJson, initialMenu, nextSelectionFile, nextDoneFile, colorsRaw) {
loadMenuJson(menuJson)
if (colorsRaw) loadColors(colorsRaw)
providersLoaded = ({})
providerQueue = []
openExistingMenu(initialMenu, nextSelectionFile, nextDoneFile)
}
function loadColors(raw) {
try {
var colors = JSON.parse(raw || "{}")
root.accent = colors.accent || colors.primary || root.accent
root.background = colors.background || root.background
root.foreground = colors.foreground || colors.backgroundText || root.foreground
root.border = colors.border || root.foreground
} catch (e) {}
}
function loadStyle(raw) {
try {
var style = JSON.parse(raw || "{}")
root.cornerRadius = Number(style.radius || 0)
} catch (e) {}
}
ListModel { id: displayModel }
Process {
id: providerProc
property string menuId: ""
property string output: ""
stdout: SplitParser {
onRead: function(data) {
providerProc.output += data + "\n"
}
}
onExited: {
root.mergeProviderJson(output, menuId)
if (root.filterText.trim()) root.loadProvidersForSearch()
root.startNextProvider()
}
}
SocketServer {
active: true
path: root.socketPath
handler: Socket {
id: clientSocket
parser: SplitParser {
onRead: function(message) {
var fields = message.split("\t")
if (fields[0] === "open") {
root.openExistingMenu(fields[1] || "root", fields[2] || "", fields[3] || "")
} else {
root.closeMenu(fields[3] || "")
}
clientSocket.connected = false
}
}
}
}
FileView {
path: root.startupMenuJsonFile
onLoaded: root.openMenu(text(), root.startupInitialMenu, root.startupSelectionFile, root.startupDoneFile, root.decodeField(root.startupColorsRaw))
}
FileView {
path: root.colorsFile
watchChanges: true
onLoaded: root.loadColors(text())
onFileChanged: { reload(); root.loadColors(text()) }
}
FileView {
path: root.styleFile
watchChanges: true
onLoaded: root.loadStyle(text())
onFileChanged: { reload(); root.loadStyle(text()) }
}
Process {
id: applyProc
onExited: {
if (root.applySerial === root.requestSerial) root.opened = false
}
}
Process {
id: releaseProc
onExited: root.releaseNextDoneFile()
}
PanelWindow {
id: panel
visible: root.opened && root.rowsLoaded
anchors { top: true; bottom: true; left: true; right: true }
color: "transparent"
WlrLayershell.namespace: "omarchy-menu"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
exclusionMode: ExclusionMode.Ignore
MouseArea {
anchors.fill: parent
onClicked: root.cancel()
}
Rectangle {
id: card
width: root.cardWidth
height: root.cardHeight
radius: root.cornerRadius
anchors.centerIn: parent
color: root.background
border.color: root.withAlpha(root.border, 0.36)
border.width: 1
MouseArea { anchors.fill: parent; onClicked: {} }
Item {
id: keyCatcher
anchors.fill: parent
focus: true
Keys.priority: Keys.BeforeItem
Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape) {
if (root.filterText) root.setFilter("")
else root.cancel()
event.accepted = true
} else if (event.key === Qt.Key_Backspace) {
if (root.filterText.length > 0) root.setFilter(root.filterText.slice(0, -1))
else root.goBack()
event.accepted = true
} else if (event.key === Qt.Key_Up) {
root.select(-1)
event.accepted = true
} else if (event.key === Qt.Key_Down) {
root.select(1)
event.accepted = true
} else if (event.key === Qt.Key_PageUp) {
root.select(-6)
event.accepted = true
} else if (event.key === Qt.Key_PageDown) {
root.select(6)
event.accepted = true
} else if (event.key === Qt.Key_Left) {
if (!root.filterText) root.goBack()
event.accepted = true
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter || event.key === Qt.Key_Right) {
root.activateIndex(root.selectedIndex)
event.accepted = true
} else if (event.text && event.text.length === 1 && event.text.charCodeAt(0) >= 32 && event.text.charCodeAt(0) !== 127 && (event.modifiers === Qt.NoModifier || event.modifiers === Qt.ShiftModifier)) {
root.setFilter(root.filterText + event.text)
event.accepted = true
}
}
}
Column {
anchors.fill: parent
anchors.margins: root.contentMargin
spacing: root.contentSpacing
Rectangle {
width: parent.width
height: root.headerHeight
radius: root.cornerRadius
color: "transparent"
border.width: 0
Text {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: root.filterText || ((root.item(root.activeMenu) ? root.item(root.activeMenu).label : "Go") + "…")
color: root.foreground
opacity: root.filterText ? 1 : 0.58
font.family: root.fontFamily
font.pixelSize: 16
elide: Text.ElideRight
}
}
Item {
width: parent.width
height: root.visibleRowsHeight
ListView {
id: resultList
anchors.fill: parent
model: displayModel
clip: true
spacing: root.rowSpacing
boundsBehavior: Flickable.StopAtBounds
section.property: "section"
section.criteria: ViewSection.FullString
section.delegate: Item {
required property string section
width: ListView.view.width
height: section === "drilldown" ? root.dividerHeight : 0
visible: section === "drilldown"
Rectangle {
anchors.left: parent.left
anchors.leftMargin: 4
anchors.right: parent.right
anchors.rightMargin: 4
anchors.verticalCenter: parent.verticalCenter
height: 1
color: root.withAlpha(root.foreground, 0.2)
}
}
delegate: Rectangle {
id: row
required property int index
required property string itemId
required property string kind
required property string icon
required property string label
required property string target
required property string detail
required property string path
required property string action
required property int childCount
width: ListView.view.width
height: root.rowHeightForDetail(row.detail)
radius: root.cornerRadius
color: index === root.selectedIndex ? root.withAlpha(root.foreground, 0.08) : root.withAlpha(root.foreground, mouseArea.containsMouse ? 0.045 : 0)
border.color: "transparent"
border.width: 0
Rectangle {
visible: false
width: 4
height: parent.height - 18
radius: Math.min(root.cornerRadius, 4)
color: root.accent
anchors.left: parent.left
anchors.leftMargin: 8
anchors.verticalCenter: parent.verticalCenter
}
Text {
id: iconText
text: row.icon
color: index === root.selectedIndex ? root.accent : root.foreground
opacity: row.kind === "back" ? 0.7 : 1
font.family: root.fontFamily
font.pixelSize: 18
width: 36
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.left: parent.left
anchors.leftMargin: 8
y: contentColumn.y + labelText.y + (labelText.height - height) / 2
}
Column {
id: contentColumn
anchors.left: iconText.right
anchors.leftMargin: 6
anchors.right: trail.left
anchors.rightMargin: 6
anchors.verticalCenter: parent.verticalCenter
spacing: 3
Text {
id: labelText
width: parent.width
text: row.label
color: index === root.selectedIndex ? root.accent : root.foreground
font.family: root.fontFamily
font.pixelSize: 16
font.weight: Font.Medium
elide: Text.ElideRight
}
Text {
width: parent.width
text: row.detail
visible: root.filterText && row.detail.length > 0
color: root.foreground
opacity: 0.52
font.family: root.fontFamily
font.pixelSize: 11
elide: Text.ElideRight
}
}
Row {
id: trail
width: 14
anchors.right: parent.right
anchors.rightMargin: 8
y: contentColumn.y + labelText.y + (labelText.height - height) / 2
spacing: 0
Text {
visible: false
text: row.childCount
color: root.foreground
opacity: 0.45
font.family: root.fontFamily
font.pixelSize: 12
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: row.kind === "menu" || row.kind === "link" ? "" : (row.kind === "back" ? "" : "↵")
color: index === root.selectedIndex ? root.accent : root.foreground
opacity: row.kind === "back" ? 0 : 0.36
font.family: root.fontFamily
font.pixelSize: 16
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.activateIndex(row.index)
}
}
}
Column {
anchors.centerIn: parent
spacing: 8
visible: displayModel.count === 0
Text {
text: "󰈉"
color: root.accent
opacity: 0.8
font.family: root.fontFamily
font.pixelSize: 28
horizontalAlignment: Text.AlignHCenter
width: 320
}
Text {
text: root.filterText ? "No matches for “" + root.filterText + "”" : "Nothing here yet"
color: root.foreground
opacity: 0.7
font.family: root.fontFamily
font.pixelSize: 14
horizontalAlignment: Text.AlignHCenter
width: 320
}
}
}
Item {
width: parent.width
height: 0
}
}
}
}
}
+6
View File
@@ -0,0 +1,6 @@
{
"accent": "{{ accent }}",
"background": "{{ background }}",
"foreground": "{{ foreground }}",
"border": "{{ foreground }}"
}
+1 -1
View File
@@ -37,7 +37,7 @@ for conf_toggle in "$toggle_state_dir"/*.conf; do
if [[ ! -f $lua_toggle ]]; then
case "$toggle_name" in
flags | single-window-aspect-ratio | window-no-gaps)
flags | rounded-corners | single-window-aspect-ratio | window-no-gaps)
if [[ -f $toggle_defaults_dir/$toggle_name.lua ]]; then
cp -f "$toggle_defaults_dir/$toggle_name.lua" "$lua_toggle"
fi
+55
View File
@@ -0,0 +1,55 @@
echo "Prime Quickshell Omarchy menu styling"
AUTOSTART_FILE="$HOME/.config/hypr/autostart.lua"
if [[ -f $AUTOSTART_FILE ]] && grep -q 'omarchy-menu --daemon' "$AUTOSTART_FILE"; then
sed -i '/omarchy-menu --daemon/d' "$AUTOSTART_FILE"
fi
TOGGLES_DIR="$HOME/.local/state/omarchy/toggles"
QUICKSHELL_MENU_STYLE="$TOGGLES_DIR/quickshell-menu.json"
mkdir -p "$TOGGLES_DIR"
if [[ ! -f $QUICKSHELL_MENU_STYLE ]]; then
radius=0
if [[ -f $TOGGLES_DIR/walker.css ]] && grep -q 'border-radius: 6px;' "$TOGGLES_DIR/walker.css"; then
radius=6
fi
printf '{ "radius": %s }\n' "$radius" >"$QUICKSHELL_MENU_STYLE"
fi
THEME_DIR="$HOME/.config/omarchy/current/theme"
COLORS_FILE="$THEME_DIR/colors.toml"
MENU_COLORS_FILE="$THEME_DIR/menu.json"
color_value() {
local key="$1"
local value
value=$(grep -E "^[[:space:]]*$key[[:space:]]*=" "$COLORS_FILE" | head -1)
value="${value#*=}"
value="${value//\"/}"
value="${value//\'/}"
value="${value//[[:space:]]/}"
printf '%s' "$value"
}
if [[ -f $COLORS_FILE && ! -f $MENU_COLORS_FILE ]]; then
accent=$(color_value accent)
background=$(color_value background)
foreground=$(color_value foreground)
cat >"$MENU_COLORS_FILE" <<JSON
{
"accent": "${accent:-#89b4fa}",
"background": "${background:-#101315}",
"foreground": "${foreground:-#cacccc}",
"border": "${foreground:-#cacccc}"
}
JSON
fi
rm -rf "${XDG_CACHE_HOME:-$HOME/.cache}/omarchy/menu"
if omarchy-cmd-present hyprctl; then
hyprctl reload >/dev/null 2>&1 || true
fi
+11
View File
@@ -0,0 +1,11 @@
echo "Convert Hyprland rounded corners toggle to Lua"
old_toggle="$HOME/.local/state/omarchy/toggles/hypr/rounded-corners.conf"
new_toggle="$HOME/.local/state/omarchy/toggles/hypr/rounded-corners.lua"
if [[ -f $old_toggle ]]; then
mkdir -p "$(dirname "$new_toggle")"
cp "$OMARCHY_PATH/default/hypr/toggles/rounded-corners.lua" "$new_toggle"
rm -f "$old_toggle"
hyprctl reload >/dev/null 2>&1 || true
fi