Merge pull request #66 from elferherrera/table

Table as string output
This commit is contained in:
JT 2021-09-26 07:00:59 +13:00 committed by GitHub
commit 22c6ed4718
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 24 deletions

View File

@ -1,7 +1,7 @@
use nu_engine::eval_expression; use nu_engine::eval_expression;
use nu_protocol::ast::Call; use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EvaluationContext}; use nu_protocol::engine::{Command, EvaluationContext};
use nu_protocol::{Signature, SyntaxShape, Value}; use nu_protocol::{ShellError, Signature, SyntaxShape, Value};
pub struct BuildString; pub struct BuildString;
@ -24,13 +24,12 @@ impl Command for BuildString {
call: &Call, call: &Call,
_input: Value, _input: Value,
) -> Result<nu_protocol::Value, nu_protocol::ShellError> { ) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
let mut output = vec![]; let output = call
.positional
.iter()
.map(|expr| eval_expression(context, expr).map(|val| val.into_string()))
.collect::<Result<Vec<String>, ShellError>>()?;
for expr in &call.positional {
let val = eval_expression(context, expr)?;
output.push(val.into_string());
}
Ok(Value::String { Ok(Value::String {
val: output.join(""), val: output.join(""),
span: call.head, span: call.head,

View File

@ -67,6 +67,8 @@ pub fn create_default_context() -> Rc<RefCell<EngineState>> {
working_set.add_decl(sig.predeclare()); working_set.add_decl(sig.predeclare());
let sig = Signature::build("stack"); let sig = Signature::build("stack");
working_set.add_decl(sig.predeclare()); working_set.add_decl(sig.predeclare());
let sig = Signature::build("contents");
working_set.add_decl(sig.predeclare());
working_set.render() working_set.render()
}; };

View File

@ -62,7 +62,7 @@ impl Command for Lines {
.filter_map(|s| { .filter_map(|s| {
if !s.is_empty() { if !s.is_empty() {
Some(Value::String { Some(Value::String {
val: s.into(), val: s.trim().into(),
span, span,
}) })
} else { } else {

View File

@ -117,7 +117,6 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> {
Ok(mut child) => { Ok(mut child) => {
// if there is a string or a stream, that is sent to the pipe std // if there is a string or a stream, that is sent to the pipe std
match input { match input {
Value::Nothing { span: _ } => (),
Value::String { val, span: _ } => { Value::String { val, span: _ } => {
if let Some(mut stdin_write) = child.stdin.take() { if let Some(mut stdin_write) = child.stdin.take() {
self.write_to_stdin(&mut stdin_write, val.as_bytes())? self.write_to_stdin(&mut stdin_write, val.as_bytes())?
@ -143,12 +142,7 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> {
} }
} }
} }
_ => { _ => (),
return Err(ShellError::ExternalCommand(
"Input is not string or binary".to_string(),
self.name.span,
))
}
} }
// If this external is not the last expression, then its output is piped to a channel // If this external is not the last expression, then its output is piped to a channel

View File

@ -65,7 +65,11 @@ fn convert_to_table(iter: impl IntoIterator<Item = Value>) -> Option<nu_table::T
let mut iter = iter.into_iter().peekable(); let mut iter = iter.into_iter().peekable();
if let Some(first) = iter.peek() { if let Some(first) = iter.peek() {
let mut headers = first.columns(); let mut headers = match first {
Value::Record { .. } => first.columns(),
_ => ["Column_0".to_string()].to_vec(),
};
headers.insert(0, "#".into()); headers.insert(0, "#".into());
let mut data = vec![]; let mut data = vec![];
@ -74,10 +78,13 @@ fn convert_to_table(iter: impl IntoIterator<Item = Value>) -> Option<nu_table::T
let mut row = vec![row_num.to_string()]; let mut row = vec![row_num.to_string()];
for header in headers.iter().skip(1) { for header in headers.iter().skip(1) {
let result = item.clone().follow_cell_path(&[PathMember::String { let result = match item {
val: header.into(), Value::Record { .. } => item.clone().follow_cell_path(&[PathMember::String {
span: Span::unknown(), val: header.into(),
}]); span: Span::unknown(),
}]),
_ => Ok(item.clone()),
};
match result { match result {
Ok(value) => row.push(value.into_string()), Ok(value) => row.push(value.into_string()),

View File

@ -113,6 +113,11 @@ impl EngineState {
} }
} }
pub fn print_contents(&self) {
let string = String::from_utf8_lossy(&self.file_contents);
println!("{}", string);
}
pub fn find_decl(&self, name: &[u8]) -> Option<DeclId> { pub fn find_decl(&self, name: &[u8]) -> Option<DeclId> {
for scope in self.scope.iter().rev() { for scope in self.scope.iter().rev() {
if let Some(decl_id) = scope.decls.get(name) { if let Some(decl_id) = scope.decls.get(name) {

View File

@ -1,11 +1,14 @@
use std::io::Write;
use miette::{IntoDiagnostic, Result}; use miette::{IntoDiagnostic, Result};
use nu_cli::{report_error, NuCompleter, NuHighlighter, NuValidator}; use nu_cli::{report_error, NuCompleter, NuHighlighter, NuValidator};
use nu_command::create_default_context; use nu_command::create_default_context;
use nu_engine::eval_block; use nu_engine::eval_block;
use nu_parser::parse; use nu_parser::parse;
use nu_protocol::{ use nu_protocol::{
ast::Call,
engine::{EngineState, EvaluationContext, StateWorkingSet}, engine::{EngineState, EvaluationContext, StateWorkingSet},
Value, ShellError, Value,
}; };
use reedline::DefaultCompletionActionHandler; use reedline::DefaultCompletionActionHandler;
@ -99,6 +102,9 @@ fn main() -> Result<()> {
} else if s.trim() == "stack" { } else if s.trim() == "stack" {
stack.print_stack(); stack.print_stack();
continue; continue;
} else if s.trim() == "contents" {
engine_state.borrow().print_contents();
continue;
} }
let (block, delta) = { let (block, delta) = {
@ -125,9 +131,7 @@ fn main() -> Result<()> {
}; };
match eval_block(&state, &block, Value::nothing()) { match eval_block(&state, &block, Value::nothing()) {
Ok(value) => { Ok(value) => print_value(value, &state)?,
println!("{}", value.into_string());
}
Err(err) => { Err(err) => {
let engine_state = engine_state.borrow(); let engine_state = engine_state.borrow();
let working_set = StateWorkingSet::new(&*engine_state); let working_set = StateWorkingSet::new(&*engine_state);
@ -157,3 +161,26 @@ fn main() -> Result<()> {
Ok(()) Ok(())
} }
} }
fn print_value(value: Value, state: &EvaluationContext) -> 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 engine_state = state.engine_state.borrow();
let output = match engine_state.find_decl("table".as_bytes()) {
Some(decl_id) => {
let table = engine_state
.get_decl(decl_id)
.run(state, &Call::new(), value)?;
table.into_string()
}
None => value.into_string(),
};
let stdout = std::io::stdout();
match stdout.lock().write_all(output.as_bytes()) {
Ok(_) => (),
Err(err) => eprintln!("{}", err),
};
Ok(())
}