forked from extern/nushell
Merge pull request #285 from jonathandturner/per_item
Add first per-item commands
This commit is contained in:
commit
0b9248cbba
@ -158,7 +158,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
|||||||
command("cd", Box::new(cd::cd)),
|
command("cd", Box::new(cd::cd)),
|
||||||
command("size", Box::new(size::size)),
|
command("size", Box::new(size::size)),
|
||||||
command("from-yaml", Box::new(from_yaml::from_yaml)),
|
command("from-yaml", Box::new(from_yaml::from_yaml)),
|
||||||
command("enter", Box::new(enter::enter)),
|
//command("enter", Box::new(enter::enter)),
|
||||||
command("nth", Box::new(nth::nth)),
|
command("nth", Box::new(nth::nth)),
|
||||||
command("n", Box::new(next::next)),
|
command("n", Box::new(next::next)),
|
||||||
command("p", Box::new(prev::prev)),
|
command("p", Box::new(prev::prev)),
|
||||||
@ -182,9 +182,10 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
|||||||
//static_command(Cd),
|
//static_command(Cd),
|
||||||
static_command(Remove),
|
static_command(Remove),
|
||||||
static_command(Open),
|
static_command(Open),
|
||||||
static_command(Where),
|
per_item_command(Where),
|
||||||
static_command(Config),
|
static_command(Config),
|
||||||
static_command(SkipWhile),
|
static_command(SkipWhile),
|
||||||
|
per_item_command(Enter),
|
||||||
static_command(Exit),
|
static_command(Exit),
|
||||||
static_command(Clip),
|
static_command(Clip),
|
||||||
static_command(Autoview),
|
static_command(Autoview),
|
||||||
|
@ -57,12 +57,13 @@ crate use autoview::Autoview;
|
|||||||
//crate use cd::Cd;
|
//crate use cd::Cd;
|
||||||
crate use clip::Clip;
|
crate use clip::Clip;
|
||||||
crate use command::{
|
crate use command::{
|
||||||
command, static_command, Command, CommandArgs, RawCommandArgs, StaticCommand,
|
command, per_item_command, static_command, Command, CommandArgs, PerItemCommand,
|
||||||
UnevaluatedCallInfo,
|
RawCommandArgs, StaticCommand, UnevaluatedCallInfo,
|
||||||
};
|
};
|
||||||
crate use config::Config;
|
crate use config::Config;
|
||||||
crate use cp::Copycp;
|
crate use cp::Copycp;
|
||||||
crate use date::Date;
|
crate use date::Date;
|
||||||
|
crate use enter::Enter;
|
||||||
crate use exit::Exit;
|
crate use exit::Exit;
|
||||||
crate use get::Get;
|
crate use get::Get;
|
||||||
crate use mkdir::Mkdir;
|
crate use mkdir::Mkdir;
|
||||||
|
@ -141,6 +141,9 @@ impl InternalCommand {
|
|||||||
context.add_span_source(uuid, span_source);
|
context.add_span_source(uuid, span_source);
|
||||||
}
|
}
|
||||||
CommandAction::Exit => std::process::exit(0),
|
CommandAction::Exit => std::process::exit(0),
|
||||||
|
CommandAction::EnterValueShell(value) => {
|
||||||
|
context.shell_manager.push(Box::new(ValueShell::new(value)));
|
||||||
|
}
|
||||||
CommandAction::EnterShell(location) => {
|
CommandAction::EnterShell(location) => {
|
||||||
let path = std::path::Path::new(&location);
|
let path = std::path::Path::new(&location);
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ impl ToDebug for UnevaluatedCallInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UnevaluatedCallInfo {
|
impl UnevaluatedCallInfo {
|
||||||
fn evaluate(
|
pub fn evaluate(
|
||||||
self,
|
self,
|
||||||
registry: ®istry::CommandRegistry,
|
registry: ®istry::CommandRegistry,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
@ -62,7 +62,7 @@ pub struct CommandArgs {
|
|||||||
pub input: InputStream,
|
pub input: InputStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Getters)]
|
#[derive(Getters, Clone)]
|
||||||
#[get = "crate"]
|
#[get = "crate"]
|
||||||
pub struct RawCommandArgs {
|
pub struct RawCommandArgs {
|
||||||
pub host: Arc<Mutex<dyn Host>>,
|
pub host: Arc<Mutex<dyn Host>>,
|
||||||
@ -346,6 +346,7 @@ pub enum CommandAction {
|
|||||||
AddSpanSource(Uuid, SpanSource),
|
AddSpanSource(Uuid, SpanSource),
|
||||||
Exit,
|
Exit,
|
||||||
EnterShell(String),
|
EnterShell(String),
|
||||||
|
EnterValueShell(Tagged<Value>),
|
||||||
PreviousShell,
|
PreviousShell,
|
||||||
NextShell,
|
NextShell,
|
||||||
LeaveShell,
|
LeaveShell,
|
||||||
@ -405,20 +406,44 @@ pub trait StaticCommand: Send + Sync {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait PerItemCommand: Send + Sync {
|
||||||
|
fn name(&self) -> &str;
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
args: RawCommandArgs,
|
||||||
|
registry: ®istry::CommandRegistry,
|
||||||
|
input: Tagged<Value>,
|
||||||
|
) -> Result<VecDeque<ReturnValue>, ShellError>;
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature {
|
||||||
|
name: self.name().to_string(),
|
||||||
|
positional: vec![],
|
||||||
|
rest_positional: true,
|
||||||
|
named: indexmap::IndexMap::new(),
|
||||||
|
is_filter: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Static(Arc<dyn StaticCommand>),
|
Static(Arc<dyn StaticCommand>),
|
||||||
|
PerItem(Arc<dyn PerItemCommand>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command {
|
impl Command {
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
Command::Static(command) => command.name(),
|
Command::Static(command) => command.name(),
|
||||||
|
Command::PerItem(command) => command.name(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn signature(&self) -> Signature {
|
pub fn signature(&self) -> Signature {
|
||||||
match self {
|
match self {
|
||||||
Command::Static(command) => command.signature(),
|
Command::Static(command) => command.signature(),
|
||||||
|
Command::PerItem(command) => command.signature(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,8 +454,29 @@ impl Command {
|
|||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
Command::Static(command) => command.run(args, registry),
|
Command::Static(command) => command.run(args, registry),
|
||||||
|
Command::PerItem(command) => self.run_helper(command.clone(), args, registry.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_helper(
|
||||||
|
&self,
|
||||||
|
command: Arc<dyn PerItemCommand>,
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let raw_args = RawCommandArgs {
|
||||||
|
host: args.host,
|
||||||
|
shell_manager: args.shell_manager,
|
||||||
|
call_info: args.call_info,
|
||||||
|
};
|
||||||
|
let out = args
|
||||||
|
.input
|
||||||
|
.values
|
||||||
|
.map(move |x| command.run(raw_args.clone(), ®istry, x).unwrap())
|
||||||
|
.flatten();
|
||||||
|
|
||||||
|
Ok(out.to_output_stream())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
@ -528,6 +574,10 @@ pub fn static_command(command: impl StaticCommand + 'static) -> Arc<Command> {
|
|||||||
Arc::new(Command::Static(Arc::new(command)))
|
Arc::new(Command::Static(Arc::new(command)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn per_item_command(command: impl PerItemCommand + 'static) -> Arc<Command> {
|
||||||
|
Arc::new(Command::PerItem(Arc::new(command)))
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn filter(
|
pub fn filter(
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -1,23 +1,46 @@
|
|||||||
use crate::commands::command::CommandAction;
|
use crate::commands::command::CommandAction;
|
||||||
|
use crate::commands::{PerItemCommand, RawCommandArgs};
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
|
use crate::evaluate::Scope;
|
||||||
|
use crate::parser::registry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub fn enter(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
pub struct Enter;
|
||||||
let args = args.evaluate_once(registry)?;
|
|
||||||
|
|
||||||
//TODO: We could also enter a value in the stream
|
impl PerItemCommand for Enter {
|
||||||
if args.len() == 0 {
|
fn name(&self) -> &str {
|
||||||
return Err(ShellError::labeled_error(
|
"enter"
|
||||||
"Enter requires a path",
|
|
||||||
"needs parameter",
|
|
||||||
args.call_info.name_span,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let location = args.expect_nth(0)?.as_string()?;
|
fn signature(&self) -> registry::Signature {
|
||||||
|
Signature::build("enter").required("location", SyntaxType::Block)
|
||||||
|
}
|
||||||
|
|
||||||
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterShell(
|
fn run(
|
||||||
location,
|
&self,
|
||||||
)))]
|
args: RawCommandArgs,
|
||||||
.into())
|
registry: ®istry::CommandRegistry,
|
||||||
|
input: Tagged<Value>,
|
||||||
|
) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||||
|
let call_info = args
|
||||||
|
.call_info
|
||||||
|
.evaluate(registry, &Scope::it_value(input))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
match call_info.args.expect_nth(0)? {
|
||||||
|
Tagged {
|
||||||
|
item: Value::Primitive(Primitive::String(location)),
|
||||||
|
..
|
||||||
|
} => Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterShell(
|
||||||
|
location.to_string(),
|
||||||
|
)))]
|
||||||
|
.into()),
|
||||||
|
x => Ok(
|
||||||
|
vec![Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(
|
||||||
|
x.clone(),
|
||||||
|
)))]
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,12 @@
|
|||||||
use crate::commands::StaticCommand;
|
use crate::commands::{PerItemCommand, RawCommandArgs};
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::object::base as value;
|
|
||||||
use crate::parser::hir::SyntaxType;
|
use crate::parser::hir::SyntaxType;
|
||||||
use crate::parser::registry;
|
use crate::parser::registry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use futures::future::ready;
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
pub struct Where;
|
pub struct Where;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
impl PerItemCommand for Where {
|
||||||
struct WhereArgs {
|
|
||||||
condition: value::Block,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StaticCommand for Where {
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"where"
|
"where"
|
||||||
}
|
}
|
||||||
@ -26,31 +17,42 @@ impl StaticCommand for Where {
|
|||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
&self,
|
&self,
|
||||||
args: CommandArgs,
|
args: RawCommandArgs,
|
||||||
registry: ®istry::CommandRegistry,
|
registry: ®istry::CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
input: Tagged<Value>,
|
||||||
args.process(registry, run)?.run()
|
) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||||
|
let input_clone = input.clone();
|
||||||
|
let call_info = args
|
||||||
|
.with_input(vec![input])
|
||||||
|
.evaluate_once(registry)
|
||||||
|
.unwrap();
|
||||||
|
let condition = &call_info.args.call_info.args.positional.unwrap()[0];
|
||||||
|
match condition {
|
||||||
|
Tagged {
|
||||||
|
item: Value::Block(block),
|
||||||
|
tag,
|
||||||
|
} => {
|
||||||
|
let result = block.invoke(&input_clone);
|
||||||
|
match result {
|
||||||
|
Ok(v) => {
|
||||||
|
if v.is_true() {
|
||||||
|
Ok(VecDeque::from(vec![Ok(ReturnSuccess::Value(input_clone))]))
|
||||||
|
} else {
|
||||||
|
Ok(VecDeque::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => Err(ShellError::labeled_error(
|
||||||
|
format!("Could not evaluate ({})", e.to_string()),
|
||||||
|
"could not evaluate",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tagged { tag, .. } => Err(ShellError::labeled_error(
|
||||||
|
"Expected a condition",
|
||||||
|
"where needs a condition",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
|
||||||
WhereArgs { condition }: WhereArgs,
|
|
||||||
context: RunnableContext,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
Ok(context
|
|
||||||
.input
|
|
||||||
.values
|
|
||||||
.filter_map(move |item| {
|
|
||||||
let result = condition.invoke(&item);
|
|
||||||
|
|
||||||
let return_value = match result {
|
|
||||||
Err(err) => Some(Err(err)),
|
|
||||||
Ok(v) if v.is_true() => Some(Ok(ReturnSuccess::Value(item.clone()))),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
ready(return_value)
|
|
||||||
})
|
|
||||||
.boxed()
|
|
||||||
.to_output_stream())
|
|
||||||
}
|
|
||||||
|
@ -115,7 +115,7 @@ impl Context {
|
|||||||
self.registry.get_command(name).unwrap()
|
self.registry.get_command(name).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate async fn run_command(
|
crate async fn run_command<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
command: Arc<Command>,
|
command: Arc<Command>,
|
||||||
name_span: Span,
|
name_span: Span,
|
||||||
|
Loading…
Reference in New Issue
Block a user