diff --git a/crates/television/cable.rs b/crates/television/cable.rs index 516a4a5..480540d 100644 --- a/crates/television/cable.rs +++ b/crates/television/cable.rs @@ -24,6 +24,8 @@ const DEFAULT_CABLE_CHANNELS: &str = const DEFAULT_CABLE_CHANNELS: &str = include_str!("../../cable/windows-channels.toml"); +const DEFAULT_CABLE_CHANNELS_FILE_NAME: &str = "default_channels.toml"; + /// Load the cable configuration from the config directory. /// /// Cable is loaded by compiling all files that match the following @@ -45,16 +47,7 @@ pub fn load_cable_channels() -> Result { // filter the files that match the pattern let file_paths = files .filter_map(|f| f.ok().map(|f| f.path())) - .filter(|p| { - p.extension() - .and_then(|e| e.to_str()) - .map_or(false, |e| e.to_lowercase() == CABLE_FILE_FORMAT) - }) - .filter(|p| { - p.file_stem() - .and_then(|s| s.to_str()) - .map_or(false, |s| s.ends_with(CABLE_FILE_NAME_SUFFIX)) - }); + .filter(|p| is_cable_file_format(p) && p.is_file()); let user_defined_prototypes = file_paths.fold(Vec::new(), |mut acc, p| { let r: ChannelPrototypes = toml::from_str( @@ -66,21 +59,48 @@ pub fn load_cable_channels() -> Result { acc }); + // If no user defined prototypes are found, write the default prototypes for the current + // platform to the config directory + if user_defined_prototypes.is_empty() { + debug!("No user defined cable channels found"); + // write the default cable channels to the config directory + let default_channels_path = + config_dir.join(DEFAULT_CABLE_CHANNELS_FILE_NAME); + std::fs::write(default_channels_path, DEFAULT_CABLE_CHANNELS)?; + } + debug!("Loaded cable channels: {:?}", user_defined_prototypes); - let default_prototypes: ChannelPrototypes = - toml::from_str(DEFAULT_CABLE_CHANNELS) - .expect("Unable to parse default cable channels"); - let mut cable_channels = HashMap::new(); - // chaining default with user defined prototypes so that users may override the - // default prototypes - for prototype in default_prototypes - .prototypes - .into_iter() - .chain(user_defined_prototypes) - { + for prototype in user_defined_prototypes { cable_channels.insert(prototype.name.clone(), prototype); } Ok(CableChannels(cable_channels)) } + +fn is_cable_file_format

(p: P) -> bool +where + P: AsRef, +{ + let p = p.as_ref(); + p.file_stem() + .and_then(|s| s.to_str()) + .map_or(false, |s| s.ends_with(CABLE_FILE_NAME_SUFFIX)) + && p.extension() + .and_then(|e| e.to_str()) + .map_or(false, |e| e.to_lowercase() == CABLE_FILE_FORMAT) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_is_cable_file() { + let path = std::path::Path::new("cable_channels.toml"); + assert!(is_cable_file_format(path)); + + let path = std::path::Path::new(DEFAULT_CABLE_CHANNELS_FILE_NAME); + assert!(is_cable_file_format(path)); + } +}