Pipe external to internal

Each line is a string object
This commit is contained in:
Yehuda Katz 2019-05-24 11:48:33 -07:00
parent f9fb353c5c
commit 9f8d2a4de5
15 changed files with 391 additions and 97 deletions

123
Cargo.lock generated
View File

@ -143,6 +143,15 @@ name = "byteorder"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bytes"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cc"
version = "1.0.37"
@ -285,6 +294,15 @@ dependencies = [
"crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-deque"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-epoch"
version = "0.3.1"
@ -299,6 +317,27 @@ dependencies = [
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-epoch"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-queue"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.2.2"
@ -650,6 +689,11 @@ name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "futures"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "futures-channel-preview"
version = "0.3.0-alpha.16"
@ -710,6 +754,7 @@ name = "futures-util-preview"
version = "0.3.0-alpha.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-channel-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-io-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
@ -717,6 +762,16 @@ dependencies = [
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures_codec"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -742,6 +797,15 @@ name = "indexmap"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "iovec"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itertools"
version = "0.8.0"
@ -917,6 +981,7 @@ dependencies = [
"dunce 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-sink-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures_codec 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 5.0.0-beta1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -927,6 +992,8 @@ dependencies = [
"rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"sysinfo 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1633,6 +1700,51 @@ dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-executor"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-fs"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-io"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-threadpool"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.5.1"
@ -1787,6 +1899,7 @@ dependencies = [
"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
"checksum byte-unit 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6754bb4703aa167bed5381f0c6842f1cc31a9ecde3b9443f726dde3ad3afb841"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
@ -1803,7 +1916,10 @@ dependencies = [
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b"
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4"
"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
@ -1842,6 +1958,7 @@ dependencies = [
"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139"
"checksum futures-channel-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4cd523712fc272e9b714669165a2832debee5a5b7e409bfccdc7c0d5cd0cf07a"
"checksum futures-core-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "719770f328642b657b849856bb5a607db9538dd5bb3000122e5ead55d0a58c36"
"checksum futures-executor-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "315dc58c908535d059576a329b86cd185933433382cfcd394fb2fa353330de03"
@ -1849,10 +1966,12 @@ dependencies = [
"checksum futures-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfeac5f016a4b5835bb93eb7961f50a64f0e001207562703d9ddf4109d7b263"
"checksum futures-sink-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "49dcfdacd6b5974ca0b9b78bc38ffd1071da0206179735c3df82e279f5b784e4"
"checksum futures-util-preview 0.3.0-alpha.16 (registry+https://github.com/rust-lang/crates.io-index)" = "f7a0451b9c5047c2b9ab93425ffd0793165511e93c04b977cd45fbd41c6e34b2"
"checksum futures_codec 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b60f48aa03e365df015d2fbf0b79f17b440350c268a5e20305da17b394adcc1e"
"checksum hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "570178d5e4952010d138b0f1d581271ff3a02406d990f887d1e87e3d6e43b0ac"
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
@ -1954,6 +2073,10 @@ dependencies = [
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e"
"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af"
"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926"
"checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2"
"checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"

View File

@ -27,8 +27,11 @@ byte-unit = "2.1.0"
ordered-float = "1.0.2"
prettyprint = "0.6.0"
cursive = { version = "0.12.0", features = ["pancurses-backend"], default-features = false }
futures-preview = "0.3.0-alpha.16"
futures-preview = { version = "0.3.0-alpha.16", features = ["compat", "io-compat"] }
futures-sink-preview = "0.3.0-alpha.16"
tokio-fs = "0.1.6"
futures_codec = "0.2.2"
term = "0.5.2"
[dependencies.pancurses]
version = "0.16"

View File

@ -1,7 +1,7 @@
use crate::prelude::*;
use crate::commands::classified::{
ClassifiedCommand, ClassifiedInputStream, ExternalCommand, InternalCommand,
ClassifiedCommand, ClassifiedInputStream, ExternalCommand, InternalCommand, StreamNext,
};
use crate::context::Context;
crate use crate::errors::ShellError;
@ -185,7 +185,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
(
Some(ClassifiedCommand::External(left)),
Some(ClassifiedCommand::External(_)),
) => match left.run(ctx, input, true).await {
) => match left.run(ctx, input, StreamNext::External).await {
Ok(val) => val,
Err(err) => return LineResult::Error(format!("{}", err.description())),
},
@ -196,12 +196,15 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
) => unimplemented!(),
(
Some(ClassifiedCommand::External(_)),
Some(ClassifiedCommand::External(left)),
Some(ClassifiedCommand::Internal(_)),
) => unimplemented!(),
) => match left.run(ctx, input, StreamNext::Internal).await {
Ok(val) => val,
Err(err) => return LineResult::Error(format!("{}", err.description())),
},
(Some(ClassifiedCommand::External(left)), None) => {
match left.run(ctx, input, false).await {
match left.run(ctx, input, StreamNext::Last).await {
Ok(val) => val,
Err(err) => return LineResult::Error(format!("{}", err.description())),
}

View File

@ -1,4 +1,6 @@
use crate::prelude::*;
use futures::compat::AsyncRead01CompatExt;
use futures_codec::{Framed, LinesCodec};
use std::sync::Arc;
use subprocess::Exec;
@ -107,20 +109,29 @@ crate struct ExternalCommand {
crate args: Vec<String>,
}
crate enum StreamNext {
Last,
External,
Internal,
}
impl ExternalCommand {
crate async fn run(
self,
context: &mut Context,
mut input: ClassifiedInputStream,
stream_next: bool,
stream_next: StreamNext,
) -> Result<ClassifiedInputStream, ShellError> {
let mut process = Exec::shell(&self.name)
.args(&self.args)
.cwd(context.env.lock().unwrap().cwd());
if stream_next {
process = process.stdout(subprocess::Redirection::Pipe)
}
let mut process = match stream_next {
StreamNext::Last => process,
StreamNext::External | StreamNext::Internal => {
process.stdout(subprocess::Redirection::Pipe)
}
};
if let Some(stdin) = input.stdin {
process = process.stdin(stdin);
@ -128,15 +139,31 @@ impl ExternalCommand {
let mut popen = process.popen().unwrap();
if stream_next {
match &popen.stdout {
None => unreachable!(),
Some(stdout) => Ok(ClassifiedInputStream::from_stdout(stdout.try_clone()?)),
match stream_next {
StreamNext::Last => {
popen.wait()?;
Ok(ClassifiedInputStream::new())
}
StreamNext::External => {
let stdout = popen.stdout.take().unwrap();
Ok(ClassifiedInputStream::from_stdout(stdout))
}
StreamNext::Internal => {
let stdout = popen.stdout.take().unwrap();
let file = futures::io::AllowStdIo::new(stdout);
let stream = Framed::new(file, LinesCodec {});
let stream = stream.map(|line| Value::string(line.unwrap()));
Ok(ClassifiedInputStream::from_input_stream(stream.boxed()))
}
} else {
popen.stdin.take();
popen.wait()?;
Ok(ClassifiedInputStream::new())
}
// if stream_next {
// let stdout = popen.stdout.take().unwrap();
// Ok(ClassifiedInputStream::from_stdout(stdout))
// } else {
// // popen.stdin.take();
// popen.wait()?;
// Ok(ClassifiedInputStream::new())
// }
}
}

19
src/env/host.rs vendored
View File

@ -1,9 +1,20 @@
pub trait Host {
fn out_terminal(&self) -> Box<term::StdoutTerminal>;
fn err_terminal(&self) -> Box<term::StderrTerminal>;
fn stdout(&mut self, out: &str);
fn stderr(&mut self, out: &str);
}
impl Host for Box<dyn Host> {
fn out_terminal(&self) -> Box<term::StdoutTerminal> {
(**self).out_terminal()
}
fn err_terminal(&self) -> Box<term::StderrTerminal> {
(**self).err_terminal()
}
fn stdout(&mut self, out: &str) {
(**self).stdout(out)
}
@ -16,6 +27,14 @@ impl Host for Box<dyn Host> {
crate struct BasicHost;
impl Host for BasicHost {
fn out_terminal(&self) -> Box<term::StdoutTerminal> {
term::stdout().unwrap()
}
fn err_terminal(&self) -> Box<term::StderrTerminal> {
term::stderr().unwrap()
}
fn stdout(&mut self, out: &str) {
match out {
"\n" => println!(""),

View File

@ -10,16 +10,9 @@ crate use generic::GenericView;
crate use table::TableView;
crate trait RenderView {
fn render_view(&self, host: &dyn Host) -> Vec<String>;
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError>;
}
fn print_rendered(lines: &[String], host: &mut dyn Host) {
for line in lines {
host.stdout(line);
}
}
crate fn print_view(view: &impl RenderView, host: &mut Host) {
// let mut ctx = context.lock().unwrap();
crate::format::print_rendered(&view.render_view(host), host);
crate fn print_view(view: &impl RenderView, host: &mut dyn Host) -> Result<(), ShellError> {
view.render_view(host)
}

View File

@ -10,7 +10,7 @@ use derive_new::new;
// another_name : ...
#[derive(new)]
pub struct EntriesView {
entries: Vec<(String, String)>,
entries: Vec<(crate::object::DescriptorName, String)>,
}
impl EntriesView {
@ -31,17 +31,28 @@ impl EntriesView {
}
impl RenderView for EntriesView {
fn render_view(&self, _host: &dyn Host) -> Vec<String> {
fn render_view(&self, _host: &mut dyn Host) -> Result<(), ShellError> {
if self.entries.len() == 0 {
return vec![];
return Ok(());
}
let max_name_size: usize = self.entries.iter().map(|(n, _)| n.len()).max().unwrap();
self.entries
let max_name_size: usize = self
.entries
.iter()
.map(|(k, v)| format!("{:width$} : {}", k, v, width = max_name_size))
.collect()
.map(|(n, _)| n.display().len())
.max()
.unwrap();
for (name, value) in &self.entries {
println!(
"{:width$} : {}",
name.display(),
value,
width = max_name_size
)
}
Ok(())
}
}
@ -58,26 +69,22 @@ impl EntriesListView {
}
impl RenderView for EntriesListView {
fn render_view(&self, host: &dyn Host) -> Vec<String> {
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError> {
if self.values.len() == 0 {
return vec![];
return Ok(());
}
let mut strings = vec![];
let last = self.values.len() - 1;
for (i, item) in self.values.iter().enumerate() {
let view = EntriesView::from_value(item);
let out = view.render_view(host);
strings.extend(out);
view.render_view(host);
if i != last {
strings.push("\n".to_string());
host.stdout("\n");
}
}
strings
Ok(())
}
}

View File

@ -10,17 +10,17 @@ pub struct GenericView<'value> {
}
impl RenderView for GenericView<'value> {
fn render_view(&self, host: &dyn Host) -> Vec<String> {
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError> {
match self.value {
Value::Primitive(p) => vec![p.format(None)],
Value::Primitive(p) => Ok(host.stdout(&p.format(None))),
Value::List(l) => {
let view = TableView::from_list(l);
if let Some(view) = view {
view.render_view(host)
} else {
vec![]
view.render_view(host);
}
Ok(())
// let mut list: Vec<String> = vec![];
// for item in l {
// match item {
@ -39,11 +39,14 @@ impl RenderView for GenericView<'value> {
o @ Value::Object(_) => {
let view = EntriesView::from_value(o);
let out = view.render_view(host);
out
view.render_view(host);
Ok(())
}
Value::Error(e) => vec![format!("{}", e)],
Value::Error(e) => {
host.stdout(&format!("{:?}", e));
Ok(())
}
}
}
}

View File

@ -11,14 +11,12 @@ pub struct ListView {
}
impl RenderView for ListView {
fn render_view(&self, _host: &dyn Host) -> Vec<String> {
let mut out = vec![];
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError> {
for output in &self.list {
let string: String = output.iter().map(|l| format!("{}\n", l)).collect();
out.push(format!("{}{}", string, self.sep));
host.stdout(&format!("{}{}", string, self.sep));
}
out
Ok(())
}
}

View File

@ -1,8 +1,9 @@
use crate::format::RenderView;
use crate::object::Value;
use crate::prelude::*;
use ansi_term::Color;
use derive_new::new;
use prettytable::{Cell, Row, Table};
use prettytable::{color, Attr, Cell, Row, Table};
// An entries list is printed like this:
//
@ -24,7 +25,7 @@ impl TableView {
let item = &values[0];
let descs = item.data_descriptors();
let headers: Vec<String> = descs.iter().map(|d| d.name.clone()).collect();
let headers: Vec<String> = descs.iter().map(|d| d.name.display().to_string()).collect();
let mut entries = vec![];
@ -43,13 +44,27 @@ impl TableView {
}
impl RenderView for TableView {
fn render_view(&self, _host: &dyn Host) -> Vec<String> {
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError> {
if self.entries.len() == 0 {
return vec![];
return Ok(());
}
let mut table = Table::new();
let header: Vec<Cell> = self.headers.iter().map(|h| Cell::new(h)).collect();
// let format = prettytable::format::FormatBuilder::new();
// .column_separator(Color::Black.bold().paint("|"));
table.set_format(*prettytable::format::consts::FORMAT_NO_COLSEP);
let header: Vec<Cell> = self
.headers
.iter()
.map(|h| {
Cell::new(h)
.with_style(Attr::ForegroundColor(color::GREEN))
.with_style(Attr::Bold)
})
.collect();
table.add_row(Row::new(header));
@ -57,9 +72,8 @@ impl RenderView for TableView {
table.add_row(Row::new(row.iter().map(|h| Cell::new(h)).collect()));
}
let mut out = vec![];
table.print(&mut out).unwrap();
table.print_term(&mut *host.out_terminal()).unwrap();
vec![String::from_utf8_lossy(&out).to_string()]
Ok(())
}
}

View File

@ -6,5 +6,6 @@ crate mod process;
crate mod types;
crate use base::{Primitive, Value};
crate use desc::{DataDescriptor, DescriptorName};
crate use dict::Dictionary;
crate use files::dir_entry_dict;

View File

@ -1,5 +1,5 @@
use crate::errors::ShellError;
use crate::object::desc::DataDescriptor;
use crate::object::{DataDescriptor, DescriptorName};
use crate::parser::parse::Operator;
use crate::prelude::*;
use ansi_term::Color;
@ -69,7 +69,7 @@ pub enum Value {
impl Value {
crate fn data_descriptors(&self) -> Vec<DataDescriptor> {
match self {
Value::Primitive(_) => vec![],
Value::Primitive(_) => vec![DataDescriptor::value_of()],
Value::Object(o) => o.data_descriptors(),
Value::List(_) => vec![],
Value::Error(_) => vec![],
@ -87,7 +87,7 @@ impl Value {
crate fn get_data(&'a self, desc: &DataDescriptor) -> MaybeOwned<'a, Value> {
match self {
Value::Primitive(_) => MaybeOwned::Owned(Value::nothing()),
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
Value::Object(o) => o.get_data(desc),
Value::List(_) => MaybeOwned::Owned(Value::nothing()),
Value::Error(_) => MaybeOwned::Owned(Value::nothing()),
@ -203,9 +203,9 @@ crate fn select_fields(obj: &Value, fields: &[String]) -> crate::object::Diction
let descs = obj.data_descriptors();
for field in fields {
match descs.iter().find(|d| d.name == *field) {
None => out.add(field.to_string(), Value::nothing()),
Some(desc) => out.add(field.to_string(), obj.get_data(desc).borrow().copy()),
match descs.iter().find(|d| d.name.is_string(field)) {
None => out.add(DataDescriptor::for_string_name(field), Value::nothing()),
Some(desc) => out.add(desc.copy(), obj.get_data(desc).borrow().copy()),
}
}
@ -218,10 +218,10 @@ crate fn reject_fields(obj: &Value, fields: &[String]) -> crate::object::Diction
let descs = obj.data_descriptors();
for desc in descs {
if fields.contains(&desc.name) {
continue;
} else {
out.add(desc.name.clone(), obj.get_data(&desc).borrow().copy())
match desc.name.as_string() {
None => continue,
Some(s) if fields.iter().any(|field| field == s) => continue,
Some(s) => out.add(desc.copy(), obj.get_data(&desc).borrow().copy()),
}
}
@ -230,7 +230,7 @@ crate fn reject_fields(obj: &Value, fields: &[String]) -> crate::object::Diction
crate fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool {
let descs = obj.data_descriptors();
match descs.iter().find(|d| d.name == *field) {
match descs.iter().find(|d| d.name.is_string(field)) {
None => false,
Some(desc) => {
let v = obj.get_data(desc).borrow().copy();

View File

@ -1,17 +1,110 @@
use crate::object::types::Type;
use crate::object::types::{AnyShell, Type};
use derive_new::new;
#[derive(new)]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum DescriptorName {
String(String),
ValueOf,
}
impl DescriptorName {
crate fn display(&self) -> &str {
match self {
DescriptorName::String(s) => s,
DescriptorName::ValueOf => "value",
}
}
crate fn as_string(&self) -> Option<&str> {
match self {
DescriptorName::String(s) => Some(s),
DescriptorName::ValueOf => None,
}
}
crate fn is_string(&self, string: &str) -> bool {
match self {
DescriptorName::String(s) => s == string,
DescriptorName::ValueOf => false,
}
}
}
#[derive(Debug, new)]
pub struct DataDescriptor {
crate name: String,
crate name: DescriptorName,
crate readonly: bool,
crate ty: Box<dyn Type>,
}
impl From<&str> for DataDescriptor {
fn from(input: &str) -> DataDescriptor {
DataDescriptor {
name: DescriptorName::String(input.to_string()),
readonly: true,
ty: Box::new(AnyShell),
}
}
}
impl From<String> for DataDescriptor {
fn from(input: String) -> DataDescriptor {
DataDescriptor {
name: DescriptorName::String(input),
readonly: true,
ty: Box::new(AnyShell),
}
}
}
impl PartialEq for DataDescriptor {
fn eq(&self, other: &DataDescriptor) -> bool {
self.name == other.name && self.readonly == other.readonly && self.ty.equal(&*other.ty)
}
}
impl DataDescriptor {}
impl std::hash::Hash for DataDescriptor {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.readonly.hash(state);
self.ty.id().hash(state);
}
}
impl Eq for DataDescriptor {}
impl DescriptorName {
crate fn for_string_name(name: impl Into<String>) -> DescriptorName {
DescriptorName::String(name.into())
}
}
impl DataDescriptor {
crate fn value_of() -> DataDescriptor {
DataDescriptor {
name: DescriptorName::ValueOf,
readonly: true,
ty: Box::new(AnyShell),
}
}
crate fn for_name(name: impl Into<DescriptorName>) -> DataDescriptor {
DataDescriptor {
name: name.into(),
readonly: true,
ty: Box::new(AnyShell),
}
}
crate fn for_string_name(name: impl Into<String>) -> DataDescriptor {
DataDescriptor::for_name(DescriptorName::for_string_name(name))
}
crate fn copy(&self) -> DataDescriptor {
DataDescriptor {
name: self.name.clone(),
readonly: self.readonly,
ty: self.ty.copy(),
}
}
}

View File

@ -1,13 +1,13 @@
use crate::prelude::*;
use crate::object::desc::DataDescriptor;
use crate::object::{DataDescriptor, DescriptorName};
use crate::object::{Primitive, Value};
use indexmap::IndexMap;
use std::cmp::{Ordering, PartialOrd};
#[derive(Debug, Default, Eq, PartialEq)]
pub struct Dictionary {
entries: IndexMap<String, Value>,
entries: IndexMap<DataDescriptor, Value>,
}
impl PartialOrd for Dictionary {
@ -41,7 +41,7 @@ impl PartialEq<Value> for Dictionary {
}
impl Dictionary {
crate fn add(&mut self, name: impl Into<String>, value: Value) {
crate fn add(&mut self, name: impl Into<DataDescriptor>, value: Value) {
self.entries.insert(name.into(), value);
}
@ -49,31 +49,30 @@ impl Dictionary {
let mut out = Dictionary::default();
for (key, value) in self.entries.iter() {
out.add(key.clone(), value.copy());
out.add(key.copy(), value.copy());
}
out
}
crate fn data_descriptors(&self) -> Vec<DataDescriptor> {
self.entries
.iter()
.map(|(name, _)| {
DataDescriptor::new(name.clone(), true, Box::new(crate::object::types::AnyShell))
})
.collect()
self.entries.iter().map(|(name, _)| name.copy()).collect()
}
crate fn get_data(&'a self, desc: &DataDescriptor) -> MaybeOwned<'a, Value> {
match self.entries.get(&desc.name) {
match self.entries.get(desc) {
Some(v) => MaybeOwned::Borrowed(v),
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),
}
}
crate fn get_data_by_key(&self, name: &str) -> MaybeOwned<'_, Value> {
match self.entries.get(name) {
Some(v) => MaybeOwned::Borrowed(v),
match self
.entries
.iter()
.find(|(desc_name, _)| desc_name.name.is_string(name))
{
Some((_, v)) => MaybeOwned::Borrowed(v),
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),
}
}

View File

@ -1,11 +1,14 @@
use std::any::Any;
use std::fmt::Debug;
pub trait Type {
pub trait Type: Debug + Send {
fn as_any(&self) -> &dyn Any;
fn equal(&self, other: &dyn Type) -> bool;
fn id(&self) -> u64;
fn copy(&self) -> Box<Type>;
}
#[derive(Eq, PartialEq)]
#[derive(Debug, Eq, PartialEq)]
pub struct AnyShell;
impl Type for AnyShell {
@ -16,4 +19,12 @@ impl Type for AnyShell {
fn equal(&self, other: &dyn Type) -> bool {
other.as_any().is::<AnyShell>()
}
fn id(&self) -> u64 {
0
}
fn copy(&self) -> Box<Type> {
Box::new(AnyShell)
}
}