Two variants:
* Czech Standard (= qwertz)
* Czech qwerty
The accented letters layout corresponds to the UCW [1] layout shipped
with xkb, so we follow this precedent.
Like the DE layout, and unlike the US layout, the CZ layout has a
comma key and a narrower space bar. The added comma key also serves as
a visual balance to the added accents key, to keep the spacebar
centered.
The layouts have been tested manually on PinePhone.
[1] c60b77ea51/test/data/symbols/cz (L180)
163 lines
5.2 KiB
Rust
163 lines
5.2 KiB
Rust
/*! Statically linked resources.
|
|
* This could be done using GResource, but that would need additional work.
|
|
*/
|
|
|
|
use std::collections::HashMap;
|
|
use ::locale::Translation;
|
|
|
|
use std::iter::FromIterator;
|
|
|
|
// TODO: keep a list of what is a language layout,
|
|
// and what a convenience layout. "_wide" is not a layout,
|
|
// neither is "number"
|
|
const KEYBOARDS: &[(*const str, *const str)] = &[
|
|
// layouts: us must be left as first, as it is the,
|
|
// fallback layout. The others should be alphabetical.
|
|
("us", include_str!("../data/keyboards/us.yaml")),
|
|
("us_wide", include_str!("../data/keyboards/us_wide.yaml")),
|
|
("br", include_str!("../data/keyboards/br.yaml")),
|
|
("de", include_str!("../data/keyboards/de.yaml")),
|
|
("be", include_str!("../data/keyboards/be.yaml")),
|
|
("be_wide", include_str!("../data/keyboards/be_wide.yaml")),
|
|
("de_wide", include_str!("../data/keyboards/de_wide.yaml")),
|
|
("cz", include_str!("../data/keyboards/cz.yaml")),
|
|
("cz_wide", include_str!("../data/keyboards/cz_wide.yaml")),
|
|
("cz+qwerty", include_str!("../data/keyboards/cz+qwerty.yaml")),
|
|
("cz+qwerty_wide", include_str!("../data/keyboards/cz+qwerty_wide.yaml")),
|
|
("dk", include_str!("../data/keyboards/dk.yaml")),
|
|
("es", include_str!("../data/keyboards/es.yaml")),
|
|
("fi", include_str!("../data/keyboards/fi.yaml")),
|
|
("fr", include_str!("../data/keyboards/fr.yaml")),
|
|
("fr_wide", include_str!("../data/keyboards/fr_wide.yaml")),
|
|
("it+fur", include_str!("../data/keyboards/it+fur.yaml")),
|
|
("gr", include_str!("../data/keyboards/gr.yaml")),
|
|
("it", include_str!("../data/keyboards/it.yaml")),
|
|
("jp+kana", include_str!("../data/keyboards/jp+kana.yaml")),
|
|
("jp+kana_wide", include_str!("../data/keyboards/jp+kana_wide.yaml")),
|
|
("no", include_str!("../data/keyboards/no.yaml")),
|
|
("number", include_str!("../data/keyboards/number.yaml")),
|
|
("pl", include_str!("../data/keyboards/pl.yaml")),
|
|
("pl_wide", include_str!("../data/keyboards/pl_wide.yaml")),
|
|
("ru", include_str!("../data/keyboards/ru.yaml")),
|
|
("se", include_str!("../data/keyboards/se.yaml")),
|
|
("th", include_str!("../data/keyboards/th.yaml")),
|
|
("ua", include_str!("../data/keyboards/ua.yaml")),
|
|
// layout+overlay
|
|
("terminal", include_str!("../data/keyboards/terminal.yaml")),
|
|
("terminal_wide", include_str!("../data/keyboards/terminal_wide.yaml")),
|
|
// Overlays
|
|
("emoji", include_str!("../data/keyboards/emoji.yaml")),
|
|
];
|
|
|
|
pub fn get_keyboard(needle: &str) -> Option<&'static str> {
|
|
// Need to dereference in unsafe code
|
|
// comparing *const str to &str will compare pointers
|
|
KEYBOARDS.iter()
|
|
.find(|(name, _)| {
|
|
let name: *const str = *name;
|
|
(unsafe { &*name }) == needle
|
|
})
|
|
.map(|(_, value)| {
|
|
let value: *const str = *value;
|
|
unsafe { &*value }
|
|
})
|
|
}
|
|
|
|
const OVERLAY_NAMES: &[*const str] = &[
|
|
"emoji",
|
|
"terminal",
|
|
];
|
|
|
|
pub fn get_overlays() -> Vec<&'static str> {
|
|
OVERLAY_NAMES.iter()
|
|
.map(|name| {
|
|
let name: *const str = *name;
|
|
unsafe { &*name }
|
|
}).collect()
|
|
}
|
|
|
|
/// Translations of the layout identifier strings
|
|
const LAYOUT_NAMES: &[(*const str, *const str)] = &[
|
|
("de-DE", include_str!("../data/langs/de-DE.txt")),
|
|
("en-US", include_str!("../data/langs/en-US.txt")),
|
|
("es-ES", include_str!("../data/langs/es-ES.txt")),
|
|
("fur-IT", include_str!("../data/langs/fur-IT.txt")),
|
|
("ja-JP", include_str!("../data/langs/ja-JP.txt")),
|
|
("pl-PL", include_str!("../data/langs/pl-PL.txt")),
|
|
("ru-RU", include_str!("../data/langs/ru-RU.txt")),
|
|
];
|
|
|
|
pub fn get_layout_names(lang: &str)
|
|
-> Option<HashMap<&'static str, Translation<'static>>>
|
|
{
|
|
let translations = LAYOUT_NAMES.iter()
|
|
.find(|(name, _data)| {
|
|
let name: *const str = *name;
|
|
(unsafe { &*name }) == lang
|
|
})
|
|
.map(|(_name, data)| {
|
|
let data: *const str = *data;
|
|
unsafe { &*data }
|
|
});
|
|
translations.map(make_mapping)
|
|
}
|
|
|
|
fn parse_line(line: &str) -> Option<(&str, Translation)> {
|
|
let comment = line.trim().starts_with("#");
|
|
if comment {
|
|
None
|
|
} else {
|
|
let mut iter = line.splitn(2, " ");
|
|
let name = iter.next().unwrap();
|
|
// will skip empty and unfinished lines
|
|
iter.next().map(|tr| (name, Translation(tr.trim())))
|
|
}
|
|
}
|
|
|
|
fn make_mapping(data: &str) -> HashMap<&str, Translation> {
|
|
HashMap::from_iter(
|
|
data.split("\n")
|
|
.filter_map(parse_line)
|
|
)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn check_overlays_present() {
|
|
for name in get_overlays() {
|
|
assert!(get_keyboard(name).is_some());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn mapping_line() {
|
|
assert_eq!(
|
|
Some(("name", Translation("translation"))),
|
|
parse_line("name translation")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn mapping_bad() {
|
|
assert_eq!(None, parse_line("bad"));
|
|
}
|
|
|
|
#[test]
|
|
fn mapping_empty() {
|
|
assert_eq!(None, parse_line(""));
|
|
}
|
|
|
|
#[test]
|
|
fn mapping_comment() {
|
|
assert_eq!(None, parse_line("# comment"));
|
|
}
|
|
|
|
#[test]
|
|
fn mapping_comment_offset() {
|
|
assert_eq!(None, parse_line(" # comment"));
|
|
}
|
|
}
|