WIP: Start on Renderer, which combines LineWrapper and LineFolder

This commit is contained in:
Nathan Sobo
2012-03-05 16:07:22 -07:00
parent 3cc559fd9c
commit 955bb383dd
2 changed files with 118 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
Renderer = require 'renderer'
Buffer = require 'buffer'
describe "Renderer", ->
[renderer, buffer] = []
beforeEach ->
buffer = new Buffer(require.resolve 'fixtures/sample.js')
renderer = new Renderer(buffer)
describe "line rendering", ->
fdescribe "soft wrapping", ->
beforeEach ->
renderer.setMaxLineLength(50)
describe "when the line is shorter than the max line length", ->
it "renders the line unchanged", ->
expect(renderer.lineForRow(0).text).toBe buffer.lineForRow(0)
describe "when the line is empty", ->
it "renders the empty line", ->
expect(renderer.lineForRow(13).text).toBe ''
describe "when there is a non-whitespace character at the max length boundary", ->
describe "when there is whitespace before the boundary", ->
it "wraps the line at the end of the first whitespace preceding the boundary", ->
expect(renderer.lineForRow(10).text).toBe ' return '
expect(renderer.lineForRow(11).text).toBe 'sort(left).concat(pivot).concat(sort(right));'
describe "when there is no whitespace before the boundary", ->
it "wraps the line exactly at the boundary since there's no more graceful place to wrap it", ->
buffer.change([[0, 0], [1, 0]], 'abcdefghijklmnopqrstuvwxyz\n')
renderer.setMaxLineLength(10)
expect(renderer.lineForRow(0).text).toBe 'abcdefghij'
expect(renderer.lineForRow(1).text).toBe 'klmnopqrst'
expect(renderer.lineForRow(2).text).toBe 'uvwxyz'
describe "when there is a whitespace character at the max length boundary", ->
it "wraps the line at the first non-whitespace character following the boundary", ->
expect(renderer.lineForRow(3).text).toBe ' var pivot = items.shift(), current, left = [], '
expect(renderer.lineForRow(4).text).toBe 'right = [];'
describe "when there is a fold placeholder straddling the max length boundary", ->
describe "folding", ->
describe "when a fold spans multiple lines", ->
describe "when a fold spans a single line", ->
describe "when a fold is nested within another fold", ->
describe "when a fold begins on the line on which another fold ends", ->
describe "when a fold starts at the beginning of a line", ->
describe "when a fold ends at the beginning of a line", ->
describe "when a fold starts on the first line of the buffer", ->
describe "soft wrapping combined with folding", ->
describe "when a line with a fold placeholder is longer than the max line length", ->

49
src/atom/renderer.coffee Normal file
View File

@@ -0,0 +1,49 @@
Highlighter = require 'highlighter'
LineMap = require 'line-map'
Point = require 'point'
module.exports =
class Renderer
lineMap: null
highlighter: null
constructor: (@buffer) ->
@highlighter = new Highlighter(@buffer)
buildLineMap: ->
@lineMap = new LineMap
@lineMap.insertAtInputRow 0, @buildLinesForBufferRows(0, @buffer.lastRow())
setMaxLineLength: (@maxLineLength) ->
@buildLineMap()
lineForRow: (row) ->
@lineMap.lineForOutputRow(row)
logLines: ->
@lineMap.logLines()
buildLinesForBufferRows: (startRow, endRow, startColumn=0) ->
return [] if startRow > endRow
line = @highlighter.lineForRow(startRow).splitAt(startColumn)[1]
if wrapColumn = @findWrapColumn(line.text)
line = line.splitAt(wrapColumn)[0]
line.outputDelta = new Point(1, 0)
[line].concat @buildLinesForBufferRows(startRow, endRow, startColumn + wrapColumn)
else
[line].concat @buildLinesForBufferRows(startRow + 1, endRow)
findWrapColumn: (line) ->
return unless line.length > @maxLineLength
if /\s/.test(line[@maxLineLength])
# search forward for the start of a word past the boundary
for column in [@maxLineLength..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 [@maxLineLength..0]
return column + 1 if /\s/.test(line[column])
return @maxLineLength