Merge branch 'fallbacks' into 'master'
layouts: Simplify fallbackss handling See merge request Librem5/squeekboard!221
This commit is contained in:
145
src/data.rs
145
src/data.rs
@ -68,7 +68,7 @@ impl fmt::Display for LoadError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
enum DataSource {
|
enum DataSource {
|
||||||
File(PathBuf),
|
File(PathBuf),
|
||||||
Resource(String),
|
Resource(String),
|
||||||
@ -83,72 +83,44 @@ impl fmt::Display for DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to load the layout from the first place where it's present.
|
/// Lists possible sources, with 0 as the most preferred one
|
||||||
/// If the layout exists, but is broken, fallback is activated.
|
fn list_layout_sources(
|
||||||
fn load_layout(
|
|
||||||
name: &str,
|
name: &str,
|
||||||
keyboards_path: Option<PathBuf>,
|
keyboards_path: Option<PathBuf>
|
||||||
) -> (
|
) -> Vec<DataSource> {
|
||||||
Result<::layout::Layout, LoadError>, // last attempted
|
let mut ret = Vec::new();
|
||||||
DataSource, // last attempt source
|
if let Some(path) = keyboards_path.clone() {
|
||||||
Option<(LoadError, DataSource)>, // first attempt source
|
ret.push(DataSource::File(path.join(name).with_extension("yaml")))
|
||||||
) {
|
}
|
||||||
let path = keyboards_path.map(|path|
|
|
||||||
path.join(name).with_extension("yaml")
|
ret.push(DataSource::Resource(name.to_owned()));
|
||||||
);
|
|
||||||
|
|
||||||
let layout = match path {
|
if let Some(path) = keyboards_path.clone() {
|
||||||
Some(path) => Some((
|
ret.push(DataSource::File(
|
||||||
|
path.join(FALLBACK_LAYOUT_NAME).with_extension("yaml")
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push(DataSource::Resource(FALLBACK_LAYOUT_NAME.to_owned()));
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_layout(source: DataSource) -> Result<::layout::Layout, LoadError> {
|
||||||
|
match source {
|
||||||
|
DataSource::File(path) => {
|
||||||
Layout::from_file(path.clone())
|
Layout::from_file(path.clone())
|
||||||
.map_err(LoadError::BadData)
|
.map_err(LoadError::BadData)
|
||||||
.and_then(|layout|
|
.and_then(|layout|
|
||||||
layout.build().map_err(LoadError::BadKeyMap)
|
layout.build().map_err(LoadError::BadKeyMap)
|
||||||
),
|
)
|
||||||
DataSource::File(path),
|
},
|
||||||
)),
|
DataSource::Resource(name) => {
|
||||||
None => None, // No env var, not an error
|
Layout::from_resource(&name)
|
||||||
};
|
|
||||||
|
|
||||||
let (failed_attempt, layout) = match layout {
|
|
||||||
Some((Ok(layout), path)) => (None, Some((layout, path))),
|
|
||||||
Some((Err(e), path)) => (Some((e, path)), None),
|
|
||||||
None => (None, None),
|
|
||||||
};
|
|
||||||
|
|
||||||
let (layout, source) = match layout {
|
|
||||||
Some((layout, path)) => (Ok(layout), path),
|
|
||||||
None => (
|
|
||||||
Layout::from_resource(name)
|
|
||||||
.and_then(|layout|
|
.and_then(|layout|
|
||||||
layout.build().map_err(LoadError::BadKeyMap)
|
layout.build().map_err(LoadError::BadKeyMap)
|
||||||
),
|
)
|
||||||
DataSource::Resource(name.into()),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
(layout, source, failed_attempt)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn log_attempt_info(attempt: Option<(LoadError, DataSource)>) {
|
|
||||||
match attempt {
|
|
||||||
Some((
|
|
||||||
LoadError::BadData(Error::Missing(e)),
|
|
||||||
DataSource::File(file)
|
|
||||||
)) => {
|
|
||||||
eprintln!(
|
|
||||||
"Tried file {:?}, but it's missing: {}",
|
|
||||||
file, e
|
|
||||||
);
|
|
||||||
// Missing file, not to worry. TODO: print in debug logging level
|
|
||||||
},
|
},
|
||||||
Some((e, source)) => {
|
}
|
||||||
eprintln!(
|
|
||||||
"Failed to load layout from {}: {}, trying builtin",
|
|
||||||
source, e
|
|
||||||
);
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_layout_with_fallback(
|
fn load_layout_with_fallback(
|
||||||
@ -158,36 +130,27 @@ fn load_layout_with_fallback(
|
|||||||
.map(PathBuf::from)
|
.map(PathBuf::from)
|
||||||
.or_else(|| xdg::data_path("squeekboard/keyboards"));
|
.or_else(|| xdg::data_path("squeekboard/keyboards"));
|
||||||
|
|
||||||
let (layout, source, attempt) = load_layout(name, path.clone());
|
for source in list_layout_sources(name, path) {
|
||||||
|
let layout = load_layout(source.clone());
|
||||||
log_attempt_info(attempt);
|
match layout {
|
||||||
|
Err(e) => match (e, source) {
|
||||||
let (layout, source, attempt) = match (layout, source) {
|
(
|
||||||
(Err(e), source) => {
|
LoadError::BadData(Error::Missing(e)),
|
||||||
eprintln!(
|
DataSource::File(file)
|
||||||
"Failed to load layout from {}: {}, using fallback",
|
) => eprintln!( // TODO: print in debug logging level
|
||||||
source, e
|
"Tried file {:?}, but it's missing: {}",
|
||||||
);
|
file, e
|
||||||
load_layout(FALLBACK_LAYOUT_NAME, path)
|
),
|
||||||
},
|
(e, source) => eprintln!(
|
||||||
(res, source) => (res, source, None),
|
"Failed to load layout from {}: {}, skipping",
|
||||||
};
|
|
||||||
|
|
||||||
log_attempt_info(attempt);
|
|
||||||
|
|
||||||
match (layout, source) {
|
|
||||||
(Err(e), source) => {
|
|
||||||
panic!(
|
|
||||||
format!("Failed to load hardcoded layout from {}: {:?}",
|
|
||||||
source, e
|
source, e
|
||||||
)
|
),
|
||||||
);
|
},
|
||||||
},
|
Ok(layout) => return layout,
|
||||||
(Ok(layout), source) => {
|
|
||||||
eprintln!("Loaded layout from {}", source);
|
|
||||||
layout
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panic!("No useful layout found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The root element describing an entire keyboard
|
/// The root element describing an entire keyboard
|
||||||
@ -700,14 +663,14 @@ mod tests {
|
|||||||
/// First fallback should be to builtin, not to FALLBACK_LAYOUT_NAME
|
/// First fallback should be to builtin, not to FALLBACK_LAYOUT_NAME
|
||||||
#[test]
|
#[test]
|
||||||
fn fallbacks_order() {
|
fn fallbacks_order() {
|
||||||
let (_layout, source, _failure) = load_layout(
|
let sources = list_layout_sources("nb", None);
|
||||||
"nb",
|
|
||||||
Some(PathBuf::from("tests"))
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
source,
|
sources,
|
||||||
load_layout("nb", None).1
|
vec!(
|
||||||
|
DataSource::Resource("nb".into()),
|
||||||
|
DataSource::Resource(FALLBACK_LAYOUT_NAME.into()),
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user