Auto merge of #52 - matthiasbeyer:notes-open, r=matthiasbeyer

Notes open

Open notes as HTML pages in browser.

Does not work fully by now, as one note should be opened, but two are opened, one in browser, one in libreoffice.

Closes #47
This commit is contained in:
Homu 2016-01-05 23:21:04 +09:00
commit 3b31fbfa3e
7 changed files with 178 additions and 0 deletions

1
Cargo.lock generated
View file

@ -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)",

View file

@ -28,4 +28,5 @@ open = "1.1.0"
itertools = "0.4.5"
hoedown = "3.0.3"
ansi_term = "0.7.1"
rand = "0.3"

View file

@ -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 <mail@beyermatthias.de>
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

View file

@ -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;

View file

@ -68,6 +68,30 @@ 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"))
}
pub fn to_html_page(self) -> String {
let header = "
<html>
<head>
<meta http-equiv='content-type' content='text/html; charset=utf-8'>
</head>
<body>
";
let content = self.to_html();
let footer = "</body></html>";
format!("{}{}{}", header, content, footer)
}
}
}

View file

@ -124,6 +124,101 @@ impl<'a> Notes<'a> {
return failed == 0;
}
fn command_open(&self, matches: &ArgMatches) -> bool {
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!("# {} <small>({})</small>", 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 {
use ansi_term::Colour::{Red, Green};
use ui::file::{FilePrinter, TablePrinter};
@ -361,6 +456,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())
},

View file

@ -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::<u64>(), ext);
debug!("Attempting to create tempfile at {}", randomname);
File::create(randomname.clone())
.map_err(|e| debug!(" Error -> {}", e))
.ok()
.map(|f| (randomname, f))
}