mirror of
https://github.com/nushell/nushell
synced 2024-12-27 21:43:09 +00:00
add -e flag to print, to print the value to stderr (#5935)
* Refactor: make stdout write all and flush as generic function * support print to stderr
This commit is contained in:
parent
be7f35246e
commit
84caf8859f
8 changed files with 64 additions and 16 deletions
|
@ -21,6 +21,7 @@ impl Command for Print {
|
|||
"print without inserting a newline for the line ending",
|
||||
Some('n'),
|
||||
)
|
||||
.switch("stderr", "print to stderr instead of stdout", Some('e'))
|
||||
.category(Category::Strings)
|
||||
}
|
||||
|
||||
|
@ -48,11 +49,12 @@ Since this command has no output, there is no point in piping it with other comm
|
|||
) -> Result<PipelineData, ShellError> {
|
||||
let args: Vec<Value> = call.rest(engine_state, stack, 0)?;
|
||||
let no_newline = call.has_flag("no-newline");
|
||||
let to_stderr = call.has_flag("stderr");
|
||||
let head = call.head;
|
||||
|
||||
for arg in args {
|
||||
arg.into_pipeline_data()
|
||||
.print(engine_state, stack, no_newline)?;
|
||||
.print(engine_state, stack, no_newline, to_stderr)?;
|
||||
}
|
||||
|
||||
Ok(PipelineData::new(head))
|
||||
|
|
|
@ -247,7 +247,7 @@ pub fn eval_source(
|
|||
set_last_exit_code(stack, 0);
|
||||
}
|
||||
|
||||
if let Err(err) = pipeline_data.print(engine_state, stack, false) {
|
||||
if let Err(err) = pipeline_data.print(engine_state, stack, false, false) {
|
||||
let working_set = StateWorkingSet::new(engine_state);
|
||||
|
||||
report_error(&working_set, &err);
|
||||
|
|
|
@ -216,7 +216,7 @@ impl Command for Watch {
|
|||
|
||||
match eval_result {
|
||||
Ok(val) => {
|
||||
val.print(engine_state, stack, false)?;
|
||||
val.print(engine_state, stack, false, false)?;
|
||||
}
|
||||
Err(err) => {
|
||||
let working_set = StateWorkingSet::new(engine_state);
|
||||
|
|
|
@ -44,6 +44,7 @@ mod open;
|
|||
mod parse;
|
||||
mod path;
|
||||
mod prepend;
|
||||
mod print;
|
||||
#[cfg(feature = "database")]
|
||||
mod query;
|
||||
mod random;
|
||||
|
|
23
crates/nu-command/tests/commands/print.rs
Normal file
23
crates/nu-command/tests/commands/print.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn print_to_stdout() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
"print 'hello world'"
|
||||
)
|
||||
);
|
||||
assert!(actual.out.contains("hello world"));
|
||||
assert!(actual.err.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn print_to_stderr() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
"print -e 'hello world'"
|
||||
)
|
||||
);
|
||||
assert!(actual.out.is_empty());
|
||||
assert!(actual.err.contains("hello world"));
|
||||
}
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
engine::{EngineState, Stack, StateWorkingSet},
|
||||
format_error, Config, ListStream, RawStream, ShellError, Span, Value,
|
||||
};
|
||||
use nu_utils::{stdout_write_all_and_flush, stdout_write_all_as_binary_and_flush};
|
||||
use nu_utils::{stderr_write_all_and_flush, stdout_write_all_and_flush};
|
||||
use std::sync::{atomic::AtomicBool, Arc};
|
||||
|
||||
/// The foundational abstraction for input and output to commands
|
||||
|
@ -414,11 +414,16 @@ impl PipelineData {
|
|||
}
|
||||
}
|
||||
|
||||
/// Consume and print self data immediately.
|
||||
///
|
||||
/// `no_newline` controls if we need to attach newline character to output.
|
||||
/// `to_stderr` controls if data is output to stderr, when the value is false, the data is ouput to stdout.
|
||||
pub fn print(
|
||||
self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
no_newline: bool,
|
||||
to_stderr: bool,
|
||||
) -> Result<(), ShellError> {
|
||||
// If the table function is in the declarations, then we can use it
|
||||
// to create the table value that will be printed in the terminal
|
||||
|
@ -436,7 +441,12 @@ impl PipelineData {
|
|||
for s in stream {
|
||||
let s_live = s?;
|
||||
let bin_output = s_live.as_binary()?;
|
||||
stdout_write_all_as_binary_and_flush(bin_output)?
|
||||
|
||||
if !to_stderr {
|
||||
stdout_write_all_and_flush(bin_output)?
|
||||
} else {
|
||||
stderr_write_all_and_flush(bin_output)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,7 +482,11 @@ impl PipelineData {
|
|||
out.push('\n');
|
||||
}
|
||||
|
||||
stdout_write_all_and_flush(out)?
|
||||
if !to_stderr {
|
||||
stdout_write_all_and_flush(out)?
|
||||
} else {
|
||||
stderr_write_all_and_flush(out)?
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
@ -491,7 +505,11 @@ impl PipelineData {
|
|||
out.push('\n');
|
||||
}
|
||||
|
||||
stdout_write_all_and_flush(out)?
|
||||
if !to_stderr {
|
||||
stdout_write_all_and_flush(out)?
|
||||
} else {
|
||||
stderr_write_all_and_flush(out)?
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
pub mod utils;
|
||||
|
||||
pub use utils::{
|
||||
enable_vt_processing, stdout_write_all_and_flush, stdout_write_all_as_binary_and_flush,
|
||||
};
|
||||
pub use utils::{enable_vt_processing, stderr_write_all_and_flush, stdout_write_all_and_flush};
|
||||
|
|
|
@ -24,9 +24,12 @@ pub fn enable_vt_processing() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn stdout_write_all_and_flush(output: String) -> Result<()> {
|
||||
pub fn stdout_write_all_and_flush<T>(output: T) -> Result<()>
|
||||
where
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
let stdout = std::io::stdout();
|
||||
let ret = match stdout.lock().write_all(output.as_bytes()) {
|
||||
let ret = match stdout.lock().write_all(output.as_ref()) {
|
||||
Ok(_) => Ok(stdout.lock().flush()?),
|
||||
Err(err) => Err(err),
|
||||
};
|
||||
|
@ -34,10 +37,13 @@ pub fn stdout_write_all_and_flush(output: String) -> Result<()> {
|
|||
ret
|
||||
}
|
||||
|
||||
pub fn stdout_write_all_as_binary_and_flush(output: &[u8]) -> Result<()> {
|
||||
let stdout = std::io::stdout();
|
||||
let ret = match stdout.lock().write_all(output) {
|
||||
Ok(_) => Ok(stdout.lock().flush()?),
|
||||
pub fn stderr_write_all_and_flush<T>(output: T) -> Result<()>
|
||||
where
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
let stderr = std::io::stderr();
|
||||
let ret = match stderr.lock().write_all(output.as_ref()) {
|
||||
Ok(_) => Ok(stderr.lock().flush()?),
|
||||
Err(err) => Err(err),
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue