mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 23:37:48 +02:00
WIP
This commit is contained in:
@ -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())
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
Reference in New Issue
Block a user