fix(keymap): make modifier layers discoverable (#249)

This commit is contained in:
blacku
2026-08-07 22:23:24 -04:00
committed by GitHub
parent d59cdacd4f
commit 6460c1a481
4 changed files with 77 additions and 4 deletions
+2
View File
@@ -102,6 +102,8 @@ In keyboard view, enable an exact Super, Ctrl, Shift, and Alt layer. Occupied
keys open the shortcuts assigned to that combination; unoccupied keys can be
sent directly to the creator. Change the physical layout from the keyboard
size selector while editing shortcuts, or set its default in plugin settings.
When a key is occupied in another modifier layer, select it and use the layer
buttons in the details card to jump directly to the matching combination.
In list view, type into the search box to filter the complete category tree.
Sequential shortcuts such as workspaces 1 through 9 can optionally be folded
+72 -3
View File
@@ -286,6 +286,33 @@ local function activeModifierSignature()
return table.concat(ordered, "+")
end
local function modifierSignatureLabel(signature)
if signature == "" then return tr("panel.keyboard.no_modifiers") end
local labels = {}
for modifier in tostring(signature):gmatch("[^+]+") do
labels[#labels + 1] = modifier == "CTRL" and "Ctrl"
or (modifier == "SUPER" and "Super" or (modifier == "SHIFT" and "Shift" or (
modifier == "ALT" and "Alt" or modifier
)))
end
return table.concat(labels, " + ")
end
local function modifierSignatureSelectable(signature)
for modifier in tostring(signature):gmatch("[^+]+") do
if activeModifiers[modifier] == nil then return false end
end
return true
end
local function selectModifierSignature(signature)
local selected = {}
for modifier in tostring(signature):gmatch("[^+]+") do selected[modifier] = true end
for _, modifier in ipairs(MODIFIER_ORDER) do
activeModifiers[modifier] = selected[modifier] == true
end
end
local function expandedKeys(value)
local canonical = canonicalKey(value)
local first, last = canonical:match("^(%d)%-(%d)$")
@@ -341,6 +368,19 @@ local function keyCallback(id, code)
return callback
end
local layerCallbackCache = {}
local function layerCallback(signature)
local callback = layerCallbackCache[signature]
if callback == nil then
callback = function()
selectModifierSignature(signature)
render()
end
layerCallbackCache[signature] = callback
end
return callback
end
local function contains(haystack, needle)
return string.find(normalized(haystack), needle, 1, true) ~= nil
end
@@ -1059,6 +1099,17 @@ local function selectedKeyDetails(index)
local signature = activeModifierSignature()
local entries = asArray(index.exact[signature .. "|" .. selectedKeyboardKey])
local otherSignatures = {}
local seenSignatures = {}
for _, entry in ipairs(asArray(index.any[selectedKeyboardKey])) do
local entrySignature = modifierSignature(entry.bind.modifiers)
if entrySignature ~= signature and not seenSignatures[entrySignature] then
seenSignatures[entrySignature] = true
otherSignatures[#otherSignatures + 1] = entrySignature
end
end
table.sort(otherSignatures)
local usedOnAnotherLayer = #entries == 0 and #otherSignatures > 0
local chordParts = {}
for _, modifier in ipairs(MODIFIER_ORDER) do
if activeModifiers[modifier] then
@@ -1073,8 +1124,11 @@ local function selectedKeyDetails(index)
ui.row({ gap = 8, align = "center" }, {
ui.label({ text = chord, color = "on_surface", fontSize = 13, fontWeight = "bold", flexGrow = 1 }),
ui.label({
text = #entries > 0 and tr("panel.keyboard.occupied") or tr("panel.keyboard.free"),
color = #entries > 0 and asString(cfg("category_color"), "primary") or "on_surface_variant",
text = #entries > 0 and tr("panel.keyboard.occupied") or (
usedOnAnotherLayer and tr("panel.keyboard.other_layer") or tr("panel.keyboard.free")
),
color = (#entries > 0 or usedOnAnotherLayer)
and asString(cfg("category_color"), "primary") or "on_surface_variant",
fontSize = 11,
fontWeight = "bold",
}),
@@ -1082,11 +1136,26 @@ local function selectedKeyDetails(index)
}
if #entries == 0 then
children[#children + 1] = ui.label({
text = tr("panel.keyboard.free_hint"),
text = tr(usedOnAnotherLayer and "panel.keyboard.other_layer_hint" or "panel.keyboard.free_hint"),
color = "on_surface_variant",
fontSize = 11,
maxLines = 2,
})
if usedOnAnotherLayer then
local layerButtons = {
ui.label({ text = tr("panel.keyboard.available_layers"), color = "on_surface_variant", fontSize = 10 }),
}
for _, otherSignature in ipairs(otherSignatures) do
layerButtons[#layerButtons + 1] = ui.button({
text = modifierSignatureLabel(otherSignature),
variant = "outline",
controlSize = "sm",
enabled = modifierSignatureSelectable(otherSignature),
onClick = layerCallback(otherSignature),
})
end
children[#children + 1] = ui.row({ gap = 6, align = "center" }, layerButtons)
end
else
for entryIndex, entry in ipairs(entries) do
if entryIndex > 5 then
+1 -1
View File
@@ -1,6 +1,6 @@
id = "blackbartblues/keymap"
name = "Keymap"
version = "1.3.5"
version = "1.3.6"
plugin_api = 9
author = "blackbartblues"
license = "MIT"
+2
View File
@@ -289,6 +289,7 @@
"unknown": "The service returned an unknown error."
},
"keyboard": {
"available_layers": "Used with",
"clear_modifiers": "Clear modifiers",
"free": "Free",
"free_hint": "This combination is not used in the currently selected layer.",
@@ -307,6 +308,7 @@
"no_modifiers": "No modifiers",
"occupied": "Occupied",
"other_layer": "Used on another layer",
"other_layer_hint": "This key is assigned with different modifiers. Choose a layer below to view its shortcuts.",
"outside": "{count} shortcuts outside the keyboard view",
"select_hint": "Select modifiers, then click a key to inspect that combination.",
"summary": "{layer}: {count} occupied keys",