Crappy cursor blinking impl
diff --git a/alacritty.yml b/alacritty.yml
index 686cb38..203b8fa 100644
--- a/alacritty.yml
+++ b/alacritty.yml
@@ -36,6 +36,10 @@
 # Display tabs using this many cells (changes require restart)
 tabspaces: 8
 
+# Cursor blinking
+cursor_blink_interval: 300
+cursor_blink: true
+
 # When true, bold text is drawn using the bright variant of colors.
 draw_bold_text_with_bright_colors: true
 
diff --git a/alacritty_macos.yml b/alacritty_macos.yml
index 007d3b4..57cc59e 100644
--- a/alacritty_macos.yml
+++ b/alacritty_macos.yml
@@ -35,6 +35,10 @@
 # Display tabs using this many cells (changes require restart)
 tabspaces: 8
 
+# Cursor blinking
+cursor_blink_interval: 300
+cursor_blink: true
+
 # When true, bold text is drawn using the bright variant of colors.
 draw_bold_text_with_bright_colors: true
 
diff --git a/src/config.rs b/src/config.rs
index 7734e7a..0e241b5 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -171,6 +171,7 @@
     }
 }
 
+
 /// Top-level config type
 #[derive(Debug, Deserialize)]
 pub struct Config {
@@ -202,6 +203,11 @@
     #[serde(default)]
     custom_cursor_colors: bool,
 
+    // TODO these should be optional
+    #[serde(deserialize_with="deserialize_duration_ms")]
+    cursor_blink_interval: Duration,
+    cursor_blink: bool,
+
     /// Should draw bold text with brighter colors intead of bold font
     #[serde(default="true_bool")]
     draw_bold_text_with_bright_colors: bool,
@@ -278,6 +284,8 @@
             font: Default::default(),
             render_timer: Default::default(),
             custom_cursor_colors: false,
+            cursor_blink: true,
+            cursor_blink_interval: Duration::from_millis(300),
             colors: Default::default(),
             key_bindings: Vec::new(),
             mouse_bindings: Vec::new(),
@@ -1142,6 +1150,14 @@
 
         Ok(contents)
     }
+
+    pub fn cursor_blink_interval(&self) -> Duration {
+        self.cursor_blink_interval
+    }
+
+    pub fn blink_enabled(&self) -> bool {
+        self.cursor_blink
+    }
 }
 
 /// Window Dimensions
diff --git a/src/event_loop.rs b/src/event_loop.rs
index c744dda..4ccf424 100644
--- a/src/event_loop.rs
+++ b/src/event_loop.rs
@@ -7,11 +7,13 @@
 use std::sync::Arc;
 
 use mio::{self, Events, PollOpt, Ready};
+use mio::timer::{self, Timer, Timeout};
 use mio::unix::EventedFd;
 
 use ansi;
 use display;
 use event;
+use config::Config;
 use term::Term;
 use util::thread;
 use sync::FairMutex;
@@ -23,7 +25,11 @@
     Input(Cow<'static, [u8]>),
 
     /// Indicates that the `EventLoop` should shut down, as Alacritty is shutting down
-    Shutdown
+    Shutdown,
+
+    /// Enable or disable blinking events. Passing true will enable them, and
+    /// false will disable them.
+    Blink(bool),
 }
 
 /// The main event!.. loop.
@@ -35,6 +41,8 @@
     pty: Io,
     rx: mio::channel::Receiver<Msg>,
     tx: mio::channel::Sender<Msg>,
+    timer: Timer<()>,
+    blink_timeout: Option<Timeout>,
     terminal: Arc<FairMutex<Term>>,
     display: display::Notifier,
     ref_test: bool,
@@ -171,20 +179,41 @@
 /// `mio::Token` for the pty file descriptor
 const PTY: mio::Token = mio::Token(1);
 
