   screenRowForNode: (node) -> parseInt(node.dataset.screenRow)
 
   buildLineNode: (id) ->
-    {screenRow, decorationClasses} = @newTileState.lines[id]
+    {lineText, tagCodes, screenRow, decorationClasses} = @newTileState.lines[id]
 
     lineNode = @domElementPool.buildElement("div", "line")
     lineNode.dataset.screenRow = screenRow

        textNode = @domElementPool.buildText(lineText.substr(startIndex, tagCode))
        startIndex += tagCode
        openScopeNode.appendChild(textNode)
        @currentLineTextNodes.push(textNode)

    if startIndex is 0
      textNode = @domElementPool.buildText(' ')
      lineNode.appendChild(textNode)
      @currentLineTextNodes.push(textNode)

  appendTokenNodes: (tokenText, isHardTab, firstNonWhitespaceIndex, firstTrailingWhitespaceIndex, hasIndentGuide, hasInvisibleCharacters, scopeNode) ->
    if isHardTab
      textNode = @domElementPool.buildText(tokenText)
      hardTabNode = @domElementPool.buildElement("span", "hard-tab")
      hardTabNode.classList.add("leading-whitespace") if firstNonWhitespaceIndex?
      hardTabNode.classList.add("trailing-whitespace") if firstTrailingWhitespaceIndex?
      hardTabNode.classList.add("indent-guide") if hasIndentGuide
      hardTabNode.classList.add("invisible-character") if hasInvisibleCharacters
      hardTabNode.appendChild(textNode)

      scopeNode.appendChild(hardTabNode)
      @currentLineTextNodes.push(textNode)
    else
      startIndex = 0
      endIndex = tokenText.length

      leadingWhitespaceNode = null
      leadingWhitespaceTextNode = null
      trailingWhitespaceNode = null
      trailingWhitespaceTextNode = null

      if firstNonWhitespaceIndex?
        leadingWhitespaceTextNode =
          @domElementPool.buildText(tokenText.substring(0, firstNonWhitespaceIndex))
        leadingWhitespaceNode = @domElementPool.buildElement("span", "leading-whitespace")
        leadingWhitespaceNode.classList.add("indent-guide") if hasIndentGuide
        leadingWhitespaceNode.classList.add("invisible-character") if hasInvisibleCharacters
        leadingWhitespaceNode.appendChild(leadingWhitespaceTextNode)

        startIndex = firstNonWhitespaceIndex

      if firstTrailingWhitespaceIndex?
        tokenIsOnlyWhitespace = firstTrailingWhitespaceIndex is 0

        trailingWhitespaceTextNode =
          @domElementPool.buildText(tokenText.substring(firstTrailingWhitespaceIndex))
        trailingWhitespaceNode = @domElementPool.buildElement("span", "trailing-whitespace")
        trailingWhitespaceNode.classList.add("indent-guide") if hasIndentGuide and not firstNonWhitespaceIndex? and tokenIsOnlyWhitespace
        trailingWhitespaceNode.classList.add("invisible-character") if hasInvisibleCharacters
        trailingWhitespaceNode.appendChild(trailingWhitespaceTextNode)

        endIndex = firstTrailingWhitespaceIndex

      if leadingWhitespaceNode?
        scopeNode.appendChild(leadingWhitespaceNode)
        @currentLineTextNodes.push(leadingWhitespaceTextNode)

      if tokenText.length > MaxTokenLength
        while startIndex < endIndex
          textNode = @domElementPool.buildText(
            @sliceText(tokenText, startIndex, startIndex + MaxTokenLength)
          )
          textSpan = @domElementPool.buildElement("span")

          textSpan.appendChild(textNode)
          scopeNode.appendChild(textSpan)
          startIndex += MaxTokenLength
          @currentLineTextNodes.push(textNode)
      else
        textNode = @domElementPool.buildText(@sliceText(tokenText, startIndex, endIndex))
        scopeNode.appendChild(textNode)
        @currentLineTextNodes.push(textNode)

      if trailingWhitespaceNode?
        scopeNode.appendChild(trailingWhitespaceNode)
        @currentLineTextNodes.push(trailingWhitespaceTextNode)

  sliceText: (tokenText, startIndex, endIndex) ->
    if startIndex? and endIndex? and startIndex > 0 or endIndex < tokenText.length
      tokenText = tokenText.slice(startIndex, endIndex)
    tokenText

  appendEndOfLineNodes: (id, lineNode) ->
    {endOfLineInvisibles} = @newTileState.lines[id]

    hasInvisibles = false
    if endOfLineInvisibles?
      for invisible in endOfLineInvisibles
        hasInvisibles = true
        invisibleSpan = @domElementPool.buildElement("span", "invisible-character")
        textNode = @domElementPool.buildText(invisible)
        invisibleSpan.appendChild(textNode)
        lineNode.appendChild(invisibleSpan)

        @currentLineTextNodes.push(textNode)

    hasInvisibles

  updateLineNode: (id) ->
    oldLineState = @oldTileState.lines[id]

      for decorationClass in decorationClasses
        lineNode.classList.add(decorationClass)

    textNodes = []
    lineLength = 0
    startIndex = 0
    openScopeNode = lineNode
