structure of project, arguments, patches
This commit is contained in:
		
							parent
							
								
									cff0563bf7
								
							
						
					
					
						commit
						90948a1c83
					
				
							
								
								
									
										59
									
								
								src/rnote/app.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/rnote/app.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
			
		||||
pub use clap::{App, AppSettings, Arg, SubCommand};
 | 
			
		||||
 | 
			
		||||
pub fn make_app() -> App<'static, 'static> {
 | 
			
		||||
    App::new("rnote")
 | 
			
		||||
        .version("0.0.0")
 | 
			
		||||
        .author("Volodymyr Patuta <vpatuta AT protonmail DOT com>")
 | 
			
		||||
        .about("Minimal note talking cli tool.")
 | 
			
		||||
        .setting(AppSettings::ArgRequiredElseHelp)
 | 
			
		||||
        .subcommand(
 | 
			
		||||
            SubCommand::with_name("new")
 | 
			
		||||
                .alias("n")
 | 
			
		||||
                .about("Create new note")
 | 
			
		||||
                .arg(
 | 
			
		||||
                    Arg::with_name("category")
 | 
			
		||||
                        .help("Create note in category.")
 | 
			
		||||
                        .short("c")
 | 
			
		||||
                        .long("category"),
 | 
			
		||||
                )
 | 
			
		||||
                .arg(Arg::with_name("header").help("Give name to the file.")),
 | 
			
		||||
        )
 | 
			
		||||
        .subcommand(
 | 
			
		||||
            SubCommand::with_name("remove")
 | 
			
		||||
                .alias("r")
 | 
			
		||||
                .about("Remove a note.")
 | 
			
		||||
                .arg(Arg::with_name("header").help("Name of the note.")),
 | 
			
		||||
        )
 | 
			
		||||
        .subcommand(
 | 
			
		||||
            SubCommand::with_name("edit")
 | 
			
		||||
                .alias("e")
 | 
			
		||||
                .about("Edit a note.")
 | 
			
		||||
                .arg(Arg::with_name("header").help("Name of the note.")),
 | 
			
		||||
        )
 | 
			
		||||
        .subcommand(
 | 
			
		||||
            SubCommand::with_name("list")
 | 
			
		||||
                .alias("l")
 | 
			
		||||
                .alias("ls")
 | 
			
		||||
                .alias("show")
 | 
			
		||||
                .about("Show all notes or one note")
 | 
			
		||||
                .arg(Arg::with_name("header").help("Name of the note."))
 | 
			
		||||
                .arg(
 | 
			
		||||
                    Arg::with_name("category")
 | 
			
		||||
                        .help("List all notes from a category.")
 | 
			
		||||
                        .short("c")
 | 
			
		||||
                        .long("category"),
 | 
			
		||||
                ),
 | 
			
		||||
        )
 | 
			
		||||
        .subcommand(
 | 
			
		||||
            SubCommand::with_name("search")
 | 
			
		||||
                .alias("s")
 | 
			
		||||
                .about("Search a note.")
 | 
			
		||||
                .arg(Arg::with_name("header").help("Name of the note."))
 | 
			
		||||
                .arg(
 | 
			
		||||
                    Arg::with_name("word")
 | 
			
		||||
                        .help("Search by word.")
 | 
			
		||||
                        .short("w")
 | 
			
		||||
                        .long("word"),
 | 
			
		||||
                ),
 | 
			
		||||
        )
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								src/rnote/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/rnote/mod.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
pub mod app;
 | 
			
		||||
mod notes;
 | 
			
		||||
pub mod process;
 | 
			
		||||
							
								
								
									
										127
									
								
								src/rnote/notes.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/rnote/notes.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,127 @@
 | 
			
		||||
use anyhow::{anyhow, Result};
 | 
			
		||||
use chrono::Utc;
 | 
			
		||||
use std::{env, fs, process::Command};
 | 
			
		||||
use text_io::read;
 | 
			
		||||
use walkdir::WalkDir;
 | 
			
		||||
 | 
			
		||||
/// Get the path to the root directory of all notes.
 | 
			
		||||
fn get_base_path() -> Result<String> {
 | 
			
		||||
    let home = env::var("HOME")?;
 | 
			
		||||
    Ok(format!("{}/.rnote/", home))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Get path to a category/date directory.
 | 
			
		||||
fn get_path(category: &str) -> Result<String> {
 | 
			
		||||
    let base = get_base_path()?;
 | 
			
		||||
    let date = Utc::now().format("%Y-%m-%d");
 | 
			
		||||
    match category.is_empty() {
 | 
			
		||||
        true => Ok(format!("{}{}/", base, date)),
 | 
			
		||||
        false => Ok(format!("{}{}/", base, category)),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Create directory for a note.
 | 
			
		||||
pub fn create_dir(category: &str) -> Result<()> {
 | 
			
		||||
    let path = get_base_path()?;
 | 
			
		||||
    let date = Utc::now().format("%Y-%m-%d");
 | 
			
		||||
    match category.is_empty() {
 | 
			
		||||
        true => fs::create_dir_all(format!("{}{}", path, date))?,
 | 
			
		||||
        false => fs::create_dir_all(format!("{}{}", path, category))?,
 | 
			
		||||
    }
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Create a new note.
 | 
			
		||||
pub fn create(header: &str, category: &str) -> Result<()> {
 | 
			
		||||
    let editor = env::var("EDITOR").unwrap_or("/bin/vi".to_owned());
 | 
			
		||||
    let file = format!("{}{}.md", get_path(category)?, header);
 | 
			
		||||
    create_dir(category)?;
 | 
			
		||||
    is_duplicate(header, category)?;
 | 
			
		||||
    Command::new(editor).arg(&file).status()?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Checks if potentially new note name already exists.
 | 
			
		||||
fn is_duplicate(header: &str, category: &str) -> Result<()> {
 | 
			
		||||
    let file = format!("{}{}.md", get_path(category)?, header);
 | 
			
		||||
    let path = format!("{}", get_path(category)?);
 | 
			
		||||
    for entry in WalkDir::new(path) {
 | 
			
		||||
        let entry = entry?;
 | 
			
		||||
        let p: &str = match entry.path().to_str() {
 | 
			
		||||
            Some(s) => s,
 | 
			
		||||
            None => "",
 | 
			
		||||
        };
 | 
			
		||||
        if p == file {
 | 
			
		||||
            return Err(anyhow!(
 | 
			
		||||
                "Duplicate in the same category/date. Choose another name."
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Finds a path to desired note.
 | 
			
		||||
fn find_path(header: &str) -> Result<String> {
 | 
			
		||||
    let mut paths: Vec<String> = Vec::new();
 | 
			
		||||
    let base = get_base_path()?;
 | 
			
		||||
    let header = format!("{}.md", header);
 | 
			
		||||
    for entry in WalkDir::new(base) {
 | 
			
		||||
        let entry = entry?;
 | 
			
		||||
        let p: &str = match entry.path().to_str() {
 | 
			
		||||
            Some(s) => s,
 | 
			
		||||
            None => "",
 | 
			
		||||
        };
 | 
			
		||||
        let name: &str = match entry.file_name().to_str() {
 | 
			
		||||
            Some(s) => s,
 | 
			
		||||
            None => "",
 | 
			
		||||
        };
 | 
			
		||||
        if name == header {
 | 
			
		||||
            paths.push(String::from(p));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if paths.is_empty() {
 | 
			
		||||
        Err(anyhow!("Note not found."))
 | 
			
		||||
    } else {
 | 
			
		||||
        if paths.len() == 1 {
 | 
			
		||||
            Ok(format!("{}.md", paths[0]))
 | 
			
		||||
        } else {
 | 
			
		||||
            let mut n: usize;
 | 
			
		||||
            loop {
 | 
			
		||||
                let mut i = 1;
 | 
			
		||||
                println!("Choose one: \n");
 | 
			
		||||
                for path in &paths {
 | 
			
		||||
                    println!("{}\t {}", i, path);
 | 
			
		||||
                    i += 1;
 | 
			
		||||
                }
 | 
			
		||||
                n = read!();
 | 
			
		||||
                if n >= 1 && n <= paths.len() {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Ok(format!("{}.md", paths[n]))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Deletes a note.
 | 
			
		||||
pub fn remove(header: &str) -> Result<()> {
 | 
			
		||||
    let path = find_path(header)?;
 | 
			
		||||
    println!("Are you sure you want to delete {} [Y/n]", header);
 | 
			
		||||
    let response: String = read!();
 | 
			
		||||
    if response == "y" || response == "Y" || response == "yes" || response == "Yes" {
 | 
			
		||||
        println!("Deleting...");
 | 
			
		||||
        fs::remove_file(path)?;
 | 
			
		||||
        println!("Successfully deleted.");
 | 
			
		||||
        Ok(())
 | 
			
		||||
    } else {
 | 
			
		||||
        Err(anyhow!("Abort."))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Modify a note.
 | 
			
		||||
pub fn modify(header: &str) -> Result<()> {
 | 
			
		||||
    let editor = env::var("EDITOR").unwrap_or("/bin/vi".to_owned());
 | 
			
		||||
    let file = find_path(header)?;
 | 
			
		||||
    Command::new(editor).arg(&file).status()?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								src/rnote/process.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/rnote/process.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
			
		||||
use crate::rnote::notes;
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use clap::ArgMatches;
 | 
			
		||||
use notes::modify;
 | 
			
		||||
use text_io::read;
 | 
			
		||||
 | 
			
		||||
pub fn new(matches: &ArgMatches) -> Result<()> {
 | 
			
		||||
    let header = match matches.value_of("header") {
 | 
			
		||||
        Some(s) => s.to_owned(),
 | 
			
		||||
        None => {
 | 
			
		||||
            print!("Enter the name of your note: ");
 | 
			
		||||
            read!()
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    let category = matches.value_of("category").unwrap_or("");
 | 
			
		||||
 | 
			
		||||
    notes::create(&header, category)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
pub fn remove(matches: &ArgMatches) -> Result<()> {
 | 
			
		||||
    let header = match matches.value_of("header") {
 | 
			
		||||
        Some(s) => s.to_owned(),
 | 
			
		||||
        None => {
 | 
			
		||||
            print!("Enter the name of your note: ");
 | 
			
		||||
            read!()
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    notes::remove(&header)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
pub fn edit(matches: &ArgMatches) -> Result<()> {
 | 
			
		||||
    let header = match matches.value_of("header") {
 | 
			
		||||
        Some(s) => s.to_owned(),
 | 
			
		||||
        None => {
 | 
			
		||||
            print!("Enter the name of your note: ");
 | 
			
		||||
            read!()
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    notes::modify(&header)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
pub fn list(matches: &ArgMatches) -> Result<()> {
 | 
			
		||||
    unimplemented!("list all notes, one note or category");
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
pub fn search(matches: &ArgMatches) -> Result<()> {
 | 
			
		||||
    unimplemented!("Search a note by header or by word.");
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user