     else
       CodeMirror.Pass
 
+  next_cell: (cm) ->
+    cell = input_cell_at_offset cm.lead_cell, 1
+    if cell?
+      cell.editor.focus()
+    else
+      CodeMirror.Pass
+
+  previous_cell: (cm) ->
+    cell = input_cell_at_offset cm.lead_cell, -1
+    if cell?
+      cell.editor.focus()
+    else
+      CodeMirror.Pass
+
+  maybe_next_cell: (cm) ->
+    cur = cm.getCursor()
+    if cur.line is cm.lineCount() - 1
+      lead_editor_commands.next_cell cm
+    else
+      CodeMirror.Pass
+
+  maybe_previous_cell: (cm) ->
+    cur = cm.getCursor()
+    if cur.line is 0
+      lead_editor_commands.previous_cell cm
+    else
+      CodeMirror.Pass
+
+lead_key_map =
+  Tab: (cm) ->
+    if cm.somethingSelected()
+      cm.indentSelection 'add'
+    else
+      spaces = Array(cm.getOption("indentUnit") + 1).join(" ")
+      cm.replaceSelection(spaces, "end", "+input")
+  Up: 'maybe_previous_cell'
+  Down: 'maybe_next_cell'
+  'Shift-Up': 'fill_with_last_value'
+  'Shift-Enter': 'run'
+  'F1': 'contextHelp'
+  'Ctrl-Space': 'suggest'
+
   fallthrough: ['default']
+
+init_codemirror = ->
+  CodeMirror.keyMap.lead = lead_key_map
+  $.extend CodeMirror.commands, lead_editor_commands
 
 contexts = []
 

    reader.readAsText file

window.init_editor = ->
  $document = $ '#document'
  $file_picker = $ '#file'
  $file_picker.on 'change', (e) ->

        from: CodeMirror.Pos cur.line, token.start
        to: CodeMirror.Pos cur.line, cur.ch

lead_editor_commands =
  run: (cm) ->
    cm.lead_cell.run()
    add_context()

  contextHelp: (cm) ->
    cur = cm.getCursor()
    token = cm.getTokenAt(cur)
    if lead.graphite.has_docs token.string
      run_in_info_context cm.lead_cell, "docs '#{token.string}'"
    else if lead.ops[token.string]?
      run_in_info_context cm.lead_cell, "help #{token.string}"

  suggest: (cm) ->
    CodeMirror.showHint cm, suggest, async: true

  fill_with_last_value: (cm) ->
    previous_context = input_cell_at_offset cm.lead_cell, -1
    if previous_context?
      cm.setValue previous_context.editor.getValue()
