diff --git a/src/keymap.rs b/src/keymap.rs
index e97fbb0082f2c45563ad646c4b671469f408db66..004cb6795f4ec57318a80be2bce3d193c3eec566 100644
--- a/src/keymap.rs
+++ b/src/keymap.rs
@@ -40,6 +40,7 @@ pub enum Cmd {
     Unknown,
     UpcaseWord,
     ViCharSearch(RepeatCount, CharSearch),
+    ViFirstPrint,
     ViYankTo(Movement),
     Yank(RepeatCount, Anchor),
     YankPop,
@@ -301,8 +302,8 @@ impl EditState {
             KeyPress::End => Cmd::EndOfLine,
             KeyPress::Char('.') => self.last_cmd.clone(), // vi-redo
             // TODO KeyPress::Char('%') => Cmd::???, Move to the corresponding opening/closing bracket
-            KeyPress::Char('0') => Cmd::BeginningOfLine, // vi-zero: Vi move to the beginning of line.
-            KeyPress::Char('^') => Cmd::BeginningOfLine, // vi-first-print TODO Move to the first non-blank character of line.
+            KeyPress::Char('0') => Cmd::BeginningOfLine,
+            KeyPress::Char('^') => Cmd::ViFirstPrint,
             KeyPress::Char('a') => {
                 // vi-append-mode: Vi enter insert mode after the cursor.
                 self.insert = true;
diff --git a/src/lib.rs b/src/lib.rs
index 83e96269e52951e9acc6515b5c26238997257758..cd038b3ac1881ead41af4aa9b171a0ecb94b3dba 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -895,6 +895,11 @@ fn readline_edit<C: Completer>(prompt: &str,
                 // Move to the beginning of line.
                 try!(edit_move_home(&mut s))
             }
+            Cmd::ViFirstPrint => {
+                editor.kill_ring.reset();
+                try!(edit_move_home(&mut s));
+                try!(edit_move_to_next_word(&mut s, At::Start, Word::Big, 1))
+            }
             Cmd::BackwardChar(n) => {
                 editor.kill_ring.reset();
                 // Move back a character.