mirror of
https://github.com/atom/atom.git
synced 2026-01-25 23:08:18 -05:00
Merge branch 'editor'
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
_ = require 'underscore'
|
||||
fs = require 'fs'
|
||||
Range = require 'range'
|
||||
|
||||
module.exports =
|
||||
class Buffer
|
||||
@@ -6,6 +8,7 @@ class Buffer
|
||||
|
||||
constructor: (@path) ->
|
||||
@url = @path # we want this to be path on master, but let's not break it on a branch
|
||||
@lines = ['']
|
||||
if @path and fs.exists(@path)
|
||||
@setText(fs.read(@path))
|
||||
else
|
||||
@@ -15,7 +18,10 @@ class Buffer
|
||||
@lines.join('\n')
|
||||
|
||||
setText: (text) ->
|
||||
@lines = text.split('\n')
|
||||
@change(@getRange(), text)
|
||||
|
||||
getRange: ->
|
||||
new Range([0, 0], [@lastRow(), @lastLine().length])
|
||||
|
||||
getTextInRange: (range) ->
|
||||
if range.start.row == range.end.row
|
||||
@@ -35,46 +41,38 @@ class Buffer
|
||||
getLine: (row) ->
|
||||
@lines[row]
|
||||
|
||||
change: (preRange, string) ->
|
||||
@remove(preRange)
|
||||
postRange = @insert(preRange.start, string)
|
||||
@trigger 'change', { preRange, postRange, string }
|
||||
|
||||
remove: (range) ->
|
||||
prefix = @lines[range.start.row][0...range.start.column]
|
||||
suffix = @lines[range.end.row][range.end.column..]
|
||||
@lines[range.start.row..range.end.row] = prefix + suffix
|
||||
|
||||
insert: ({row, column}, string) ->
|
||||
postRange =
|
||||
start: { row, column }
|
||||
end: { row, column }
|
||||
|
||||
prefix = @lines[row][0...column]
|
||||
suffix = @lines[row][column..]
|
||||
|
||||
lines = string.split('\n')
|
||||
|
||||
if lines.length == 1
|
||||
@lines[row] = prefix + string + suffix
|
||||
postRange.end.column += string.length
|
||||
else
|
||||
for line, i in lines
|
||||
curRow = row + i
|
||||
if i == 0 # replace first line
|
||||
@lines[curRow] = prefix + line
|
||||
else if i < lines.length - 1 # insert middle lines
|
||||
@lines[curRow...curRow] = line
|
||||
else # insert last line
|
||||
@lines[curRow...curRow] = line + suffix
|
||||
postRange.end.row = curRow
|
||||
postRange.end.column = line.length
|
||||
|
||||
postRange
|
||||
|
||||
numLines: ->
|
||||
@getLines().length
|
||||
|
||||
lastRow: ->
|
||||
@getLines().length - 1
|
||||
|
||||
lastLine: ->
|
||||
@getLine(@lastRow())
|
||||
|
||||
insert: (point, text) ->
|
||||
@change(new Range(point, point), text)
|
||||
|
||||
change: (preRange, newText) ->
|
||||
postRange = new Range(_.clone(preRange.start), _.clone(preRange.start))
|
||||
prefix = @lines[preRange.start.row][0...preRange.start.column]
|
||||
suffix = @lines[preRange.end.row][preRange.end.column..]
|
||||
|
||||
newTextLines = newText.split('\n')
|
||||
|
||||
if newTextLines.length == 1
|
||||
postRange.end.column += newText.length
|
||||
newTextLines = [prefix + newText + suffix]
|
||||
else
|
||||
lastLineIndex = newTextLines.length - 1
|
||||
newTextLines[0] = prefix + newTextLines[0]
|
||||
postRange.end.row += lastLineIndex
|
||||
postRange.end.column = newTextLines[lastLineIndex].length
|
||||
newTextLines[lastLineIndex] += suffix
|
||||
|
||||
@lines[preRange.start.row..preRange.end.row] = newTextLines
|
||||
@trigger 'change', { preRange, postRange, string: newText }
|
||||
|
||||
save: ->
|
||||
if not @path then throw new Error("Tried to save buffer with no url")
|
||||
fs.write @path, @getText()
|
||||
@@ -87,3 +85,14 @@ class Buffer
|
||||
trigger: (eventName, event) ->
|
||||
@eventHandlers?[eventName]?.forEach (handler) -> handler(event)
|
||||
|
||||
modeName: ->
|
||||
extension = if @path then @path.split('/').pop().split('.').pop() else null
|
||||
switch extension
|
||||
when 'js' then 'javascript'
|
||||
when 'coffee' then 'coffee'
|
||||
when 'rb', 'ru' then 'ruby'
|
||||
when 'c', 'h', 'cpp' then 'c_cpp'
|
||||
when 'html', 'htm' then 'html'
|
||||
when 'css' then 'css'
|
||||
else 'text'
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ Buffer = require 'buffer'
|
||||
Point = require 'point'
|
||||
Cursor = require 'cursor'
|
||||
Selection = require 'selection'
|
||||
Highlighter = require 'highlighter'
|
||||
Range = require 'range'
|
||||
|
||||
$ = require 'jquery'
|
||||
$$ = require 'template/builder'
|
||||
_ = require 'underscore'
|
||||
@@ -26,6 +28,7 @@ class Editor extends Template
|
||||
|
||||
initialize: () ->
|
||||
requireStylesheet 'editor.css'
|
||||
requireStylesheet 'theme/twilight.css'
|
||||
@bindKeys()
|
||||
@buildCursorAndSelection()
|
||||
@handleEvents()
|
||||
@@ -97,16 +100,23 @@ class Editor extends Template
|
||||
@hiddenInput.width(@charWidth)
|
||||
@focus()
|
||||
|
||||
buildLineElement: (lineText) ->
|
||||
if lineText is ''
|
||||
$$.pre class: "line", -> @raw(' ')
|
||||
else
|
||||
$$.pre class: "line", lineText
|
||||
buildLineElement: (row) ->
|
||||
tokens = @highlighter.tokensForRow(row)
|
||||
$$.pre class: 'line', ->
|
||||
if tokens.length
|
||||
for token in tokens
|
||||
classes = token.type.split('.').map((c) -> "ace_#{c}").join(' ')
|
||||
@span { class: token.type.replace('.', ' ') }, token.value
|
||||
else
|
||||
@raw ' '
|
||||
|
||||
setBuffer: (@buffer) ->
|
||||
@highlighter = new Highlighter(@buffer)
|
||||
|
||||
@lines.empty()
|
||||
for line in @buffer.getLines()
|
||||
@lines.append @buildLineElement(line)
|
||||
for row in [0..@buffer.lastRow()]
|
||||
line = @buildLineElement(row)
|
||||
@lines.append line
|
||||
|
||||
@setCursorPosition(row: 0, column: 0)
|
||||
|
||||
@@ -128,18 +138,13 @@ class Editor extends Template
|
||||
else
|
||||
@updateLineElement(row)
|
||||
|
||||
@selection.bufferChanged(e)
|
||||
@cursor.bufferChanged(e)
|
||||
|
||||
updateLineElement: (row) ->
|
||||
line = @buffer.getLine(row)
|
||||
element = @getLineElement(row)
|
||||
if line == ''
|
||||
element.html(' ')
|
||||
else
|
||||
element.text(line)
|
||||
@getLineElement(row).replaceWith(@buildLineElement(row))
|
||||
|
||||
insertLineElement: (row) ->
|
||||
@getLineElement(row).before(@buildLineElement(@buffer.getLine(row)))
|
||||
@getLineElement(row).before(@buildLineElement(row))
|
||||
|
||||
removeLineElement: (row) ->
|
||||
@getLineElement(row).remove()
|
||||
|
||||
43
src/atom/highlighter.coffee
Normal file
43
src/atom/highlighter.coffee
Normal file
@@ -0,0 +1,43 @@
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class Highlighter
|
||||
buffer: null
|
||||
tokenizer: null
|
||||
lines: []
|
||||
|
||||
constructor: (@buffer) ->
|
||||
@buildTokenizer()
|
||||
@lines = @tokenizeRows('start', 0, @buffer.lastRow())
|
||||
@buffer.on 'change', (e) => @handleBufferChange(e)
|
||||
|
||||
buildTokenizer: ->
|
||||
Mode = require("ace/mode/#{@buffer.modeName()}").Mode
|
||||
@tokenizer = (new Mode).getTokenizer()
|
||||
|
||||
handleBufferChange: (e) ->
|
||||
{ preRange, postRange } = e
|
||||
|
||||
previousState = @lines[preRange.end.row].state
|
||||
newLines = @tokenizeRows('start', postRange.start.row, postRange.end.row)
|
||||
@lines[preRange.start.row..preRange.end.row] = newLines
|
||||
|
||||
for row in [postRange.end.row...@buffer.lastRow()]
|
||||
break if @lines[row].state == previousState
|
||||
nextRow = row + 1
|
||||
previousState = @lines[nextRow].state
|
||||
@lines[nextRow] = @tokenizeRow(@lines[row].state, nextRow)
|
||||
|
||||
tokenizeRows: (startState, startRow, endRow) ->
|
||||
state = startState
|
||||
for row in [startRow..endRow]
|
||||
line = @tokenizeRow(state, row)
|
||||
state = line.state
|
||||
line
|
||||
|
||||
tokenizeRow: (state, row) ->
|
||||
@tokenizer.getLineTokens(@buffer.getLine(row), state)
|
||||
|
||||
tokensForRow: (row) ->
|
||||
@lines[row].tokens
|
||||
|
||||
@@ -26,9 +26,6 @@ class Selection extends Template
|
||||
@anchor = null
|
||||
@updateAppearance()
|
||||
|
||||
bufferChanged: (e) ->
|
||||
@cursor.setPosition(e.postRange.end)
|
||||
|
||||
updateAppearance: ->
|
||||
@clearRegions()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user