Skip to content
Snippets Groups Projects
Commit 13054955 authored by Michael Aaron Murphy's avatar Michael Aaron Murphy
Browse files

Implement $find() & @split_at()

parent cf0c2c27
No related branches found
No related tags found
No related merge requests found
...@@ -31,4 +31,8 @@ echo $repeat("one ", 5) ...@@ -31,4 +31,8 @@ echo $repeat("one ", 5)
echo $join([one two three], "\n") echo $join([one two three], "\n")
echo $join([one two three], "\t") echo $join([one two three], "\t")
echo $join([one two three], "\\n") echo $join([one two three], "\\n")
echo $replace($join([one two three], "\n"), "\n" "\t") echo $replace($join([one two three], "\n"), "\n" "\t")
\ No newline at end of file let a = "applesauce"
let pos = $find(a, "s")
let array = [@split_at(a, $pos)]
echo $join(array, "\n")
\ No newline at end of file
...@@ -63,3 +63,5 @@ three ...@@ -63,3 +63,5 @@ three
one two three one two three
one\ntwo\nthree one\ntwo\nthree
one two three one two three
apple
sauce
...@@ -350,13 +350,7 @@ pub(crate) fn expand_tokens<E: Expander>( ...@@ -350,13 +350,7 @@ pub(crate) fn expand_tokens<E: Expander>(
Select::Key(_) => (), Select::Key(_) => (),
}, },
WordToken::ArrayMethod(ref array_method) => { WordToken::ArrayMethod(ref array_method) => {
return if array_method.returns_array() { return array_method.handle_as_array(expand_func)
array_method.handle_as_array(expand_func)
} else {
let mut output = String::new();
array_method.handle(&mut output, expand_func);
array!(output)
}
} }
_ => (), _ => (),
} }
......
use super::{Pattern, Select, SelectWithSize}; use super::{Pattern, Select, SelectWithSize};
use super::pattern::unescape;
use super::super::Index; use super::super::Index;
use super::super::super::{expand_string, Expander}; use super::super::super::{expand_string, Expander};
use super::super::super::is_expression; use super::super::super::is_expression;
use smallstring::SmallString;
use std::char; use std::char;
use std::io::{self, Write}; use std::io::{self, Write};
use types::Array; use types::Array;
...@@ -16,13 +18,6 @@ pub(crate) struct ArrayMethod<'a> { ...@@ -16,13 +18,6 @@ pub(crate) struct ArrayMethod<'a> {
} }
impl<'a> ArrayMethod<'a> { impl<'a> ArrayMethod<'a> {
pub(crate) fn returns_array(&self) -> bool {
match self.method {
"split" | "chars" | "bytes" | "graphemes" => true,
_ => false,
}
}
pub(crate) fn handle<E: Expander>(&self, current: &mut String, expand_func: &E) { pub(crate) fn handle<E: Expander>(&self, current: &mut String, expand_func: &E) {
match self.method { match self.method {
"split" => { "split" => {
...@@ -35,7 +30,7 @@ impl<'a> ArrayMethod<'a> { ...@@ -35,7 +30,7 @@ impl<'a> ArrayMethod<'a> {
}; };
match (&self.pattern, self.selection.clone()) { match (&self.pattern, self.selection.clone()) {
(&Pattern::StringPattern(pattern), Select::All) => current.push_str(&variable (&Pattern::StringPattern(pattern), Select::All) => current.push_str(&variable
.split(&expand_string(pattern, expand_func, false).join(" ")) .split(&unescape(expand_string(pattern, expand_func, false).join(" ")))
.collect::<Vec<&str>>() .collect::<Vec<&str>>()
.join(" ")), .join(" ")),
(&Pattern::Whitespace, Select::All) => current.push_str(&variable (&Pattern::Whitespace, Select::All) => current.push_str(&variable
...@@ -47,7 +42,9 @@ impl<'a> ArrayMethod<'a> { ...@@ -47,7 +42,9 @@ impl<'a> ArrayMethod<'a> {
(&Pattern::StringPattern(pattern), Select::Index(Index::Forward(id))) => { (&Pattern::StringPattern(pattern), Select::Index(Index::Forward(id))) => {
current.push_str( current.push_str(
variable variable
.split(&expand_string(pattern, expand_func, false).join(" ")) .split(
&unescape(expand_string(pattern, expand_func, false).join(" ")),
)
.nth(id) .nth(id)
.unwrap_or_default(), .unwrap_or_default(),
) )
...@@ -62,7 +59,9 @@ impl<'a> ArrayMethod<'a> { ...@@ -62,7 +59,9 @@ impl<'a> ArrayMethod<'a> {
(&Pattern::StringPattern(pattern), Select::Index(Index::Backward(id))) => { (&Pattern::StringPattern(pattern), Select::Index(Index::Backward(id))) => {
current.push_str( current.push_str(
variable variable
.rsplit(&expand_string(pattern, expand_func, false).join(" ")) .rsplit(
&unescape(expand_string(pattern, expand_func, false).join(" ")),
)
.nth(id) .nth(id)
.unwrap_or_default(), .unwrap_or_default(),
) )
...@@ -76,7 +75,9 @@ impl<'a> ArrayMethod<'a> { ...@@ -76,7 +75,9 @@ impl<'a> ArrayMethod<'a> {
.unwrap_or_default(), .unwrap_or_default(),
), ),
(&Pattern::StringPattern(pattern), Select::Range(range)) => { (&Pattern::StringPattern(pattern), Select::Range(range)) => {
let expansion = expand_string(pattern, expand_func, false).join(" "); let expansion = unescape(
unescape(expand_string(pattern, expand_func, false).join(" ")),
);
let iter = variable.split(&expansion); let iter = variable.split(&expansion);
if let Some((start, length)) = range.bounds(iter.clone().count()) { if let Some((start, length)) = range.bounds(iter.clone().count()) {
let range = iter.skip(start).take(length).collect::<Vec<_>>().join(" "); let range = iter.skip(start).take(length).collect::<Vec<_>>().join(" ");
...@@ -127,7 +128,7 @@ impl<'a> ArrayMethod<'a> { ...@@ -127,7 +128,7 @@ impl<'a> ArrayMethod<'a> {
return match (&self.pattern, self.selection.clone()) { return match (&self.pattern, self.selection.clone()) {
(_, Select::None) => Some("".into()).into_iter().collect(), (_, Select::None) => Some("".into()).into_iter().collect(),
(&Pattern::StringPattern(pattern), Select::All) => variable (&Pattern::StringPattern(pattern), Select::All) => variable
.split(&expand_string(pattern, expand_func, false).join(" ")) .split(&unescape(expand_string(pattern, expand_func, false).join(" ")))
.map(From::from) .map(From::from)
.collect(), .collect(),
(&Pattern::Whitespace, Select::All) => variable (&Pattern::Whitespace, Select::All) => variable
...@@ -137,7 +138,7 @@ impl<'a> ArrayMethod<'a> { ...@@ -137,7 +138,7 @@ impl<'a> ArrayMethod<'a> {
.collect(), .collect(),
(&Pattern::StringPattern(pattern), Select::Index(Index::Forward(id))) => { (&Pattern::StringPattern(pattern), Select::Index(Index::Forward(id))) => {
variable variable
.split(&expand_string(pattern, expand_func, false).join(" ")) .split(&unescape(expand_string(pattern, expand_func, false).join(" ")))
.nth(id) .nth(id)
.map(From::from) .map(From::from)
.into_iter() .into_iter()
...@@ -152,7 +153,7 @@ impl<'a> ArrayMethod<'a> { ...@@ -152,7 +153,7 @@ impl<'a> ArrayMethod<'a> {
.collect(), .collect(),
(&Pattern::StringPattern(pattern), Select::Index(Index::Backward(id))) => { (&Pattern::StringPattern(pattern), Select::Index(Index::Backward(id))) => {
variable variable
.rsplit(&expand_string(pattern, expand_func, false).join(" ")) .rsplit(&unescape(expand_string(pattern, expand_func, false).join(" ")))
.nth(id) .nth(id)
.map(From::from) .map(From::from)
.into_iter() .into_iter()
...@@ -166,7 +167,8 @@ impl<'a> ArrayMethod<'a> { ...@@ -166,7 +167,8 @@ impl<'a> ArrayMethod<'a> {
.into_iter() .into_iter()
.collect(), .collect(),
(&Pattern::StringPattern(pattern), Select::Range(range)) => { (&Pattern::StringPattern(pattern), Select::Range(range)) => {
let expansion = expand_string(pattern, expand_func, false).join(" "); let expansion =
unescape(expand_string(pattern, expand_func, false).join(" "));
let iter = variable.split(&expansion); let iter = variable.split(&expansion);
if let Some((start, length)) = range.bounds(iter.clone().count()) { if let Some((start, length)) = range.bounds(iter.clone().count()) {
iter.skip(start).take(length).map(From::from).collect() iter.skip(start).take(length).map(From::from).collect()
...@@ -192,6 +194,25 @@ impl<'a> ArrayMethod<'a> { ...@@ -192,6 +194,25 @@ impl<'a> ArrayMethod<'a> {
(_, Select::Key(_)) => Some("".into()).into_iter().collect(), (_, Select::Key(_)) => Some("".into()).into_iter().collect(),
}; };
} }
"split_at" => {
let variable = resolve_var!();
match self.pattern {
Pattern::StringPattern(string) => if let Ok(value) =
expand_string(string, expand_func, false).join(" ").parse::<usize>()
{
if value < variable.len() {
let (l, r) = variable.split_at(value);
return array![SmallString::from(l), SmallString::from(r)];
}
eprintln!("ion: split_at: value is out of bounds");
} else {
eprintln!("ion: split_at: requires a valid number as an argument");
},
Pattern::Whitespace => {
eprintln!("ion: split_at: requires an argument");
}
}
}
"graphemes" => { "graphemes" => {
let variable = resolve_var!(); let variable = resolve_var!();
let graphemes = UnicodeSegmentation::graphemes(variable.as_str(), true); let graphemes = UnicodeSegmentation::graphemes(variable.as_str(), true);
......
...@@ -3,8 +3,8 @@ mod pattern; ...@@ -3,8 +3,8 @@ mod pattern;
mod strings; mod strings;
pub(crate) use self::arrays::ArrayMethod; pub(crate) use self::arrays::ArrayMethod;
pub(crate) use self::strings::StringMethod;
pub(crate) use self::pattern::Pattern; pub(crate) use self::pattern::Pattern;
pub(crate) use self::strings::StringMethod;
use super::{Index, Range}; use super::{Index, Range};
use super::super::ranges::parse_index_range; use super::super::ranges::parse_index_range;
......
...@@ -13,10 +13,19 @@ pub(crate) fn unescape(input: String) -> String { ...@@ -13,10 +13,19 @@ pub(crate) fn unescape(input: String) -> String {
output += &input[start..id]; output += &input[start..id];
if let Some((_, character)) = characters.next() { if let Some((_, character)) = characters.next() {
start = match character { start = match character {
'n' => {output.push('\n'); id + 2}, 'n' => {
'\\' => {output.push('\\'); id + 2}, output.push('\n');
't' => {output.push('\t'); id + 2}, id + 2
_ => id + 1 }
'\\' => {
output.push('\\');
id + 2
}
't' => {
output.push('\t');
id + 2
}
_ => id + 1,
}; };
} }
} }
...@@ -26,4 +35,4 @@ pub(crate) fn unescape(input: String) -> String { ...@@ -26,4 +35,4 @@ pub(crate) fn unescape(input: String) -> String {
output += &input[start..]; output += &input[start..];
} }
output output
} }
\ No newline at end of file
...@@ -3,6 +3,7 @@ use super::pattern::unescape; ...@@ -3,6 +3,7 @@ use super::pattern::unescape;
use super::super::super::{expand_string, Expander}; use super::super::super::{expand_string, Expander};
use super::super::super::{is_expression, slice}; use super::super::super::{is_expression, slice};
use super::super::super::super::ArgumentSplitter; use super::super::super::super::ArgumentSplitter;
use parser::assignments::is_array;
use shell::plugins::methods::{self, MethodArguments, StringMethodPlugins}; use shell::plugins::methods::{self, MethodArguments, StringMethodPlugins};
use std::path::Path; use std::path::Path;
use sys; use sys;
...@@ -172,6 +173,17 @@ impl<'a> StringMethod<'a> { ...@@ -172,6 +173,17 @@ impl<'a> StringMethod<'a> {
let rev_graphs = UnicodeSegmentation::graphemes(word.as_str(), true).rev(); let rev_graphs = UnicodeSegmentation::graphemes(word.as_str(), true).rev();
output.push_str(rev_graphs.collect::<String>().as_str()); output.push_str(rev_graphs.collect::<String>().as_str());
}, },
"find" => {
let pattern = unescape(expand_string(pattern, expand, false).join(" "));
let out = if let Some(value) = expand.variable(variable, false) {
value.find(&pattern)
} else if is_expression(variable) {
expand_string(variable, expand, false).join(" ").find(&pattern)
} else {
None
};
output.push_str(&out.unwrap_or(0).to_string());
}
method @ _ => { method @ _ => {
if sys::is_root() { if sys::is_root() {
eprintln!("ion: root is not allowed to execute plugins"); eprintln!("ion: root is not allowed to execute plugins");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment