Finish remove the last traces of per-item (#1685)

This commit is contained in:
Jonathan Turner 2020-04-30 14:23:40 +12:00 committed by GitHub
parent f8b4784891
commit d834708be8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 130 deletions

View File

@ -207,7 +207,7 @@ pub struct RunnableContext {
} }
impl RunnableContext { impl RunnableContext {
pub fn get_command(&self, name: &str) -> Option<Arc<Command>> { pub fn get_command(&self, name: &str) -> Option<Command> {
self.registry.get_command(name) self.registry.get_command(name)
} }
} }
@ -370,146 +370,54 @@ pub trait WholeStreamCommand: Send + Sync {
} }
} }
pub trait PerItemCommand: Send + Sync { #[derive(Clone)]
fn name(&self) -> &str; pub struct Command(Arc<dyn WholeStreamCommand>);
fn signature(&self) -> Signature {
Signature::new(self.name()).desc(self.usage()).filter()
}
fn usage(&self) -> &str;
fn run(
&self,
call_info: &CallInfo,
registry: &CommandRegistry,
raw_args: &RawCommandArgs,
input: Value,
) -> Result<OutputStream, ShellError>;
fn is_binary(&self) -> bool {
false
}
}
pub enum Command {
WholeStream(Arc<dyn WholeStreamCommand>),
PerItem(Arc<dyn PerItemCommand>),
}
impl PrettyDebugWithSource for Command { impl PrettyDebugWithSource for Command {
fn pretty_debug(&self, source: &str) -> DebugDocBuilder { fn pretty_debug(&self, source: &str) -> DebugDocBuilder {
match self { b::typed(
Command::WholeStream(command) => b::typed( "whole stream command",
"whole stream command", b::description(self.name())
b::description(command.name()) + b::space()
+ b::space() + b::equals()
+ b::equals() + b::space()
+ b::space() + self.signature().pretty_debug(source),
+ command.signature().pretty_debug(source), )
),
Command::PerItem(command) => b::typed(
"per item command",
b::description(command.name())
+ b::space()
+ b::equals()
+ b::space()
+ command.signature().pretty_debug(source),
),
}
} }
} }
impl std::fmt::Debug for Command { impl std::fmt::Debug for Command {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { write!(f, "Command({})", self.name())
Command::WholeStream(command) => write!(f, "WholeStream({})", command.name()),
Command::PerItem(command) => write!(f, "PerItem({})", command.name()),
}
} }
} }
impl Command { impl Command {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
match self { self.0.name()
Command::WholeStream(command) => command.name(),
Command::PerItem(command) => command.name(),
}
} }
pub fn signature(&self) -> Signature { pub fn signature(&self) -> Signature {
match self { self.0.signature()
Command::WholeStream(command) => command.signature(),
Command::PerItem(command) => command.signature(),
}
} }
pub fn usage(&self) -> &str { pub fn usage(&self) -> &str {
match self { self.0.usage()
Command::WholeStream(command) => command.usage(),
Command::PerItem(command) => command.usage(),
}
} }
pub fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream { pub fn run(&self, args: CommandArgs, registry: &CommandRegistry) -> OutputStream {
if args.call_info.switch_present("help") { if args.call_info.switch_present("help") {
get_help(self.name(), self.usage(), self.signature()).into() get_help(self.name(), self.usage(), self.signature()).into()
} else { } else {
match self { match self.0.run(args, registry) {
Command::WholeStream(command) => match command.run(args, registry) { Ok(stream) => stream,
Ok(stream) => stream, Err(err) => OutputStream::one(Err(err)),
Err(err) => OutputStream::one(Err(err)),
},
Command::PerItem(command) => {
self.run_helper(command.clone(), args, registry.clone())
}
} }
} }
} }
fn run_helper(
&self,
command: Arc<dyn PerItemCommand>,
args: CommandArgs,
registry: CommandRegistry,
) -> OutputStream {
let raw_args = RawCommandArgs {
host: args.host,
ctrl_c: args.ctrl_c,
shell_manager: args.shell_manager,
call_info: args.call_info,
};
let out = args
.input
.map(move |x| {
let call_info = UnevaluatedCallInfo {
args: raw_args.call_info.args.clone(),
name_tag: raw_args.call_info.name_tag.clone(),
scope: raw_args.call_info.scope.clone().set_it(x.clone()),
}
.evaluate(&registry);
match call_info {
Ok(call_info) => match command.run(&call_info, &registry, &raw_args, x) {
Ok(o) => o,
Err(e) => {
futures::stream::iter(vec![ReturnValue::Err(e)]).to_output_stream()
}
},
Err(e) => futures::stream::iter(vec![ReturnValue::Err(e)]).to_output_stream(),
}
})
.flatten();
out.to_output_stream()
}
pub fn is_binary(&self) -> bool { pub fn is_binary(&self) -> bool {
match self { self.0.is_binary()
Command::WholeStream(command) => command.is_binary(),
Command::PerItem(command) => command.is_binary(),
}
} }
} }
@ -571,6 +479,6 @@ impl WholeStreamCommand for FnFilterCommand {
} }
} }
pub fn whole_stream_command(command: impl WholeStreamCommand + 'static) -> Arc<Command> { pub fn whole_stream_command(command: impl WholeStreamCommand + 'static) -> Command {
Arc::new(Command::WholeStream(Arc::new(command))) Command(Arc::new(command))
} }

