From ace07de2126a56c37cb257cce6b756862f6dd658 Mon Sep 17 00:00:00 2001
From: Michael Aaron Murphy <mmstickman@gmail.com>
Date: Thu, 12 Oct 2017 23:20:10 -0400
Subject: [PATCH] Additional words module refactoring

---
 .../shell_expand/words/methods/arrays.rs      |  7 +-
 src/parser/shell_expand/words/methods/mod.rs  | 70 +------------------
 .../shell_expand/words/methods/strings.rs     |  6 +-
 src/parser/shell_expand/words/mod.rs          |  4 +-
 src/parser/shell_expand/words/select.rs       | 69 ++++++++++++++++++
 5 files changed, 80 insertions(+), 76 deletions(-)
 create mode 100644 src/parser/shell_expand/words/select.rs

diff --git a/src/parser/shell_expand/words/methods/arrays.rs b/src/parser/shell_expand/words/methods/arrays.rs
index f699ae28..73baf2fa 100644
--- a/src/parser/shell_expand/words/methods/arrays.rs
+++ b/src/parser/shell_expand/words/methods/arrays.rs
@@ -1,8 +1,7 @@
-use super::{Pattern, Select, SelectWithSize};
+use super::Pattern;
 use super::pattern::unescape;
-use super::super::Index;
-use super::super::super::{expand_string, Expander};
-use super::super::super::is_expression;
+use super::super::{Index, Select, SelectWithSize};
+use super::super::super::{expand_string, Expander, is_expression};
 use smallstring::SmallString;
 use std::char;
 use std::io::{self, Write};
diff --git a/src/parser/shell_expand/words/methods/mod.rs b/src/parser/shell_expand/words/methods/mod.rs
index af15a9b6..efede944 100644
--- a/src/parser/shell_expand/words/methods/mod.rs
+++ b/src/parser/shell_expand/words/methods/mod.rs
@@ -6,16 +6,13 @@ pub(crate) use self::arrays::ArrayMethod;
 pub(crate) use self::pattern::Pattern;
 pub(crate) use self::strings::StringMethod;
 
-use super::{Index, Range, Expander, expand_string};
-use super::super::ranges::parse_index_range;
+use super::{Expander, expand_string};
 use super::super::super::ArgumentSplitter;
