Label the keyboard widget with the xkb language code (#6699)
* Label the keyboard widget with the xkb language code The label was the first word of the layout description cut to three characters, so a US layout read ENG and a Portuguese one read POR. xkb already pairs every layout and variant with a short language code, which is the code GNOME shows in its own indicator. Read that table once at startup from xkbcli list and key it by description, which is what hyprctl reports as the active keymap, so the same layouts read EN and PT. The code is a language rather than a country, so it stays sensible for the layouts named after neither: Esperanto is EO, Arabic is AR, and Latin American Spanish is ES. Layouts missing from the table keep the old truncated description. * Read the exotic xkb rulesets for the keyboard label xkbcli list leaves out the exotic rulesets, so layouts like trans were missing from the table and fell back to the truncated description: the IPA layout read INT rather than IPA. Those layouts ship in the same xkeyboard-config package and set just as well, so read them too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Keep the keyboard label to three characters The brief was used verbatim while the fallback was truncated, but not every brief is two or three characters: Burmese (Zawgyi) is my-zwg and Shan (Zawgyi) is shn-zwg. Selecting either widened the widget past its neighbours on the bar. Drop the script suffix and cap the brief the same way the fallback is capped, so those read MY and SHN. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Stop an xkb brief carrying past its own block The brief was only cleared once a description consumed it, so a block printing a brief without one would hand its code to the next block's description and label it wrongly rather than falling back. Nothing in the current xkb data does that, and the option groups were skipped only because the last layout happened to consume its brief first. Clear the brief when a line starts a new block so the pairing is explicit, and cover the option list the 2-space match is what keeps out. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Fall back when a layout description names a built-in A custom xkb group called constructor or toString reached an inherited member of the lookup rather than a brief, and splitting it threw a TypeError that took the whole label binding down instead of falling back to the truncated description. Take the lookup only when it returns a string. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: David Heinemeier Hansson <david@hey.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
David Heinemeier Hansson
parent
5edc3497fa
commit
66f3155f0c
@@ -0,0 +1,62 @@
|
||||
// Label math for the keyboard layout widget, kept Qt-free so it can be unit
|
||||
// tested under node (test/shell.d/keyboard-layout-test.sh).
|
||||
|
||||
// xkbcli list prints YAML, and every layout and variant block pairs a brief with
|
||||
// the description hyprctl reports as the active keymap:
|
||||
//
|
||||
// - layout: 'us'
|
||||
// variant: ''
|
||||
// brief: 'en'
|
||||
// description: English (US)
|
||||
//
|
||||
// The models and option groups it also prints carry no brief of their own, and
|
||||
// a brief never carries past the block it was printed in, so neither reaches
|
||||
// the table.
|
||||
function layoutBriefs(text) {
|
||||
var briefs = {}
|
||||
var brief = ""
|
||||
|
||||
String(text || "").split("\n").forEach(function (line) {
|
||||
if (/^\s*- /.test(line)) brief = ""
|
||||
|
||||
var field = line.match(/^ (brief|description): (.*)$/)
|
||||
if (!field) return
|
||||
|
||||
if (field[1] === "brief") {
|
||||
brief = field[2].replace(/^'|'$/g, "")
|
||||
} else if (brief) {
|
||||
briefs[field[2]] = brief
|
||||
brief = ""
|
||||
}
|
||||
})
|
||||
|
||||
return briefs
|
||||
}
|
||||
|
||||
// The brief is a short language code rather than a country one, which keeps the
|
||||
// label sensible for the layouts named after a language: Esperanto reads EO and
|
||||
// Arabic reads AR. It is the same code GNOME shows in its own indicator.
|
||||
//
|
||||
// Layouts missing from the table fall back to the first word of the description,
|
||||
// which reads as ENG/POR but at least says something.
|
||||
//
|
||||
// Nearly every brief is a bare two-letter code, but a few tack a script onto it
|
||||
// (Burmese (Zawgyi) is my-zwg) and the custom layout's is a word, so drop the
|
||||
// script and cap the result at the same three characters the fallback gets.
|
||||
// The widget sits between fixed neighbours on the bar and has no room to grow.
|
||||
function shortLabel(description, briefs) {
|
||||
if (!description) return ""
|
||||
|
||||
// A description like "constructor" reaches an inherited member rather than a
|
||||
// brief, so take the lookup only when it hands back the string it promises.
|
||||
var brief = (briefs || {})[description]
|
||||
var label = typeof brief === "string" && brief ? brief.split("-")[0] : description.split(/\s+/)[0]
|
||||
return label.substring(0, 3).toUpperCase()
|
||||
}
|
||||
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = {
|
||||
layoutBriefs: layoutBriefs,
|
||||
shortLabel: shortLabel
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user