extern crate yaml_rust;
mod configparser;
use configparser::ConfigParser;
use std::collections::HashMap;
use std::fmt;
use yaml_rust::{Yaml, YamlLoader};
use std::path::PathBuf;
#[derive(Clone)]
pub struct Config {
pub language: String,
pub shell_config: ShellConfig,
pub alias: HashMap<String, String>,
pub output_config: OutputConfig,
pub prompt_config: PromptConfig,
}
#[derive(Clone)]
pub struct ShellConfig {
pub exec: String,
pub args: Vec<String>
}
#[derive(Clone)]
pub struct OutputConfig {
pub translate_output: bool,
}
#[derive(Clone)]
pub struct PromptConfig {
pub prompt_line: String,
pub history_size: usize,
pub translate: bool,
pub break_enabled: bool,
pub break_str: String,
pub min_duration: usize,
pub rc_ok: String,
pub rc_err: String,
pub git_branch: String,
pub git_commit_ref: usize,
pub git_commit_prepend: Option<String>,
pub git_commit_append: Option<String>
}
#[derive(Copy, Clone, PartialEq, fmt::Debug)]
pub enum ConfigErrorCode {
NoSuchFileOrDirectory,
CouldNotReadFile,
YamlSyntaxError,
}
pub struct ConfigError {
pub code: ConfigErrorCode,
pub message: String,
}
impl fmt::Display for ConfigErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let code_str: &str = match self {
ConfigErrorCode::NoSuchFileOrDirectory => "NoSuchFileOrDirectory",
ConfigErrorCode::CouldNotReadFile => "CouldNotReadFile",
ConfigErrorCode::YamlSyntaxError => "YamlSyntaxError",
};
write!(f, "{}", code_str)
}
}
impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} ({})", self.message, self.code)
}
}
impl Config {
pub fn default() -> Config {
let alias_config: HashMap<String, String> = HashMap::new();
Config {
language: String::from("ru"),
shell_config: ShellConfig::default(),
alias: alias_config,
output_config: OutputConfig::default(),
prompt_config: PromptConfig::default(),
}
}
pub fn parse_config(config_file: PathBuf) -> Result<Config, ConfigError> {
let config_str: String = match std::fs::read_to_string(config_file.clone()) {
Ok(config) => config,
Err(err) => match err.kind() {
std::io::ErrorKind::NotFound => {
return Err(ConfigError {
code: ConfigErrorCode::NoSuchFileOrDirectory,
message: format!("No such file or directory: {}", config_file.display()),
})
}
_ => {
return Err(ConfigError {
code: ConfigErrorCode::CouldNotReadFile,
message: format!("Could not read file {}", config_file.display())
})
}
},
};
Config::parse_config_str(config_str)
}
fn parse_config_str(config: String) -> Result<Config, ConfigError> {
let yaml_docs: Vec<Yaml> = match YamlLoader::load_from_str(config.as_str()) {
Ok(doc) => doc,
Err(_) => {
return Err(ConfigError {
code: ConfigErrorCode::YamlSyntaxError,
message: String::from("Configuration is not a valid YAML"),
});
}
};
if yaml_docs.len() == 0 {
return Err(ConfigError {
code: ConfigErrorCode::YamlSyntaxError,
message: String::from("File does not contain any YAML document"),
});
};
let yaml_doc: &Yaml = &yaml_docs[0];
let language: String = match ConfigParser::get_child(&yaml_doc, String::from("language")) {
Ok(node) => match Config::parse_language(&node) {
Ok(l) => l,
Err(err) => return Err(err),
},
Err(_) => String::from("ru"),
};
let alias_config: HashMap<String, String> = match ConfigParser::get_child(&yaml_doc, String::from("alias")) {
Ok(node) => match Config::parse_alias(&node) {
Ok(cfg) => cfg,
Err(err) => return Err(err),
},
Err(_) => HashMap::new(),
};
let shell_config: ShellConfig = match ConfigParser::get_child(&yaml_doc, String::from("shell")) {
Ok(node) => match ShellConfig::parse_config(&node) {
Ok(cfg) => cfg,
Err(err) => return Err(err)
},
Err(_) => ShellConfig::default()
};
let output_config: OutputConfig =
match ConfigParser::get_child(&yaml_doc, String::from("output")) {
Ok(node) => match OutputConfig::parse_config(&node) {
Ok(config) => config,
Err(err) => return Err(err),
},
Err(_) => OutputConfig::default(),
};
let prompt_config: PromptConfig =
match ConfigParser::get_child(&yaml_doc, String::from("prompt")) {
Ok(node) => match PromptConfig::parse_config(&node) {
Ok(config) => config,
Err(err) => return Err(err),
},
Err(_) => PromptConfig::default(),
};
Ok(Config {
language: language,
shell_config: shell_config,
alias: alias_config,
output_config: output_config,
prompt_config: prompt_config,
})
}
pub fn get_alias(&self, alias: &String) -> Option<String> {
match self.alias.get(alias) {
Some(cmd) => Some(cmd.clone()),
None => None,
}
}
fn parse_alias(alias_yaml: &Yaml) -> Result<HashMap<String, String>, ConfigError> {
if !alias_yaml.is_array() {
return Err(ConfigError {
code: ConfigErrorCode::YamlSyntaxError,
message: String::from("'alias' key is not an array"),
});
}
let mut alias_table: HashMap<String, String> = HashMap::new();
for pair in alias_yaml.as_vec().unwrap() {
for p in pair.as_hash().unwrap().iter() {
let key: String = String::from(p.0.as_str().unwrap());
let value: String = String::from(p.1.as_str().unwrap());
alias_table.insert(key, value);
}
}
Ok(alias_table)
}
fn parse_language(language_yaml: &Yaml) -> Result<String, ConfigError> {
match language_yaml.as_str() {
Some(s) => Ok(String::from(s)),
None => Err(ConfigError {
code: ConfigErrorCode::YamlSyntaxError,
message: String::from("'language' is not a string"),
}),
}
}
}
impl ShellConfig {
pub fn default() -> ShellConfig {
ShellConfig {
exec: String::from("bash"),
args: vec![]
}
}
pub fn parse_config(shell_yaml: &Yaml) -> Result<ShellConfig, ConfigError> {
let exec: String = match ConfigParser::get_string(&shell_yaml, String::from("exec")) {
Ok(s) => s,
Err(err) => return Err(err)
};
let args: Vec<String> = match ConfigParser::get_child(&shell_yaml, String::from("args")) {
Ok(args_yaml) => {
let mut args: Vec<String> = Vec::new();
for arg in args_yaml.as_vec().unwrap() {
args.push(match arg.as_str() {
Some(s) => String::from(s),
None => return Err(ConfigError {code: ConfigErrorCode::YamlSyntaxError, message: String::from("Shell arg is not a string")})
});
}
args
},
Err(_) => Vec::new()
};
Ok(ShellConfig {
exec: exec,
args: args
})
}
}
impl OutputConfig {
pub fn default() -> OutputConfig {
OutputConfig {
translate_output: true,
}
}
pub fn parse_config(output_yaml: &Yaml) -> Result<OutputConfig, ConfigError> {
let translate_output: bool =
match ConfigParser::get_bool(&output_yaml, String::from("translate")) {
Ok(t) => t,
Err(err) => return Err(err),
};
Ok(OutputConfig {
translate_output: translate_output,
})
}
}
impl PromptConfig {
pub fn default() -> PromptConfig {
PromptConfig {
prompt_line: String::from("${USER}@${HOSTNAME}:${WRKDIR}$"),
history_size: 256,
translate: false,
break_enabled: false,
break_str: String::from("❯"),
min_duration: 2000,
rc_ok: String::from("✔"),
rc_err: String::from("✖"),
git_branch: String::from("on "),
git_commit_ref: 8,
git_commit_append: None,
git_commit_prepend: None
}
}
pub fn parse_config(prompt_config_yaml: &Yaml) -> Result<PromptConfig, ConfigError> {
let prompt_line: String =
match ConfigParser::get_string(&prompt_config_yaml, String::from("prompt_line")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let history_size: usize =
match ConfigParser::get_usize(&prompt_config_yaml, String::from("history_size")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let translate: bool =
match ConfigParser::get_bool(&prompt_config_yaml, String::from("translate")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let brk: &Yaml = match ConfigParser::get_child(&prompt_config_yaml, String::from("break")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let break_enabled: bool = match ConfigParser::get_bool(&brk, String::from("enabled")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let break_str: String = match ConfigParser::get_string(&brk, String::from("with")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let duration: &Yaml =
match ConfigParser::get_child(&prompt_config_yaml, String::from("duration")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let min_duration: usize =
match ConfigParser::get_usize(&duration, String::from("min_elapsed_time")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let rc: &Yaml = match ConfigParser::get_child(&prompt_config_yaml, String::from("rc")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let rc_ok: String = match ConfigParser::get_string(&rc, String::from("ok")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let rc_err: String = match ConfigParser::get_string(&rc, String::from("error")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let git: &Yaml = match ConfigParser::get_child(&prompt_config_yaml, String::from("git")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let git_branch: String = match ConfigParser::get_string(&git, String::from("branch")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let git_commit_ref: usize =
match ConfigParser::get_usize(&git, String::from("commit_ref_len")) {
Ok(ret) => ret,
Err(err) => return Err(err),
};
let git_commit_prepend: Option<String> =
match ConfigParser::get_string(&git, String::from("commit_prepend")) {
Ok(ret) => Some(ret),
Err(_) => None,
};
let git_commit_append: Option<String> =
match ConfigParser::get_string(&git, String::from("commit_append")) {
Ok(ret) => Some(ret),
Err(_) => None,
};
Ok(PromptConfig {
prompt_line: prompt_line,
history_size: history_size,
translate: translate,
break_enabled: break_enabled,
break_str: break_str,
min_duration: min_duration,
rc_ok: rc_ok,
rc_err: rc_err,
git_branch: git_branch,
git_commit_ref: git_commit_ref,
git_commit_append: git_commit_append,
git_commit_prepend: git_commit_prepend
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
#[test]
fn test_config_default() {
let config: Config = Config::default();
assert!(config.get_alias(&String::from("чд")).is_none());
assert_eq!(config.output_config.translate_output, true);
assert_eq!(config.language, String::from("ru"));
let prompt_config: PromptConfig = config.prompt_config;
assert_eq!(prompt_config.prompt_line, String::from("${USER}@${HOSTNAME}:${WRKDIR}$"));
assert_eq!(prompt_config.break_enabled, false);
assert_eq!(prompt_config.break_str, String::from("❯"));
assert_eq!(prompt_config.git_branch, String::from("on "));
assert_eq!(prompt_config.git_commit_ref, 8);
assert_eq!(prompt_config.git_commit_prepend, None);
assert_eq!(prompt_config.git_commit_append, None);
assert_eq!(prompt_config.history_size, 256);
assert_eq!(prompt_config.min_duration, 2000);
assert_eq!(prompt_config.rc_err, String::from("✖"));
assert_eq!(prompt_config.rc_ok, String::from("✔"));
assert_eq!(prompt_config.translate, false);
assert_eq!(config.shell_config.exec, String::from("bash"));
assert_eq!(config.shell_config.args.len(), 0);
}
#[test]
fn test_config_file() {
let config_file: tempfile::NamedTempFile = write_config_file_en();
let config_file_path: PathBuf = PathBuf::from(config_file.path().to_str().unwrap());
println!("Generated config file: {}", config_file_path.display());
let config: Result<Config, ConfigError> =Config::parse_config(config_file_path);
assert!(config.is_ok());
let config: Config = config.ok().unwrap();
assert!(config.get_alias(&String::from("чд")).is_some());
assert_eq!(config.output_config.translate_output, true);
assert_eq!(config.language, String::from("ru"));
let prompt_config: PromptConfig = config.prompt_config;
assert_eq!(prompt_config.prompt_line, String::from("${USER}@${HOSTNAME}:${WRKDIR}$"));
assert_eq!(prompt_config.break_enabled, false);
assert_eq!(prompt_config.break_str, String::from("❯"));
assert_eq!(prompt_config.git_branch, String::from("on "));
assert_eq!(prompt_config.git_commit_ref, 8);
assert_eq!(prompt_config.git_commit_prepend, None);
assert_eq!(prompt_config.git_commit_append, None);
assert_eq!(prompt_config.history_size, 256);
assert_eq!(prompt_config.min_duration, 2000);
assert_eq!(prompt_config.rc_err, String::from("✖"));
assert_eq!(prompt_config.rc_ok, String::from("✔"));
assert_eq!(prompt_config.translate, false);
assert_eq!(config.shell_config.exec, String::from("bash"));
assert_eq!(config.shell_config.args.len(), 0);
}
#[test]
fn test_config_no_file() {
assert_eq!(
Config::parse_config(PathBuf::from("config.does.not.exist.yml"))
.err()
.unwrap()
.code,
ConfigErrorCode::NoSuchFileOrDirectory
);
}
#[cfg(not(target_os = "macos"))]
#[test]
fn test_config_not_accessible() {
assert_eq!(
Config::parse_config(PathBuf::from("/dev/ttyS0"))
.err()
.unwrap()
.code,
ConfigErrorCode::CouldNotReadFile
);
}
#[test]
fn test_config_en_alias() {
let config: String =
String::from("alias:\n - чд: \"cd\"\n - пвд: \"pwd\"\n - уич: \"which\"");
match Config::parse_config_str(config) {
Ok(config) => {
assert_eq!(
config.get_alias(&String::from("чд")).unwrap(),
String::from("cd")
);
assert_eq!(
config.get_alias(&String::from("пвд")).unwrap(),
String::from("pwd")
);
assert_eq!(
config.get_alias(&String::from("уич")).unwrap(),
String::from("which")
);
assert!(config
.get_alias(&String::from("thiskeydoesnotexist"))
.is_none());
}
Err(error) => panic!(
"Parse_config should have returned OK, but returned {} ({:?})",
error.message, error.code
),
};
}
#[test]
fn test_config_no_alias() {
let config: String = String::from("language: ru\n");
let config: Config = Config::parse_config_str(config).ok().unwrap();
assert!(config.get_alias(&String::from("чд")).is_none());
}
#[test]
fn test_config_alias_not_array() {
let config: String = String::from("alias: 5\n");
assert_eq!(
Config::parse_config_str(config).err().unwrap().code,
ConfigErrorCode::YamlSyntaxError
);
}
#[test]
fn test_config_shell_config() {
let config: String = String::from("shell:\n exec: \"sh\"\n args:\n - \"-l\"\n - \"-h\"\n");
let config: Config = Config::parse_config_str(config).ok().unwrap();
assert_eq!(config.shell_config.exec, String::from("sh"));
assert_eq!(config.shell_config.args, vec![String::from("-l"), String::from("-h")]);
}
#[test]
fn test_config_shell_config_bad() {
let config: String = String::from("shell:\n args:\n - \"-l\"\n - \"-h\"\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("shell:\n args: 5\n");
assert!(Config::parse_config_str(config).is_err());
}
#[test]
fn test_config_output_config() {
let config: String =
String::from("alias:\n - чд: \"cd\"\n - пвд: \"pwd\"\n - уич: \"which\"");
let config: Config = Config::parse_config_str(config).ok().unwrap();
assert!(config.output_config.translate_output);
let config: String = String::from("output:\n translate: false\n");
let config: Config = Config::parse_config_str(config).ok().unwrap();
assert!(!config.output_config.translate_output);
}
#[test]
fn test_config_bad_output_config() {
let config: String = String::from("output: 5\n");
assert_eq!(
Config::parse_config_str(config).err().unwrap().code,
ConfigErrorCode::YamlSyntaxError
);
let config: String = String::from("output:\n translate: foobar\n");
assert_eq!(
Config::parse_config_str(config).err().unwrap().code,
ConfigErrorCode::YamlSyntaxError
);
let config: String = String::from("output:\n trsnlate: true\n");
assert_eq!(
Config::parse_config_str(config).err().unwrap().code,
ConfigErrorCode::YamlSyntaxError
);
}
#[test]
fn test_config_language() {
let config: String = String::from("language: bg\n");
let config: Config = Config::parse_config_str(config).ok().unwrap();
assert_eq!(config.language, String::from("bg"));
}
#[test]
fn test_config_language_missing() {
let config: String = String::from("output:\n translate: false\n");
let config: Config = Config::parse_config_str(config).ok().unwrap();
assert_eq!(config.language, String::from("ru"));
}
#[test]
#[should_panic]
fn test_config_language_badvalue() {
let config: String = String::from("language:\n name: ru\n");
assert!(Config::parse_config_str(config).is_ok());
}
#[test]
fn test_config_prompt_default() {
let config: String = String::from("language:\n ru\n");
let config: Config = Config::parse_config_str(config).ok().unwrap();
let prompt_config: PromptConfig = config.prompt_config;
assert_eq!(prompt_config.prompt_line, String::from("${USER}@${HOSTNAME}:${WRKDIR}$"));
assert_eq!(prompt_config.break_enabled, false);
assert_eq!(prompt_config.break_str, String::from("❯"));
assert_eq!(prompt_config.git_branch, String::from("on "));
assert_eq!(prompt_config.git_commit_ref, 8);
assert_eq!(prompt_config.history_size, 256);
assert_eq!(prompt_config.min_duration, 2000);
assert_eq!(prompt_config.rc_err, String::from("✖"));
assert_eq!(prompt_config.rc_ok, String::from("✔"));
assert_eq!(prompt_config.translate, false);
}
#[test]
fn test_config_prompt() {
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n commit_prepend: \"(\"\n commit_append: \")\"\n");
let config: Config = Config::parse_config_str(config).ok().unwrap();
let prompt_config: PromptConfig = config.prompt_config;
assert_eq!(prompt_config.prompt_line, String::from("${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}"));
assert_eq!(prompt_config.break_enabled, false);
assert_eq!(prompt_config.break_str, String::from(">"));
assert_eq!(prompt_config.git_branch, String::from("on "));
assert_eq!(prompt_config.git_commit_ref, 4);
assert_eq!(prompt_config.git_commit_prepend, Some(String::from("(")));
assert_eq!(prompt_config.git_commit_append, Some(String::from(")")));
assert_eq!(prompt_config.history_size, 1024);
assert_eq!(prompt_config.min_duration, 5000);
assert_eq!(prompt_config.rc_err, String::from("x_x"));
assert_eq!(prompt_config.rc_ok, String::from("^_^"));
assert_eq!(prompt_config.translate, true);
}
#[test]
fn test_config_prompt_bad() {
let config: String = String::from("prompt:\n prompt_le: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n histosize: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n trslate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n bak:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n eled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n th: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n dution:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsime: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n r:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n o: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n err: \"x_x\"\n git:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n gi:\n branch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n brch: \"on \"\n commit_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
let config: String = String::from("prompt:\n prompt_line: \"${USER} on ${HOSTNAME} in ${WRKDIR} ${GIT_BRANCH} (${GIT_COMMIT}) ${CMD_TIME}\"\n history_size: 1024\n translate: true\n break:\n enabled: false\n with: \">\"\n duration:\n min_elapsed_time: 5000\n rc:\n ok: \"^_^\"\n error: \"x_x\"\n git:\n branch: \"on \"\n com_ref_len: 4\n");
assert!(Config::parse_config_str(config).is_err());
}
#[test]
fn test_config_bad_syntax() {
let config: String = String::from("foobar: 5:\n");
assert_eq!(
Config::parse_config_str(config).err().unwrap().code,
ConfigErrorCode::YamlSyntaxError
);
}
#[test]
fn test_config_empty_yaml() {
let config: String = String::from("\n");
assert_eq!(
Config::parse_config_str(config).err().unwrap().code,
ConfigErrorCode::YamlSyntaxError
);
}
#[test]
fn test_config_error_display() {
println!(
"{};{};{}",
ConfigErrorCode::CouldNotReadFile,
ConfigErrorCode::NoSuchFileOrDirectory,
ConfigErrorCode::YamlSyntaxError
);
println!(
"{}",
ConfigError {
code: ConfigErrorCode::NoSuchFileOrDirectory,
message: String::from("No such file or directory ~/.config/pyc/pyc.yml")
}
);
}
fn write_config_file_en() -> tempfile::NamedTempFile {
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
write!(
tmpfile,
"alias:\n - чд: \"cd\"\n - пвд: \"pwd\"\n - уич: \"which\""
)
.unwrap();
tmpfile
}
}