         do @view.render
     DELETE:
       display: 'Delete (operator)'
-      key: 'd'
     CHANGE:
       display: 'Change (operator)'
-      key: 'c'
     DELETE_CHAR:
       display: 'Delete character'
-      key: 'x'
       fn: () ->
         @view.delCharsAfterCursor @repeat, {yank: true}
         do @view.moveCursorBackIfNeeded
     DELETE_LAST_CHAR:
       display: 'Delete last character'
-      key: 'X'
       fn: () ->
         num = Math.min @view.cursor.col, @repeat
         if num > 0
           @view.delCharsBeforeCursor num, {yank: true}
     CHANGE_CHAR:
       display: 'Change character'
-      key: 's'
       insert: true
       fn: () ->
         @view.delCharsAfterCursor 1, {cursor: 'pastEnd'}, {yank: true}

    for k,v of @bindings
      row = $('<tr>')
      row.append $('<td>').text v.display
      row.append $('<td>').text v.key
      table.append row

    @keybindingsDiv.empty().append(table)


  buildKeyMap: () ->
    # reverse of bindings map
    # key -> 'STRING_DESCRIBING_ACTION'
    keyMap = {}

    # TODO: ensure no collision
    for k, v of @bindings
        keyMap[v.key] = k
        if v.alternateKeys
          for key in v.alternateKeys
            keyMap[key] = k

    @keyMap = keyMap

  setMode: (mode) ->
    @mode = mode

# binds keys to manipulation of view/data

class KeyBindings
  keyDefinitions =
    HELP:
      display: 'Show/hide key bindings'

    INSERT:
      display: 'Insert at character'
      insert: true
      fn: () -> return
    INSERT_AFTER:
      display: 'Insert after character'
      insert: true
      fn: () ->
        @view.moveCursorRight {cursor: 'pastEnd'}
    INSERT_HOME:
      display: 'Insert at beginning of line'
      insert: true
      fn: () ->
        do @view.moveCursorHome
    INSERT_END:
      display: 'Insert after end of line'
      insert: true
      fn: () ->
        @view.moveCursorEnd {cursor: 'pastEnd'}
    INSERT_LINE_BELOW:
      display: 'Insert on new line after current line'
      insert: true
      fn: () ->
        do @view.newLineBelow
    INSERT_LINE_ABOVE:
      display: 'Insert on new line before current line'
      insert: true
      fn: () ->
        do @view.newLineAbove
    REPLACE:
      display: 'Replace character'

    EX:
      display: 'Enter EX mode'

    UNDO:
      display: 'Undo'
      drop: true
      fn: () ->
        for i in [1..@repeat]
          do @view.undo
    REDO:
      display: 'Redo'
      drop: true
      fn: () ->
        for i in [1..@repeat]
          do @view.redo
    REPEAT:
      display: 'Repeat last command'

    LEFT:
      display: 'Move cursor left'
      motion: true
    RIGHT:
      display: 'Move cursor right'
      motion: true
    UP:
      display: 'Move cursor up'
      motion: true
    DOWN:
      display: 'Move cursor down'
      motion: true
    HOME:
      display: 'Move cursor to beginning of line'
      motion: true
    END:
      display: 'Move cursor to end of line'
      motion: true
    BEGINNING_WORD:
      display: 'Move cursor to the first word-beginning before it'
      motion: true
    END_WORD:
      display: 'Move cursor to the first word-ending after it'
      motion: true
    NEXT_WORD:
      display: 'Move cursor to the beginning of the next word'
      motion: true
    BEGINNING_BLOCK:
      display: 'Move cursor to the first block-beginning before it'
      motion: true
    END_BLOCK:
      display: 'Move cursor to the first block-ending after it'
      motion: true
    NEXT_BLOCK:
      display: 'Move cursor to the beginning of the next block'
      motion: true
    FIND_NEXT_CHAR:
      display: 'Move cursor to next occurrence of character in line'
      motion: true
      find: true
    FIND_PREV_CHAR:
      display: 'Move cursor to previous occurrence of character in line'
      motion: true
      find: true
    TO_NEXT_CHAR:
      display: 'Move cursor to just before next occurrence of character in line'
      motion: true
      find: true
    TO_PREV_CHAR:
      display: 'Move cursor to just after previous occurrence of character in line'
      motion: true
      find: true
    GO:
      display: 'Various commands for navigation (operator)'
    GO_END:
      display: 'Go to end of visible document'
      drop: true
      fn: () ->
        row = do @view.data.lastVisible
