forked from extern/nushell
Merge branch 'source-command' of https://github.com/moonrise-tk/engine-q into source-command
This commit is contained in:
35
crates/nu-command/src/core_commands/export_def.rs
Normal file
35
crates/nu-command/src/core_commands/export_def.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct ExportDef;
|
||||
|
||||
impl Command for ExportDef {
|
||||
fn name(&self) -> &str {
|
||||
"export def"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Define a custom command and export it from a module"
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("export def")
|
||||
.required("target", SyntaxShape::String, "definition name")
|
||||
.required("params", SyntaxShape::Signature, "parameters")
|
||||
.required(
|
||||
"block",
|
||||
SyntaxShape::Block(Some(vec![])),
|
||||
"body of the definition",
|
||||
)
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
Ok(Value::Nothing { span: call.head })
|
||||
}
|
||||
}
|
28
crates/nu-command/src/core_commands/hide.rs
Normal file
28
crates/nu-command/src/core_commands/hide.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct Hide;
|
||||
|
||||
impl Command for Hide {
|
||||
fn name(&self) -> &str {
|
||||
"hide"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Hide definitions in the current scope"
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("hide").required("pattern", SyntaxShape::String, "import pattern")
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
Ok(Value::Nothing { span: call.head })
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
mod alias;
|
||||
mod def;
|
||||
mod do_;
|
||||
mod export_def;
|
||||
mod help;
|
||||
mod hide;
|
||||
mod if_;
|
||||
mod let_;
|
||||
mod module;
|
||||
@ -11,7 +13,9 @@ mod use_;
|
||||
pub use alias::Alias;
|
||||
pub use def::Def;
|
||||
pub use do_::Do;
|
||||
pub use export_def::ExportDef;
|
||||
pub use help::Help;
|
||||
pub use hide::Hide;
|
||||
pub use if_::If;
|
||||
pub use let_::Let;
|
||||
pub use module::Module;
|
||||
|
@ -14,7 +14,7 @@ impl Command for Use {
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("use").required("module_name", SyntaxShape::String, "module name")
|
||||
Signature::build("use").required("pattern", SyntaxShape::String, "import pattern")
|
||||
}
|
||||
|
||||
fn run(
|
||||
|
@ -5,11 +5,7 @@ use nu_protocol::{
|
||||
Signature,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Alias, Benchmark, BuildString, Def, Do, Each, External, For, From, FromJson, Git, GitCheckout,
|
||||
Help, If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Ps, Source, Sys, Table, Use,
|
||||
Where,
|
||||
};
|
||||
use crate::*;
|
||||
|
||||
pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
||||
let engine_state = Rc::new(RefCell::new(EngineState::new()));
|
||||
@ -20,14 +16,18 @@ pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
||||
working_set.add_decl(Box::new(Alias));
|
||||
working_set.add_decl(Box::new(Benchmark));
|
||||
working_set.add_decl(Box::new(BuildString));
|
||||
working_set.add_decl(Box::new(Cd));
|
||||
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(ExportDef));
|
||||
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(Get));
|
||||
working_set.add_decl(Box::new(Help));
|
||||
working_set.add_decl(Box::new(Hide));
|
||||
working_set.add_decl(Box::new(If));
|
||||
working_set.add_decl(Box::new(Length));
|
||||
working_set.add_decl(Box::new(Let));
|
||||
@ -36,10 +36,12 @@ pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
||||
working_set.add_decl(Box::new(Ls));
|
||||
working_set.add_decl(Box::new(Module));
|
||||
working_set.add_decl(Box::new(Ps));
|
||||
working_set.add_decl(Box::new(Select));
|
||||
working_set.add_decl(Box::new(Sys));
|
||||
working_set.add_decl(Box::new(Table));
|
||||
working_set.add_decl(Box::new(Use));
|
||||
working_set.add_decl(Box::new(Where));
|
||||
working_set.add_decl(Box::new(Wrap));
|
||||
|
||||
// This is a WIP proof of concept
|
||||
working_set.add_decl(Box::new(ListGitBranches));
|
||||
|
46
crates/nu-command/src/filesystem/cd.rs
Normal file
46
crates/nu-command/src/filesystem/cd.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct Cd;
|
||||
|
||||
impl Command for Cd {
|
||||
fn name(&self) -> &str {
|
||||
"cd"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Change directory."
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("cd").optional("path", SyntaxShape::FilePath, "the path to change to")
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let path: Option<String> = call.opt(context, 0)?;
|
||||
|
||||
let path = match path {
|
||||
Some(path) => {
|
||||
let path = nu_path::expand_tilde(path);
|
||||
path.to_string_lossy().to_string()
|
||||
}
|
||||
None => {
|
||||
let path = nu_path::expand_tilde("~");
|
||||
path.to_string_lossy().to_string()
|
||||
}
|
||||
};
|
||||
let _ = std::env::set_current_dir(&path);
|
||||
|
||||
//FIXME: this only changes the current scope, but instead this environment variable
|
||||
//should probably be a block that loads the information from the state in the overlay
|
||||
context.add_env_var("PWD".into(), path);
|
||||
Ok(Value::Nothing { span: call.head })
|
||||
}
|
||||
}
|
@ -63,8 +63,8 @@ impl Command for Ls {
|
||||
} else {
|
||||
Value::Nothing { span: call_span }
|
||||
},
|
||||
Value::Int {
|
||||
val: filesize as i64,
|
||||
Value::Filesize {
|
||||
val: filesize,
|
||||
span: call_span,
|
||||
},
|
||||
],
|
||||
|
@ -1,3 +1,5 @@
|
||||
mod cd;
|
||||
mod ls;
|
||||
|
||||
pub use cd::Cd;
|
||||
pub use ls::Ls;
|
||||
|
35
crates/nu-command/src/filters/get.rs
Normal file
35
crates/nu-command/src/filters/get.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::{Call, CellPath};
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct Get;
|
||||
|
||||
impl Command for Get {
|
||||
fn name(&self) -> &str {
|
||||
"get"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Extract data using a cell path."
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("wrap").required(
|
||||
"cell_path",
|
||||
SyntaxShape::CellPath,
|
||||
"the cell path to the data",
|
||||
)
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let cell_path: CellPath = call.req(context, 0)?;
|
||||
|
||||
input.follow_cell_path(&cell_path.members)
|
||||
}
|
||||
}
|
@ -62,7 +62,7 @@ impl Command for Lines {
|
||||
.filter_map(|s| {
|
||||
if !s.is_empty() {
|
||||
Some(Value::String {
|
||||
val: s.trim().into(),
|
||||
val: s.into(),
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
|
@ -1,11 +1,17 @@
|
||||
mod each;
|
||||
mod for_;
|
||||
mod get;
|
||||
mod length;
|
||||
mod lines;
|
||||
mod select;
|
||||
mod where_;
|
||||
mod wrap;
|
||||
|
||||
pub use each::Each;
|
||||
pub use for_::For;
|
||||
pub use get::Get;
|
||||
pub use length::Length;
|
||||
pub use lines::Lines;
|
||||
pub use select::Select;
|
||||
pub use where_::Where;
|
||||
pub use wrap::Wrap;
|
||||
|
182
crates/nu-command/src/filters/select.rs
Normal file
182
crates/nu-command/src/filters/select.rs
Normal file
@ -0,0 +1,182 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::{Call, CellPath};
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Example, IntoValueStream, ShellError, Signature, Span, SyntaxShape, Value};
|
||||
|
||||
pub struct Select;
|
||||
|
||||
impl Command for Select {
|
||||
fn name(&self) -> &str {
|
||||
"select"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("select").rest(
|
||||
"rest",
|
||||
SyntaxShape::CellPath,
|
||||
"the columns to select from the table",
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Down-select table to only these columns."
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let columns: Vec<CellPath> = call.rest(context, 0)?;
|
||||
let span = call.head;
|
||||
|
||||
select(span, columns, input)
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Select just the name column",
|
||||
example: "ls | select name",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Select the name and size columns",
|
||||
example: "ls | select name size",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn select(span: Span, columns: Vec<CellPath>, input: Value) -> Result<Value, ShellError> {
|
||||
if columns.is_empty() {
|
||||
return Err(ShellError::CantFindColumn(span));
|
||||
}
|
||||
|
||||
match input {
|
||||
Value::List {
|
||||
vals: input_vals,
|
||||
span,
|
||||
} => {
|
||||
let mut output = vec![];
|
||||
|
||||
for input_val in input_vals {
|
||||
let mut cols = vec![];
|
||||
let mut vals = vec![];
|
||||
for path in &columns {
|
||||
//FIXME: improve implementation to not clone
|
||||
let fetcher = input_val.clone().follow_cell_path(&path.members)?;
|
||||
|
||||
cols.push(path.into_string());
|
||||
vals.push(fetcher);
|
||||
}
|
||||
|
||||
output.push(Value::Record { cols, vals, span })
|
||||
}
|
||||
|
||||
Ok(Value::List { vals: output, span })
|
||||
}
|
||||
Value::Stream { stream, span } => Ok(Value::Stream {
|
||||
stream: stream
|
||||
.map(move |x| {
|
||||
let mut cols = vec![];
|
||||
let mut vals = vec![];
|
||||
for path in &columns {
|
||||
//FIXME: improve implementation to not clone
|
||||
match x.clone().follow_cell_path(&path.members) {
|
||||
Ok(value) => {
|
||||
cols.push(path.into_string());
|
||||
vals.push(value);
|
||||
}
|
||||
Err(error) => {
|
||||
cols.push(path.into_string());
|
||||
vals.push(Value::Error { error });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Value::Record { cols, vals, span }
|
||||
})
|
||||
.into_value_stream(),
|
||||
span,
|
||||
}),
|
||||
v => {
|
||||
let mut cols = vec![];
|
||||
let mut vals = vec![];
|
||||
|
||||
for cell_path in columns {
|
||||
// FIXME: remove clone
|
||||
let result = v.clone().follow_cell_path(&cell_path.members)?;
|
||||
|
||||
cols.push(cell_path.into_string());
|
||||
vals.push(result);
|
||||
}
|
||||
|
||||
Ok(Value::Record { cols, vals, span })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use nu_protocol::ColumnPath;
|
||||
// use nu_source::Span;
|
||||
// use nu_source::SpannedItem;
|
||||
// use nu_source::Tag;
|
||||
// use nu_stream::InputStream;
|
||||
// use nu_test_support::value::nothing;
|
||||
// use nu_test_support::value::row;
|
||||
// use nu_test_support::value::string;
|
||||
|
||||
// use super::select;
|
||||
// use super::Command;
|
||||
// use super::ShellError;
|
||||
|
||||
// #[test]
|
||||
// fn examples_work_as_expected() -> Result<(), ShellError> {
|
||||
// use crate::examples::test as test_examples;
|
||||
|
||||
// test_examples(Command {})
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn select_using_sparse_table() {
|
||||
// // Create a sparse table with 3 rows:
|
||||
// // col_foo | col_bar
|
||||
// // -----------------
|
||||
// // foo |
|
||||
// // | bar
|
||||
// // foo |
|
||||
// let input = vec![
|
||||
// row(indexmap! {"col_foo".into() => string("foo")}),
|
||||
// row(indexmap! {"col_bar".into() => string("bar")}),
|
||||
// row(indexmap! {"col_foo".into() => string("foo")}),
|
||||
// ];
|
||||
|
||||
// let expected = vec![
|
||||
// row(
|
||||
// indexmap! {"col_none".into() => nothing(), "col_foo".into() => string("foo"), "col_bar".into() => nothing()},
|
||||
// ),
|
||||
// row(
|
||||
// indexmap! {"col_none".into() => nothing(), "col_foo".into() => nothing(), "col_bar".into() => string("bar")},
|
||||
// ),
|
||||
// row(
|
||||
// indexmap! {"col_none".into() => nothing(), "col_foo".into() => string("foo"), "col_bar".into() => nothing()},
|
||||
// ),
|
||||
// ];
|
||||
|
||||
// let actual = select(
|
||||
// Tag::unknown(),
|
||||
// vec![
|
||||
// ColumnPath::build(&"col_none".to_string().spanned(Span::unknown())),
|
||||
// ColumnPath::build(&"col_foo".to_string().spanned(Span::unknown())),
|
||||
// ColumnPath::build(&"col_bar".to_string().spanned(Span::unknown())),
|
||||
// ],
|
||||
// input.into(),
|
||||
// );
|
||||
|
||||
// assert_eq!(Ok(expected), actual.map(InputStream::into_vec));
|
||||
// }
|
||||
// }
|
59
crates/nu-command/src/filters/wrap.rs
Normal file
59
crates/nu-command/src/filters/wrap.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{IntoValueStream, Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct Wrap;
|
||||
|
||||
impl Command for Wrap {
|
||||
fn name(&self) -> &str {
|
||||
"wrap"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Wrap the value into a column."
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("wrap").required("name", SyntaxShape::String, "the name of the column")
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let span = call.head;
|
||||
let name: String = call.req(context, 0)?;
|
||||
|
||||
match input {
|
||||
Value::List { vals, .. } => Ok(Value::List {
|
||||
vals: vals
|
||||
.into_iter()
|
||||
.map(move |x| Value::Record {
|
||||
cols: vec![name.clone()],
|
||||
vals: vec![x],
|
||||
span,
|
||||
})
|
||||
.collect(),
|
||||
span,
|
||||
}),
|
||||
Value::Stream { stream, .. } => Ok(Value::Stream {
|
||||
stream: stream
|
||||
.map(move |x| Value::Record {
|
||||
cols: vec![name.clone()],
|
||||
vals: vec![x],
|
||||
span,
|
||||
})
|
||||
.into_value_stream(),
|
||||
span,
|
||||
}),
|
||||
_ => Ok(Value::Record {
|
||||
cols: vec![name],
|
||||
vals: vec![input],
|
||||
span,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
@ -274,10 +274,11 @@ pub fn host(sys: &mut System, span: Span) -> Option<Value> {
|
||||
span,
|
||||
});
|
||||
}
|
||||
// dict.insert_untagged(
|
||||
// "uptime",
|
||||
// UntaggedValue::duration(1000000000 * sys.uptime() as i64),
|
||||
// );
|
||||
cols.push("uptime".into());
|
||||
vals.push(Value::Duration {
|
||||
val: 1000000000 * sys.uptime() as u64,
|
||||
span,
|
||||
});
|
||||
|
||||
let mut users = vec![];
|
||||
for user in sys.users() {
|
||||
|
@ -63,7 +63,7 @@ impl Command for Table {
|
||||
output.push(vec![
|
||||
StyledString {
|
||||
contents: c,
|
||||
style: nu_table::TextStyle::default_header(),
|
||||
style: nu_table::TextStyle::default_field(),
|
||||
},
|
||||
StyledString {
|
||||
contents: v.into_string(),
|
||||
|
Reference in New Issue
Block a user