From 1d53b2d8ec4f219a96ff61aeff5d7478676b1373 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 3 Jan 2016 16:43:48 +0100 Subject: [PATCH 1/7] notes: open: Add cli spec --- etc/cli.yml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/etc/cli.yml b/etc/cli.yml index 955c6ac7..a7b7de64 100644 --- a/etc/cli.yml +++ b/etc/cli.yml @@ -314,6 +314,45 @@ subcommands: required: false takes_value: true + - open: + about: Open notes as HTML page in browser (via XDG-open) + version: 0.1 + author: Matthias Beyer + args: + - onepage: + long: onepage + short: o + help: Open notes as one page + required: false + takes_value: false + + - id: + long: id + help: Open note with this ID + required: false + takes_value: true + + - namegrep: + short: n + long: name + help: Open where name matches this regex + required: false + takes_value: true + + - grep: + short: g + long: grep + help: Open where grep with regex finds something + required: false + takes_value: true + + - tags: + short: t + long: tags + help: Open all notes with these tags + required: false + takes_value: true + - list: about: List notes version: 0.1 From 90756a93c7a8b43ca5a72019d394bf5b21c56110 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 3 Jan 2016 16:43:56 +0100 Subject: [PATCH 2/7] Add command_open stub --- src/module/notes/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/module/notes/mod.rs b/src/module/notes/mod.rs index 7662f851..48b4dcdd 100644 --- a/src/module/notes/mod.rs +++ b/src/module/notes/mod.rs @@ -124,6 +124,10 @@ impl<'a> Notes<'a> { return failed == 0; } + fn command_open(&self, matches: &ArgMatches) -> bool { + unimplemented!() + } + fn command_list(&self, matches: &ArgMatches) -> bool { use ansi_term::Colour::{Red, Green}; use ui::file::{FilePrinter, TablePrinter}; @@ -361,6 +365,10 @@ impl<'a> Module<'a> for Notes<'a> { self.command_edit(matches.subcommand_matches("edit").unwrap()) }, + Some("open") => { + self.command_open(matches.subcommand_matches("open").unwrap()) + }, + Some("list") => { self.command_list(matches.subcommand_matches("list").unwrap()) }, From adf12992bb3510acd3800a6434d0030c3402d65c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 3 Jan 2016 16:59:31 +0100 Subject: [PATCH 3/7] Add dep: rand --- Cargo.lock | 1 + Cargo.toml | 1 + src/main.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 105498e3..61a216b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,7 @@ dependencies = [ "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "prettytable-rs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 9a513a53..45898863 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,4 +28,5 @@ open = "1.1.0" itertools = "0.4.5" hoedown = "3.0.3" ansi_term = "0.7.1" +rand = "0.3" diff --git a/src/main.rs b/src/main.rs index 3348a680..52ac03d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ extern crate config; extern crate open; extern crate itertools; extern crate ansi_term; +extern crate rand; pub use cli::CliConfig; pub use configuration::Configuration; From 62ced34964e50cbb6ec473b7180cfba1d37d14f4 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 3 Jan 2016 17:19:29 +0100 Subject: [PATCH 4/7] Add helper: get_tempfile() --- src/ui/external/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/ui/external/mod.rs b/src/ui/external/mod.rs index 07699817..a6a128c1 100644 --- a/src/ui/external/mod.rs +++ b/src/ui/external/mod.rs @@ -1 +1,14 @@ +use std::fs::File; + pub mod editor; + +pub fn get_tempfile(ext: &str) -> Option<(String, File)> { + use rand::random; + + let randomname = format!("/tmp/imag-{}.{}", random::(), ext); + debug!("Attempting to create tempfile at {}", randomname); + File::create(randomname.clone()) + .map_err(|e| debug!(" Error -> {}", e)) + .ok() + .map(|f| (randomname, f)) +} From 06996ee903cc354dad8c2d9acd4c34c09881fb45 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 3 Jan 2016 17:19:49 +0100 Subject: [PATCH 5/7] Add Markdown->HTML parsing --- src/module/helpers/content.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/module/helpers/content.rs b/src/module/helpers/content.rs index d896bcdf..4479a39e 100644 --- a/src/module/helpers/content.rs +++ b/src/module/helpers/content.rs @@ -68,6 +68,17 @@ pub mod markdown { renderer.extract() } + pub fn to_html(self) -> String { + use hoedown::renderer::html::Html; + use hoedown::renderer::html; + + String::from( + Html::new(html::Flags::empty(), 0) + .render(&self.text) + .to_str() + .unwrap_or("UTF8Error")) + } + } } From 64a2c30a75b3f44ee9fbb3dbabf19c1bbfb4d9d6 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 5 Jan 2016 15:19:19 +0100 Subject: [PATCH 6/7] Add helper to put content into tags --- src/module/helpers/content.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/module/helpers/content.rs b/src/module/helpers/content.rs index 4479a39e..08711368 100644 --- a/src/module/helpers/content.rs +++ b/src/module/helpers/content.rs @@ -79,6 +79,19 @@ pub mod markdown { .unwrap_or("UTF8Error")) } + pub fn to_html_page(self) -> String { + let header = " + + + + + + "; + let content = self.to_html(); + let footer = ""; + format!("{}{}{}", header, content, footer) + } + } } From dbed6934cc090b68bc3462ad6e96f842a7c96711 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 3 Jan 2016 17:19:59 +0100 Subject: [PATCH 7/7] Notes: Add command_open() implementation --- src/module/notes/mod.rs | 93 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/src/module/notes/mod.rs b/src/module/notes/mod.rs index 48b4dcdd..cd86f118 100644 --- a/src/module/notes/mod.rs +++ b/src/module/notes/mod.rs @@ -125,7 +125,98 @@ impl<'a> Notes<'a> { } fn command_open(&self, matches: &ArgMatches) -> bool { - unimplemented!() + use std::io::Write; + use std::process::exit; + + use open; + + use self::header::get_name_from_header; + use ui::external::get_tempfile; + + use module::helpers::content::markdown::MarkdownParser; + + let parser = Parser::new(JsonHeaderParser::new(None)); + + let filter = { + let hash_filter = create_hash_filter(matches, "id", true); + let head_filter = create_text_header_field_grep_filter(matches, "match", "NAME", true); + let text_filter = create_content_grep_filter(matches, "match", true); + let tags_filter = create_tag_filter(matches, "tags", true); + hash_filter.and(Box::new(head_filter)).and(Box::new(text_filter)).and(Box::new(tags_filter)) + }; + + let files = self.rt + .store() + .load_for_module(self, &parser) + .into_iter() + .filter(|file| { + let res = filter.filter_file(file); + debug!("Filter: {} -> {}", file.deref().borrow().id(), res); + res + }); + + if matches.is_present("onepage") { + let tmpcontent = files.fold(String::new(), |acc, file| { + let heading = { + let name = get_name_from_header(file.deref().borrow().header()); + if name.len() == 0 { + format!("# {}", file.deref().borrow().id) + } else { + format!("# {} ({})", name, file.deref().borrow().id()) + } + }; + + format!("{}\n\n{}\n\n{}", acc, heading, file.deref().borrow().data()) + }); + + let (temppath, mut tempfile) = match get_tempfile("html") { + Some(tpl) => tpl, + None => { + error!("Could not create tempfile"); + exit(1); + } + }; + + let html = MarkdownParser::new(&tmpcontent).to_html_page(); + + tempfile.write_all(html.as_ref()); + open::that(&temppath[..]).is_ok() + } else { + let result = files.map(|file| { + let (temppath, mut tempfile) = match get_tempfile("html") { + Some(tpl) => tpl, + None => { + error!("Could not create tempfile"); + exit(1); + } + }; + + let content = format!("# {}\n\n{}", + get_name_from_header(file.deref().borrow().header()), + file.deref().borrow().data()); + + let html = MarkdownParser::new(&content).to_html_page(); + + tempfile.write_all(html.as_ref()); + open::that(&temppath[..]).is_ok() + }) + .fold((0, 0), |acc, succeeded| { + let (worked, failed) = acc; + if succeeded { + (worked + 1, failed) + } else { + (worked, failed + 1) + } + }); + + let (worked, failed) = result; + + info!("Opening as HTML page succeeded for {} files", worked); + info!("Opening as HTML page failed for {} files", failed); + + failed == 0 + } + } fn command_list(&self, matches: &ArgMatches) -> bool {