From 1fa4d9562d65b65e5e1ae1c04169468f9b97db0f 2014-03-21 01:41:15
From: Jonathan Frederic <jon.freder@gmail.com>
Date: 2014-03-21 01:41:15
Subject: [PATCH] More progress...

---

diff --git a/IPython/html/static/notebook/js/completer.js b/IPython/html/static/notebook/js/completer.js
index 30a824a..f7dbd1e 100644
--- a/IPython/html/static/notebook/js/completer.js
+++ b/IPython/html/static/notebook/js/completer.js
@@ -233,12 +233,10 @@ var IPython = (function (IPython) {
             this.sel.dblclick(function () {
                 that.pick();
             });
-            this.editor.on('keydown', function (event) {
+            this._handle_keydown = function (cm, event) {
                 that.keydown(event);
-            });
-            this.editor.on('keypress', function (event) {
-                that.keypress(event);
-            });
+            };
+            this.editor.on('keydown', this._handle_keydown);
         }
         this.sel.attr('size', Math.min(10, this.raw_result.length));
 
@@ -280,30 +278,33 @@ var IPython = (function (IPython) {
     Completer.prototype.close = function () {
         this.done = true;
         $('#complete').remove();
+        if (this._handle_keydown) {
+            this.editor.off('keydown', this._handle_keydown);
+            this._handle_keydown = undefined;
+        }
         this.visible = false;
     };
 
     Completer.prototype.pick = function () {
         this.insert(this.raw_result[this.sel[0].selectedIndex]);
         this.close();
-        var that = this;
     };
 
     Completer.prototype.keydown = function (event) {
+        console.log(event);
         var code = event.keyCode;
         var that = this;
+        if (!this.visible) return;
 
         // Enter
         if (code == keycodes.enter) {
-            CodeMirror.e_stop(event);
+            event.stopPropagation();
+            event.codemirrorIgnore = true;
             this.pick();
-        }
         // Escape or backspace
-        else if (code == keycodes.esc) {
-            CodeMirror.e_stop(event);
-            this.close();
-
-        } else if (code == keycodes.backspace) {
+        } else if (code == keycodes.esc || code == keycodes.backspace) {
+            event.stopPropagation();
+            event.codemirrorIgnore = true;
             this.close();
         } else if (code == keycodes.tab) {
             //all the fastforwarding operation,
@@ -315,7 +316,8 @@ var IPython = (function (IPython) {
                 this.insert(sh);
             }
             this.close();
-            CodeMirror.e_stop(event);
+            event.codemirrorIgnore = true;
+            event.stopPropagation();
             //reinvoke self
             setTimeout(function () {
                 that.carry_on_completion();
@@ -324,31 +326,20 @@ var IPython = (function (IPython) {
             // need to do that to be able to move the arrow
             // when on the first or last line ofo a code cell
             event.stopPropagation();
-        }
-    };
-    
-    Completer.prototype.keypress = function (event) {
-        // FIXME: This is a band-aid.
-        // on keypress, trigger insertion of a single character.
-        // This simulates the old behavior of completion as you type,
-        // before events were disconnected and CodeMirror stopped
-        // receiving events while the completer is focused.
-        if (!this.visible) return;
+            event.codemirrorIgnore = true;
 
-        var that = this;
-        var code = event.keyCode;
-        
-        // don't handle keypress if it's not a character (arrows on FF)
-        // or ENTER/TAB
-        if (event.charCode === 0 ||
-            code == keycodes.enter ||
-            code == keycodes.tab
-        ) return;
-        
-        this.close();
-        setTimeout(function () {
-            that.carry_on_completion();
-        }, 50);
+            var options = this.sel.find('option');
+            var index = this.sel[0].selectedIndex;
+            if (code == keycodes.up) {
+                index--;
+            }
+            if (code == keycodes.down) {
+                index++;
+            }
+            index = Math.min(Math.max(index, 0), options.length-1);
+            console.log('compl set index', index);
+            this.sel[0].selectedIndex = index;
+        }
     };
 
     IPython.Completer = Completer;
diff --git a/IPython/html/tests/notebook/arrow_keys.js b/IPython/html/tests/notebook/arrow_keys.js
index 6f089ba..b658562 100644
--- a/IPython/html/tests/notebook/arrow_keys.js
+++ b/IPython/html/tests/notebook/arrow_keys.js
@@ -2,23 +2,22 @@
 // Check for errors with up and down arrow presses in a non-empty notebook.
 //
 casper.notebook_test(function () {
-    var result = this.evaluate(function() {
-        IPython.notebook.command_mode();
-        pos0 = IPython.notebook.get_selected_index();
-        IPython.keyboard.trigger_keydown('b');
-        pos1 = IPython.notebook.get_selected_index();
-        IPython.keyboard.trigger_keydown('b');
-        pos2 = IPython.notebook.get_selected_index();
-        // Simulate the "up arrow" and "down arrow" keys.
-        IPython.keyboard.trigger_keydown('up');
-        pos3 = IPython.notebook.get_selected_index();
-        IPython.keyboard.trigger_keydown('down');
-        pos4 = IPython.notebook.get_selected_index();
-        return  pos0 == 0 &&
-                pos1 == 1 &&
-                pos2 == 2 &&
-                pos3 == 1 &&
-                pos4 == 2;
+    this.then(function(){
+        var result = this.evaluate(function() {
+            IPython.notebook.command_mode();
+            pos0 = IPython.notebook.get_selected_index();
+            IPython.keyboard.trigger_keydown('b');
+            pos1 = IPython.notebook.get_selected_index();
+            IPython.keyboard.trigger_keydown('b');
+            pos2 = IPython.notebook.get_selected_index();
+            // Simulate the "up arrow" and "down arrow" keys.
+            IPython.keyboard.trigger_keydown('up');
+            pos3 = IPython.notebook.get_selected_index();
+            IPython.keyboard.trigger_keydown('down');
+            pos4 = IPython.notebook.get_selected_index();
+            return [pos0, pos1, pos2, pos3, pos4];
+        });
+        this.test.assertEquals(result, [0, 1, 2, 1, 2], 'Up/down arrow okay in non-empty notebook.');
     });
-    this.test.assertTrue(result, 'Up/down arrow okay in non-empty notebook.');
+    
 });
diff --git a/IPython/html/tests/notebook/safe_append_output.js b/IPython/html/tests/notebook/safe_append_output.js
index 1217740..6126048 100644
--- a/IPython/html/tests/notebook/safe_append_output.js
+++ b/IPython/html/tests/notebook/safe_append_output.js
@@ -25,7 +25,7 @@ casper.notebook_test(function () {
     this.then(function () {
         var output = this.get_output_cell(0);
         this.test.assert(messages.length > 0, "Captured log message");
-        this.test.assertEquals(messages[messages.length-1], "Invalid type for image/png 5", "Logged Invalid type message");
+        this.test.assertEquals(messages[messages.length-1].splice(0, 26), "Invalid type for image/png", "Logged Invalid type message");
         this.test.assertEquals(output['image/png'], undefined, "Non-string png data was stripped");
         this.test.assertEquals(output['text/plain'], '5', "text data is fine");
     });