View File

@ -16,7 +16,7 @@ use std::sync::Arc;
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct CommandRegistry { pub struct CommandRegistry {
registry: Arc<Mutex<IndexMap<String, Arc<Command>>>>, registry: Arc<Mutex<IndexMap<String, Command>>>,
} }
impl SignatureRegistry for CommandRegistry { impl SignatureRegistry for CommandRegistry {
@ -42,13 +42,13 @@ impl CommandRegistry {
} }
impl CommandRegistry { impl CommandRegistry {
pub(crate) fn get_command(&self, name: &str) -> Option<Arc<Command>> { pub(crate) fn get_command(&self, name: &str) -> Option<Command> {
let registry = self.registry.lock(); let registry = self.registry.lock();
registry.get(name).cloned() registry.get(name).cloned()
} }
pub(crate) fn expect_command(&self, name: &str) -> Result<Arc<Command>, ShellError> { pub(crate) fn expect_command(&self, name: &str) -> Result<Command, ShellError> {
self.get_command(name).ok_or_else(|| { self.get_command(name).ok_or_else(|| {
ShellError::untagged_runtime_error(format!("Could not load command: {}", name)) ShellError::untagged_runtime_error(format!("Could not load command: {}", name))
}) })
@ -60,7 +60,7 @@ impl CommandRegistry {
registry.contains_key(name) registry.contains_key(name)
} }
pub(crate) fn insert(&mut self, name: impl Into<String>, command: Arc<Command>) { pub(crate) fn insert(&mut self, name: impl Into<String>, command: Command) {
let mut registry = self.registry.lock(); let mut registry = self.registry.lock();
registry.insert(name.into(), command); registry.insert(name.into(), command);
} }
@ -209,23 +209,23 @@ impl Context {
block(&mut *errors) block(&mut *errors)
} }
pub fn add_commands(&mut self, commands: Vec<Arc<Command>>) { pub fn add_commands(&mut self, commands: Vec<Command>) {
for command in commands { for command in commands {
self.registry.insert(command.name().to_string(), command); self.registry.insert(command.name().to_string(), command);
} }
} }
pub(crate) fn get_command(&self, name: &str) -> Option<Arc<Command>> { pub(crate) fn get_command(&self, name: &str) -> Option<Command> {
self.registry.get_command(name) self.registry.get_command(name)
} }
pub(crate) fn expect_command(&self, name: &str) -> Result<Arc<Command>, ShellError> { pub(crate) fn expect_command(&self, name: &str) -> Result<Command, ShellError> {
self.registry.expect_command(name) self.registry.expect_command(name)
} }
pub(crate) fn run_command( pub(crate) fn run_command(
&mut self, &mut self,
command: Arc<Command>, command: Command,
name_tag: Tag, name_tag: Tag,
args: hir::Call, args: hir::Call,
scope: &Scope, scope: &Scope,

View File

@ -2,22 +2,15 @@ use crate::commands::command::Command;
use crate::data::TaggedListBuilder; use crate::data::TaggedListBuilder;
use crate::prelude::*; use crate::prelude::*;
use nu_protocol::{NamedType, PositionalType, Signature, TaggedDictBuilder, UntaggedValue, Value}; use nu_protocol::{NamedType, PositionalType, Signature, TaggedDictBuilder, UntaggedValue, Value};
use std::ops::Deref;
pub(crate) fn command_dict(command: Arc<Command>, tag: impl Into<Tag>) -> Value { pub(crate) fn command_dict(command: Command, tag: impl Into<Tag>) -> Value {
let tag = tag.into(); let tag = tag.into();
let mut cmd_dict = TaggedDictBuilder::new(&tag); let mut cmd_dict = TaggedDictBuilder::new(&tag);
cmd_dict.insert_untagged("name", UntaggedValue::string(command.name())); cmd_dict.insert_untagged("name", UntaggedValue::string(command.name()));
cmd_dict.insert_untagged( cmd_dict.insert_untagged("type", UntaggedValue::string("Command"));
"type",
UntaggedValue::string(match command.deref() {
Command::WholeStream(_) => "Command",
Command::PerItem(_) => "Filter",
}),
);
cmd_dict.insert_value("signature", signature_dict(command.signature(), tag)); cmd_dict.insert_value("signature", signature_dict(command.signature(), tag));
cmd_dict.insert_untagged("usage", UntaggedValue::string(command.usage())); cmd_dict.insert_untagged("usage", UntaggedValue::string(command.usage()));