Skip to content

Commit

Permalink
feat(CLI): field cursor complete and untested
Browse files Browse the repository at this point in the history
Tests just need to be run, and of course, the impementation might need
fixing.

Related to #64
  • Loading branch information
Byron committed Apr 16, 2015
1 parent c9c3ad0 commit 1dd1fcf
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 2 deletions.
78 changes: 76 additions & 2 deletions src/rust/cli/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}

Expand Down Expand Up @@ -197,20 +250,41 @@ 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),
ParseError((&'static str, &'static str, String, String)),
UnknownParameter(String),
InvalidKeyValueSyntax(String),
Input(InputError),
Field(FieldError),
}

impl fmt::Display for CLIError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
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),
Expand Down
4 changes: 4 additions & 0 deletions src/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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");
}
}

0 comments on commit 1dd1fcf

Please sign in to comment.