mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 02:55:07 +02:00
Add commands
This commit is contained in:
34
crates/nu-command/src/alias.rs
Normal file
34
crates/nu-command/src/alias.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct Alias;
|
||||
|
||||
impl Command for Alias {
|
||||
fn name(&self) -> &str {
|
||||
"alias"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Alias a command (with optional flags) to a new name"
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("alias")
|
||||
.required("name", SyntaxShape::String, "name of the alias")
|
||||
.required(
|
||||
"initial_value",
|
||||
SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)),
|
||||
"equals sign followed by value",
|
||||
)
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
Ok(Value::Nothing { span: call.head })
|
||||
}
|
||||
}
|
44
crates/nu-command/src/benchmark.rs
Normal file
44
crates/nu-command/src/benchmark.rs
Normal file
@ -0,0 +1,44 @@
|
||||
use std::time::Instant;
|
||||
|
||||
use nu_engine::eval_block;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct Benchmark;
|
||||
|
||||
impl Command for Benchmark {
|
||||
fn name(&self) -> &str {
|
||||
"benchmark"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Time the running time of a block"
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("benchmark").required("block", SyntaxShape::Block, "the block to run")
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let block = call.positional[0]
|
||||
.as_block()
|
||||
.expect("internal error: expected block");
|
||||
let engine_state = context.engine_state.borrow();
|
||||
let block = engine_state.get_block(block);
|
||||
|
||||
let state = context.enter_scope();
|
||||
let start_time = Instant::now();
|
||||
eval_block(&state, block)?;
|
||||
let end_time = Instant::now();
|
||||
println!("{} ms", (end_time - start_time).as_millis());
|
||||
Ok(Value::Nothing {
|
||||
span: call.positional[0].span,
|
||||
})
|
||||
}
|
||||
}
|
39
crates/nu-command/src/build_string.rs
Normal file
39
crates/nu-command/src/build_string.rs
Normal file
@ -0,0 +1,39 @@
|
||||
use nu_engine::eval_expression;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct BuildString;
|
||||
|
||||
impl Command for BuildString {
|
||||
fn name(&self) -> &str {
|
||||
"build-string"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Create a string from the arguments."
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("build-string").rest(SyntaxShape::String, "list of string")
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let mut output = vec![];
|
||||
|
||||
for expr in &call.positional {
|
||||
let val = eval_expression(context, expr)?;
|
||||
|
||||
output.push(val.into_string());
|
||||
}
|
||||
Ok(Value::String {
|
||||
val: output.join(""),
|
||||
span: call.head,
|
||||
})
|
||||
}
|
||||
}
|
31
crates/nu-command/src/def.rs
Normal file
31
crates/nu-command/src/def.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct Def;
|
||||
|
||||
impl Command for Def {
|
||||
fn name(&self) -> &str {
|
||||
"def"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Define a custom command"
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("def")
|
||||
.required("def_name", SyntaxShape::String, "definition name")
|
||||
.required("params", SyntaxShape::Signature, "parameters")
|
||||
.required("block", SyntaxShape::Block, "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 })
|
||||
}
|
||||
}
|
55
crates/nu-command/src/default_context.rs
Normal file
55
crates/nu-command/src/default_context.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use nu_protocol::{
|
||||
engine::{EngineState, StateWorkingSet},
|
||||
Signature, SyntaxShape,
|
||||
};
|
||||
|
||||
use crate::{Alias, Benchmark, BuildString, Def, For, If, Let, LetEnv};
|
||||
|
||||
pub fn create_default_context() -> Rc<RefCell<EngineState>> {
|
||||
let engine_state = Rc::new(RefCell::new(EngineState::new()));
|
||||
let delta = {
|
||||
let engine_state = engine_state.borrow();
|
||||
let mut working_set = StateWorkingSet::new(&*engine_state);
|
||||
|
||||
let sig =
|
||||
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(Benchmark));
|
||||
|
||||
let sig = Signature::build("exit");
|
||||
working_set.add_decl(sig.predeclare());
|
||||
let sig = Signature::build("vars");
|
||||
working_set.add_decl(sig.predeclare());
|
||||
let sig = Signature::build("decls");
|
||||
working_set.add_decl(sig.predeclare());
|
||||
let sig = Signature::build("blocks");
|
||||
working_set.add_decl(sig.predeclare());
|
||||
let sig = Signature::build("stack");
|
||||
working_set.add_decl(sig.predeclare());
|
||||
|
||||
working_set.render()
|
||||
};
|
||||
|
||||
{
|
||||
EngineState::merge_delta(&mut *engine_state.borrow_mut(), delta);
|
||||
}
|
||||
|
||||
engine_state
|
||||
}
|
75
crates/nu-command/src/for_.rs
Normal file
75
crates/nu-command/src/for_.rs
Normal file
@ -0,0 +1,75 @@
|
||||
use nu_engine::{eval_block, eval_expression};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, Span, SyntaxShape, Value};
|
||||
|
||||
pub struct For;
|
||||
|
||||
impl Command for For {
|
||||
fn name(&self) -> &str {
|
||||
"for"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Loop over a range"
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("for")
|
||||
.required(
|
||||
"var_name",
|
||||
SyntaxShape::Variable,
|
||||
"name of the looping variable",
|
||||
)
|
||||
.required(
|
||||
"range",
|
||||
SyntaxShape::Keyword(b"in".to_vec(), Box::new(SyntaxShape::Int)),
|
||||
"range of the loop",
|
||||
)
|
||||
.required("block", SyntaxShape::Block, "the block to run")
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let var_id = call.positional[0]
|
||||
.as_var()
|
||||
.expect("internal error: missing variable");
|
||||
|
||||
let keyword_expr = call.positional[1]
|
||||
.as_keyword()
|
||||
.expect("internal error: missing keyword");
|
||||
let end_val = eval_expression(context, keyword_expr)?;
|
||||
|
||||
let block = call.positional[2]
|
||||
.as_block()
|
||||
.expect("internal error: expected block");
|
||||
let engine_state = context.engine_state.borrow();
|
||||
let block = engine_state.get_block(block);
|
||||
|
||||
let state = context.enter_scope();
|
||||
|
||||
let mut x = Value::Int {
|
||||
val: 0,
|
||||
span: Span::unknown(),
|
||||
};
|
||||
|
||||
loop {
|
||||
if x == end_val {
|
||||
break;
|
||||
} else {
|
||||
state.add_var(var_id, x.clone());
|
||||
eval_block(&state, block)?;
|
||||
}
|
||||
if let Value::Int { ref mut val, .. } = x {
|
||||
*val += 1
|
||||
}
|
||||
}
|
||||
Ok(Value::Nothing {
|
||||
span: call.positional[0].span,
|
||||
})
|
||||
}
|
||||
}
|
67
crates/nu-command/src/if_.rs
Normal file
67
crates/nu-command/src/if_.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use nu_engine::{eval_block, eval_expression};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{ShellError, Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct If;
|
||||
|
||||
impl Command for If {
|
||||
fn name(&self) -> &str {
|
||||
"if"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Create a variable and give it a value."
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("if")
|
||||
.required("cond", SyntaxShape::Expression, "condition")
|
||||
.required("then_block", SyntaxShape::Block, "then block")
|
||||
.optional(
|
||||
"else",
|
||||
SyntaxShape::Keyword(b"else".to_vec(), Box::new(SyntaxShape::Expression)),
|
||||
"optional else followed by else block",
|
||||
)
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let cond = &call.positional[0];
|
||||
let then_block = call.positional[1]
|
||||
.as_block()
|
||||
.expect("internal error: expected block");
|
||||
let else_case = call.positional.get(2);
|
||||
|
||||
let result = eval_expression(context, cond)?;
|
||||
match result {
|
||||
Value::Bool { val, span } => {
|
||||
let engine_state = context.engine_state.borrow();
|
||||
if val {
|
||||
let block = engine_state.get_block(then_block);
|
||||
let state = context.enter_scope();
|
||||
eval_block(&state, block)
|
||||
} else if let Some(else_case) = else_case {
|
||||
if let Some(else_expr) = else_case.as_keyword() {
|
||||
if let Some(block_id) = else_expr.as_block() {
|
||||
let block = engine_state.get_block(block_id);
|
||||
let state = context.enter_scope();
|
||||
eval_block(&state, block)
|
||||
} else {
|
||||
eval_expression(context, else_expr)
|
||||
}
|
||||
} else {
|
||||
eval_expression(context, else_case)
|
||||
}
|
||||
} else {
|
||||
Ok(Value::Nothing { span })
|
||||
}
|
||||
}
|
||||
_ => Err(ShellError::CantConvert("bool".into(), result.span())),
|
||||
}
|
||||
}
|
||||
}
|
50
crates/nu-command/src/let_.rs
Normal file
50
crates/nu-command/src/let_.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use nu_engine::eval_expression;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct Let;
|
||||
|
||||
impl Command for Let {
|
||||
fn name(&self) -> &str {
|
||||
"let"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Create a variable and give it a value."
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("let")
|
||||
.required("var_name", SyntaxShape::VarWithOptType, "variable name")
|
||||
.required(
|
||||
"initial_value",
|
||||
SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)),
|
||||
"equals sign followed by value",
|
||||
)
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let var_id = call.positional[0]
|
||||
.as_var()
|
||||
.expect("internal error: missing variable");
|
||||
|
||||
let keyword_expr = call.positional[1]
|
||||
.as_keyword()
|
||||
.expect("internal error: missing keyword");
|
||||
|
||||
let rhs = eval_expression(context, keyword_expr)?;
|
||||
|
||||
//println!("Adding: {:?} to {}", rhs, var_id);
|
||||
|
||||
context.add_var(var_id, rhs);
|
||||
Ok(Value::Nothing {
|
||||
span: call.positional[0].span,
|
||||
})
|
||||
}
|
||||
}
|
51
crates/nu-command/src/let_env.rs
Normal file
51
crates/nu-command/src/let_env.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use nu_engine::eval_expression;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EvaluationContext};
|
||||
use nu_protocol::{Signature, SyntaxShape, Value};
|
||||
|
||||
pub struct LetEnv;
|
||||
|
||||
impl Command for LetEnv {
|
||||
fn name(&self) -> &str {
|
||||
"let-env"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Create an environment variable and give it a value."
|
||||
}
|
||||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("let-env")
|
||||
.required("var_name", SyntaxShape::String, "variable name")
|
||||
.required(
|
||||
"initial_value",
|
||||
SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::String)),
|
||||
"equals sign followed by value",
|
||||
)
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &EvaluationContext,
|
||||
call: &Call,
|
||||
_input: Value,
|
||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||
let env_var = call.positional[0]
|
||||
.as_string()
|
||||
.expect("internal error: missing variable");
|
||||
|
||||
let keyword_expr = call.positional[1]
|
||||
.as_keyword()
|
||||
.expect("internal error: missing keyword");
|
||||
|
||||
let rhs = eval_expression(context, keyword_expr)?;
|
||||
let rhs = rhs.as_string()?;
|
||||
|
||||
//println!("Adding: {:?} to {}", rhs, var_id);
|
||||
|
||||
context.add_env_var(env_var, rhs);
|
||||
Ok(Value::Nothing {
|
||||
span: call.positional[0].span,
|
||||
})
|
||||
}
|
||||
}
|
@ -1,7 +1,19 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
||||
mod alias;
|
||||
mod benchmark;
|
||||
mod build_string;
|
||||
mod def;
|
||||
mod default_context;
|
||||
mod for_;
|
||||
mod if_;
|
||||
mod let_;
|
||||
mod let_env;
|
||||
|
||||
pub use alias::Alias;
|
||||
pub use benchmark::Benchmark;
|
||||
pub use build_string::BuildString;
|
||||
pub use def::Def;
|
||||
pub use default_context::create_default_context;
|
||||
pub use for_::For;
|
||||
pub use if_::If;
|
||||
pub use let_::Let;
|
||||
pub use let_env::LetEnv;
|
||||
|
Reference in New Issue
Block a user