add cli tests + refactor
parent
564147daae
commit
b6e93bd5cc
@ -0,0 +1,159 @@
|
||||
|
||||
use super::{Columns, Column};
|
||||
use anyhow::{anyhow, Result};
|
||||
use regex::Regex;
|
||||
|
||||
/// split input text into columns based on separator character
|
||||
/// returns a type representing a variable length array of strings (columns) ?
|
||||
///
|
||||
/// TODO:
|
||||
///
|
||||
/// error handling
|
||||
/// accept &str and String
|
||||
///
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InputText<'a> {
|
||||
raw: &'a str,
|
||||
|
||||
pub sep: String,
|
||||
}
|
||||
|
||||
impl<'a> InputText<'a> {
|
||||
|
||||
pub fn new(raw: &'a str, sep: &str) -> Self {
|
||||
InputText {
|
||||
raw: raw.into(),
|
||||
sep: sep.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn n_cols(&self) -> Result<usize> {
|
||||
// read the first line stripping empty lines
|
||||
let lines: Vec<&str> = self.raw.trim().lines().collect();
|
||||
// eprintln!("lines: {:?}", lines);
|
||||
|
||||
let re = Regex::new(&self.sep).unwrap();
|
||||
|
||||
// count number of columns
|
||||
match lines.first() {
|
||||
Some(line) => Ok(re.split(line).count()),
|
||||
None => Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(self) -> usize {
|
||||
self.raw.len()
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the number of columns given input text and a separator
|
||||
pub fn n_columns(text: &str, sep: &str) -> Result<usize> {
|
||||
// read the first line stripping empty lines
|
||||
let lines: Vec<&str> = text.trim().lines().collect();
|
||||
// eprintln!("lines: {:?}", lines);
|
||||
|
||||
let re = Regex::new(sep).unwrap();
|
||||
|
||||
// count number of columns
|
||||
match lines.first() {
|
||||
Some(line) => Ok(re.split(line).count()),
|
||||
None => return Err(anyhow!("no lines left")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn split_columns(text: &str, sep: &str) -> Result<Columns> {
|
||||
let re = Regex::new(sep).unwrap();
|
||||
|
||||
// eprintln!("# columns: {n_col}");
|
||||
let lines: Vec<&str> = text.trim().lines().collect();
|
||||
|
||||
let n_col = n_columns(text, sep)?;
|
||||
let mut columns = vec![Column::new(); n_col];
|
||||
|
||||
for (n, line) in lines.iter().enumerate() {
|
||||
// eprintln!("checking line {}", i);
|
||||
|
||||
let new_n_col = re.split(line).count();
|
||||
|
||||
if new_n_col != n_col {
|
||||
return Err(anyhow!(
|
||||
"unmatched column: expected {n_col} got {new_n_col} on line {}",
|
||||
n + 1
|
||||
));
|
||||
}
|
||||
// eprintln!("number of columns: {}", columns.len());
|
||||
|
||||
for (c_idx, col) in re.split(line).enumerate() {
|
||||
columns[c_idx].push(col.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
eprintln!("{:?}", columns);
|
||||
|
||||
Ok(Columns(columns))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::DEFAULT_SEP_PATTERN;
|
||||
use regex::Regex;
|
||||
use std::error::Error;
|
||||
|
||||
type TestResult = Result<(), Box<dyn Error>>;
|
||||
|
||||
#[test]
|
||||
fn test_split_columns_default_sep() -> TestResult {
|
||||
let coltext1 = "
|
||||
file1.txt\t\ttitle1
|
||||
file2.pdf\t\ttitle2
|
||||
file3\t\t\ttitle3
|
||||
file with space \textra
|
||||
";
|
||||
let columns = split_columns(coltext1, DEFAULT_SEP_PATTERN)?;
|
||||
|
||||
// should have two columns
|
||||
assert_eq!(2, columns.clone().len());
|
||||
|
||||
assert_eq!(
|
||||
vec!["file1.txt", "file2.pdf", "file3", "file with space "],
|
||||
columns[0]
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_wrong_ncol_default_sep() {
|
||||
let coltext1 = "
|
||||
file1.txt\t\ttitle1
|
||||
file2.pdf\t\ttitle2
|
||||
file3\t\t\ttitle3
|
||||
file with space\ttitle 4\textra
|
||||
";
|
||||
split_columns(coltext1, DEFAULT_SEP_PATTERN).unwrap();
|
||||
}
|
||||
|
||||
// #[test]
|
||||
fn test_re_split() {
|
||||
let text = "this is two tabs";
|
||||
let re = Regex::new(r"[\t]+").unwrap();
|
||||
let fields: Vec<&str> = re.split(text).collect();
|
||||
eprintln!("{:?}", fields);
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_columns_from_str() {
|
||||
let res: Columns = "first column\tsecond column\t\tthird column"
|
||||
.try_into()
|
||||
.unwrap();
|
||||
assert_eq!(res.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_text(){
|
||||
// it =
|
||||
}
|
||||
}
|
@ -1,20 +1,8 @@
|
||||
.rw-r--r-- 894 root 9 Sep 22:19 coredump.conf
|
||||
.rw-r--r-- 540 root 20 Sep 2020 homed.conf
|
||||
.rw-r--r-- 766 root 9 Sep 22:19 homed.conf.pacnew
|
||||
.rw-r--r-- 894 root 9 Sep 22:19 journal-remote.conf
|
||||
.rw-r--r-- 822 root 9 Sep 22:19 journal-upload.conf
|
||||
.rw-r--r-- 1.3k root 9 Sep 22:19 journald.conf
|
||||
.rw-r--r-- 1.1k root 24 Feb 2022 logind.conf
|
||||
.rw-r--r-- 1.5k root 9 Sep 22:19 logind.conf.pacnew
|
||||
drwxr-xr-x - root 25 Jan 18:33 network
|
||||
.rw-r--r-- 872 root 9 Sep 22:19 networkd.conf
|
||||
.rw-r--r-- 804 root 9 Sep 22:19 oomd.conf
|
||||
.rw-r--r-- 670 root 9 Sep 22:19 pstore.conf
|
||||
.rw-r--r-- 763 root 19 Aug 2020 resolved.conf
|
||||
.rw-r--r-- 1.6k root 9 Sep 22:19 resolved.conf.pacnew
|
||||
.rw-r--r-- 953 root 9 Sep 22:19 sleep.conf
|
||||
drwxr-xr-x - root 2 Feb 18:04 system
|
||||
.rw-r--r-- 2.2k root 9 Sep 22:19 system.conf
|
||||
.rw-r--r-- 856 root 9 Sep 22:19 timesyncd.conf
|
||||
drwxr-xr-x - root 9 Nov 2022 user
|
||||
.rw-r--r-- 1.6k root 9 Sep 22:19 user.conf
|
||||
.rw-rw-r-- 11k blob42 21 Sep 23:25 Cargo.lock
|
||||
.rw-rw-r-- 303 blob42 21 Sep 23:25 Cargo.toml
|
||||
drwxrwxr-x - blob42 10 Sep 12:27 examples
|
||||
.rw-rw-r-- 1.6k blob42 1 Oct 17:24 README.md
|
||||
drwxrwxr-x - blob42 21 Sep 23:31 src
|
||||
drwxrwxr-x - blob42 1 Oct 17:26 target
|
||||
drwxrwxr-x - blob42 21 Sep 00:44 tests
|
||||
.rw-rw-r-- 222 blob42 17 Sep 19:03 TODO.md
|
||||
|
Loading…
Reference in New Issue