Merge branch 'rework' into 'main'
Rework See merge request paris8-rust/rnote!10
This commit is contained in:
commit
5e518c3366
30
src/main.rs
30
src/main.rs
@ -1,21 +1,20 @@
|
|||||||
use anyhow::Result;
|
use anyhow::{anyhow, Result};
|
||||||
use dialoguer::{theme::ColorfulTheme, Input};
|
|
||||||
use rnote::{app, process};
|
use rnote::{app, process};
|
||||||
|
|
||||||
mod rnote;
|
mod rnote;
|
||||||
|
|
||||||
/// Check if variable `EDITOR` is set.
|
/// Check if variable `EDITOR` and `XDG_DATA_HOME` are set.
|
||||||
fn check() -> Result<()> {
|
fn check() -> Result<()> {
|
||||||
let editor = std::env::var("EDITOR").unwrap_or("".to_owned());
|
let editor = std::env::var("EDITOR").unwrap_or("".to_owned());
|
||||||
if editor.is_empty() {
|
let data_home = std::env::var("XDG_DATA_HOME").unwrap_or("".to_owned());
|
||||||
let editor: String = Input::with_theme(&ColorfulTheme::default())
|
if editor.is_empty() || data_home.is_empty() {
|
||||||
.with_prompt("Your text editor")
|
Err(anyhow!(
|
||||||
.interact_text()?;
|
"Please make sure variables EDITOR and XDG_DATA_HOME are set.\n\n\texport XDG_DATA_HOME=\"$HOME/.local/share\""
|
||||||
std::env::set_var("EDITOR", editor);
|
))
|
||||||
}
|
} else {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let mut app = app::make_app();
|
let mut app = app::make_app();
|
||||||
@ -34,3 +33,14 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn check_test() {
|
||||||
|
assert!(check().is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,15 +11,15 @@ pub fn make_app() -> App<'static, 'static> {
|
|||||||
SubCommand::with_name("new")
|
SubCommand::with_name("new")
|
||||||
.alias("n")
|
.alias("n")
|
||||||
.about("Create new note")
|
.about("Create new note")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("header")
|
||||||
|
.index(1)
|
||||||
|
.help("Give name to the note."),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("category")
|
Arg::with_name("category")
|
||||||
.help("Create note in category.")
|
.help("Create note in category.")
|
||||||
.index(2),
|
.index(2),
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("header")
|
|
||||||
.index(1)
|
|
||||||
.help("Give name to the file."),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
@ -31,6 +31,7 @@ pub fn make_app() -> App<'static, 'static> {
|
|||||||
Arg::with_name("date")
|
Arg::with_name("date")
|
||||||
.help("Delete all notes created at given date.")
|
.help("Delete all notes created at given date.")
|
||||||
.short("d")
|
.short("d")
|
||||||
|
.conflicts_with("header")
|
||||||
.long("date"),
|
.long("date"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -60,6 +61,7 @@ pub fn make_app() -> App<'static, 'static> {
|
|||||||
Arg::with_name("word")
|
Arg::with_name("word")
|
||||||
.help("Search by word.")
|
.help("Search by word.")
|
||||||
.short("w")
|
.short("w")
|
||||||
|
.conflicts_with("header")
|
||||||
.long("word"),
|
.long("word"),
|
||||||
)
|
)
|
||||||
.arg(Arg::with_name("header").help("Name of the note.")),
|
.arg(Arg::with_name("header").help("Name of the note.")),
|
||||||
@ -70,13 +72,15 @@ pub fn make_app() -> App<'static, 'static> {
|
|||||||
Arg::with_name("all")
|
Arg::with_name("all")
|
||||||
.help("Show all notes.")
|
.help("Show all notes.")
|
||||||
.short("a")
|
.short("a")
|
||||||
|
.conflicts_with("header")
|
||||||
.long("all"),
|
.long("all"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("category")
|
Arg::with_name("category")
|
||||||
.help("Show all notes from a category/date")
|
.help("Show all notes from a category/date")
|
||||||
.short("c")
|
.short("c")
|
||||||
.long("category"),
|
.long("category")
|
||||||
|
.conflicts_with("header"),
|
||||||
)
|
)
|
||||||
.arg(Arg::with_name("header").help("Name of the note.")),
|
.arg(Arg::with_name("header").help("Name of the note.")),
|
||||||
)
|
)
|
||||||
|
@ -7,12 +7,12 @@ use walkdir::WalkDir;
|
|||||||
|
|
||||||
/// Get the path to the root directory of all notes.
|
/// Get the path to the root directory of all notes.
|
||||||
pub fn get_base_path() -> Result<String> {
|
pub fn get_base_path() -> Result<String> {
|
||||||
let home = env::var("HOME")?;
|
let home = env::var("XDG_DATA_HOME")?;
|
||||||
Ok(format!("{}/.rnote/", home))
|
Ok(format!("{}/rnote/", home))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get path to a category/date directory.
|
/// Get path to a category/date directory.
|
||||||
fn get_path(category: &str) -> Result<String> {
|
fn get_category_path(category: &str) -> Result<String> {
|
||||||
let base = get_base_path()?;
|
let base = get_base_path()?;
|
||||||
let date = Utc::now().format("%Y-%m-%d");
|
let date = Utc::now().format("%Y-%m-%d");
|
||||||
match category.is_empty() {
|
match category.is_empty() {
|
||||||
@ -21,6 +21,57 @@ fn get_path(category: &str) -> Result<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get all note paths.
|
||||||
|
pub fn get_all_notes() -> Result<Vec<String>> {
|
||||||
|
let path = get_base_path()?;
|
||||||
|
let mut files: Vec<String> = Vec::new();
|
||||||
|
for (_, file) in WalkDir::new(path)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|file| file.ok())
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
if file.metadata()?.is_file() {
|
||||||
|
let p = file.path().to_str().unwrap_or("");
|
||||||
|
if !p.is_empty() {
|
||||||
|
files.push(p.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if files.is_empty() {
|
||||||
|
Err(anyhow!("No notes found."))
|
||||||
|
} else {
|
||||||
|
Ok(files)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get all notes in category.
|
||||||
|
pub fn get_notes_in_category(category: &str) -> Result<Vec<String>> {
|
||||||
|
let base = get_base_path()?;
|
||||||
|
let path = format!("{}{}", base, category);
|
||||||
|
let mut files: Vec<String> = Vec::new();
|
||||||
|
if std::path::Path::new(&path).exists() {
|
||||||
|
for (_, file) in WalkDir::new(path)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|file| file.ok())
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
if file.metadata()?.is_file() {
|
||||||
|
let p = file.path().to_str().unwrap_or("");
|
||||||
|
if !p.is_empty() {
|
||||||
|
files.push(p.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if files.is_empty() {
|
||||||
|
Err(anyhow!("Category is empty."))
|
||||||
|
} else {
|
||||||
|
Ok(files)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("Category no found."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create directory for a note.
|
/// Create directory for a note.
|
||||||
pub fn create_dir(category: &str) -> Result<()> {
|
pub fn create_dir(category: &str) -> Result<()> {
|
||||||
let base = get_base_path()?;
|
let base = get_base_path()?;
|
||||||
@ -45,40 +96,8 @@ pub fn create_dir(category: &str) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new note.
|
|
||||||
pub fn create(header: &str, category: &str) -> Result<()> {
|
|
||||||
let editor = env::var("EDITOR")?;
|
|
||||||
let file = format!("{}{}.md", get_path(category)?, header);
|
|
||||||
create_dir(category)?;
|
|
||||||
is_duplicate(header, category)?;
|
|
||||||
let mut f = fs::File::create(&file)?;
|
|
||||||
f.set_permissions(fs::Permissions::from_mode(0o600))?;
|
|
||||||
f.write(format!("# {}\n", header).as_bytes())?;
|
|
||||||
Command::new(editor).arg(&file).status()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check 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(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find a path to desired note.
|
/// Find a path to desired note.
|
||||||
pub fn find_path(header: &str) -> Result<Option<String>> {
|
pub fn get_note_path(header: &str) -> Result<Vec<String>> {
|
||||||
let mut paths: Vec<String> = Vec::new();
|
let mut paths: Vec<String> = Vec::new();
|
||||||
let base = get_base_path()?;
|
let base = get_base_path()?;
|
||||||
let header = format!("{}.md", header);
|
let header = format!("{}.md", header);
|
||||||
@ -99,60 +118,12 @@ pub fn find_path(header: &str) -> Result<Option<String>> {
|
|||||||
if paths.is_empty() {
|
if paths.is_empty() {
|
||||||
Err(anyhow!("Note not found."))
|
Err(anyhow!("Note not found."))
|
||||||
} else {
|
} else {
|
||||||
if paths.len() == 1 {
|
Ok(paths)
|
||||||
Ok(Some(paths.remove(0)))
|
|
||||||
} else {
|
|
||||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
|
||||||
.with_prompt("Optionally choose a note")
|
|
||||||
.default(0)
|
|
||||||
.items(&paths)
|
|
||||||
.interact_opt()?;
|
|
||||||
match selection {
|
|
||||||
Some(s) => Ok(Some(paths.remove(s))),
|
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a note.
|
/// Find all notes that contain a given string.
|
||||||
pub fn remove(header: &str) -> Result<()> {
|
pub fn get_files_by_word(word: &str) -> Result<Vec<String>> {
|
||||||
let path = find_path(header)?;
|
|
||||||
if Confirm::with_theme(&ColorfulTheme::default())
|
|
||||||
.with_prompt(format!("Do you want to delete {}?", header))
|
|
||||||
.interact()?
|
|
||||||
&& path.is_some()
|
|
||||||
{
|
|
||||||
println!("Deleting...");
|
|
||||||
fs::remove_file(path.unwrap())?;
|
|
||||||
remove_empty_dirs()?;
|
|
||||||
println!("Successfully deleted.");
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(anyhow!("Abort."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Modify a note.
|
|
||||||
pub fn modify(header: &str) -> Result<()> {
|
|
||||||
let editor = env::var("EDITOR")?;
|
|
||||||
let file = find_path(header)?;
|
|
||||||
match file {
|
|
||||||
Some(f) => {
|
|
||||||
Command::new(editor).arg(f).status()?;
|
|
||||||
println!("Edited successfully!");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
println!("Abort.");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Search all notes that contain a given string.
|
|
||||||
pub fn search_by_word(word: &str) -> Result<()> {
|
|
||||||
extern crate fstream;
|
|
||||||
let path = get_base_path()?;
|
let path = get_base_path()?;
|
||||||
let mut paths: Vec<String> = Vec::new();
|
let mut paths: Vec<String> = Vec::new();
|
||||||
for (_, file) in WalkDir::new(path)
|
for (_, file) in WalkDir::new(path)
|
||||||
@ -174,10 +145,115 @@ pub fn search_by_word(word: &str) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(paths)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new note.
|
||||||
|
pub fn create(header: &str, category: &str) -> Result<()> {
|
||||||
|
let editor = env::var("EDITOR")?;
|
||||||
|
let file = format!("{}{}.md", get_category_path(category)?, header);
|
||||||
|
create_dir(category)?;
|
||||||
|
is_duplicate(header, category)?;
|
||||||
|
let mut f = fs::File::create(&file)?;
|
||||||
|
f.set_permissions(fs::Permissions::from_mode(0o600))?;
|
||||||
|
f.write(format!("# {}\n", header).as_bytes())?;
|
||||||
|
Command::new(editor).arg(&file).status()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if potentially new note name already exists.
|
||||||
|
fn is_duplicate(header: &str, category: &str) -> Result<()> {
|
||||||
|
let file = format!("{}{}.md", get_category_path(category)?, header);
|
||||||
|
let path = format!("{}", get_category_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(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find a path to desired note and prompt to choose one to open.
|
||||||
|
pub fn get_note_path_interractive(header: &str) -> Result<Option<String>> {
|
||||||
|
let mut paths: Vec<String> = get_note_path(header)?;
|
||||||
|
let mut p: Vec<String> = paths.clone();
|
||||||
|
let r = p[0].find("rnote").unwrap_or(0);
|
||||||
|
p = p.into_iter().map(|mut s| s.drain(r..).collect()).collect();
|
||||||
|
if paths.len() == 1 {
|
||||||
|
Ok(Some(paths.remove(0)))
|
||||||
|
} else {
|
||||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||||
.with_prompt("Optionally choose a note")
|
.with_prompt("Optionally choose a note")
|
||||||
.default(0)
|
.default(0)
|
||||||
.items(&paths)
|
.items(&p)
|
||||||
|
.interact_opt()?;
|
||||||
|
match selection {
|
||||||
|
Some(s) => Ok(Some(paths.remove(s))),
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete a note.
|
||||||
|
pub fn remove_note(path: &str) -> Result<()> {
|
||||||
|
println!("Deleting...");
|
||||||
|
fs::remove_file(path)?;
|
||||||
|
remove_empty_dirs()?;
|
||||||
|
println!("Successfully deleted.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prompt user to delete a note.
|
||||||
|
pub fn remove_interractive(header: &str) -> Result<()> {
|
||||||
|
let path = get_note_path_interractive(header)?;
|
||||||
|
if path.is_none() {
|
||||||
|
return Err(anyhow!("Abort."));
|
||||||
|
}
|
||||||
|
if Confirm::with_theme(&ColorfulTheme::default())
|
||||||
|
.with_prompt(format!("Do you want to delete {}?", header))
|
||||||
|
.interact()?
|
||||||
|
{
|
||||||
|
remove_note(&path.unwrap())?;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("Abort."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify a note.
|
||||||
|
pub fn modify(header: &str) -> Result<()> {
|
||||||
|
let editor = env::var("EDITOR")?;
|
||||||
|
let file = get_note_path_interractive(header)?;
|
||||||
|
match file {
|
||||||
|
Some(f) => {
|
||||||
|
Command::new(editor).arg(f).status()?;
|
||||||
|
println!("Edited successfully!");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
println!("Abort.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prompt user to open one of found notes by word.
|
||||||
|
pub fn search_by_word(word: &str) -> Result<()> {
|
||||||
|
let mut paths: Vec<String> = get_files_by_word(word)?;
|
||||||
|
let mut p: Vec<String> = paths.clone();
|
||||||
|
let r = p[0].find("rnote").unwrap_or(0);
|
||||||
|
p = p.into_iter().map(|mut s| s.drain(r..).collect()).collect();
|
||||||
|
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||||
|
.with_prompt("Optionally choose a note")
|
||||||
|
.default(0)
|
||||||
|
.items(&p)
|
||||||
.interact_opt()?;
|
.interact_opt()?;
|
||||||
if let Some(selection) = selection {
|
if let Some(selection) = selection {
|
||||||
let editor = std::env::var("EDITOR")?;
|
let editor = std::env::var("EDITOR")?;
|
||||||
@ -191,9 +267,9 @@ pub fn search_by_word(word: &str) -> Result<()> {
|
|||||||
|
|
||||||
/// Show all notes.
|
/// Show all notes.
|
||||||
pub fn show_all() -> Result<()> {
|
pub fn show_all() -> Result<()> {
|
||||||
let path = get_base_path()?;
|
let base: String = get_base_path()?;
|
||||||
let mut files: Vec<String> = Vec::new();
|
let mut files: Vec<String> = Vec::new();
|
||||||
for (_, file) in WalkDir::new(path)
|
for (_, file) in WalkDir::new(base)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|file| file.ok())
|
.filter_map(|file| file.ok())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@ -210,7 +286,7 @@ pub fn show_all() -> Result<()> {
|
|||||||
|
|
||||||
/// Show one note.
|
/// Show one note.
|
||||||
pub fn show(header: &str) -> Result<()> {
|
pub fn show(header: &str) -> Result<()> {
|
||||||
let path = find_path(header)?;
|
let path = get_note_path_interractive(header)?;
|
||||||
match path {
|
match path {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
let skin = show::make_skin();
|
let skin = show::make_skin();
|
||||||
@ -240,30 +316,22 @@ pub fn show_category(category: &str) -> Result<()> {
|
|||||||
let skin = show::make_skin();
|
let skin = show::make_skin();
|
||||||
let md = &files.join("---\n");
|
let md = &files.join("---\n");
|
||||||
show::run_app(skin, md)?;
|
show::run_app(skin, md)?;
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("Category does not exist."))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List all notes and optionally open one.
|
/// List all notes and prompt to open one.
|
||||||
pub fn list_all() -> Result<()> {
|
pub fn list_all_notes() -> Result<()> {
|
||||||
let path = get_base_path()?;
|
let mut files: Vec<String> = get_all_notes()?;
|
||||||
let mut files: Vec<String> = Vec::new();
|
let mut p: Vec<String> = files.clone();
|
||||||
for (_, file) in WalkDir::new(path)
|
let r = p[0].find("rnote").unwrap_or(0);
|
||||||
.into_iter()
|
p = p.into_iter().map(|mut s| s.drain(r..).collect()).collect();
|
||||||
.filter_map(|file| file.ok())
|
|
||||||
.enumerate()
|
|
||||||
{
|
|
||||||
if file.metadata()?.is_file() {
|
|
||||||
let p = file.path().to_str().unwrap_or("");
|
|
||||||
if !p.is_empty() {
|
|
||||||
files.push(p.to_owned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||||
.with_prompt("Optionally choose a note")
|
.with_prompt("Optionally choose a note")
|
||||||
.default(0)
|
.default(0)
|
||||||
.items(&files)
|
.items(&p)
|
||||||
.interact_opt()?;
|
.interact_opt()?;
|
||||||
if let Some(selection) = selection {
|
if let Some(selection) = selection {
|
||||||
let editor = std::env::var("EDITOR")?;
|
let editor = std::env::var("EDITOR")?;
|
||||||
@ -276,26 +344,14 @@ pub fn list_all() -> Result<()> {
|
|||||||
|
|
||||||
/// List all notes in the given category and optionally open one.
|
/// List all notes in the given category and optionally open one.
|
||||||
pub fn list_category(category: &str) -> Result<()> {
|
pub fn list_category(category: &str) -> Result<()> {
|
||||||
let base = get_base_path()?;
|
let mut files: Vec<String> = get_notes_in_category(category)?;
|
||||||
let path = format!("{}{}", base, category);
|
let mut p: Vec<String> = files.clone();
|
||||||
let mut files: Vec<String> = Vec::new();
|
let r = p[0].find("rnote").unwrap_or(0);
|
||||||
if std::path::Path::new(&path).exists() {
|
p = p.into_iter().map(|mut s| s.drain(r..).collect()).collect();
|
||||||
for (_, file) in WalkDir::new(path)
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|file| file.ok())
|
|
||||||
.enumerate()
|
|
||||||
{
|
|
||||||
if file.metadata()?.is_file() {
|
|
||||||
let p = file.path().to_str().unwrap_or("");
|
|
||||||
if !p.is_empty() {
|
|
||||||
files.push(p.to_owned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||||
.with_prompt("Optionally choose a note")
|
.with_prompt("Optionally choose a note")
|
||||||
.default(0)
|
.default(0)
|
||||||
.items(&files)
|
.items(&p)
|
||||||
.interact_opt()?;
|
.interact_opt()?;
|
||||||
if let Some(selection) = selection {
|
if let Some(selection) = selection {
|
||||||
let editor = std::env::var("EDITOR")?;
|
let editor = std::env::var("EDITOR")?;
|
||||||
@ -303,7 +359,6 @@ pub fn list_category(category: &str) -> Result<()> {
|
|||||||
.arg(files.remove(selection))
|
.arg(files.remove(selection))
|
||||||
.status()?;
|
.status()?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,3 +401,57 @@ fn remove_empty_dirs() -> Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure to remove rnote directory before tests.
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_base_path_test() {
|
||||||
|
assert!(get_base_path().is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn find_by_word_test() {
|
||||||
|
assert!(create("test", "test_word").is_ok());
|
||||||
|
assert!(get_files_by_word("test").is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_note_path_test() {
|
||||||
|
assert!(create("test", "test_path").is_ok());
|
||||||
|
assert!(get_note_path("test").is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_category_path_create_dir_test() {
|
||||||
|
assert!(create_dir("test_dir").is_ok());
|
||||||
|
assert!(get_category_path("test").is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_remove_test() {
|
||||||
|
assert!(create("test1", "test1").is_ok());
|
||||||
|
let data_home = std::env::var("XDG_DATA_HOME").unwrap_or("".to_owned());
|
||||||
|
assert!(remove_note(&format!("{}/rnote/test1/test1.md", data_home)).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_empty_dirs_test() {
|
||||||
|
assert!(create_dir("test_empty").is_ok());
|
||||||
|
assert!(remove_empty_dirs().is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn wipe_date_test() {
|
||||||
|
assert!(wipe_date("1999-10-10").is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_notes_in_category_test() {
|
||||||
|
assert!(create("test", "test_c").is_ok());
|
||||||
|
assert!(get_notes_in_category("test_c").is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,7 +20,7 @@ pub fn new(matches: &ArgMatches) -> Result<()> {
|
|||||||
/// Process argument `remove`.
|
/// Process argument `remove`.
|
||||||
pub fn remove(matches: &ArgMatches) -> Result<()> {
|
pub fn remove(matches: &ArgMatches) -> Result<()> {
|
||||||
match matches.value_of("header") {
|
match matches.value_of("header") {
|
||||||
Some(s) => notes::remove(s)?,
|
Some(s) => notes::remove_interractive(s)?,
|
||||||
None => match matches.is_present("date") {
|
None => match matches.is_present("date") {
|
||||||
true => {
|
true => {
|
||||||
let date: String = Input::with_theme(&ColorfulTheme::default())
|
let date: String = Input::with_theme(&ColorfulTheme::default())
|
||||||
@ -33,7 +33,7 @@ pub fn remove(matches: &ArgMatches) -> Result<()> {
|
|||||||
let header: String = Input::with_theme(&ColorfulTheme::default())
|
let header: String = Input::with_theme(&ColorfulTheme::default())
|
||||||
.with_prompt("Name of your note")
|
.with_prompt("Name of your note")
|
||||||
.interact_text()?;
|
.interact_text()?;
|
||||||
notes::remove(&header)?;
|
notes::remove_interractive(&header)?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ pub fn list(matches: &ArgMatches) -> Result<()> {
|
|||||||
.interact_text()?;
|
.interact_text()?;
|
||||||
notes::list_category(&s)?;
|
notes::list_category(&s)?;
|
||||||
}
|
}
|
||||||
false => notes::list_all()?,
|
false => notes::list_all_notes()?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ pub fn list(matches: &ArgMatches) -> Result<()> {
|
|||||||
pub fn search(matches: &ArgMatches) -> Result<()> {
|
pub fn search(matches: &ArgMatches) -> Result<()> {
|
||||||
match matches.value_of("header") {
|
match matches.value_of("header") {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
let p = notes::find_path(s)?;
|
let p = notes::get_note_path_interractive(s)?;
|
||||||
match p {
|
match p {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
let editor = std::env::var("EDITOR")?;
|
let editor = std::env::var("EDITOR")?;
|
||||||
|
Loading…
Reference in New Issue
Block a user