Merge pull request #615 from jonathandturner/echo

Fix exec::shell and add echo command
This commit is contained in:
Jonathan Turner
2019-09-08 14:30:24 +12:00
committed by GitHub
8 changed files with 164 additions and 125 deletions

View File

@ -210,6 +210,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
per_item_command(Open),
per_item_command(Post),
per_item_command(Where),
per_item_command(Echo),
whole_stream_command(Config),
whole_stream_command(SkipWhile),
per_item_command(Enter),

View File

@ -11,6 +11,7 @@ pub(crate) mod config;
pub(crate) mod cp;
pub(crate) mod date;
pub(crate) mod debug;
pub(crate) mod echo;
pub(crate) mod enter;
pub(crate) mod exit;
pub(crate) mod fetch;
@ -76,6 +77,7 @@ pub(crate) use config::Config;
pub(crate) use cp::Cpy;
pub(crate) use date::Date;
pub(crate) use debug::Debug;
pub(crate) use echo::Echo;
pub(crate) use enter::Enter;
pub(crate) use exit::Exit;
pub(crate) use fetch::Fetch;

View File

@ -58,7 +58,7 @@ pub fn autoview(
}
}
};
} else if is_single_text_value(&input) {
} else if is_single_origined_text_value(&input) {
let text = context.get_command("textview");
if let Some(text) = text {
let result = text.run(raw.with_input(input), &context.commands);
@ -73,6 +73,15 @@ pub fn autoview(
}
}
}
} else if is_single_text_value(&input) {
for i in input {
match i.item {
Value::Primitive(Primitive::String(s)) => {
println!("{}", s);
}
_ => {}
}
}
} else {
let table = context.expect_command("table");
let result = table.run(raw.with_input(input), &context.commands);
@ -96,3 +105,20 @@ fn is_single_text_value(input: &Vec<Tagged<Value>>) -> bool {
false
}
}
fn is_single_origined_text_value(input: &Vec<Tagged<Value>>) -> bool {
if input.len() != 1 {
return false;
}
if let Tagged {
item: Value::Primitive(Primitive::String(_)),
tag: Tag {
origin: Some(_), ..
},
} = input[0]
{
true
} else {
false
}
}

View File

@ -220,111 +220,60 @@ impl ExternalCommand {
let mut process;
#[cfg(windows)]
{
process = Exec::shell(&self.name);
process = Exec::cmd(&self.name);
if arg_string.contains("$it") {
let mut first = true;
for i in &inputs {
if i.as_string().is_err() {
let mut span = None;
for arg in &self.args {
if arg.item.contains("$it") {
span = Some(arg.span());
}
}
if let Some(span) = span {
return Err(ShellError::labeled_error(
"External $it needs string data",
"given row instead of string data",
span,
));
} else {
return Err(ShellError::string("Error: $it needs string data"));
}
}
if !first {
process = process.arg("&&");
process = process.arg(&self.name);
} else {
first = false;
}
if arg_string.contains("$it") {
let mut first = true;
for i in &inputs {
if i.as_string().is_err() {
let mut span = None;
for arg in &self.args {
if arg.chars().all(|c| c.is_whitespace()) {
continue;
if arg.item.contains("$it") {
span = Some(arg.span());
}
process = process.arg(&arg.replace("$it", &i.as_string()?));
}
if let Some(span) = span {
return Err(ShellError::labeled_error(
"External $it needs string data",
"given row instead of string data",
span,
));
} else {
return Err(ShellError::string("Error: $it needs string data"));
}
}
} else {
if !first {
process = process.arg("&&");
process = process.arg(&self.name);
} else {
first = false;
}
for arg in &self.args {
let arg_chars: Vec<_> = arg.chars().collect();
if arg_chars.len() > 1
&& arg_chars[0] == '"'
&& arg_chars[arg_chars.len() - 1] == '"'
{
// quoted string
let new_arg: String = arg_chars[1..arg_chars.len() - 1].iter().collect();
process = process.arg(new_arg);
} else {
process = process.arg(arg.item.clone());
if arg.chars().all(|c| c.is_whitespace()) {
continue;
}
process = process.arg(&arg.replace("$it", &i.as_string()?));
}
}
} else {
for arg in &self.args {
let arg_chars: Vec<_> = arg.chars().collect();
if arg_chars.len() > 1
&& arg_chars[0] == '"'
&& arg_chars[arg_chars.len() - 1] == '"'
{
// quoted string
let new_arg: String = arg_chars[1..arg_chars.len() - 1].iter().collect();
process = process.arg(new_arg);
} else {
process = process.arg(arg.item.clone());
}
}
}
#[cfg(not(windows))]
{
let mut new_arg_string = self.name.to_string();
if arg_string.contains("$it") {
let mut first = true;
for i in &inputs {
let i = match i.as_string() {
Err(_err) => {
let mut span = name_span;
for arg in &self.args {
if arg.item.contains("$it") {
span = arg.span();
}
}
return Err(ShellError::labeled_error(
"External $it needs string data",
"given row instead of string data",
span,
));
}
Ok(val) => val,
};
if !first {
new_arg_string.push_str("&&");
new_arg_string.push_str(&self.name);
} else {
first = false;
}
for arg in &self.args {
if arg.chars().all(|c| c.is_whitespace()) {
continue;
}
new_arg_string.push_str(" ");
new_arg_string.push_str(&arg.replace("$it", &i));
}
}
} else {
for arg in &self.args {
new_arg_string.push_str(" ");
new_arg_string.push_str(&arg);
}
}
process = Exec::shell(new_arg_string);
}
process = process.cwd(context.shell_manager.path());
let mut process = match stream_next {

72
src/commands/echo.rs Normal file
View File

@ -0,0 +1,72 @@
use crate::data::Value;
use crate::errors::ShellError;
use crate::prelude::*;
use crate::parser::registry::Signature;
pub struct Echo;
impl PerItemCommand for Echo {
fn name(&self) -> &str {
"echo"
}
fn signature(&self) -> Signature {
Signature::build("echo").rest(SyntaxType::Any)
}
fn usage(&self) -> &str {
"Echo the argments back to the user."
}
fn run(
&self,
call_info: &CallInfo,
registry: &CommandRegistry,
raw_args: &RawCommandArgs,
_input: Tagged<Value>,
) -> Result<OutputStream, ShellError> {
run(call_info, registry, raw_args)
}
}
fn run(
call_info: &CallInfo,
_registry: &CommandRegistry,
_raw_args: &RawCommandArgs,
) -> Result<OutputStream, ShellError> {
let name = call_info.name_span;
let mut output = String::new();
let mut first = true;
if let Some(ref positional) = call_info.args.positional {
for i in positional {
match i.as_string() {
Ok(s) => {
if !first {
output.push_str(" ");
} else {
first = false;
}
output.push_str(&s);
}
_ => {
return Err(ShellError::labeled_error(
"Expect a string from pipeline",
"not a string-compatible value",
i.span(),
));
}
}
}
}
let stream = VecDeque::from(vec![Ok(ReturnSuccess::Value(
Value::string(output).simple_spanned(name),
))]);
Ok(stream.to_output_stream())
}