     rightText = @text.substring(column)
 
     leftTags = []
+    rightTags = []
+
+    leftSpecialTokens = {}
+    rightSpecialTokens = {}
+
     rightParentScopes = @parentScopes.slice()
 
     screenColumn = 0
+
+    for tag, index in @tags
+      # tag represents a token
+      if tag >= 0
+        # token ends before the soft wrap column
+        if screenColumn + tag <= column
+          if specialToken = @specialTokens[index]
+            leftSpecialTokens[index] = specialToken
+          leftTags.push(tag)
+          screenColumn += tag
+
+        # token starts before and ends after the split column
+        else if screenColumn <= column
+          leftSuffix = column - screenColumn
+          rightPrefix = screenColumn + tag - column
+
+          leftTags.push(leftSuffix) if leftSuffix > 0
+
+          softWrapIndent = @indentLevel * @tabLength + (hangingIndent ? 0)
+          rightText = ' ' + rightText for i in [0...softWrapIndent] by 1
+          while softWrapIndent > 0
+            indentToken = Math.min(softWrapIndent, @tabLength)
+            rightSpecialTokens[rightTags.length] = SoftWrapIndent
+            rightTags.push(indentToken)
+            softWrapIndent -= indentToken
+
+          rightTags.push(rightPrefix) if rightPrefix > 0
+
+          screenColumn += tag
+
+         # token is after split column
+        else
+          if specialToken = @specialTokens[index]
+            rightSpecialTokens[rightTags.length] = specialToken
+          rightTags.push(tag)
+
+      # tag represents the start or end of a scop
+      else if (tag % 2) is -1
+        if screenColumn < column
+          leftTags.push(tag)
+          rightParentScopes.push(tag)
+        else
+          rightTags.push(tag)
+      else
+        if screenColumn < column
+          leftTags.push(tag)
+          rightParentScopes.pop()
+        else
+          rightTags.push(tag)
+
+    splitBufferColumn = @bufferColumnForScreenColumn(column)
+
+    leftFragment = new TokenizedLine
+    leftFragment.parentScopes = @parentScopes
+    leftFragment.text = leftText
+    leftFragment.tags = leftTags
+    leftFragment.specialTokens = leftSpecialTokens
+    leftFragment.startBufferColumn = @startBufferColumn
+    leftFragment.bufferDelta = splitBufferColumn - @startBufferColumn
+    leftFragment.ruleStack = @ruleStack
+    leftFragment.invisibles = @invisibles
+    leftFragment.lineEnding = null
+    leftFragment.indentLevel = @indentLevel
+    leftFragment.tabLength = @tabLength
+    leftFragment.firstNonWhitespaceIndex = Math.min(column, @firstNonWhitespaceIndex)
+    leftFragment.firstTrailingWhitespaceIndex = Math.min(column, @firstTrailingWhitespaceIndex)
+
+    rightFragment = new TokenizedLine
+    rightFragment.parentScopes = rightParentScopes
+    rightFragment.text = rightText
+    rightFragment.tags = rightTags
+    rightFragment.specialTokens = rightSpecialTokens
+    rightFragment.startBufferColumn = splitBufferColumn
+    rightFragment.bufferDelta = @bufferDelta - splitBufferColumn
+    rightFragment.ruleStack = @ruleStack
+    rightFragment.invisibles = @invisibles
+    rightFragment.lineEnding = @lineEnding
+    rightFragment.indentLevel = @indentLevel
+    rightFragment.tabLength = @tabLength
+    rightFragment.endOfLineInvisibles = @endOfLineInvisibles
+    rightFragment.firstNonWhitespaceIndex = Math.max(0, @firstNonWhitespaceIndex - column)
+    rightFragment.firstTrailingWhitespaceIndex = Math.max(0, @firstTrailingWhitespaceIndex - column)
+
+    [leftFragment, rightFragment]
+
+  isSoftWrapped: ->
+    @lineEnding is null
+
+  isColumnInsideSoftWrapIndentation: (targetColumn) ->
+    targetColumn < @getSoftWrapIndentationDelta()
+
+  getSoftWrapIndentationDelta: ->
+    delta = 0
     for tag, index in @tags
       if tag >= 0
-        if screenColumn + tag < column
-          screenColumn += tag
-        else
-          leftTags.push(column - screenColumn)
-          rightTags = @tags.slice(index + 1)
-          rightPrefix = screenColumn + tag - column
-          rightTags.unshift(rightPrefix) if rightPrefix > 0
+        if @specialTokens[index] is SoftWrapIndent
+          delta += tag
+        else
           break
-      else if (tag % 2) is -1
-        rightParentScopes.push(tag)
-      else
-        rightParentScopes.pop()
-      leftTags.push(tag)
-
-    softWrapIndent = @indentLevel * @tabLength + (hangingIndent ? 0)
-    rightTags.unshift(softWrapIndent) if softWrapIndent > 0
-
-    leftFragment = new TokenizedLine(
-      parentScopes: @parentScopes
-      text: leftText
-      tags: leftTags
-      startBufferColumn: @startBufferColumn
-      ruleStack: @ruleStack
-      invisibles: @invisibles
-      lineEnding: null,
-      indentLevel: @indentLevel,
-      tabLength: @tabLength
-    )
-    rightFragment = new TokenizedLine(
-      parentScopes: rightParentScopes
-      text: rightText
-      tags: rightTags
-      startBufferColumn: @bufferColumnForScreenColumn(column)
-      ruleStack: @ruleStack
-      invisibles: @invisibles
-      lineEnding: @lineEnding
-      indentLevel: @indentLevel
-      tabLength: @tabLength
-    )
-    [leftFragment, rightFragment]
-
-  isSoftWrapped: ->
-    @lineEnding is null
-
-  isColumnInsideSoftWrapIndentation: (column) ->
-    false
-    # return false if @softWrapIndentationTokens.length is 0
-    #
-    # column < @softWrapIndentationDelta
-
-  getSoftWrapIndentationTokens: ->
-    []
-    # _.select(@tokens, (token) -> token.isSoftWrapIndentation)
-
-  buildSoftWrapIndentationDelta: ->
-    _.reduce @softWrapIndentationTokens, ((acc, token) -> acc + token.screenDelta), 0
+    delta
 
   hasOnlySoftWrapIndentation: ->
-    @tokens.length is @softWrapIndentationTokens.length
+    @getSoftWrapIndentationDelta() is @text.length
 
   tokenAtBufferColumn: (bufferColumn) ->
     @tokens[@tokenIndexAtBufferColumn(bufferColumn)]

SoftTab = Symbol('SoftTab')
HardTab = Symbol('HardTab')
PairedCharacter = Symbol('PairedCharacter')

NonWhitespaceRegex = /\S/
LeadingWhitespaceRegex = /^\s*/


    @subdivideTokens()
    @buildEndOfLineInvisibles() if @invisibles? and @lineEnding?

  subdivideTokens: ->
    text = ''
