Implement backspace on Editor

This commit is contained in:
Corey Johnson & Nathan Sobo 2012-01-25 16:07:04 -08:00
parent 3a423e2a16
commit b5317b83a5
7 changed files with 94 additions and 25 deletions

View File

@ -70,29 +70,47 @@ describe 'Buffer', ->
expect(buffer.getLine(4)).toBe lineBelowOriginalLine
describe ".backspace(position)", ->
it "can remove a character from middle of line", ->
originalLineLength = buffer.getLine(1).length
expect(buffer.getLine(1).charAt(6)).toBe 's'
buffer.backspace({row: 1, col: 7})
expect(buffer.getLine(1).charAt(6)).toBe 'o'
expect(buffer.getLine(1).length).toBe originalLineLength - 1
changeHandler = null
beforeEach ->
changeHandler = jasmine.createSpy('changeHandler')
buffer.on 'change', changeHandler
it "can remove a character from the end of the line", ->
originalLineLength = buffer.getLine(1).length
expect(buffer.getLine(1).charAt(originalLineLength - 1)).toBe '{'
buffer.backspace({row: 1, col: originalLineLength})
expect(buffer.getLine(1).length).toBe originalLineLength - 1
expect(buffer.getLine(1).charAt(originalLineLength - 2)).toBe '{'
describe "when the given position is in the middle of a line", ->
it "removes the preceding character and emits a change event", ->
originalLineLength = buffer.getLine(1).length
it "can remove a character from the begining of the line", ->
originalLineCount = buffer.getLines().length
originalLineLengthFromAbove = buffer.getLine(11).length
originalLineLength = buffer.getLine(12).length
expect(buffer.getLine(12).charAt(0)).toBe '}'
buffer.backspace({row: 12, col: 0})
expect(buffer.getLines().length).toBe originalLineCount - 1
expect(buffer.getLine(11).charAt(originalLineLengthFromAbove)).toBe '}'
expect(buffer.getLine(11).length).toBe originalLineLengthFromAbove + originalLineLength
expect(buffer.getLine(1)).toBe ' var sort = function(items) {'
buffer.backspace({row: 1, col: 7})
expect(buffer.getLine(1)).toBe ' var ort = function(items) {'
expect(buffer.getLine(1).length).toBe originalLineLength - 1
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
expect(event.string).toBe ''
expect(event.preRange.start).toEqual { row: 1, col: 6 }
expect(event.preRange.end).toEqual { row: 1, col: 7 }
expect(event.postRange.start).toEqual { row: 1, col: 6 }
expect(event.postRange.end).toEqual { row: 1, col: 6 }
describe "when the given position is at the beginning of a line", ->
it "appends the current line to the previous and emits a change event", ->
originalLineCount = buffer.getLines().length
lineAboveOriginalLine = buffer.getLine(11)
originalLine = buffer.getLine(12)
buffer.backspace({row: 12, col: 0})
expect(buffer.getLines().length).toBe(originalLineCount - 1)
expect(buffer.getLine(11)).toBe lineAboveOriginalLine + originalLine
expect(changeHandler).toHaveBeenCalled()
[event] = changeHandler.argsForCall[0]
expect(event.string).toBe ''
expect(event.preRange.start).toEqual { row: 11, col: lineAboveOriginalLine.length }
expect(event.preRange.end).toEqual { row: 12, col: 0 }
expect(event.postRange.start).toEqual { row: 11, col: lineAboveOriginalLine.length }
expect(event.postRange.end).toEqual { row: 11, col: lineAboveOriginalLine.length }
describe ".save()", ->
describe "when the buffer has a path", ->

View File

@ -261,4 +261,16 @@ describe "Editor", ->
expect(editor.lines.find('pre:eq(2)')).toHaveHtml ' '
expect(editor.getPosition()).toEqual(row: 2, col: 0)
describe "when backspace is pressed", ->
describe "when the cursor is on the middle of the line", ->
it "removes the character before the cursor", ->
editor.setPosition(row: 1, col: 7)
spyOn(buffer, 'backspace').andCallThrough()
editor.trigger keydownEvent('backspace')
expect(buffer.backspace).toHaveBeenCalledWith(row: 1, col: 7)
expect(editor.lines.find('pre:eq(1)')).toHaveText buffer.getLine(1)
expect(editor.getPosition()).toEqual {row: 1, col: 6}

View File

@ -10,4 +10,4 @@ var quicksort = function () {
};
return sort(Array.apply(this, arguments));
};
};

View File

@ -43,10 +43,22 @@ class Buffer
backspace: ({row, col}) ->
line = @lines[row]
preRange =
start: { row, col }
end: { row, col }
if col == 0
preRange.start.col = @lines[row - 1].length
preRange.start.row--
@lines[row-1..row] = @lines[row - 1] + @lines[row]
else
@lines[row] = line[row..col] + line[col + 1..]
preRange.start.col--
@lines[row] = line[0...col-1] + line[col..]
postRange = { start: preRange.start, end: preRange.start }
@trigger 'change', { preRange, postRange, string: '' }
numLines: ->
@getLines().length

View File

@ -18,6 +18,9 @@ class Cursor extends Template
else
@setColumn(@getColumn() + e.string.length)
bufferChanged: (e) ->
@setPosition(e.postRange.end)
setPosition: (point) ->
@point = @editor.clipPosition(point)
@goalColumn = null

View File

@ -35,12 +35,14 @@ class Editor extends Template
down: 'move-down'
up: 'move-up'
enter: 'newline'
backspace: 'backspace'
@on 'move-right', => @moveRight()
@on 'move-left', => @moveLeft()
@on 'move-down', => @moveDown()
@on 'move-up', => @moveUp()
@on 'newline', => @buffer.insert @getPosition(), "\n"
@on 'backspace', => @buffer.backspace @getPosition()
handleEvents: ->
@on 'focus', =>
@ -70,12 +72,32 @@ class Editor extends Template
@buffer.on 'insert', (e) =>
{row} = e.range.start
updatedLine = @buildLineElement(@buffer.getLine(row))
@lines.find('pre').eq(row).replaceWith(updatedLine)
if e.string == '\n'
updatedLine.after @buildLineElement(@buffer.getLine(row + 1))
@buffer.on 'change', (e) =>
curRow = e.preRange.start.row
while curRow <= e.preRange.end.row
if curRow <= e.postRange.end.row
@updateLineElement(curRow)
else
@removeLineElement(curRow)
curRow++
console.log @buffer.getText()
@cursor.bufferChanged(e)
updateLineElement: (row) ->
@getLineElement(row).replaceWith(@buildLineElement(@buffer.getLine(row)))
removeLineElement: (row) ->
@getLineElement(row).remove()
getLineElement: (row) ->
@lines.find("pre:eq(#{row})")
clipPosition: ({row, col}) ->
line = @buffer.getLine(row)
{ row: row, col: Math.min(line.length, col) }

2
test.txt Normal file
View File

@ -0,0 +1,2 @@
0123
abcd