forked from extern/nushell
Add 'from json'
This commit is contained in:
@ -6,8 +6,8 @@ use nu_protocol::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Alias, Benchmark, BuildString, Def, Do, Each, External, For, Git, GitCheckout, If, Length, Let,
|
||||
LetEnv, Lines, ListGitBranches, Ls, Module, Table, Use, Where,
|
||||
Alias, Benchmark, BuildString, Def, Do, Each, External, For, From, FromJson, Git, GitCheckout,
|
||||
If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Table, Use, Where,
|
||||
};
|
||||
|
||||
pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
||||
@ -20,41 +20,26 @@ pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
||||
Signature::build("where").required("cond", SyntaxShape::RowCondition, "condition");
|
||||
working_set.add_decl(sig.predeclare());
|
||||
|
||||
working_set.add_decl(Box::new(If));
|
||||
|
||||
working_set.add_decl(Box::new(Let));
|
||||
|
||||
working_set.add_decl(Box::new(LetEnv));
|
||||
|
||||
working_set.add_decl(Box::new(Alias));
|
||||
|
||||
working_set.add_decl(Box::new(BuildString));
|
||||
|
||||
working_set.add_decl(Box::new(Def));
|
||||
|
||||
working_set.add_decl(Box::new(For));
|
||||
|
||||
working_set.add_decl(Box::new(Each));
|
||||
|
||||
working_set.add_decl(Box::new(Where));
|
||||
|
||||
working_set.add_decl(Box::new(Do));
|
||||
|
||||
working_set.add_decl(Box::new(Benchmark));
|
||||
|
||||
working_set.add_decl(Box::new(Length));
|
||||
|
||||
working_set.add_decl(Box::new(Ls));
|
||||
|
||||
working_set.add_decl(Box::new(Module));
|
||||
|
||||
working_set.add_decl(Box::new(Use));
|
||||
|
||||
working_set.add_decl(Box::new(Table));
|
||||
|
||||
working_set.add_decl(Box::new(BuildString));
|
||||
working_set.add_decl(Box::new(Def));
|
||||
working_set.add_decl(Box::new(Do));
|
||||
working_set.add_decl(Box::new(Each));
|
||||
working_set.add_decl(Box::new(External));
|
||||
|
||||
working_set.add_decl(Box::new(For));
|
||||
working_set.add_decl(Box::new(From));
|
||||
working_set.add_decl(Box::new(FromJson));
|
||||
working_set.add_decl(Box::new(If));
|
||||
working_set.add_decl(Box::new(Length));
|
||||
working_set.add_decl(Box::new(Let));
|
||||
working_set.add_decl(Box::new(LetEnv));
|
||||
working_set.add_decl(Box::new(Lines));
|
||||
working_set.add_decl(Box::new(Ls));
|
||||
working_set.add_decl(Box::new(Module));
|
||||
working_set.add_decl(Box::new(Table));
|
||||
working_set.add_decl(Box::new(Use));
|
||||
working_set.add_decl(Box::new(Where));
|
||||
|
||||
// This is a WIP proof of concept
|
||||
working_set.add_decl(Box::new(ListGitBranches));
|
||||
|
28
crates/nu-command/src/formats/from/command.rs
Normal file
28
crates/nu-command/src/formats/from/command.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{ShellError, Signature, Value};
|
||||
|
||||
pub struct From;
|
||||
|
||||
impl Command for From {
|
||||
fn name(&self) -> &str {
|
||||
"from"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Parse a string or binary data into structured data"
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("from")
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_context: &EvaluationContext,
|
||||
_call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, ShellError> {
|
||||
Ok(Value::nothing())
|
||||
}
|
||||
}
|
111
crates/nu-command/src/formats/from/json.rs
Normal file
111
crates/nu-command/src/formats/from/json.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{IntoValueStream, ShellError, Signature, Span, Value};
|
||||
|
||||
pub struct FromJson;
|
||||
|
||||
impl Command for FromJson {
|
||||
fn name(&self) -> &str {
|
||||
"from json"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Convert from json to structured data"
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("from json").switch(
|
||||
"objects",
|
||||
"treat each line as a separate value",
|
||||
Some('o'),
|
||||
)
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_context: &EvaluationContext,
|
||||
call: &Call,
|
||||
input: Value,
|
||||
) -> Result<nu_protocol::Value, ShellError> {
|
||||
let span = input.span();
|
||||
let mut string_input = input.into_string();
|
||||
string_input.push('\n');
|
||||
|
||||
// TODO: turn this into a structured underline of the nu_json error
|
||||
if call.has_flag("objects") {
|
||||
#[allow(clippy::needless_collect)]
|
||||
let lines: Vec<String> = string_input.lines().map(|x| x.to_string()).collect();
|
||||
Ok(Value::Stream {
|
||||
stream: lines
|
||||
.into_iter()
|
||||
.map(move |mut x| {
|
||||
x.push('\n');
|
||||
match convert_string_to_value(x, span) {
|
||||
Ok(v) => v,
|
||||
Err(error) => Value::Error { error },
|
||||
}
|
||||
})
|
||||
.into_value_stream(),
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
convert_string_to_value(string_input, span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_nujson_to_value(value: &nu_json::Value, span: Span) -> Value {
|
||||
match value {
|
||||
nu_json::Value::Array(array) => {
|
||||
let v: Vec<Value> = array
|
||||
.iter()
|
||||
.map(|x| convert_nujson_to_value(x, span))
|
||||
.collect();
|
||||
|
||||
Value::List { vals: v, span }
|
||||
}
|
||||
nu_json::Value::Bool(b) => Value::Bool { val: *b, span },
|
||||
nu_json::Value::F64(f) => Value::Float { val: *f, span },
|
||||
nu_json::Value::I64(i) => Value::Int { val: *i, span },
|
||||
nu_json::Value::Null => Value::Nothing { span },
|
||||
nu_json::Value::Object(k) => {
|
||||
let mut cols = vec![];
|
||||
let mut vals = vec![];
|
||||
|
||||
for item in k {
|
||||
cols.push(item.0.clone());
|
||||
vals.push(convert_nujson_to_value(item.1, span));
|
||||
}
|
||||
|
||||
Value::Record { cols, vals, span }
|
||||
}
|
||||
nu_json::Value::U64(u) => {
|
||||
if *u > i64::MAX as u64 {
|
||||
Value::Error {
|
||||
error: ShellError::CantConvert("i64 sized integer".into(), span),
|
||||
}
|
||||
} else {
|
||||
Value::Int {
|
||||
val: *u as i64,
|
||||
span,
|
||||
}
|
||||
}
|
||||
}
|
||||
nu_json::Value::String(s) => Value::String {
|
||||
val: s.clone(),
|
||||
span,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_string_to_value(string_input: String, span: Span) -> Result<Value, ShellError> {
|
||||
let result: Result<nu_json::Value, nu_json::Error> = nu_json::from_str(&string_input);
|
||||
match result {
|
||||
Ok(value) => Ok(convert_nujson_to_value(&value, span)),
|
||||
|
||||
Err(_x) => Err(ShellError::CantConvert(
|
||||
"structured data from json".into(),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
5
crates/nu-command/src/formats/from/mod.rs
Normal file
5
crates/nu-command/src/formats/from/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod command;
|
||||
mod json;
|
||||
|
||||
pub use command::From;
|
||||
pub use json::FromJson;
|
3
crates/nu-command/src/formats/mod.rs
Normal file
3
crates/nu-command/src/formats/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod from;
|
||||
|
||||
pub use from::*;
|
@ -4,6 +4,7 @@ mod env;
|
||||
mod experimental;
|
||||
mod filesystem;
|
||||
mod filters;
|
||||
mod formats;
|
||||
mod strings;
|
||||
mod system;
|
||||
mod viewers;
|
||||
@ -14,6 +15,7 @@ pub use env::*;
|
||||
pub use experimental::*;
|
||||
pub use filesystem::*;
|
||||
pub use filters::*;
|
||||
pub use formats::*;
|
||||
pub use strings::*;
|
||||
pub use system::*;
|
||||
pub use viewers::*;
|
||||
|
Reference in New Issue
Block a user