-use std::iter::{empty, FromIterator};
-use std::str::FromStr;
 use self::pattern::unescape;
 
 #[derive(Debug, PartialEq, Clone)]
 pub(crate) struct Key {
-    key: ::types::Key,
+    pub(crate) key: ::types::Key,
 }
 
 impl Key {
@@ -24,69 +21,6 @@ impl Key {
     pub(crate) fn get(&self) -> &::types::Key { return &self.key; }
 }
 
-/// Represents a filter on a vector-like object
-#[derive(Debug, PartialEq, Clone)]
-pub(crate) enum Select {
-    /// Select no elements
-    None,
-    /// Select all elements
-    All,
-    /// Select a single element based on its index
-    Index(Index),
-    /// Select a range of elements
-    Range(Range),
-    /// Select an element by mapped key
-    Key(Key),
-}
-
-pub(crate) trait SelectWithSize {
-    type Item;
-    fn select<O>(&mut self, Select, usize) -> O
-        where O: FromIterator<Self::Item>;
-}
-
-impl<I, T> SelectWithSize for I
-    where I: Iterator<Item = T>
-{
-    type Item = T;
-    fn select<O>(&mut self, s: Select, size: usize) -> O
-        where O: FromIterator<Self::Item>
-    {
-        match s {
-            Select::None => empty().collect(),
-            Select::All => self.collect(),
-            Select::Index(idx) => {
-                idx.resolve(size).and_then(|idx| self.nth(idx)).into_iter().collect()
-            }
-            Select::Range(range) => if let Some((start, length)) = range.bounds(size) {
-                self.skip(start).take(length).collect()
-            } else {
-                empty().collect()
-            },
-            Select::Key(_) => empty().collect(),
-        }
-    }
-}
-
-impl FromStr for Select {
-    type Err = ();
-    fn from_str(data: &str) -> Result<Select, ()> {
-        if ".." == data {
-            return Ok(Select::All);
-        }
-
-        if let Ok(index) = data.parse::<isize>() {
-            return Ok(Select::Index(Index::new(index)));
-        }
-
-        if let Some(range) = parse_index_range(data) {
-            return Ok(Select::Range(range));
-        }
-
-        Ok(Select::Key(Key { key: data.into() }))
-    }
-}
-
 pub(crate) struct MethodArgs<'a, 'b, E: 'b + Expander> {
     args:   &'a str,
     expand: &'b E,
diff --git a/src/parser/shell_expand/words/methods/strings.rs b/src/parser/shell_expand/words/methods/strings.rs
index 3c19ae22..7f819677 100644
--- a/src/parser/shell_expand/words/methods/strings.rs
+++ b/src/parser/shell_expand/words/methods/strings.rs
@@ -1,6 +1,6 @@
-use super::{Select, MethodArgs};
-use super::super::super::{expand_string, Expander};
-use super::super::super::{is_expression, slice};
+use super::MethodArgs;
+use super::super::Select;
+use super::super::super::{expand_string, Expander, is_expression, slice};
 use parser::assignments::is_array;
 use shell::plugins::methods::{self, MethodArguments, StringMethodPlugins};
 use std::path::Path;
diff --git a/src/parser/shell_expand/words/mod.rs b/src/parser/shell_expand/words/mod.rs
index d1dc3323..2176f773 100644
--- a/src/parser/shell_expand/words/mod.rs
+++ b/src/parser/shell_expand/words/mod.rs
@@ -3,12 +3,14 @@ mod tests;
 mod index;
 mod methods;
 mod range;
+mod select;
 
 pub(crate) use self::index::Index;
-pub(crate) use self::methods::{ArrayMethod, Pattern, Select, StringMethod};
+pub(crate) use self::methods::{ArrayMethod, Pattern, StringMethod};
 #[cfg(test)]
 pub(crate) use self::methods::Key;
 pub(crate) use self::range::Range;
+pub(crate) use self::select::{Select, SelectWithSize};
 use super::{expand_string, Expander};
 use super::super::ArgumentSplitter;
 
diff --git a/src/parser/shell_expand/words/select.rs b/src/parser/shell_expand/words/select.rs
new file mode 100644
index 00000000..6ca210dc
--- /dev/null
+++ b/src/parser/shell_expand/words/select.rs
@@ -0,0 +1,69 @@
+use super::super::ranges::parse_index_range;
+use super::{Index, Range};
+use std::iter::{empty, FromIterator};
+use super::methods::Key;
+use std::str::FromStr;
+
+
+/// Represents a filter on a vector-like object
+#[derive(Debug, PartialEq, Clone)]
+pub(crate) enum Select {
+    /// Select no elements
+    None,
+    /// Select all elements
+    All,
+    /// Select a single element based on its index
+    Index(Index),
+    /// Select a range of elements
+    Range(Range),
+    /// Select an element by mapped key
+    Key(Key),
+}
+
+pub(crate) trait SelectWithSize {
+    type Item;
+    fn select<O>(&mut self, Select, usize) -> O
+        where O: FromIterator<Self::Item>;
+}
+
+impl<I, T> SelectWithSize for I
+    where I: Iterator<Item = T>
+{
+    type Item = T;
+    fn select<O>(&mut self, s: Select, size: usize) -> O
+        where O: FromIterator<Self::Item>
+    {
+        match s {
+            Select::None => empty().collect(),
+            Select::All => self.collect(),
+            Select::Index(idx) => {
+                idx.resolve(size).and_then(|idx| self.nth(idx)).into_iter().collect()
+            }
+            Select::Range(range) => if let Some((start, length)) = range.bounds(size) {
+                self.skip(start).take(length).collect()
+            } else {
+                empty().collect()
+            },
+            Select::Key(_) => empty().collect(),
+        }
+    }
+}
+
+impl FromStr for Select {
+    type Err = ();
+    fn from_str(data: &str) -> Result<Select, ()> {
+        if ".." == data {
+            return Ok(Select::All);
+        }
+
+        if let Ok(index) = data.parse::<isize>() {
+            return Ok(Select::Index(Index::new(index)));
+        }
+
+        if let Some(range) = parse_index_range(data) {
+            return Ok(Select::Range(range));
+        }
+
+        Ok(Select::Key(Key { key: data.into() }))
+    }
+}
\ No newline at end of file
-- 
GitLab