diff --git a/bin/domain/imag-log/Cargo.toml b/bin/domain/imag-log/Cargo.toml index 6db308e6..38646041 100644 --- a/bin/domain/imag-log/Cargo.toml +++ b/bin/domain/imag-log/Cargo.toml @@ -28,6 +28,7 @@ toml-query = "0.8" is-match = "0.1" itertools = "0.7" failure = "0.1" +textwrap = "0.10" libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" } libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } diff --git a/bin/domain/imag-log/src/main.rs b/bin/domain/imag-log/src/main.rs index 2f985e6a..6110dd90 100644 --- a/bin/domain/imag-log/src/main.rs +++ b/bin/domain/imag-log/src/main.rs @@ -41,6 +41,7 @@ extern crate toml; extern crate toml_query; extern crate itertools; extern crate failure; +extern crate textwrap; extern crate libimaglog; #[macro_use] extern crate libimagrt; @@ -49,6 +50,9 @@ extern crate libimagerror; extern crate libimagdiary; use std::io::Write; +use std::io::Cursor; +use std::result::Result as RResult; +use std::str::FromStr; use failure::Error; use failure::err_msg; @@ -61,8 +65,10 @@ use libimagerror::exit::ExitUnwrap; use libimagerror::iter::TraceIterator; use libimagerror::exit::ExitCode; use libimagdiary::diary::Diary; +use libimagdiary::diaryid::DiaryId; use libimaglog::log::Log; use libimagstore::iter::get::StoreIdGetIteratorExtension; +use libimagstore::store::FileLockEntry; mod ui; use ui::build_ui; @@ -142,6 +148,18 @@ fn show(rt: &Runtime) { } }; + let mut do_wrap = if scmd.is_present("show-wrap") { + Some(80) + } else { + None + }; + + if let Some(wrap_value) = scmd.value_of("show-wrap") { + do_wrap = Some(usize::from_str(wrap_value).map_err(Error::from).map_err_trace_exit_unwrap()); + } + + let mut output = rt.stdout(); + Itertools::flatten(iters.into_iter()) .into_get_iter(rt.store()) .trace_unwrap_exit() @@ -158,16 +176,24 @@ fn show(rt: &Runtime) { .into_iter() .map(|tpl| { debug!("Found entry: {:?}", tpl.1); tpl }) .map(|(id, entry)| { - let _ = writeln!(rt.stdout(), - "{dname: >10} - {y: >4}-{m:0>2}-{d:0>2}T{H:0>2}:{M:0>2} - {text}", - dname = id.diary_name(), - y = id.year(), - m = id.month(), - d = id.day(), - H = id.hour(), - M = id.minute(), - text = entry.get_content().trim_right()) - .to_exit_code()?; + if let Some(wrap_limit) = do_wrap { + // assume a capacity here: + // diaryname + year + month + day + hour + minute + delimiters + whitespace + // 10 + 4 + 2 + 2 + 2 + 2 + 6 + 4 = 32 + // plus text, which we assume to be 120 characters... lets allocate 256 bytes. + let mut buffer = Cursor::new(Vec::with_capacity(256)); + let _ = do_write_to(&mut buffer, id, &entry).unwrap_or_exit(); + let buffer = String::from_utf8(buffer.into_inner()) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + + // now lets wrap + for line in ::textwrap::wrap(&buffer, wrap_limit).iter() { + let _ = writeln!(&mut output, "{}", line).to_exit_code()?; + } + } else { + let _ = do_write_to(&mut output, id, &entry).unwrap_or_exit(); + } let _ = rt .report_touched(entry.get_location()) @@ -237,3 +263,17 @@ fn get_log_text(rt: &Runtime) -> String { acc }) } + +fn do_write_to<'a>(sink: &mut Write, id: DiaryId, entry: &FileLockEntry<'a>) -> RResult<(), ExitCode> { + writeln!(sink, + "{dname: >10} - {y: >4}-{m:0>2}-{d:0>2}T{H:0>2}:{M:0>2} - {text}", + dname = id.diary_name(), + y = id.year(), + m = id.month(), + d = id.day(), + H = id.hour(), + M = id.minute(), + text = entry.get_content().trim_right()) + .to_exit_code() +} + diff --git a/bin/domain/imag-log/src/ui.rs b/bin/domain/imag-log/src/ui.rs index 1b0d21cd..bc4bad89 100644 --- a/bin/domain/imag-log/src/ui.rs +++ b/bin/domain/imag-log/src/ui.rs @@ -57,6 +57,14 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .conflicts_with("show-all") .help("Show logs. Multiple possible (will be sorted by date, still).")) + .arg(Arg::with_name("show-wrap") + .long("wrap") + .short("w") + .takes_value(true) + .multiple(false) + .required(false) + .help("Wrap at N characters, defaults to 80.")) + ) }