This commit is contained in:
JT
2021-10-25 19:31:39 +13:00
parent 397a31e69c
commit b5965ee8ef
60 changed files with 502 additions and 455 deletions

View File

@ -2,7 +2,7 @@ use std::time::Instant;
use nu_engine::eval_block;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EvaluationContext};
use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack};
use nu_protocol::{PipelineData, Signature, SyntaxShape, Value};
#[derive(Clone)]
@ -27,18 +27,19 @@ impl Command for Benchmark {
fn run(
&self,
context: &EvaluationContext,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
let block = call.positional[0]
.as_block()
.expect("internal error: expected block");
let block = context.engine_state.get_block(block);
let block = engine_state.get_block(block);
let state = context.enter_scope();
let mut stack = stack.enter_scope();
let start_time = Instant::now();
eval_block(&state, block, PipelineData::new())?;
eval_block(&engine_state, &mut stack, block, PipelineData::new())?;
let end_time = Instant::now();
println!("{} ms", (end_time - start_time).as_millis());
Ok(PipelineData::new())

View File

@ -1,6 +1,6 @@
use nu_protocol::{
ast::Call,
engine::{Command, EvaluationContext},
engine::{Command, EngineState, EvaluationContext, Stack},
Example, IntoPipelineData, PipelineData, ShellError, Signature, Value,
};
use sysinfo::{ProcessExt, System, SystemExt};
@ -30,7 +30,8 @@ impl Command for Ps {
fn run(
&self,
_context: &EvaluationContext,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {

View File

@ -1,19 +1,21 @@
use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::io::{BufRead, BufReader, Write};
use std::process::{ChildStdin, Command as CommandSys, Stdio};
use std::rc::Rc;
use std::sync::mpsc;
use nu_protocol::engine::{EngineState, Stack};
use nu_protocol::{
ast::{Call, Expression},
engine::{Command, EvaluationContext},
ShellError, Signature, SyntaxShape, Value,
};
use nu_protocol::{IntoPipelineData, PipelineData, Span, ValueStream};
use nu_protocol::{IntoPipelineData, PipelineData, Span, Spanned, ValueStream};
use nu_engine::eval_expression;
use nu_engine::{eval_expression, CallExt};
const OUTPUT_BUFFER_SIZE: usize = 8192;
@ -37,52 +39,34 @@ impl Command for External {
fn run(
&self,
context: &EvaluationContext,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let command = ExternalCommand::try_new(call, context)?;
let name: Spanned<String> = call.req(engine_state, stack, 0)?;
let args: Vec<String> = call.rest(engine_state, stack, 1)?;
let last_expression = call.has_flag("last_expression");
let env_vars = stack.get_env_vars();
let command = ExternalCommand {
name,
args,
last_expression,
env_vars,
};
command.run_with_input(input)
}
}
pub struct ExternalCommand<'call, 'contex> {
pub name: &'call Expression,
pub args: &'call [Expression],
pub context: &'contex EvaluationContext,
pub struct ExternalCommand {
pub name: Spanned<String>,
pub args: Vec<String>,
pub last_expression: bool,
pub env_vars: HashMap<String, String>,
}
impl<'call, 'contex> ExternalCommand<'call, 'contex> {
pub fn try_new(
call: &'call Call,
context: &'contex EvaluationContext,
) -> Result<Self, ShellError> {
if call.positional.is_empty() {
return Err(ShellError::ExternalNotSupported(call.head));
}
Ok(Self {
name: &call.positional[0],
args: &call.positional[1..],
context,
last_expression: call.has_flag("last_expression"),
})
}
pub fn get_name(&self) -> Result<String, ShellError> {
let value = eval_expression(self.context, self.name)?;
value.as_string()
}
pub fn get_args(&self) -> Vec<String> {
self.args
.iter()
.filter_map(|expr| eval_expression(self.context, expr).ok())
.filter_map(|value| value.as_string().ok())
.collect()
}
impl ExternalCommand {
pub fn run_with_input(&self, input: PipelineData) -> Result<PipelineData, ShellError> {
let mut process = self.create_command();
@ -91,8 +75,7 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> {
let path = env::current_dir().unwrap();
process.current_dir(path);
let envs = self.context.stack.get_env_vars();
process.envs(envs);
process.envs(&self.env_vars);
// If the external is not the last command, its output will get piped
// either as a string or binary
@ -195,8 +178,8 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> {
// for minimal builds cwd is unused
let mut process = CommandSys::new("cmd");
process.arg("/c");
process.arg(&self.get_name().unwrap());
for arg in self.get_args() {
process.arg(&self.name.item);
for arg in &self.args {
// Clean the args before we use them:
// https://stackoverflow.com/questions/1200235/how-to-pass-a-quoted-pipe-character-to-cmd-exe
// cmd.exe needs to have a caret to escape a pipe
@ -205,7 +188,7 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> {
}
process
} else {
let cmd_with_args = vec![self.get_name().unwrap(), self.get_args().join(" ")].join(" ");
let cmd_with_args = vec![self.name.item.clone(), self.args.join(" ")].join(" ");
let mut process = CommandSys::new("sh");
process.arg("-c").arg(cmd_with_args);
process

View File

@ -1,6 +1,6 @@
use nu_protocol::{
ast::Call,
engine::{Command, EvaluationContext},
engine::{Command, EngineState, EvaluationContext, Stack},
Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value,
};
use sysinfo::{ComponentExt, DiskExt, NetworkExt, ProcessorExt, System, SystemExt, UserExt};
@ -25,7 +25,8 @@ impl Command for Sys {
fn run(
&self,
_context: &EvaluationContext,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {