mirror of
https://github.com/nushell/nushell
synced 2024-12-27 05:23:11 +00:00
Add an explicit 'print' command (#4535)
This commit is contained in:
parent
786e4ab971
commit
06f9047be4
6 changed files with 151 additions and 71 deletions
|
@ -1,13 +1,17 @@
|
||||||
mod completions;
|
mod completions;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod nu_highlight;
|
mod nu_highlight;
|
||||||
|
mod print;
|
||||||
mod prompt;
|
mod prompt;
|
||||||
mod syntax_highlight;
|
mod syntax_highlight;
|
||||||
|
mod util;
|
||||||
mod validation;
|
mod validation;
|
||||||
|
|
||||||
pub use completions::NuCompleter;
|
pub use completions::NuCompleter;
|
||||||
pub use errors::CliError;
|
pub use errors::CliError;
|
||||||
pub use nu_highlight::NuHighlight;
|
pub use nu_highlight::NuHighlight;
|
||||||
|
pub use print::Print;
|
||||||
pub use prompt::NushellPrompt;
|
pub use prompt::NushellPrompt;
|
||||||
pub use syntax_highlight::NuHighlighter;
|
pub use syntax_highlight::NuHighlighter;
|
||||||
|
pub use util::print_pipeline_data;
|
||||||
pub use validation::NuValidator;
|
pub use validation::NuValidator;
|
||||||
|
|
57
crates/nu-cli/src/print.rs
Normal file
57
crates/nu-cli/src/print.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use nu_engine::CallExt;
|
||||||
|
use nu_protocol::ast::Call;
|
||||||
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
|
use nu_protocol::{
|
||||||
|
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Print;
|
||||||
|
|
||||||
|
impl Command for Print {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"print"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("print")
|
||||||
|
.rest("rest", SyntaxShape::Any, "the values to print")
|
||||||
|
.category(Category::Strings)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Prints the values given"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
stack: &mut Stack,
|
||||||
|
call: &Call,
|
||||||
|
_input: PipelineData,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let args: Vec<Value> = call.rest(engine_state, stack, 0)?;
|
||||||
|
let head = call.head;
|
||||||
|
|
||||||
|
for arg in args {
|
||||||
|
crate::util::print_pipeline_data(arg.into_pipeline_data(), engine_state, stack)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(PipelineData::new(head))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![
|
||||||
|
Example {
|
||||||
|
description: "Print 'hello world'",
|
||||||
|
example: r#"print "hello world""#,
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Print the sum of 2 and 3",
|
||||||
|
example: r#"print (2 + 3)"#,
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
73
crates/nu-cli/src/util.rs
Normal file
73
crates/nu-cli/src/util.rs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use nu_protocol::{
|
||||||
|
ast::Call,
|
||||||
|
engine::{EngineState, Stack},
|
||||||
|
PipelineData, ShellError, Span, Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn print_pipeline_data(
|
||||||
|
input: PipelineData,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
stack: &mut Stack,
|
||||||
|
) -> 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
|
||||||
|
|
||||||
|
let config = stack.get_config().unwrap_or_default();
|
||||||
|
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
|
||||||
|
if let PipelineData::RawStream(stream, _, _) = input {
|
||||||
|
for s in stream {
|
||||||
|
let _ = stdout.lock().write_all(s?.as_binary()?);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
match engine_state.find_decl("table".as_bytes()) {
|
||||||
|
Some(decl_id) => {
|
||||||
|
let table = engine_state.get_decl(decl_id).run(
|
||||||
|
engine_state,
|
||||||
|
stack,
|
||||||
|
&Call::new(Span::new(0, 0)),
|
||||||
|
input,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
for item in table {
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
|
||||||
|
if let Value::Error { error } = item {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut out = item.into_string("\n", &config);
|
||||||
|
out.push('\n');
|
||||||
|
|
||||||
|
match stdout.lock().write_all(out.as_bytes()) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(err) => eprintln!("{}", err),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
for item in input {
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
|
||||||
|
if let Value::Error { error } = item {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut out = item.into_string("\n", &config);
|
||||||
|
out.push('\n');
|
||||||
|
|
||||||
|
match stdout.lock().write_all(out.as_bytes()) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(err) => eprintln!("{}", err),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -146,7 +146,19 @@ impl Iterator for RawStream {
|
||||||
}
|
}
|
||||||
Err(e) => Some(Err(e)),
|
Err(e) => Some(Err(e)),
|
||||||
},
|
},
|
||||||
None => None,
|
None => {
|
||||||
|
if !self.leftover.is_empty() {
|
||||||
|
let output = Ok(Value::Binary {
|
||||||
|
val: self.leftover.clone(),
|
||||||
|
span: self.span,
|
||||||
|
});
|
||||||
|
self.leftover.clear();
|
||||||
|
|
||||||
|
Some(output)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ fn main() -> Result<()> {
|
||||||
let delta = {
|
let delta = {
|
||||||
let mut working_set = nu_protocol::engine::StateWorkingSet::new(&engine_state);
|
let mut working_set = nu_protocol::engine::StateWorkingSet::new(&engine_state);
|
||||||
working_set.add_decl(Box::new(nu_cli::NuHighlight));
|
working_set.add_decl(Box::new(nu_cli::NuHighlight));
|
||||||
|
working_set.add_decl(Box::new(nu_cli::Print));
|
||||||
|
|
||||||
working_set.render()
|
working_set.render()
|
||||||
};
|
};
|
||||||
|
|
73
src/utils.rs
73
src/utils.rs
|
@ -1,13 +1,12 @@
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_cli::CliError;
|
use nu_cli::{print_pipeline_data, CliError};
|
||||||
use nu_engine::eval_block;
|
use nu_engine::eval_block;
|
||||||
use nu_parser::{lex, parse, trim_quotes, Token, TokenContents};
|
use nu_parser::{lex, parse, trim_quotes, Token, TokenContents};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
|
||||||
engine::{EngineState, Stack, StateWorkingSet},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
PipelineData, ShellError, Span, Value,
|
PipelineData, ShellError, Value,
|
||||||
};
|
};
|
||||||
use std::{io::Write, path::PathBuf};
|
use std::path::PathBuf;
|
||||||
|
|
||||||
// This will collect environment variables from std::env and adds them to a stack.
|
// This will collect environment variables from std::env and adds them to a stack.
|
||||||
//
|
//
|
||||||
|
@ -188,72 +187,6 @@ pub(crate) fn gather_parent_env_vars(engine_state: &mut EngineState) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_pipeline_data(
|
|
||||||
input: PipelineData,
|
|
||||||
engine_state: &EngineState,
|
|
||||||
stack: &mut Stack,
|
|
||||||
) -> 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
|
|
||||||
|
|
||||||
let config = stack.get_config().unwrap_or_default();
|
|
||||||
|
|
||||||
let stdout = std::io::stdout();
|
|
||||||
|
|
||||||
if let PipelineData::RawStream(stream, _, _) = input {
|
|
||||||
for s in stream {
|
|
||||||
let _ = stdout.lock().write_all(s?.as_binary()?);
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
match engine_state.find_decl("table".as_bytes()) {
|
|
||||||
Some(decl_id) => {
|
|
||||||
let table = engine_state.get_decl(decl_id).run(
|
|
||||||
engine_state,
|
|
||||||
stack,
|
|
||||||
&Call::new(Span::new(0, 0)),
|
|
||||||
input,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
for item in table {
|
|
||||||
let stdout = std::io::stdout();
|
|
||||||
|
|
||||||
if let Value::Error { error } = item {
|
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut out = item.into_string("\n", &config);
|
|
||||||
out.push('\n');
|
|
||||||
|
|
||||||
match stdout.lock().write_all(out.as_bytes()) {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(err) => eprintln!("{}", err),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
for item in input {
|
|
||||||
let stdout = std::io::stdout();
|
|
||||||
|
|
||||||
if let Value::Error { error } = item {
|
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut out = item.into_string("\n", &config);
|
|
||||||
out.push('\n');
|
|
||||||
|
|
||||||
match stdout.lock().write_all(out.as_bytes()) {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(err) => eprintln!("{}", err),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn eval_source(
|
pub(crate) fn eval_source(
|
||||||
engine_state: &mut EngineState,
|
engine_state: &mut EngineState,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
|
|
Loading…
Reference in a new issue