Integrate omarchy menu into shell
This commit is contained in:
+14
-26
@@ -29,40 +29,28 @@ if [[ -n $font_name ]]; then
|
||||
sed -i "s/font_family = .*/font_family = $font_name/g" ~/.config/hypr/hyprlock.conf
|
||||
sed -i "s/font-family: .*/font-family: '$font_name';/g" ~/.config/waybar/style.css
|
||||
mkdir -p "$HOME/.config/omarchy"
|
||||
python3 - "$HOME/.config/omarchy/shell.json" "$font_name" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
shell_config="$HOME/.config/omarchy/shell.json"
|
||||
tmp=$(mktemp)
|
||||
|
||||
path, font_name = sys.argv[1], sys.argv[2]
|
||||
try:
|
||||
with open(path) as file:
|
||||
data = json.load(file)
|
||||
if not isinstance(data, dict):
|
||||
data = {}
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
data = {}
|
||||
if [[ -s $shell_config ]] && jq -e 'type == "object"' "$shell_config" >/dev/null 2>&1; then
|
||||
jq --arg font_name "$font_name" '
|
||||
.version = 1 |
|
||||
.bar = ((.bar // {}) | if type == "object" then . else {} end) |
|
||||
.bar.fontFamily = $font_name
|
||||
' "$shell_config" >"$tmp"
|
||||
else
|
||||
jq -n --arg font_name "$font_name" '{ version: 1, bar: { fontFamily: $font_name } }' >"$tmp"
|
||||
fi
|
||||
|
||||
data.setdefault("version", 1)
|
||||
bar = data.get("bar")
|
||||
if not isinstance(bar, dict):
|
||||
bar = {}
|
||||
data["bar"] = bar
|
||||
bar["fontFamily"] = font_name
|
||||
|
||||
with open(path, "w") as file:
|
||||
json.dump(data, file, indent=2)
|
||||
file.write("\n")
|
||||
PY
|
||||
mv "$tmp" "$shell_config"
|
||||
sed -i "s/font-family: .*/font-family: '$font_name';/g" ~/.config/swayosd/style.css
|
||||
xmlstarlet ed -L \
|
||||
-u '//match[@target="pattern"][test/string="monospace"]/edit[@name="family"]/string' \
|
||||
-v "$font_name" \
|
||||
~/.config/fontconfig/fonts.conf
|
||||
|
||||
omarchy-restart-waybar
|
||||
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
|
||||
if quickshell list -p "$OMARCHY_PATH/default/quickshell/omarchy-shell" 2>/dev/null | grep -q '^Instance '; then
|
||||
omarchy-restart-bar
|
||||
if pgrep -x waybar >/dev/null; then
|
||||
omarchy-restart-waybar
|
||||
fi
|
||||
omarchy-restart-swayosd
|
||||
|
||||
|
||||
+728
-829
File diff suppressed because it is too large
Load Diff
@@ -7,14 +7,11 @@ set -e
|
||||
|
||||
USER_CONFIG="$HOME/.config/omarchy/shell.json"
|
||||
|
||||
# Removing the user file lets the shell fall back to shell-defaults.json on
|
||||
# its next reload. omarchy-restart-bar (which is now an alias for restarting
|
||||
# omarchy-shell) reloads the shell so the change takes effect immediately.
|
||||
# Removing the user file lets the running shell fall back to shell-defaults.json
|
||||
# via its FileView watcher. The next shell start will also use the defaults.
|
||||
if [[ -f $USER_CONFIG ]]; then
|
||||
backup="$USER_CONFIG.bak.$(date +%s)"
|
||||
cp "$USER_CONFIG" "$backup"
|
||||
echo "Backed up user shell config to $backup"
|
||||
rm -f "$USER_CONFIG"
|
||||
fi
|
||||
|
||||
omarchy-restart-bar
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Restart the bar
|
||||
# omarchy:examples=omarchy restart bar
|
||||
# omarchy:summary=Restart Omarchy Quickshell
|
||||
# omarchy:examples=omarchy restart quickshell | omarchy-restart-quickshell
|
||||
|
||||
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
|
||||
CONFIG_DIR="$OMARCHY_PATH/default/quickshell/omarchy-shell"
|
||||
@@ -15,29 +15,16 @@ if [[ ! $position =~ ^(top|bottom|left|right)$ ]]; then
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$CONFIG_FILE")"
|
||||
python3 - "$CONFIG_FILE" "$position" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
tmp=$(mktemp)
|
||||
|
||||
path, position = sys.argv[1], sys.argv[2]
|
||||
try:
|
||||
with open(path) as file:
|
||||
data = json.load(file)
|
||||
if not isinstance(data, dict):
|
||||
data = {}
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
data = {}
|
||||
if [[ -s $CONFIG_FILE ]] && jq -e 'type == "object"' "$CONFIG_FILE" >/dev/null 2>&1; then
|
||||
jq --arg position "$position" '
|
||||
.version = 1 |
|
||||
.bar = ((.bar // {}) | if type == "object" then . else {} end) |
|
||||
.bar.position = $position
|
||||
' "$CONFIG_FILE" >"$tmp"
|
||||
else
|
||||
jq -n --arg position "$position" '{ version: 1, bar: { position: $position } }' >"$tmp"
|
||||
fi
|
||||
|
||||
data.setdefault("version", 1)
|
||||
bar = data.get("bar")
|
||||
if not isinstance(bar, dict):
|
||||
bar = {}
|
||||
data["bar"] = bar
|
||||
bar["position"] = position
|
||||
|
||||
with open(path, "w") as file:
|
||||
json.dump(data, file, indent=2)
|
||||
file.write("\n")
|
||||
PY
|
||||
|
||||
omarchy-restart-bar
|
||||
mv "$tmp" "$CONFIG_FILE"
|
||||
|
||||
@@ -53,10 +53,6 @@ fi
|
||||
if pgrep -x waybar >/dev/null; then
|
||||
omarchy-restart-waybar
|
||||
fi
|
||||
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
|
||||
if quickshell list -p "$OMARCHY_PATH/default/quickshell/omarchy-shell" 2>/dev/null | grep -q '^Instance '; then
|
||||
omarchy-restart-bar
|
||||
fi
|
||||
omarchy-restart-swayosd
|
||||
omarchy-restart-terminal
|
||||
omarchy-restart-hyprctl
|
||||
|
||||
@@ -20,10 +20,9 @@ if gum confirm "Install Voxtype + AI model (~150MB) to enable dictation?"; then
|
||||
fi
|
||||
voxtype setup systemd
|
||||
|
||||
omarchy-restart-waybar
|
||||
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
|
||||
if quickshell list -p "$OMARCHY_PATH/default/quickshell/omarchy-shell" 2>/dev/null | grep -q '^Instance '; then
|
||||
omarchy-restart-bar
|
||||
if pgrep -x waybar >/dev/null; then
|
||||
omarchy-restart-waybar
|
||||
fi
|
||||
omarchy-restart-quickshell
|
||||
notify-send " Voxtype Dictation Ready" "Hold F9 to dictate (or toggle with Super + Ctrl + X)." -t 10000
|
||||
fi
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
set -e
|
||||
|
||||
omarchy-launch-floating-terminal-with-presentation "voxtype setup model"
|
||||
omarchy-restart-waybar
|
||||
OMARCHY_PATH=${OMARCHY_PATH:-$HOME/.local/share/omarchy}
|
||||
if quickshell list -p "$OMARCHY_PATH/default/quickshell/omarchy-shell" 2>/dev/null | grep -q '^Instance '; then
|
||||
omarchy-restart-bar
|
||||
if pgrep -x waybar >/dev/null; then
|
||||
omarchy-restart-waybar
|
||||
fi
|
||||
omarchy-restart-quickshell
|
||||
|
||||
@@ -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,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" })
|
||||
|
||||
@@ -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" })
|
||||
@@ -23,4 +23,4 @@ hl.window_rule({ match = { tag = "pop" }, rounding = 8 })
|
||||
hl.window_rule({ match = { tag = "noidle" }, idle_inhibit = "always" })
|
||||
|
||||
-- Image selector.
|
||||
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,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,7 +1,7 @@
|
||||
hl.on("hyprland.start", function()
|
||||
hl.exec_cmd("uwsm-app -- hypridle")
|
||||
hl.exec_cmd("uwsm-app -- mako")
|
||||
hl.exec_cmd("! omarchy-toggle-enabled bar-off && uwsm-app -- env OMARCHY_PATH=$HOME/.local/share/omarchy quickshell -p $HOME/.local/share/omarchy/default/quickshell/omarchy-shell")
|
||||
hl.exec_cmd("! omarchy-toggle-enabled bar-off && omarchy-restart-quickshell")
|
||||
hl.exec_cmd("uwsm-app -- fcitx5 --disable notificationitem")
|
||||
hl.exec_cmd("uwsm-app -- swaybg -i ~/.config/omarchy/current/background -m fill")
|
||||
hl.exec_cmd("/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1")
|
||||
|
||||
@@ -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 bar quickshell 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 bar quickshell"},
|
||||
"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":"Bar","keywords":"top bar quickshell","action":"omarchy-toggle-bar"},
|
||||
"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.bar": {"icon":"","label":"Bar","keywords":"quickshell top bottom left right settings"},
|
||||
"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.bar.top": {"icon":"","label":"Top","keywords":"position","action":"omarchy-style-bar-position top"},
|
||||
"style.bar.bottom": {"icon":"","label":"Bottom","keywords":"position","action":"omarchy-style-bar-position bottom"},
|
||||
"style.bar.left": {"icon":"","label":"Left","keywords":"position","action":"omarchy-style-bar-position left"},
|
||||
"style.bar.right": {"icon":"","label":"Right","keywords":"position","action":"omarchy-style-bar-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 bar quickshell walker waybar"},
|
||||
"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.bar": {"icon":"","label":"Bar","keywords":"quickshell shell config","action":"omarchy-launch-bar-settings"},
|
||||
"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.quickshell": {"icon":"","label":"Quickshell","keywords":"restart bar shell","action":"omarchy-restart-quickshell"},
|
||||
"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.bar": {"icon":"","label":"Bar","keywords":"refresh quickshell","action":"present_terminal omarchy-refresh-bar"},
|
||||
"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"},
|
||||
}
|
||||
@@ -30,6 +30,7 @@ default/quickshell/omarchy-shell/
|
||||
bar/ first-party plugins (see plugins/README.md)
|
||||
bar-settings/
|
||||
image-picker/
|
||||
menu/
|
||||
```
|
||||
|
||||
The plugin discovery path is documented in [plugins/README.md](plugins/README.md).
|
||||
@@ -98,7 +99,9 @@ are discovered the same way and cannot be disabled.
|
||||
|
||||
The shell exposes a single `shell` IPC target plus whatever extra targets
|
||||
individual plugins register (e.g. the bar's `bar` target for refresh
|
||||
hooks, the background switcher's `image-selector` target).
|
||||
hooks, the image picker's `image-selector` target). `omarchy-menu` uses the
|
||||
shell target to summon the first-party `omarchy.menu` plugin instead of
|
||||
running a separate Quickshell instance.
|
||||
|
||||
| Method | Returns | Effect |
|
||||
|------------------------------------------|---------|-------------------------------------------------------|
|
||||
@@ -116,6 +119,9 @@ Direct invocation:
|
||||
quickshell ipc -p $OMARCHY_PATH/default/quickshell/omarchy-shell call shell ping
|
||||
```
|
||||
|
||||
Hyprland starts the shell through `omarchy-restart-quickshell` on boot.
|
||||
Use `omarchy restart quickshell` to reload the long-running shell process.
|
||||
|
||||
A convenience wrapper, [`omarchy-shell-ipc`](../../../bin/omarchy-shell-ipc),
|
||||
starts the shell if it is not already running, then forwards a `call`. It
|
||||
is the canonical way for other Omarchy CLIs to talk to the shell.
|
||||
|
||||
@@ -13,6 +13,7 @@ User-installed plugins live alongside these conceptually but on disk under
|
||||
| Bar | `omarchy.bar` | `bar` | persistent | `bar/Bar.qml` |
|
||||
| Bar settings | `omarchy.bar-settings` | `panel` | on-demand | `bar-settings/BarSettingsPanel.qml` |
|
||||
| Image picker | `omarchy.image-picker` | `overlay` | on-demand | `image-picker/ImagePicker.qml` |
|
||||
| Omarchy menu | `omarchy.menu` | `menu` | on-demand | `menu/Menu.qml` |
|
||||
|
||||
## Bar
|
||||
|
||||
@@ -62,8 +63,23 @@ clears it without writing a selection.
|
||||
The plugin has `keepLoaded: true` so the layer-shell window survives
|
||||
between summons within a single shell session.
|
||||
|
||||
## Omarchy menu
|
||||
|
||||
Quickshell-powered replacement for the legacy Walker-driven `omarchy-menu`.
|
||||
The menu UI lives in `menu/Menu.qml` as a first-party `menu` plugin and is
|
||||
summoned through the shell (`omarchy-shell-ipc shell summon omarchy.menu ...`),
|
||||
so it shares the long-running `omarchy-shell` process instead of starting a
|
||||
second Quickshell instance.
|
||||
|
||||
The menu definition lives outside the shell host code:
|
||||
|
||||
- defaults: `default/omarchy/omarchy-menu.jsonc`
|
||||
- user extensions: `~/.config/omarchy/extensions/omarchy-menu.jsonc`
|
||||
|
||||
`bin/omarchy-menu` still owns the Bash action helpers and dynamic providers;
|
||||
it builds the menu JSON, summons `omarchy.menu`, waits for the selection, and
|
||||
runs the selected action.
|
||||
|
||||
## Coming soon
|
||||
|
||||
- `omarchy.menu` — folds the existing `omarchy-menu` (currently on another
|
||||
branch) into the shell as a `menu` plugin. Not present on this branch.
|
||||
- `omarchy.theme-switcher` — folds theme switching into the shell.
|
||||
|
||||
@@ -0,0 +1,914 @@
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
// Injected by omarchy-shell when this plugin is summoned.
|
||||
property string omarchyPath: Quickshell.env("OMARCHY_PATH") || (Quickshell.env("HOME") + "/.local/share/omarchy")
|
||||
property var shell: null
|
||||
property var manifest: null
|
||||
property var pluginRegistry: null
|
||||
|
||||
// Plugin lifecycle hooks. The host calls open(payloadJson) after
|
||||
// `omarchy-shell-ipc shell summon omarchy.menu ...` and close() when hidden.
|
||||
property string menuJsonFile: ""
|
||||
property string pendingInitialMenu: "root"
|
||||
property string pendingSelectionFile: ""
|
||||
property string pendingDoneFile: ""
|
||||
property string pendingColorsRaw: ""
|
||||
|
||||
function decodeBase64(value) {
|
||||
var s = String(value || "")
|
||||
if (!s) return ""
|
||||
try { return Qt.atob(s) } catch (e) { return s }
|
||||
}
|
||||
|
||||
function open(payloadJson) {
|
||||
var payload = ({})
|
||||
try { payload = JSON.parse(payloadJson || "{}") } catch (e) { payload = ({}) }
|
||||
|
||||
root.pendingInitialMenu = payload.initialMenu || "root"
|
||||
root.pendingSelectionFile = payload.selectionFile || ""
|
||||
root.pendingDoneFile = payload.doneFile || ""
|
||||
root.pendingColorsRaw = payload.colorsRawBase64 ? root.decodeBase64(payload.colorsRawBase64) : (payload.colorsRaw || "")
|
||||
if (payload.fontFamily) root.fontFamily = payload.fontFamily
|
||||
|
||||
var menuJson = payload.menuJsonBase64 ? root.decodeBase64(payload.menuJsonBase64) : (payload.menuJson || "")
|
||||
if (menuJson) {
|
||||
root.openMenu(menuJson, root.pendingInitialMenu, root.pendingSelectionFile, root.pendingDoneFile, root.pendingColorsRaw)
|
||||
return
|
||||
}
|
||||
|
||||
root.menuJsonFile = payload.menuJsonFile || ""
|
||||
if (root.menuJsonFile) menuJsonFileView.reload()
|
||||
}
|
||||
|
||||
function close() {
|
||||
root.closeMenu("")
|
||||
}
|
||||
|
||||
property string menuBin: omarchyPath + "/bin/omarchy-menu"
|
||||
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/colors.toml")
|
||||
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) {
|
||||
var lines = String(raw || "").split("\n")
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var match = lines[i].match(/^\s*([A-Za-z0-9_-]+)\s*=\s*["']?(#[0-9A-Fa-f]{6})/)
|
||||
if (!match) continue
|
||||
if (match[1] === "foreground") foreground = match[2]
|
||||
else if (match[1] === "background") background = match[2]
|
||||
else if (match[1] === "color4" || match[1] === "accent") accent = match[2]
|
||||
}
|
||||
border = foreground
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: menuJsonFileView
|
||||
path: root.menuJsonFile
|
||||
printErrors: false
|
||||
onLoaded: root.openMenu(text(), root.pendingInitialMenu, root.pendingSelectionFile, root.pendingDoneFile, root.pendingColorsRaw)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "omarchy.menu",
|
||||
"name": "Omarchy menu",
|
||||
"version": "1.0.0",
|
||||
"author": "Omarchy",
|
||||
"description": "Quickshell-powered Omarchy command menu",
|
||||
"kinds": ["menu"],
|
||||
"activation": "on-demand",
|
||||
"keepLoaded": true,
|
||||
"entryPoints": { "menu": "Menu.qml" },
|
||||
"ipc": {
|
||||
"summon": "menu"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user