Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1492 from atom/ns-fix-softwrap
Browse files Browse the repository at this point in the history
Fix whacky soft-wrap issues
  • Loading branch information
Nathan Sobo committed Feb 14, 2014
2 parents 7f903bc + d64fefd commit 950a0ce
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 446 deletions.
3 changes: 3 additions & 0 deletions package.json
Expand Up @@ -144,5 +144,8 @@
"scripts": {
"preinstall": "node -e 'process.exit(0)'",
"test": "node script/test"
},
"devDependencies": {
"random-words": "0.0.1"
}
}
112 changes: 112 additions & 0 deletions spec/random-editor-spec.coffee
@@ -0,0 +1,112 @@
{times, random} = require 'underscore-plus'
randomWords = require 'random-words'
Editor = require '../src/editor'
TextBuffer = require '../src/text-buffer'

describe "Editor", ->
[editor, tokenizedBuffer, buffer, steps, previousSteps] = []

softWrapColumn = 80

beforeEach ->
atom.config.set('editor.softWrapAtPreferredLineLength', true)
atom.config.set('editor.preferredLineLength', softWrapColumn)

it "properly renders soft-wrapped lines when randomly mutated", ->
previousSteps = JSON.parse(localStorage.steps ? '[]')

times 10, (i) ->
buffer = new TextBuffer
editor = new Editor({buffer})
editor.setEditorWidthInChars(80)
tokenizedBuffer = editor.displayBuffer.tokenizedBuffer
steps = []

times 30, ->
randomlyMutateEditor()
verifyLines()

verifyLines = ->
{bufferRows, screenLines} = getReferenceScreenLines()
for referenceBufferRow, screenRow in bufferRows
referenceScreenLine = screenLines[screenRow]
actualBufferRow = editor.bufferRowForScreenRow(screenRow)
unless actualBufferRow is referenceBufferRow
logLines()
throw new Error("Invalid buffer row #{actualBufferRow} for screen row #{screenRow}", )

actualScreenLine = editor.lineForScreenRow(screenRow)
unless actualScreenLine.text is referenceScreenLine.text
logLines()
throw new Error("Invalid line text at screen row #{screenRow}")

logLines = ->
console.log "==== screen lines ===="
editor.logScreenLines()
console.log "==== reference lines ===="
{bufferRows, screenLines} = getReferenceScreenLines()
for bufferRow, screenRow in bufferRows
console.log screenRow, bufferRow, screenLines[screenRow].text

randomlyMutateEditor = ->
if Math.random() < .2
softWrap = not editor.getSoftWrap()
steps.push(['setSoftWrap', softWrap])
editor.setSoftWrap(softWrap)
else
range = getRandomRange()
text = getRandomText()
steps.push(['setTextInBufferRange', range, text])
editor.setTextInBufferRange(range, text)

getRandomRange = ->
startRow = random(0, buffer.getLastRow())
startColumn = random(0, buffer.lineForRow(startRow).length)
endRow = random(startRow, buffer.getLastRow())
endColumn = random(0, buffer.lineForRow(endRow).length)
[[startRow, startColumn], [endRow, endColumn]]

getRandomText = ->
text = []
max = buffer.getText().split(/\s/).length * 0.75

times random(5, max), ->
if Math.random() < .1
text += '\n'
else
text += " " if /\w$/.test(text)
text += randomWords(exactly: 1)
text

getReferenceScreenLines = ->
if editor.getSoftWrap()
screenLines = []
bufferRows = []
for bufferRow in [0..tokenizedBuffer.getLastRow()]
for screenLine in softWrapLine(tokenizedBuffer.lineForScreenRow(bufferRow))
screenLines.push(screenLine)
bufferRows.push(bufferRow)
else
screenLines = tokenizedBuffer.tokenizedLines.slice()
bufferRows = [0..tokenizedBuffer.getLastRow()]
{screenLines, bufferRows}

softWrapLine = (tokenizedLine) ->
wrappedLines = []
while tokenizedLine.text.length > softWrapColumn and wrapScreenColumn = findWrapColumn(tokenizedLine.text)
[wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(wrapScreenColumn)
wrappedLines.push(wrappedLine)
wrappedLines.push(tokenizedLine)
wrappedLines

findWrapColumn = (line) ->
if /\s/.test(line[softWrapColumn])
# search forward for the start of a word past the boundary
for column in [softWrapColumn..line.length]
return column if /\S/.test(line[column])
return line.length
else
# search backward for the start of the word on the boundary
for column in [softWrapColumn..0]
return column + 1 if /\s/.test(line[column])
return softWrapColumn

0 comments on commit 950a0ce

Please sign in to comment.