Add runtime feature: Ignore id reporting

This feature gives the users of the Runtime API the possibility to check
whether the user wants the ID reporting to be ignored as well (and more
important) to override the default behaviour where the runtime assumes
that if STDOUT is a pipe, it is a pipe to an imag command.

Before, this would not have been possible:

    imag contact find Jonas --json | jq 'map(.fullname)'

because the runtime automatically prints the output of the command to
stderr and the touched IDs to stdout.
But now with this change, a user can override this default behaviour and
do:

    imag contact --ignore-ids find Jonas --json | jq 'map(.fullname)'

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
Matthias Beyer 2019-02-05 00:55:30 +01:00
parent b010d69e62
commit 3fbfb19419

View file

@ -62,6 +62,8 @@ pub struct Runtime<'a> {
has_output_pipe: bool,
has_input_pipe: bool,
ignore_ids: bool
}
impl<'a> Runtime<'a> {
@ -146,9 +148,11 @@ impl<'a> Runtime<'a> {
let has_output_pipe = !atty::is(atty::Stream::Stdout);
let has_input_pipe = !atty::is(atty::Stream::Stdin);
let ignore_ids = matches.is_present(Runtime::arg_ignore_ids_name());
debug!("has output pipe = {}", has_output_pipe);
debug!("has input pipe = {}", has_input_pipe);
debug!("ignore ids = {}", ignore_ids);
store_result.map(|store| Runtime {
cli_matches: matches,
@ -158,6 +162,7 @@ impl<'a> Runtime<'a> {
has_output_pipe,
has_input_pipe,
ignore_ids,
})
.context(err_msg("Cannot instantiate runtime"))
.map_err(Error::from)
@ -247,6 +252,13 @@ impl<'a> Runtime<'a> {
.takes_value(true)
.value_name("LOGDESTS"))
.arg(Arg::with_name(Runtime::arg_ignore_ids_name())
.long(Runtime::arg_ignore_ids_name())
.help("Do not assume that the output is a pipe to another imag command. This overrides the default behaviour where imag only prints the IDs of the touched entries to stdout if stdout is a pipe.")
.long_help("Without this flag, imag assumes that if stdout is a pipe, the command imag pipes to is also an imag command. Thus, it prints the IDs of the processed entries to stdout and automatically redirects the command output to stderr. By providing this flag, this behaviour gets overridden: The IDs are not printed at all and the normal output is printed to stdout.")
.required(false)
.takes_value(false))
}
/// Get the argument names of the Runtime which are available
@ -260,9 +272,15 @@ impl<'a> Runtime<'a> {
Runtime::arg_runtimepath_name(),
Runtime::arg_storepath_name(),
Runtime::arg_editor_name(),
Runtime::arg_ignore_ids_name(),
]
}
/// Get the normal-output argument name for the Runtime
pub fn arg_ignore_ids_name() -> &'static str {
"ignore-ids"
}
/// Get the verbosity argument name for the Runtime
pub fn arg_verbosity_name() -> &'static str {
"verbosity"
@ -461,8 +479,15 @@ impl<'a> Runtime<'a> {
self.has_output_pipe
}
/// Check whether the runtime ignores touched ids
///
/// "Ignoring" in this context means whether the runtime prints them or not.
pub fn ignore_ids(&self) -> bool {
self.ignore_ids
}
pub fn stdout(&self) -> OutputProxy {
if self.output_is_pipe() {
if self.output_is_pipe() && !self.ignore_ids {
OutputProxy::Err(::std::io::stderr())
} else {
OutputProxy::Out(::std::io::stdout())
@ -585,7 +610,7 @@ impl<'a> Runtime<'a> {
fn report_touched_id(&self, id: &StoreId, output: &mut StdoutLock) -> Result<()> {
use std::io::Write;
if self.output_is_pipe() {
if self.output_is_pipe() && !self.ignore_ids {
trace!("Reporting: {} to {:?}", id, output);
writeln!(output, "{}", id)?;
}