+/// `mio::Token` for timers
+const TIMER: mio::Token = mio::Token(2);
+
 impl<Io> EventLoop<Io>
     where Io: io::Read + io::Write + Send + AsRawFd + 'static
 {
     /// Create a new event loop
     pub fn new(
         terminal: Arc<FairMutex<Term>>,
+        config: &Config,
         display: display::Notifier,
         pty: Io,
         ref_test: bool,
     ) -> EventLoop<Io> {
         let (tx, rx) = ::mio::channel::channel();
+        let mut timer = timer::Builder::default()
+            .capacity(2)
+            .num_slots(2)
+            .build();
+        let timeout = {
+            let term = terminal.lock();
+            if term.mode().contains(::term::mode::CURSOR_BLINK) {
+                println!("setup blink");
+                let timeout = timer.set_timeout(term.cursor_blink_interval, ()).unwrap();
+                Some(timeout)
+            } else {
+                println!("no setup blink");
+                None
+            }
+        };
         EventLoop {
             poll: mio::Poll::new().expect("create mio Poll"),
             pty: pty,
+            timer: timer,
+            blink_timeout: timeout,
             tx: tx,
             rx: rx,
             terminal: terminal,
@@ -201,7 +230,7 @@
     //
     // Returns a `DrainResult` indicating the result of receiving from the channe;
     //
-    fn drain_recv_channel(&self, state: &mut State) -> DrainResult {
+    fn drain_recv_channel(&mut self, state: &mut State) -> DrainResult {
         let mut received_item = false;
         while let Ok(msg) = self.rx.try_recv() {
             received_item = true;
@@ -209,6 +238,20 @@
                 Msg::Input(input) => {
                     state.write_list.push_back(input);
                 },
+                Msg::Blink(true) => {
+                    // Set timeout if it's not running
+                    if self.blink_timeout.is_none() {
+                        let mut terminal = self.terminal.lock();
+                        let interval = terminal.cursor_blink_interval;
+                        self.blink_timeout = Some(self.timer.set_timeout(interval, ()).unwrap());
+                    }
+                },
+                Msg::Blink(false) => {
+                    // Cancel timeout if it's running
+                    if let Some(timeout) = self.blink_timeout.take() {
+                        self.timer.cancel_timeout(&timeout);
+                    }
+                },
                 Msg::Shutdown => {
                     return DrainResult::Shutdown;
                 }
@@ -342,6 +385,25 @@
         Ok(())
     }
 
+    fn handle_timers(&mut self) {
+        if self.timer.poll().is_some() {
+            println!("timers!");
+            // Dispatch blink
+            let mut terminal = self.terminal.lock();
+            terminal.toggle_blink_state();
+            if !terminal.dirty {
+                self.display.notify();
+                terminal.dirty = true;
+            }
+
+            // Reregister timer
+            println!("set_timeout {:?}", terminal.cursor_blink_interval);
+            self.timer.set_timeout(terminal.cursor_blink_interval, ()).unwrap();
+        } else {
+            println!("timers :(");
+        }
+    }
+
     pub fn spawn(
         mut self,
         state: Option<State>
@@ -357,6 +419,7 @@
 
             self.poll.register(&self.rx, CHANNEL, Ready::readable(), poll_opts).unwrap();
             self.poll.register(&fd, PTY, Ready::readable(), poll_opts).unwrap();
+            self.poll.register(&self.timer, TIMER, Ready::readable(), poll_opts).unwrap();
 
             let mut events = Events::with_capacity(1024);
 
@@ -383,6 +446,13 @@
                                 break 'event_loop;
                             }
                         },
+                        TIMER => {
+                            self.handle_timers();
+                            println!("reregister timer");
+                            self.poll
+                                .reregister(&self.timer, TIMER, Ready::readable(), poll_opts)
+                                .expect("reregister timer");
+                        },
                         PTY => {
                             let kind = event.kind();
 
diff --git a/src/main.rs b/src/main.rs
index 9db5ce5..c61cfd6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -123,6 +123,7 @@
     // consumes it periodically.
     let event_loop = EventLoop::new(
         terminal.clone(),
+        &config,
         display.notifier(),
         pty.reader(),
         options.ref_test,
diff --git a/src/term/mod.rs b/src/term/mod.rs
index d898fe2..7074138 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -114,6 +114,7 @@
         cursor: &'b Point,
         colors: &'b color::List,
         mode: TermMode,
+        cursor_blink: bool,
         config: &'b Config,
         selection: Option<RangeInclusive<index::Linear>>,
         cursor_style: CursorStyle,
@@ -131,7 +132,7 @@
             config: config,
             colors: colors,
             cursor_cells: ArrayDeque::new(),
-        }.initialize(cursor_style)
+        }.initialize(cursor_style, cursor_blink)
     }
 
     fn populate_block_cursor(&mut self) {
@@ -242,8 +243,8 @@
         });
     }
 
-    fn initialize(mut self, cursor_style: CursorStyle) -> Self {
-        if self.cursor_is_visible() {
+    fn initialize(mut self, cursor_style: CursorStyle, blink: bool) -> Self {
+        if !blink && self.cursor_is_visible() {
             match cursor_style {
                 CursorStyle::Block => {
                     self.populate_block_cursor();
@@ -391,19 +392,20 @@
 pub mod mode {
     bitflags! {
         pub flags TermMode: u16 {
-            const SHOW_CURSOR         = 0b000000000001,
-            const APP_CURSOR          = 0b000000000010,
-            const APP_KEYPAD          = 0b000000000100,
-            const MOUSE_REPORT_CLICK  = 0b000000001000,
-            const BRACKETED_PASTE     = 0b000000010000,
-            const SGR_MOUSE           = 0b000000100000,
-            const MOUSE_MOTION        = 0b000001000000,
-            const LINE_WRAP           = 0b000010000000,
-            const LINE_FEED_NEW_LINE  = 0b000100000000,
-            const ORIGIN              = 0b001000000000,
-            const INSERT              = 0b010000000000,
-            const FOCUS_IN_OUT        = 0b100000000000,
-            const ANY                 = 0b111111111111,
+            const SHOW_CURSOR         = 0b0000000000001,
+            const APP_CURSOR          = 0b0000000000010,
+            const APP_KEYPAD          = 0b0000000000100,
+            const MOUSE_REPORT_CLICK  = 0b0000000001000,
+            const BRACKETED_PASTE     = 0b0000000010000,
+            const SGR_MOUSE           = 0b0000000100000,
+            const MOUSE_MOTION        = 0b0000001000000,
+            const LINE_WRAP           = 0b0000010000000,
+            const LINE_FEED_NEW_LINE  = 0b0000100000000,
+            const ORIGIN              = 0b0001000000000,
+            const INSERT              = 0b0010000000000,
+            const FOCUS_IN_OUT        = 0b0100000000000,
+            const CURSOR_BLINK        = 0b1000000000000,
+            const ANY                 = 0b1111111111111,
             const NONE                = 0,
         }
     }
@@ -677,6 +679,9 @@
     colors: color::List,
 
     cursor_style: CursorStyle,
+
+    pub cursor_blink_interval: Duration,
+    pub cursor_blink: bool,
 }
 
 /// Terminal size info
@@ -741,6 +746,10 @@
         self.next_title.take()
     }
 
+    pub fn toggle_blink_state(&mut self) {
+        self.cursor_blink = !self.cursor_blink;
+    }
+
     pub fn new(config : &Config, size: SizeInfo) -> Term {
         let template = Cell::default();
 
@@ -756,11 +765,19 @@
         let alt = grid.clone();
         let scroll_region = Line(0)..grid.num_lines();
 
+        let mut mode = TermMode::default();
+        if config.blink_enabled() {
+            println!("enable blink from term");
+            mode.insert(mode::CURSOR_BLINK);
+        }
+
         Term {
             next_title: None,
             dirty: false,
             visual_bell: VisualBell::new(config),
             input_needs_wrap: false,
+            cursor_blink_interval: config.cursor_blink_interval(),
+            cursor_blink: false,
             grid: grid,
             alt_grid: alt,
             alt: false,
@@ -769,7 +786,7 @@
             cursor_save: Default::default(),
             cursor_save_alt: Default::default(),
             tabs: tabs,
-            mode: Default::default(),
+            mode: mode,
             scroll_region: scroll_region,
             size_info: size,
             empty_cell: template,
@@ -949,6 +966,7 @@
             &self.cursor.point,
             &self.colors,
             self.mode,
+            self.cursor_blink,
             config,
             selection,
             self.cursor_style