Modify Editor Config #137

Introduce a Configurer trait
diff --git a/src/config.rs b/src/config.rs
index 86c04dc..c82a234 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -34,6 +34,10 @@
         self.max_history_size
     }
 
+    pub(crate) fn set_max_history_size(&mut self, max_size: usize) {
+        self.max_history_size = max_size;
+    }
+
     /// Tell if lines which match the previous history entry are saved or not
     /// in the history list.
     ///
@@ -42,6 +46,14 @@
         self.history_duplicates
     }
 
+    pub(crate) fn set_history_ignore_dups(&mut self, yes: bool) {
+        self.history_duplicates = if yes {
+            HistoryDuplicates::IgnoreConsecutive
+        } else {
+            HistoryDuplicates::AlwaysAdd
+        };
+    }
+
     /// Tell if lines which begin with a space character are saved or not in
     /// the history list.
     ///
@@ -50,6 +62,10 @@
         self.history_ignore_space
     }
 
+    pub(crate) fn set_history_ignore_space(&mut self, yes: bool) {
+        self.history_ignore_space = yes;
+    }
+
     pub fn completion_type(&self) -> CompletionType {
         self.completion_type
     }
@@ -79,6 +95,10 @@
     pub fn color_mode(&self) -> ColorMode {
         self.color_mode
     }
+
+    pub(crate) fn set_color_mode(&mut self, color_mode: ColorMode) {
+        self.color_mode = color_mode;
+    }
 }
 
 impl Default for Config {
@@ -144,7 +164,7 @@
 
     /// Set the maximum length for the history.
     pub fn max_history_size(mut self, max_size: usize) -> Builder {
-        self.p.max_history_size = max_size;
+        self.set_max_history_size(max_size);
         self
     }
 
@@ -153,11 +173,7 @@
     ///
     /// By default, they are ignored.
     pub fn history_ignore_dups(mut self, yes: bool) -> Builder {
-        self.p.history_duplicates = if yes {
-            HistoryDuplicates::IgnoreConsecutive
-        } else {
-            HistoryDuplicates::AlwaysAdd
-        };
+        self.set_history_ignore_dups(yes);
         self
     }
 
@@ -166,20 +182,20 @@
     ///
     /// By default, they are saved.
     pub fn history_ignore_space(mut self, yes: bool) -> Builder {
-        self.p.history_ignore_space = yes;
+        self.set_history_ignore_space(yes);
         self
     }
 
     /// Set `completion_type`.
     pub fn completion_type(mut self, completion_type: CompletionType) -> Builder {
-        self.p.completion_type = completion_type;
+        self.set_completion_type(completion_type);
         self
     }
 
     /// The number of possible completions that determines when the user is
     /// asked whether the list of possibilities should be displayed.
     pub fn completion_prompt_limit(mut self, completion_prompt_limit: usize) -> Builder {
-        self.p.completion_prompt_limit = completion_prompt_limit;
+        self.set_completion_prompt_limit(completion_prompt_limit);
         self
     }
 
@@ -189,17 +205,13 @@
     /// After seeing an ESC key, wait at most `keyseq_timeout_ms` for another
     /// byte.
     pub fn keyseq_timeout(mut self, keyseq_timeout_ms: i32) -> Builder {
-        self.p.keyseq_timeout = keyseq_timeout_ms;
+        self.set_keyseq_timeout(keyseq_timeout_ms);
         self
     }
 
     /// Choose between Emacs or Vi mode.
     pub fn edit_mode(mut self, edit_mode: EditMode) -> Builder {
-        self.p.edit_mode = edit_mode;
-        match edit_mode {
-            EditMode::Emacs => self.p.keyseq_timeout = -1, // no timeout
-            EditMode::Vi => self.p.keyseq_timeout = 500,
-        };
+        self.set_edit_mode(edit_mode);
         self
     }
 
@@ -207,7 +219,7 @@
     ///
     /// By default, they are not.
     pub fn auto_add_history(mut self, yes: bool) -> Builder {
-        self.p.auto_add_history = yes;
+        self.set_auto_add_history(yes);
         self
     }
 
@@ -215,7 +227,7 @@
     ///
     /// By default, colorization is on except if stdout is not a tty.
     pub fn color_mode(mut self, color_mode: ColorMode) -> Builder {
-        self.p.color_mode = color_mode;
+        self.set_color_mode(color_mode);
         self
     }
 
@@ -223,3 +235,72 @@
         self.p
     }
 }
