WIP - types check

This commit is contained in:
Yehuda Katz
2019-08-02 19:17:28 -07:00
parent fc173c46d8
commit 586aa6bae1
23 changed files with 239 additions and 89 deletions

View File

@@ -1,4 +1,4 @@
use crate::commands::StaticCommand;
use crate::commands::{RawCommandArgs, StaticCommand};
use crate::context::{SourceMap, SpanSource};
use crate::errors::ShellError;
use crate::format::GenericView;
@@ -7,6 +7,9 @@ use std::path::Path;
pub struct Autoview;
#[derive(Deserialize)]
pub struct AutoviewArgs {}
impl StaticCommand for Autoview {
fn name(&self) -> &str {
"autoview"
@@ -17,37 +20,49 @@ impl StaticCommand for Autoview {
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, autoview)?.run()
args.process_raw(registry, autoview)?.run()
}
fn signature(&self) -> Signature {
Signature::build("autoview").sink()
Signature::build("autoview")
}
}
pub fn autoview(args: (), context: RunnableContext) -> Result<OutputStream, ShellError> {
if args.input.len() > 0 {
if let Spanned {
item: Value::Binary(_),
..
} = args.input[0]
{
args.ctx.get_sink("binaryview").run(args)?;
} else if is_single_text_value(&args.input) {
view_text_value(&args.input[0], &args.call_info.source_map);
} else if equal_shapes(&args.input) {
args.ctx.get_sink("table").run(args)?;
} else {
let mut host = args.ctx.host.lock().unwrap();
for i in args.input.iter() {
let view = GenericView::new(&i);
handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
host.stdout("");
pub fn autoview(
AutoviewArgs {}: AutoviewArgs,
mut context: RunnableContext,
raw: RawCommandArgs,
) -> Result<OutputStream, ShellError> {
let stream = async_stream_block! {
let input = context.input.drain_vec().await;
if input.len() > 0 {
if let Spanned {
item: Value::Binary(_),
..
} = input[0]
{
let binary = context.expect_command("binaryview");
binary.run(raw.with_input(input), &context.commands).await;
} else if is_single_text_value(&input) {
view_text_value(&input[0], &raw.call_info.source_map);
} else if equal_shapes(&input) {
let table = context.expect_command("table");
table.run(raw.with_input(input), &context.commands).await;
} else {
println!("TODO!")
// TODO
// let mut host = context.host.lock().unwrap();
// for i in input.iter() {
// let view = GenericView::new(&i);
// handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
// host.stdout("");
// }
}
}
}
};
Ok(OutputStream::empty())
Ok(OutputStream::new(stream))
}
fn equal_shapes(input: &Vec<Spanned<Value>>) -> bool {

View File

@@ -24,7 +24,7 @@ impl StaticCommand for Clip {
}
fn signature(&self) -> Signature {
Signature::build("clip").sink()
Signature::build("clip")
}
}

View File

@@ -59,6 +59,25 @@ pub struct CommandArgs {
pub input: InputStream,
}
#[derive(Getters)]
#[get = "crate"]
pub struct RawCommandArgs {
pub host: Arc<Mutex<dyn Host>>,
pub env: Arc<Mutex<Environment>>,
pub call_info: UnevaluatedCallInfo,
}
impl RawCommandArgs {
pub fn with_input(self, input: Vec<Spanned<Value>>) -> CommandArgs {
CommandArgs {
host: self.host,
env: self.env,
call_info: self.call_info,
input: input.into(),
}
}
}
impl ToDebug for CommandArgs {
fn fmt_debug(&self, f: &mut fmt::Formatter, source: &str) -> fmt::Result {
self.call_info.fmt_debug(f, source)
@@ -88,6 +107,7 @@ impl CommandArgs {
callback: fn(T, RunnableContext) -> Result<OutputStream, ShellError>,
) -> Result<RunnableArgs<T>, ShellError> {
let env = self.env.clone();
let host = self.host.clone();
let args = self.evaluate_once(registry)?;
let (input, args) = args.split();
let name_span = args.call_info.name_span;
@@ -97,12 +117,46 @@ impl CommandArgs {
args: T::deserialize(&mut deserializer)?,
context: RunnableContext {
input: input,
commands: registry.clone(),
env,
name: name_span,
host,
},
callback,
})
}
pub fn process_raw<'de, T: Deserialize<'de>>(
self,
registry: &CommandRegistry,
callback: fn(T, RunnableContext, RawCommandArgs) -> Result<OutputStream, ShellError>,
) -> Result<RunnableRawArgs<T>, ShellError> {
let raw_args = RawCommandArgs {
host: self.host.clone(),
env: self.env.clone(),
call_info: self.call_info.clone(),
};
let env = self.env.clone();
let host = self.host.clone();
let args = self.evaluate_once(registry)?;
let (input, args) = args.split();
let name_span = args.call_info.name_span;
let mut deserializer = ConfigDeserializer::from_call_node(args);
Ok(RunnableRawArgs {
args: T::deserialize(&mut deserializer)?,
context: RunnableContext {
input: input,
commands: registry.clone(),
env,
name: name_span,
host,
},
raw_args,
callback,
})
}
}
pub struct SinkContext {
@@ -120,6 +174,8 @@ pub struct SinkArgs<T> {
pub struct RunnableContext {
pub input: InputStream,
pub env: Arc<Mutex<Environment>>,
pub host: Arc<Mutex<dyn Host>>,
pub commands: CommandRegistry,
pub name: Option<Span>,
}
@@ -130,6 +186,12 @@ impl RunnableContext {
env.path.clone()
}
pub fn expect_command(&self, name: &str) -> Arc<Command> {
self.commands
.get_command(name)
.expect(&format!("Expected command {}", name))
}
}
pub struct RunnableArgs<T> {
@@ -144,6 +206,19 @@ impl<T> RunnableArgs<T> {
}
}
pub struct RunnableRawArgs<T> {
args: T,
raw_args: RawCommandArgs,
context: RunnableContext,
callback: fn(T, RunnableContext, RawCommandArgs) -> Result<OutputStream, ShellError>,
}
impl<T> RunnableRawArgs<T> {
pub fn run(self) -> Result<OutputStream, ShellError> {
(self.callback)(self.args, self.context, self.raw_args)
}
}
pub struct EvaluatedStaticCommandArgs {
pub args: EvaluatedCommandArgs,
pub input: InputStream,

View File

@@ -30,7 +30,6 @@ impl StaticCommand for Config {
.named("remove", SyntaxType::Any)
.switch("clear")
.switch("path")
.sink()
}
fn run(

View File

@@ -28,7 +28,6 @@ impl StaticCommand for Open {
Signature::build(self.name())
.required("path", SyntaxType::Block)
.switch("raw")
.sink()
}
fn run(

View File

@@ -23,7 +23,6 @@ impl StaticCommand for Remove {
Signature::build("rm")
.required("path", SyntaxType::Path)
.switch("recursive")
.sink()
}
fn run(

View File

@@ -7,13 +7,12 @@ use crate::errors::ShellError;
use crate::object::{Primitive, Value};
use crate::parser::Spanned;
use crate::prelude::*;
use futures_async_stream::async_stream_block;
use std::path::{Path, PathBuf};
pub struct Save;
#[derive(Deserialize)]
struct SaveArgs {
pub struct SaveArgs {
path: Spanned<PathBuf>,
raw: bool,
}
@@ -27,7 +26,6 @@ impl StaticCommand for Save {
Signature::build("save")
.required("path", SyntaxType::Path)
.switch("raw")
.sink()
}
fn run(
@@ -55,7 +53,7 @@ pub fn save(
let contents = match full_path.extension() {
Some(x) if x == "csv" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
yield Err(ShellError::string(
"saving to csv requires a single object (or use --raw)",
));
}
@@ -63,7 +61,7 @@ pub fn save(
}
Some(x) if x == "toml" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
yield Err(ShellError::string(
"saving to toml requires a single object (or use --raw)",
));
}
@@ -71,7 +69,7 @@ pub fn save(
}
Some(x) if x == "json" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
yield Err(ShellError::string(
"saving to json requires a single object (or use --raw)",
));
}
@@ -79,7 +77,7 @@ pub fn save(
}
Some(x) if x == "yml" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
yield Err(ShellError::string(
"saving to yml requires a single object (or use --raw)",
));
}
@@ -87,7 +85,7 @@ pub fn save(
}
Some(x) if x == "yaml" && !save_raw => {
if input.len() != 1 {
return Err(ShellError::string(
yield Err(ShellError::string(
"saving to yaml requires a single object (or use --raw)",
));
}
@@ -113,7 +111,5 @@ pub fn save(
let _ = std::fs::write(full_path, contents);
};
let stream: BoxStream<'static, ReturnValue> = stream.boxed();
Ok(OutputStream::from(stream))
Ok(OutputStream::new(stream))
}

View File

@@ -1,15 +1,42 @@
use crate::commands::StaticCommand;
use crate::errors::ShellError;
use crate::format::TableView;
use crate::prelude::*;
use futures_async_stream::async_stream_block;
pub fn table(args: CommandArgs, context: RunnableContext) -> Result<(), ShellError> {
if args.input.len() > 0 {
let mut host = args.ctx.host.lock().unwrap();
let view = TableView::from_list(&args.input);
if let Some(view) = view {
handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
}
pub struct Table;
#[derive(Deserialize)]
pub struct TableArgs {}
impl StaticCommand for Table {
fn name(&self) -> &str {
"table"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, table)?.run()
}
fn signature(&self) -> Signature {
Signature::build("table")
}
Ok(())
}
pub fn table(_args: TableArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
let stream = async_stream_block! {
let input: Vec<Spanned<Value>> = context.input.into_vec().await;
if input.len() > 0 {
let mut host = context.host.lock().unwrap();
let view = TableView::from_list(&input);
println!("{:#?}", view);
if let Some(view) = view {
handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
}
}
};
Ok(OutputStream::new(stream))
}

View File

@@ -1,15 +1,41 @@
use crate::commands::StaticCommand;
use crate::errors::ShellError;
use crate::format::VTableView;
use crate::prelude::*;
pub fn vtable(args: CommandArgs, context: RunnableContext) -> Result<(), ShellError> {
if args.input.len() > 0 {
let mut host = args.ctx.host.lock().unwrap();
let view = VTableView::from_list(&args.input);
if let Some(view) = view {
handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
}
}
pub struct VTable;
Ok(())
#[derive(Deserialize)]
pub struct VTableArgs {}
impl StaticCommand for VTable {
fn name(&self) -> &str {
"vtable"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, vtable)?.run()
}
fn signature(&self) -> Signature {
Signature::build("vtable")
}
}
pub fn vtable(args: VTableArgs, context: RunnableContext) -> Result<OutputStream, ShellError> {
let stream = async_stream_block! {
let input = context.input.into_vec().await;
if input.len() > 0 {
let mut host = context.host.lock().unwrap();
let view = VTableView::from_list(&input);
if let Some(view) = view {
handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
}
}
};
Ok(OutputStream::new(stream))
}

View File

@@ -21,9 +21,7 @@ impl StaticCommand for Where {
}
fn signature(&self) -> registry::Signature {
Signature::build("where")
.required("condition", SyntaxType::Block)
.sink()
Signature::build("where").required("condition", SyntaxType::Block)
}
fn run(