#!/bin/bash

# A script to display Hyprland keybindings defined in your configuration
#
# original script from omarchy

# Fetch dynamic keybindings from Hyprland
#
# Also do some pre-processing:
# - Remove standard Omarchy bin path prefix
# - Remove uwsm prefix
# - Map numeric modifier key mask to a textual rendition
# - Output comma-separated values that the parser can understand
dynamic_bindings() {
  hyprctl -j binds | \
      jq -r '.[] | {modmask, key, keycode, description, dispatcher, arg, submap} | "\(.modmask),\(.key)@\(.keycode),\(.description),\(.dispatcher),\(.arg),\(.submap)"' | \
    sed -E \
        -e 's/null//' \
        -e 's,uwsm app -- ,,' \
        -e 's|exec,.*/([^/]*)|exec,\1|' \
        -e 's/@0//' \
        -e 's/,@/,code:/' \
        -e 's/^0,/,/' \
        -e 's/^1,/SHIFT,/' \
        -e 's/^4,/CTRL,/' \
        -e 's/^5,/SHIFT + CTRL,/' \
        -e 's/^8,/ALT,/' \
        -e 's/^9,/SHIFT + ALT,/' \
        -e 's/^12,/CTRL + ALT,/' \
        -e 's/^13,/SHIFT + CTRL + ALT,/' \
        -e 's/^64,/SUPER,/' \
        -e 's/^65,/SUPER + SHIFT,/' \
        -e 's/^68,/SUPER + CTRL,/' \
        -e 's/^69,/SUPER + SHIFT + CTRL,/' \
        -e 's/^72,/SUPER + ALT,/' \
        -e 's/^73,/SUPER + SHIFT + ALT,/' \
        -e 's/^76,/SUPER + CTRL + ALT,/' \
        -e 's/^77,/HYPR,/'
}

# Parse and format keybindings
#
# `awk` does the heavy lifting:
# - Set the field separator to a comma ','.
# - Joins the key combination (e.g., "SUPER + Q").
# - Joins the command that the key executes.
# - Prints everything in a nicely aligned format.
parse_bindings() {
  awk -F, '
{
    # Combine the modifier and key (first two fields)
    key_combo = $1 " + " $2;

    # Clean up: strip leading "+" if present, trim spaces
    gsub(/^[ \t]*\+?[ \t]*/, "", key_combo);
    gsub(/[ \t]+$/, "", key_combo);

    # Use description, if set
    action = $3;
    submenu = $NF;

    if (action == "") {
        # Reconstruct the command from the remaining fields
        for (i = 4; i <= NF - 1; i++) {
            action = action $i (i < NF ? "," : "");
        }

        # Clean up trailing commas, remove leading "exec, ", and trim
        sub(/,$/, "", action);
        gsub(/(^|,)[[:space:]]*exec[[:space:]]*,?/, "", action);
        gsub(/^[ \t]+|[ \t]+$/, "", action);
        gsub(/[ \t]+/, " ", key_combo);  # Collapse multiple spaces to one

        # Escape XML entities
        gsub(/&/, "\\&amp;", action);
        gsub(/</, "\\&lt;", action);
        gsub(/>/, "\\&gt;", action);
        gsub(/"/, "\\&quot;", action);
        gsub(/'"'"'/, "\\&apos;", action);
    }

    if (action != "") {
        if (submenu != "") {
            printf "%-10s | %-22s → %s\n", submenu, key_combo, action;
        } else {
            printf "%-35s → %s\n", key_combo, action;
        }
    }
}'
}

dynamic_bindings | parse_bindings | sort -u
