Merge branch 'fallbacks' into 'master'

layouts: Simplify fallbackss handling

See merge request Librem5/squeekboard!221
This commit is contained in:
Dorota Czaplejewicz
2019-10-22 13:25:15 +00:00

View File

@ -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()),
)
); );
} }