From eaa700b8a0ed14d02d3d53ffb1e1bce4059e76f2 Mon Sep 17 00:00:00 2001
From: Thomas Kinnen <thomas.kinnen@gmail.com>
Date: Thu, 14 Dec 2017 13:50:43 +0100
Subject: [PATCH] Add @lines() method (#441)

---
 examples/array_methods.ion                    |  1 +
 manual/src/ch05-05-method.md                  | 21 +++++++++++++++++++
 .../shell_expand/words/methods/arrays.rs      | 21 +++++++++++++++++++
 3 files changed, 43 insertions(+)

diff --git a/examples/array_methods.ion b/examples/array_methods.ion
index 5d2b3645..22566049 100644
--- a/examples/array_methods.ion
+++ b/examples/array_methods.ion
@@ -3,3 +3,4 @@ echo @split_at("onetwoone", "3")
 echo @graphemes("onetwo", "3")
 echo @bytes("onetwo")
 echo @chars("onetwo")
+echo @lines($unescape("firstline\nsecondline"))
diff --git a/manual/src/ch05-05-method.md b/manual/src/ch05-05-method.md
index 51864ab6..6a4f5425 100644
--- a/manual/src/ch05-05-method.md
+++ b/manual/src/ch05-05-method.md
@@ -455,12 +455,33 @@ echo $unescape($line)
 
 The following are the currently-supported array methods.
 
+- [lines](#lines)
 - [split](#split)
 - [split_at](#split_at)
 - [bytes](#bytes)
 - [chars](#chars)
 - [graphemes](#graphemes)
 
+### lines
+
+Defaults to string variables. The supplied string will be split into one string per line in the input argument.
+
+#### Examples
+
+```ion
+for line in @lines($unescape("first\nsecond\nthird")
+    echo $line
+end
+```
+
+#### Output
+
+```
+first
+second
+third
+```
+
 ### split
 
 Defaults to string variables. The supplied string will be split according to a pattern specified
diff --git a/src/parser/shell_expand/words/methods/arrays.rs b/src/parser/shell_expand/words/methods/arrays.rs
index 7df75fc8..624560b0 100644
--- a/src/parser/shell_expand/words/methods/arrays.rs
+++ b/src/parser/shell_expand/words/methods/arrays.rs
@@ -34,6 +34,7 @@ impl<'a> ArrayMethod<'a> {
             "graphemes" => self.graphemes(expand_func),
             "bytes" => self.bytes(expand_func),
             "chars" => self.chars(expand_func),
+            "lines" => self.lines(expand_func),
             _ => Err("invalid array method"),
         };
 
@@ -174,6 +175,11 @@ impl<'a> ArrayMethod<'a> {
             .map(|c| c.to_string())
             .select(self.selection.clone(), len))
     }
+
+    fn lines<E: Expander>(&self, expand_func: &E) -> Result<Array, &'static str> {
+        let variable = self.resolve_var(expand_func);
+        Ok(variable.lines().into_iter().map(|line| line.to_string()).collect())
+    }
 }
 
 #[cfg(test)]
@@ -190,6 +196,7 @@ mod test {
             match variable {
                 "FOO" => Some("FOOBAR".to_owned()),
                 "SPACEDFOO" => Some("FOO BAR".to_owned()),
+                "MULTILINE" => Some("FOO\nBAR".to_owned()),
                 _ => None,
             }
         }
@@ -413,4 +420,18 @@ mod test {
             array!["F", "O", "O", "B", "A", "R"]
         );
     }
+
+    #[test]
+    fn test_lines() {
+        let method = ArrayMethod {
+            method:    "lines",
+            variable:  "$MULTILINE",
+            pattern:   Pattern::StringPattern("3"),
+            selection: Select::All,
+        };
+        assert_eq!(
+            method.handle_as_array(&VariableExpander),
+            array!["FOO", "BAR"]
+        );
+    }
 }
-- 
GitLab