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",
|
"print without inserting a newline for the line ending",
|
||||||
Some('n'),
|
Some('n'),
|
||||||
)
|
)
|
||||||
|
.switch("stderr", "print to stderr instead of stdout", Some('e'))
|
||||||
.category(Category::Strings)
|
.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> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let args: Vec<Value> = call.rest(engine_state, stack, 0)?;
|
let args: Vec<Value> = call.rest(engine_state, stack, 0)?;
|
||||||
let no_newline = call.has_flag("no-newline");
|
let no_newline = call.has_flag("no-newline");
|
||||||
|
let to_stderr = call.has_flag("stderr");
|
||||||
let head = call.head;
|
let head = call.head;
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
arg.into_pipeline_data()
|
arg.into_pipeline_data()
|
||||||
.print(engine_state, stack, no_newline)?;
|
.print(engine_state, stack, no_newline, to_stderr)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PipelineData::new(head))
|
Ok(PipelineData::new(head))
|
||||||
|
|
|
@ -247,7 +247,7 @@ pub fn eval_source(
|
||||||
set_last_exit_code(stack, 0);
|
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);
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
|
||||||
report_error(&working_set, &err);
|
report_error(&working_set, &err);
|
||||||
|
|
|
@ -216,7 +216,7 @@ impl Command for Watch {
|
||||||
|
|
||||||
match eval_result {
|
match eval_result {
|
||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
val.print(engine_state, stack, false)?;
|
val.print(engine_state, stack, false, false)?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let working_set = StateWorkingSet::new(engine_state);
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
|
|
@ -44,6 +44,7 @@ mod open;
|
||||||
mod parse;
|
mod parse;
|
||||||
mod path;
|
mod path;
|
||||||
mod prepend;
|
mod prepend;
|
||||||
|
mod print;
|
||||||
#[cfg(feature = "database")]
|
#[cfg(feature = "database")]
|
||||||
mod query;
|
mod query;
|
||||||
mod random;
|
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},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
format_error, Config, ListStream, RawStream, ShellError, Span, Value,
|
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};
|
use std::sync::{atomic::AtomicBool, Arc};
|
||||||
|
|
||||||
/// The foundational abstraction for input and output to commands
|
/// 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(
|
pub fn print(
|
||||||
self,
|
self,
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
no_newline: bool,
|
no_newline: bool,
|
||||||
|
to_stderr: bool,
|
||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
// If the table function is in the declarations, then we can use it
|
// 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
|
// to create the table value that will be printed in the terminal
|
||||||
|
@ -436,7 +441,12 @@ impl PipelineData {
|
||||||
for s in stream {
|
for s in stream {
|
||||||
let s_live = s?;
|
let s_live = s?;
|
||||||
let bin_output = s_live.as_binary()?;
|
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');
|
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 => {
|
None => {
|
||||||
|
@ -491,7 +505,11 @@ impl PipelineData {
|
||||||
out.push('\n');
|
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 mod utils;
|
||||||
|
|
||||||
pub use utils::{
|
pub use utils::{enable_vt_processing, stderr_write_all_and_flush, stdout_write_all_and_flush};
|
||||||
enable_vt_processing, stdout_write_all_and_flush, stdout_write_all_as_binary_and_flush,
|
|
||||||
};
|
|
||||||
|
|
|
@ -24,9 +24,12 @@ pub fn enable_vt_processing() -> Result<()> {
|
||||||
Ok(())
|
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 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()?),
|
Ok(_) => Ok(stdout.lock().flush()?),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
};
|
};
|
||||||
|
@ -34,10 +37,13 @@ pub fn stdout_write_all_and_flush(output: String) -> Result<()> {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stdout_write_all_as_binary_and_flush(output: &[u8]) -> Result<()> {
|
pub fn stderr_write_all_and_flush<T>(output: T) -> Result<()>
|
||||||
let stdout = std::io::stdout();
|
where
|
||||||
let ret = match stdout.lock().write_all(output) {
|
T: AsRef<[u8]>,
|
||||||
Ok(_) => Ok(stdout.lock().flush()?),
|
{
|
||||||
|
let stderr = std::io::stderr();
|
||||||
|
let ret = match stderr.lock().write_all(output.as_ref()) {
|
||||||
|
Ok(_) => Ok(stderr.lock().flush()?),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue