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 keys open the shortcuts assigned to that combination; unoccupied keys can be
sent directly to the creator. Change the physical layout from the keyboard sent directly to the creator. Change the physical layout from the keyboard
size selector while editing shortcuts, or set its default in plugin settings. 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. 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 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, "+") return table.concat(ordered, "+")
end 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 function expandedKeys(value)
local canonical = canonicalKey(value) local canonical = canonicalKey(value)
local first, last = canonical:match("^(%d)%-(%d)$") local first, last = canonical:match("^(%d)%-(%d)$")
@@ -341,6 +368,19 @@ local function keyCallback(id, code)
return callback return callback
end 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) local function contains(haystack, needle)
return string.find(normalized(haystack), needle, 1, true) ~= nil return string.find(normalized(haystack), needle, 1, true) ~= nil
end end
@@ -1059,6 +1099,17 @@ local function selectedKeyDetails(index)
local signature = activeModifierSignature() local signature = activeModifierSignature()
local entries = asArray(index.exact[signature .. "|" .. selectedKeyboardKey]) 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 = {} local chordParts = {}
for _, modifier in ipairs(MODIFIER_ORDER) do for _, modifier in ipairs(MODIFIER_ORDER) do
if activeModifiers[modifier] then if activeModifiers[modifier] then
@@ -1073,8 +1124,11 @@ local function selectedKeyDetails(index)
ui.row({ gap = 8, align = "center" }, { ui.row({ gap = 8, align = "center" }, {
ui.label({ text = chord, color = "on_surface", fontSize = 13, fontWeight = "bold", flexGrow = 1 }), ui.label({ text = chord, color = "on_surface", fontSize = 13, fontWeight = "bold", flexGrow = 1 }),
ui.label({ ui.label({
text = #entries > 0 and tr("panel.keyboard.occupied") or tr("panel.keyboard.free"), text = #entries > 0 and tr("panel.keyboard.occupied") or (
color = #entries > 0 and asString(cfg("category_color"), "primary") or "on_surface_variant", 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, fontSize = 11,
fontWeight = "bold", fontWeight = "bold",
}), }),
@@ -1082,11 +1136,26 @@ local function selectedKeyDetails(index)
} }
if #entries == 0 then if #entries == 0 then
children[#children + 1] = ui.label({ 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", color = "on_surface_variant",
fontSize = 11, fontSize = 11,
maxLines = 2, 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 else
for entryIndex, entry in ipairs(entries) do for entryIndex, entry in ipairs(entries) do
if entryIndex > 5 then if entryIndex > 5 then
+1 -1
View File
@@ -1,6 +1,6 @@
id = "blackbartblues/keymap" id = "blackbartblues/keymap"
name = "Keymap" name = "Keymap"
version = "1.3.5" version = "1.3.6"
plugin_api = 9 plugin_api = 9
author = "blackbartblues" author = "blackbartblues"
license = "MIT" license = "MIT"
+2
View File
@@ -289,6 +289,7 @@
"unknown": "The service returned an unknown error." "unknown": "The service returned an unknown error."
}, },
"keyboard": { "keyboard": {
"available_layers": "Used with",
"clear_modifiers": "Clear modifiers", "clear_modifiers": "Clear modifiers",
"free": "Free", "free": "Free",
"free_hint": "This combination is not used in the currently selected layer.", "free_hint": "This combination is not used in the currently selected layer.",
@@ -307,6 +308,7 @@
"no_modifiers": "No modifiers", "no_modifiers": "No modifiers",
"occupied": "Occupied", "occupied": "Occupied",
"other_layer": "Used on another layer", "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", "outside": "{count} shortcuts outside the keyboard view",
"select_hint": "Select modifiers, then click a key to inspect that combination.", "select_hint": "Select modifiers, then click a key to inspect that combination.",
"summary": "{layer}: {count} occupied keys", "summary": "{layer}: {count} occupied keys",