Merge pull request #1376 from matthiasbeyer/imag-view/multiple-ids
imag-view: Add support for viewing multiple entries
This commit is contained in:
commit
1d5171d770
3 changed files with 124 additions and 76 deletions
|
@ -54,11 +54,18 @@ use handlebars::Handlebars;
|
||||||
use toml_query::read::TomlValueReadTypeExt;
|
use toml_query::read::TomlValueReadTypeExt;
|
||||||
|
|
||||||
use libimagrt::setup::generate_runtime_setup;
|
use libimagrt::setup::generate_runtime_setup;
|
||||||
|
use libimagrt::runtime::Runtime;
|
||||||
use libimagerror::str::ErrFromStr;
|
use libimagerror::str::ErrFromStr;
|
||||||
use libimagerror::trace::MapErrTrace;
|
use libimagerror::trace::MapErrTrace;
|
||||||
|
use libimagerror::iter::TraceIterator;
|
||||||
use libimagentryview::builtin::stdout::StdoutViewer;
|
use libimagentryview::builtin::stdout::StdoutViewer;
|
||||||
use libimagentryview::viewer::Viewer;
|
use libimagentryview::viewer::Viewer;
|
||||||
use libimagentryview::error::ViewError as VE;
|
use libimagentryview::error::ViewError as VE;
|
||||||
|
use libimagstore::storeid::IntoStoreId;
|
||||||
|
use libimagstore::error::StoreError;
|
||||||
|
use libimagstore::iter::get::StoreIdGetIteratorExtension;
|
||||||
|
use libimagstore::store::FileLockEntry;
|
||||||
|
use libimagstore::storeid::StoreId;
|
||||||
|
|
||||||
mod ui;
|
mod ui;
|
||||||
use ui::build_ui;
|
use ui::build_ui;
|
||||||
|
@ -70,85 +77,64 @@ fn main() {
|
||||||
"View entries (readonly)",
|
"View entries (readonly)",
|
||||||
build_ui);
|
build_ui);
|
||||||
|
|
||||||
let entry_id = rt.cli().value_of("id").unwrap(); // enforced by clap
|
let entry_ids = entry_ids(&rt);
|
||||||
let view_header = rt.cli().is_present("view-header");
|
let view_header = rt.cli().is_present("view-header");
|
||||||
let hide_content = rt.cli().is_present("not-view-content");
|
let hide_content = rt.cli().is_present("not-view-content");
|
||||||
|
|
||||||
let entry = match rt.store().get(PathBuf::from(entry_id)).map_err_trace_exit_unwrap(1) {
|
|
||||||
Some(fle) => fle,
|
|
||||||
None => {
|
|
||||||
error!("Cannot get {}, there is no such id in the store", entry_id);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if rt.cli().is_present("in") {
|
if rt.cli().is_present("in") {
|
||||||
let viewer = rt
|
let files = entry_ids
|
||||||
.cli()
|
.into_iter()
|
||||||
.value_of("in")
|
.into_get_iter(rt.store())
|
||||||
.ok_or_else::<VE, _>(|| "No viewer given".to_owned().into())
|
.map(|e| {
|
||||||
.map_err_trace_exit_unwrap(1);
|
e.map_err_trace_exit_unwrap(1)
|
||||||
|
.ok_or_else(|| String::from("BUG"))
|
||||||
let config = rt
|
.map_err(StoreError::from)
|
||||||
.config()
|
.map_err_trace_exit_unwrap(1)
|
||||||
.ok_or_else::<VE, _>(|| "No configuration, cannot continue".to_owned().into())
|
})
|
||||||
.map_err_trace_exit_unwrap(1);
|
.map(|entry| create_tempfile_for(&entry, view_header, hide_content))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let query = format!("view.viewers.{}", viewer);
|
|
||||||
|
|
||||||
let viewer_template = config
|
|
||||||
.read_string(&query)
|
|
||||||
.map_err_trace_exit_unwrap(1)
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
error!("Cannot find '{}' in config", query);
|
|
||||||
exit(1)
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut handlebars = Handlebars::new();
|
|
||||||
handlebars.register_escape_fn(::handlebars::no_escape);
|
|
||||||
|
|
||||||
let _ = handlebars
|
|
||||||
.register_template_string("template", viewer_template)
|
|
||||||
.err_from_str()
|
|
||||||
.map_err(VE::from)
|
|
||||||
.map_err_trace_exit_unwrap(1);
|
|
||||||
|
|
||||||
let file = {
|
|
||||||
let mut tmpfile = tempfile::NamedTempFile::new()
|
|
||||||
.err_from_str()
|
|
||||||
.map_err(VE::from)
|
|
||||||
.map_err_trace_exit_unwrap(1);
|
|
||||||
if view_header {
|
|
||||||
let hdr = toml::ser::to_string_pretty(entry.get_header())
|
|
||||||
.err_from_str()
|
|
||||||
.map_err(VE::from)
|
|
||||||
.map_err_trace_exit_unwrap(1);
|
|
||||||
let _ = tmpfile.write(format!("---\n{}---\n", hdr).as_bytes())
|
|
||||||
.err_from_str()
|
|
||||||
.map_err(VE::from)
|
|
||||||
.map_err_trace_exit_unwrap(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hide_content {
|
|
||||||
let _ = tmpfile.write(entry.get_content().as_bytes())
|
|
||||||
.err_from_str()
|
|
||||||
.map_err(VE::from)
|
|
||||||
.map_err_trace_exit_unwrap(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpfile
|
|
||||||
};
|
|
||||||
|
|
||||||
let file_path = file
|
|
||||||
.path()
|
|
||||||
.to_str()
|
|
||||||
.map(String::from)
|
|
||||||
.ok_or::<VE>("Cannot build path".to_owned().into())
|
|
||||||
.map_err_trace_exit_unwrap(1);
|
|
||||||
|
|
||||||
let mut command = {
|
let mut command = {
|
||||||
|
let viewer = rt
|
||||||
|
.cli()
|
||||||
|
.value_of("in")
|
||||||
|
.ok_or_else::<VE, _>(|| "No viewer given".to_owned().into())
|
||||||
|
.map_err_trace_exit_unwrap(1);
|
||||||
|
|
||||||
|
let config = rt
|
||||||
|
.config()
|
||||||
|
.ok_or_else::<VE, _>(|| "No configuration, cannot continue".to_owned().into())
|
||||||
|
.map_err_trace_exit_unwrap(1);
|
||||||
|
|
||||||
|
let query = format!("view.viewers.{}", viewer);
|
||||||
|
|
||||||
|
let viewer_template = config
|
||||||
|
.read_string(&query)
|
||||||
|
.map_err_trace_exit_unwrap(1)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
error!("Cannot find '{}' in config", query);
|
||||||
|
exit(1)
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut handlebars = Handlebars::new();
|
||||||
|
handlebars.register_escape_fn(::handlebars::no_escape);
|
||||||
|
|
||||||
|
let _ = handlebars
|
||||||
|
.register_template_string("template", viewer_template)
|
||||||
|
.err_from_str()
|
||||||
|
.map_err(VE::from)
|
||||||
|
.map_err_trace_exit_unwrap(1);
|
||||||
|
|
||||||
let mut data = BTreeMap::new();
|
let mut data = BTreeMap::new();
|
||||||
data.insert("entry", file_path);
|
|
||||||
|
let file_paths = files
|
||||||
|
.iter()
|
||||||
|
.map(|&(_, ref path)| path.clone())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
data.insert("entries", file_paths);
|
||||||
|
|
||||||
let call = handlebars
|
let call = handlebars
|
||||||
.render("template", &data)
|
.render("template", &data)
|
||||||
|
@ -169,6 +155,8 @@ fn main() {
|
||||||
cmd
|
cmd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
debug!("Calling: {:?}", command);
|
||||||
|
|
||||||
if !command
|
if !command
|
||||||
.status()
|
.status()
|
||||||
.err_from_str()
|
.err_from_str()
|
||||||
|
@ -178,10 +166,69 @@ fn main() {
|
||||||
{
|
{
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop(files);
|
||||||
} else {
|
} else {
|
||||||
let _ = StdoutViewer::new(view_header, !hide_content)
|
let viewer = StdoutViewer::new(view_header, !hide_content);
|
||||||
.view_entry(&entry)
|
|
||||||
.map_err_trace_exit_unwrap(1);
|
entry_ids
|
||||||
|
.into_iter()
|
||||||
|
.into_get_iter(rt.store())
|
||||||
|
.map(|e| {
|
||||||
|
e.map_err_trace_exit_unwrap(1)
|
||||||
|
.ok_or_else(|| String::from("BUG"))
|
||||||
|
.map_err(StoreError::from)
|
||||||
|
.map_err_trace_exit_unwrap(1)
|
||||||
|
})
|
||||||
|
.for_each(|e| {
|
||||||
|
viewer.view_entry(&e).map_err_trace_exit_unwrap(1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn entry_ids(rt: &Runtime) -> Vec<StoreId> {
|
||||||
|
rt.cli()
|
||||||
|
.values_of("id")
|
||||||
|
.unwrap() // enforced by clap
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.map(PathBuf::into_storeid)
|
||||||
|
.trace_unwrap_exit(1)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_tempfile_for<'a>(entry: &FileLockEntry<'a>, view_header: bool, hide_content: bool)
|
||||||
|
-> (tempfile::NamedTempFile, String)
|
||||||
|
{
|
||||||
|
let mut tmpfile = tempfile::NamedTempFile::new()
|
||||||
|
.err_from_str()
|
||||||
|
.map_err(VE::from)
|
||||||
|
.map_err_trace_exit_unwrap(1);
|
||||||
|
|
||||||
|
if view_header {
|
||||||
|
let hdr = toml::ser::to_string_pretty(entry.get_header())
|
||||||
|
.err_from_str()
|
||||||
|
.map_err(VE::from)
|
||||||
|
.map_err_trace_exit_unwrap(1);
|
||||||
|
let _ = tmpfile.write(format!("---\n{}---\n", hdr).as_bytes())
|
||||||
|
.err_from_str()
|
||||||
|
.map_err(VE::from)
|
||||||
|
.map_err_trace_exit_unwrap(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hide_content {
|
||||||
|
let _ = tmpfile.write(entry.get_content().as_bytes())
|
||||||
|
.err_from_str()
|
||||||
|
.map_err(VE::from)
|
||||||
|
.map_err_trace_exit_unwrap(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = tmpfile
|
||||||
|
.path()
|
||||||
|
.to_str()
|
||||||
|
.map(String::from)
|
||||||
|
.ok_or::<VE>("Cannot build path".to_owned().into())
|
||||||
|
.map_err_trace_exit_unwrap(1);
|
||||||
|
|
||||||
|
(tmpfile, file_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
|
||||||
.index(1)
|
.index(1)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.required(true)
|
.required(true)
|
||||||
|
.multiple(true)
|
||||||
.help("View this entry at this store path")
|
.help("View this entry at this store path")
|
||||||
.value_name("ID"))
|
.value_name("ID"))
|
||||||
|
|
||||||
|
|
|
@ -270,8 +270,8 @@ default_collection = "default"
|
||||||
|
|
||||||
[view.viewers]
|
[view.viewers]
|
||||||
# Configure which viewers there are for `imag view <entry> in <viewer>`.
|
# Configure which viewers there are for `imag view <entry> in <viewer>`.
|
||||||
editor = "vim -R {{entry}}"
|
editor = "vim -R {{entries}}"
|
||||||
web = "chromium {{entry}}"
|
web = "chromium {{entries}}"
|
||||||
|
|
||||||
[contact]
|
[contact]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue