#[cfg(test)]
mod tests {
use super::*;
#[test]
fn extract_tags() {
let contents = "\
tags: C/C++, code, algorithms
";
assert_eq!(vec!["C/C++", "code", "algorithms"], get_tags(contents));
}
}
use std::io;
use std::fs;
use std::env;
use std::error::Error;
#[derive(Debug)]
enum Action {
List,
Edit,
Show,
}
#[derive(Debug)]
pub struct Config {
fpath : String,
action : Action,
}
impl Config {
pub fn new(mut args : env::Args) -> Result<Config, &'static str> {
args.next();
let action_cli = args.next().expect("no action");
let action = if action_cli.contains("list") {
Action::List
} else if action_cli.contains("edit") {
Action::Edit
} else if action_cli.contains("show") {
Action::Show
} else {
Action::List };
let config_str = match env::var("TN_CONFIG") {
Ok(c) => c,
Err(_) => String::from(env::var("HOME").unwrap() + "/.tn"),
};
Ok(Config {
fpath: String::from(config_str),
action: action,
})
}
}
pub fn get_notes(content: &str) -> Vec<&str> {
content
.lines()
.filter(|line| line.contains("todo:"))
.collect()
}
use std::io::prelude::*; use std::io::BufReader;
use std::fs::File;
pub fn get_title(content: &str) -> Result<String, Box<dyn Error>> {
let fname = content.replace("todo:", "");
let f = File::open(fname)?;
let mut reader = BufReader::new(f);
for line in reader.lines() {
if let Ok(cont) = line {
if cont.starts_with('=') {
return Ok(String::from(cont
.trim_start_matches("=")
.trim_start_matches(" ")));
}
} else {
return Err(Box::from("I/O failed"));
}
}
Err(Box::from("title not found"))
}
pub fn get_due(content: &str) -> Result<String, Box<dyn Error>> {
let fname = content.replace("todo:", "");
let f = File::open(fname)?;
let mut reader = BufReader::new(f);
for line in reader.lines() {
if let Ok(cont) = line {
if cont.starts_with("* due:") {
return Ok(String::from(cont
.trim_start_matches("* due:")
.trim_start()
.trim_end()));
}
} else {
return Err(Box::from("I/O failed"));
}
}
Err(Box::from("tags not found"))
}
pub fn get_tags(content: &str) -> Result<Vec<String>, Box<dyn Error>> {
let fname = content.replace("todo:", "");
let f = File::open(fname)?;
let mut reader = BufReader::new(f);
for line in reader.lines() {
if let Ok(cont) = line {
if cont.starts_with("* tags:") {
return Ok(cont
.trim_start_matches("* tags:")
.trim_start_matches(" ")
.split(",")
.map(|blubb| String::from(blubb))
.collect());
}
} else {
return Err(Box::from("I/O failed"));
}
}
Err(Box::from("tags not found"))
}
pub fn list_notes(config: &Config) -> Result<(), Box<dyn Error>> {
let contents = fs::read_to_string(&config.fpath)?;
let notes = get_notes(&contents);
println!("title tags due completion");
println!("============================================================");
for n in notes {
print!("{}", get_title(n)?);
print!(" ");
for t in get_tags(n)? {
print!("{},", t);
}
print!(" ");
print!("{}", get_due(n)?);
println!("");
}
Ok(())
}
pub fn show_notes(config: &Config) -> Result<(), Box<dyn Error>> {
Err(Box::from("show not implemented"))
}
pub fn edit_notes(config: &Config) -> Result<(), Box<dyn Error>> {
Err(Box::from("edit not implemented"))
}
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
match config.action {
Action::List => list_notes(&config),
Action::Edit => edit_notes(&config),
Action::Show => show_notes(&config),
}
}