+
+impl Configurer for Builder {
+    fn config_mut(&mut self) -> &mut Config {
+        &mut self.p
+    }
+}
+
+pub trait Configurer {
+    fn config_mut(&mut self) -> &mut Config;
+
+    /// Set the maximum length for the history.
+    fn set_max_history_size(&mut self, max_size: usize) {
+        self.config_mut().set_max_history_size(max_size);
+    }
+
+    /// Tell if lines which match the previous history entry are saved or not
+    /// in the history list.
+    ///
+    /// By default, they are ignored.
+    fn set_history_ignore_dups(&mut self, yes: bool) {
+        self.config_mut().set_history_ignore_dups(yes);
+    }
+
+    /// Tell if lines which begin with a space character are saved or not in
+    /// the history list.
+    ///
+    /// By default, they are saved.
+    fn set_history_ignore_space(&mut self, yes: bool) {
+        self.config_mut().set_history_ignore_space(yes);
+    }
+    /// Set `completion_type`.
+    fn set_completion_type(&mut self, completion_type: CompletionType) {
+        self.config_mut().completion_type = completion_type;
+    }
+
+    /// The number of possible completions that determines when the user is
+    /// asked whether the list of possibilities should be displayed.
+    fn set_completion_prompt_limit(&mut self, completion_prompt_limit: usize) {
+        self.config_mut().completion_prompt_limit = completion_prompt_limit;
+    }
+
+    /// Timeout for ambiguous key sequences in milliseconds.
+    fn set_keyseq_timeout(&mut self, keyseq_timeout_ms: i32) {
+        self.config_mut().keyseq_timeout = keyseq_timeout_ms;
+    }
+
+    /// Choose between Emacs or Vi mode.
+    fn set_edit_mode(&mut self, edit_mode: EditMode) {
+        self.config_mut().edit_mode = edit_mode;
+        match edit_mode {
+            EditMode::Emacs => self.set_keyseq_timeout(-1), // no timeout
+            EditMode::Vi => self.set_keyseq_timeout(500),
+        }
+    }
+
+    /// Tell if lines are automatically added to the history.
+    ///
+    /// By default, they are not.
+    fn set_auto_add_history(&mut self, yes: bool) {
+        self.config_mut().auto_add_history = yes;
+    }
+
+    /// Forces colorization on or off.
+    ///
+    /// By default, colorization is on except if stdout is not a tty.
+    fn set_color_mode(&mut self, color_mode: ColorMode) {
+        self.config_mut().set_color_mode(color_mode);
+    }
+}
diff --git a/src/history.rs b/src/history.rs
index 76a5bcf..dac738b 100644
--- a/src/history.rs
+++ b/src/history.rs
@@ -24,8 +24,8 @@
 pub struct History {
     entries: VecDeque<String>,
     max_len: usize,
-    ignore_space: bool,
-    ignore_dups: bool,
+    pub(crate) ignore_space: bool,
+    pub(crate) ignore_dups: bool,
 }
 
 impl History {
diff --git a/src/lib.rs b/src/lib.rs
index 25a2ff4..e3254b0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -56,7 +56,7 @@
 use tty::{RawMode, RawReader, Renderer, Term, Terminal};
 
 use completion::{longest_common_prefix, Candidate, Completer};
-pub use config::{CompletionType, Config, EditMode, HistoryDuplicates};
+pub use config::{ColorMode, CompletionType, Config, EditMode, HistoryDuplicates};
 pub use consts::KeyPress;
 use edit::State;
 use highlight::Highlighter;
@@ -785,6 +785,32 @@
     }
 }
 
+impl<H: Helper> config::Configurer for Editor<H> {
+    fn config_mut(&mut self) -> &mut Config {
+        &mut self.config
+    }
+
+    fn set_max_history_size(&mut self, max_size: usize) {
+        self.config_mut().set_max_history_size(max_size);
+        self.history.set_max_len(max_size);
+    }
+
+    fn set_history_ignore_dups(&mut self, yes: bool) {
+        self.config_mut().set_history_ignore_dups(yes);
+        self.history.ignore_dups = yes;
+    }
+
+    fn set_history_ignore_space(&mut self, yes: bool) {
+        self.config_mut().set_history_ignore_space(yes);
+        self.history.ignore_space = yes;
+    }
+
+    fn set_color_mode(&mut self, color_mode: ColorMode) {
+        self.config_mut().set_color_mode(color_mode);
+        self.term.color_mode = color_mode;
+    }
+}
+
 impl<H: Helper> fmt::Debug for Editor<H> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("Editor")
diff --git a/src/tty/test.rs b/src/tty/test.rs
index 4166948..c4aa81c 100644
--- a/src/tty/test.rs
+++ b/src/tty/test.rs
@@ -119,6 +119,7 @@
 pub struct DummyTerminal {
     pub keys: Vec<KeyPress>,
     pub cursor: usize, // cursor position before last command
+    pub color_mode: ColorMode,
 }
 
 impl Term for DummyTerminal {
@@ -126,10 +127,11 @@
     type Reader = IntoIter<KeyPress>;
     type Writer = Sink;
 
-    fn new(_color_mode: ColorMode) -> DummyTerminal {
+    fn new(color_mode: ColorMode) -> DummyTerminal {
         DummyTerminal {
             keys: Vec::new(),
             cursor: 0,
+            color_mode: color_mode,
         }
     }
 
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index e029bff..1a07a0e 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -565,7 +565,7 @@
     unsupported: bool,
     stdin_isatty: bool,
     stdout_isatty: bool,
-    color_mode: ColorMode,
+    pub(crate) color_mode: ColorMode,
 }
 
 impl Term for PosixTerminal {
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index a27b9fb..249efad 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -400,7 +400,7 @@
     stdin_handle: HANDLE,
     stdout_isatty: bool,
     stdout_handle: HANDLE,
-    color_mode: ColorMode,
+    pub(crate) color_mode: ColorMode,
     ansi_colors_supported: bool,
 }