     @model.setVerticalScrollbarWidth(@measuredVerticalScrollbarWidth) if @measuredVerticalScrollbarWidth?
     @model.setHorizontalScrollbarHeight(@measuredHorizontalScrollbarHeight) if @measuredHorizontalScrollbarHeight?
 
-  # Determines whether {TextEditorPresenter} is currently batching changes.
+  # Private: Determines whether {TextEditorPresenter} is currently batching changes.
   # Returns a {Boolean}, `true` if is collecting changes, `false` if is applying them.
   isBatching: ->
     @updating == false
 
+  # Private: Executes `fn` if `isBatching()` is false, otherwise sets `@[flagName]` to `true` for later processing. In either cases, it calls `emitDidUpdateState`.
+  # * `flagName` {String} name of a property of this presenter
+  # * `fn` {Function} to call when not batching.
+  batch: (flagName, fn) ->
+    if @isBatching()
+      @[flagName] = true
+    else
+      fn.apply(this)
+
+    @emitDidUpdateState()
+
+  # Public: Gets this presenter's state, updating it just in time before returning from this function.
+  # Returns a state {Object}, useful for rendering to screen.
   getState: ->
     @updating = true
 

    else if decoration.isType('overlay')
      @updateOverlaysState()

  updateDecorations: ->
    if @isBatching()
      @shouldUpdateDecorations = true
    else
      @lineDecorationsByScreenRow = {}
      @lineNumberDecorationsByScreenRow = {}
      @highlightDecorationsById = {}

      visibleHighlights = {}
      return unless 0 <= @startRow <= @endRow <= Infinity

      for markerId, decorations of @model.decorationsForScreenRowRange(@startRow, @endRow - 1)
        range = @model.getMarker(markerId).getScreenRange()
        for decoration in decorations
          if decoration.isType('line') or decoration.isType('line-number')
            @addToLineDecorationCaches(decoration, range)
          else if decoration.isType('highlight')
            visibleHighlights[decoration.id] = @updateHighlightState(decoration)

      for id of @state.content.highlights
        unless visibleHighlights[id]
          delete @state.content.highlights[id]

      @emitDidUpdateState()


  removeFromLineDecorationCaches: (decoration, range) ->

      top: row * @lineHeight
      decorationClasses: @lineDecorationClassesForRow(row)

  updateCursorsState: -> @batch "shouldUpdateCursorsState", ->
    @state.content.cursors = {}
    @updateCursorState(cursor) for cursor in @model.cursors # using property directly to avoid allocation

  updateCursorState: (cursor, destroyOnly = false) ->
    delete @state.content.cursors[cursor.id]
