use crate::commands::{
add, clear, del, del_all, display, display_all, select_one, upd, upd_notename,
};
use crate::errors::NotebookError;
use sqlx::{self, PgPool};
use std::{io, process};
use structopt::StructOpt;
use tracing::{event, Level};
#[derive(StructOpt)]
enum Command {
AddNote {
notename: String,
},
DelNote {
notename: String,
},
DelAll,
ClearNote {
notename: String,
},
UpdNotename {
notename: String,
new_notename: String,
},
UpdNote {
notename: String,
},
DisplayNote {
notename: String,
},
}
#[derive(StructOpt)]
pub struct NoteCommand {
#[structopt(subcommand)]
cmd: Option<Command>,
}
impl NoteCommand {
pub async fn new() -> Result<NoteCommand, structopt::clap::Error> {
Ok(NoteCommand::from_args_safe()?)
}
pub async fn execute_command(&self, pool: &PgPool) -> Result<(), NotebookError> {
match self.cmd.as_ref() {
Some(Command::AddNote { notename }) => {
println!("Enter note you want to add into `{}`", notename);
println!("(At the end of the note, enter `#endnote#` to finish writing the note):");
let mut note = String::new();
loop {
let mut note_part = String::new();
io::stdin().read_line(&mut note_part).unwrap_or_else(|e| {
event!(Level::DEBUG, "Problem to read line: {e}");
process::exit(1);
});
if note_part.contains("#endnote#") {
delete_end(&mut note_part, "#endnote#").await;
note = note + note_part.as_str();
break;
} else {
note = note + note_part.as_str();
}
}
println!("Note to add into `{notename}`:\n{note}");
add(¬ename, ¬e, pool).await?;
}
Some(Command::DelNote { notename }) => {
del(¬ename, pool).await?;
}
Some(Command::DelAll) => {
del_all(pool).await?;
}
Some(Command::ClearNote { notename }) => {
clear(notename, pool).await?;
}
Some(Command::UpdNotename {
notename,
new_notename,
}) => {
upd_notename(¬ename, &new_notename, pool).await?;
}
Some(Command::UpdNote { notename }) => {
println!(
"Current content of `{}`:\n{}",
notename,
select_one(notename, pool).await?.note_str().await
);
println!(
"Enter note you want to add instead old note in `{}`",
notename
);
println!("(At the end of the note, enter `#endnote#` to finish writing the note):");
let mut note = String::new();
loop {
let mut note_part = String::new();
io::stdin().read_line(&mut note_part).unwrap_or_else(|e| {
event!(Level::DEBUG, "Problem to read line: {e}");
process::exit(1);
});
if note_part.contains("#endnote#") {
delete_end(&mut note_part, "#endnote#").await;
note = note + note_part.as_str();
break;
} else {
note = note + note_part.as_str();
}
}
println!("Note to add into `{notename}` instead old note:\n{note}");
upd(¬ename, ¬e, pool).await?;
}
Some(Command::DisplayNote { notename }) => {
display(notename, pool).await?;
}
None => {
display_all(pool).await?;
}
}
Ok(())
}
}
async fn delete_end(source: &mut String, end: &str) -> String {
let _: Vec<_> = source
.to_owned()
.char_indices()
.map(|(i, _)| {
let len = i + end.len();
if source.contains(end) {
if &source[i..len] == end {
source.drain(i..);
}
}
})
.collect();
source.to_owned()
}