       console.log { changed_index: event }
       {target} = event
       @showGhostText target.current()
+
+  completeTokens: ({n, all}) ->
+    {entropy, tokens} = @predictionList.current()
+    n = tokens.length if all
+    insertTokens = tokens.slice(0, n)
+
+    insertText = GambogeView.textFromTokens insertTokens
+    cursorPosition = @editor.getCursorBufferPosition()
+
+    @ignoreNextChange()
+    @editor.setTextInBufferRange([cursorPosition, cursorPosition], insertText)
+
+
+
+  @specialTokens:
+    '<NEWLINE>': (editor) -> '\n'
+    '<NL>':      (editor) -> '\n'
+    '<INDENT>':           -> ''
+    'DEDENT':             -> ''
+
+  # TODO: Extract the method into its own module!
+  # TODO: Make it take in the current indent level. Do a bunch of indentation
+  # thing!
+  @textFromTokens: (tokens) ->
+    text = ""
+    for token in tokens
+      text +=
+        if token of GambogeView.specialTokens then GambogeView.specialTokens[token]()
+        else " #{token}"
+    text
 
 
   # Using markers, shows the GhostText.

        return unless predictions?
        @predictionList.setPredictions predictions

    @predictionList.onDidChangePredictions =>
      console.log did_prediction_change: @predictionList



  registerEvents: ->
    console.log 'Registering events...'
    # Updates the prediction model. Invoked 300ms after last buffer change.
    # TODO: use `onDidChange` instead?
    @editor.onDidStopChanging =>
      return @resetChangeIgnorance() if @lastChangeWasPredictionInsert

      text = @getTextForCursorContext()

