feat(CLI): field cursor complete and untested

Tests just need to be run, and of course, the impementation might need
fixing.

Related to #64
This commit is contained in:
Sebastian Thiel
2015-04-16 15:25:44 +02:00
parent c9c3ad011f
commit 1dd1fcf4b8
2 changed files with 80 additions and 2 deletions

View File

@@ -13,19 +13,72 @@ use std::io::{Write, Read, stdout};
use std::default::Default;
const FIELD_SEP: &'static str = ".";
const FIELD_SEP: char = 'c';
#[derive(Clone, Default)]
pub struct FieldCursor(Vec<String>);
impl ToString for FieldCursor {
fn to_string(&self) -> String {
String::new()
self.0.connect(".")
}
}
impl FieldCursor {
pub fn set(&mut self, value: &str) -> Result<(), CLIError> {
let mut first_is_field_sep = false;
let mut char_count: usize = 0;
let mut last_c = FIELD_SEP;
let mut num_conscutive_field_seps = 0;
let mut field = String::new();
let mut fields = self.0.clone();
let push_field = |fields: &mut Vec<String>, field: &mut String| {
if field.len() > 0 {
fields.push(field.clone());
field.truncate(0);
}
};
for (cid, c) in value.chars().enumerate() {
char_count = cid + 1;
if cid == 0 && c == FIELD_SEP {
first_is_field_sep = true;
}
if c == FIELD_SEP {
num_conscutive_field_seps += 1;
if last_c == FIELD_SEP {
if fields.pop().is_none() {
return Err(CLIError::Field(FieldError::PopOnEmpty))
}
} else {
push_field(&mut fields, &mut field);
}
} else {
num_conscutive_field_seps = 0;
if cid == 1 {
if first_is_field_sep {
fields.truncate(0);
}
}
field.push(c);
}
last_c = c;
}
push_field(&mut fields, &mut field);
if char_count == 1 && first_is_field_sep {
fields.truncate(0);
}
if char_count > 1 && num_conscutive_field_seps == 1 {
return Err(CLIError::Field(FieldError::TrailingFieldSep))
}
self.0 = fields;
Ok(())
}
@@ -197,6 +250,25 @@ impl fmt::Display for InputError {
}
}
#[derive(Debug)]
pub enum FieldError {
PopOnEmpty,
TrailingFieldSep,
}
impl fmt::Display for FieldError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
FieldError::PopOnEmpty
=> writeln!(f, "Cannot move up on empty field cursor"),
FieldError::TrailingFieldSep
=> writeln!(f, "Single field separator may not be last character"),
}
}
}
#[derive(Debug)]
pub enum CLIError {
Configuration(ConfigurationError),
@@ -204,6 +276,7 @@ pub enum CLIError {
UnknownParameter(String),
InvalidKeyValueSyntax(String),
Input(InputError),
Field(FieldError),
}
impl fmt::Display for CLIError {
@@ -211,6 +284,7 @@ impl fmt::Display for CLIError {
match *self {
CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err),
CLIError::Input(ref err) => write!(f, "Input -> {}", err),
CLIError::Field(ref err) => write!(f, "Field -> {}", err),
CLIError::ParseError((arg_name, type_name, ref value, ref err_desc))
=> writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}",
arg_name, value, type_name, err_desc),

View File

@@ -165,6 +165,7 @@ mod test_cli {
assert_eq!(c.to_string(), "");
assert_eq!(c.num_fields(), 0);
assert!(c.set("").is_err());
assert!(c.set(".").is_ok());
assert!(c.set("..").is_err());
assert_eq!(c.num_fields(), 0);
@@ -190,5 +191,8 @@ mod test_cli {
assert!(c.set(".one.two.three...beer").is_ok());
assert_eq!(c.num_fields(), 2);
assert_eq!(c.to_string(), "one.beer");
assert!(c.set("one.two.three...").is_ok());
assert_eq!(c.num_fields(), 3);
assert_eq!(c.to_string(), "one.beer.one");
}
}