Merge remote-tracking branch 'origin/master' into cj-deleted-files-not-modified

This commit is contained in:
probablycorey
2013-12-10 14:46:26 -08:00
21 changed files with 242 additions and 210 deletions

View File

@@ -41,6 +41,7 @@ class Atom
# Private:
constructor: ->
@loadTime = null
@workspaceViewParentSelector = 'body'
@deserializers = new DeserializerManager()
@@ -80,6 +81,12 @@ class Atom
setBodyPlatformClass: ->
document.body.classList.add("platform-#{process.platform}")
# Public: Create a new telepath model. We won't need to define this method when
# the atom global is a telepath model itself because all model subclasses inherit
# a create method.
create: (model) ->
@site.createDocument(model)
# Public: Get the current window
getCurrentWindow: ->
remote.getCurrentWindow()
@@ -420,7 +427,7 @@ class Atom
serializedWindowState = @loadSerializedWindowState()
doc = Document.deserialize(serializedWindowState) if serializedWindowState?
doc ?= Document.create()
doc.registerModelClasses(require('./text-buffer'), require('./project'))
doc.registerModelClasses(require('./text-buffer'), require('./project'), require('./tokenized-buffer'), require('./display-buffer'))
# TODO: Remove this when everything is using telepath models
if @site?
@site.setRootDocument(doc)
@@ -444,6 +451,16 @@ class Atom
else
@windowState
# Public: Get the time taken to completely load the current window.
#
# This time include things like loading and activating packages, creating
# DOM elements for the editor, and reading the config.
#
# Returns the number of milliseconds taken to load the window or null
# if the window hasn't finished loading yet.
getWindowLoadTime: ->
@loadTime
# Private: Returns a replicated copy of the current state.
replicate: ->
@getWindowState().replicate()

View File

@@ -1,8 +1,7 @@
_ = require 'underscore-plus'
{Emitter, Subscriber} = require 'emissary'
guid = require 'guid'
telepath = require 'telepath'
{Point, Range} = telepath
{Model, Point, Range} = require 'telepath'
TokenizedBuffer = require './tokenized-buffer'
RowMap = require './row-map'
Fold = require './fold'
@@ -12,34 +11,28 @@ ConfigObserver = require './config-observer'
# Private:
module.exports =
class DisplayBuffer
Emitter.includeInto(this)
Subscriber.includeInto(this)
class DisplayBuffer extends Model
_.extend @prototype, ConfigObserver
@acceptsDocuments: true
atom.deserializers.add(this)
@version: 2
@properties
tokenizedBuffer: null
softWrap: -> atom.config.get('editor.softWrap') ? false
editorWidthInChars: null
@deserialize: (state) -> new this(state)
constructor: ->
super
@deserializing = @state?
constructor: (optionsOrState) ->
if optionsOrState instanceof telepath.Document
@state = optionsOrState
@id = @state.get('id')
@tokenizedBuffer = atom.deserializers.deserialize(@state.get('tokenizedBuffer'))
@buffer = @tokenizedBuffer.buffer
created: ->
if @deserializing
@deserializing = false
return
if @tokenizedBuffer?
@tokenizedBuffer?.created()
else
{@buffer, softWrap, editorWidthInChars} = optionsOrState
@id = guid.create().toString()
@tokenizedBuffer = new TokenizedBuffer(optionsOrState)
@state = atom.site.createDocument
deserializer: @constructor.name
version: @constructor.version
id: @id
tokenizedBuffer: @tokenizedBuffer.getState()
softWrap: softWrap ? atom.config.get('editor.softWrap') ? false
editorWidthInChars: editorWidthInChars
@tokenizedBuffer = new TokenizedBuffer({@tabLength, @buffer, project: atom.project})
@buffer = @tokenizedBuffer.buffer
@markers = {}
@foldsByMarkerId = {}
@@ -56,16 +49,13 @@ class DisplayBuffer
@updateWrappedScreenLines()
@observeConfig 'editor.preferredLineLength', callNow: false, =>
@updateWrappedScreenLines() if @getSoftWrap() and atom.config.get('editor.softWrapAtPreferredLineLength')
@updateWrappedScreenLines() if @softWrap and atom.config.get('editor.softWrapAtPreferredLineLength')
@observeConfig 'editor.softWrapAtPreferredLineLength', callNow: false, =>
@updateWrappedScreenLines() if @getSoftWrap()
serialize: -> @state.clone()
getState: -> @state
@updateWrappedScreenLines() if @softWrap
copy: ->
newDisplayBuffer = new DisplayBuffer({@buffer, tabLength: @getTabLength()})
newDisplayBuffer = atom.create(new DisplayBuffer({@buffer, tabLength: @getTabLength()}))
for marker in @findMarkers(displayBufferId: @id)
marker.copy(displayBufferId: newDisplayBuffer.id)
newDisplayBuffer
@@ -98,25 +88,26 @@ class DisplayBuffer
# visible - A {Boolean} indicating of the tokenized buffer is shown
setVisible: (visible) -> @tokenizedBuffer.setVisible(visible)
setSoftWrap: (softWrap) -> @state.set('softWrap', softWrap)
# Deprecated: Use the softWrap property directly
setSoftWrap: (@softWrap) -> @softWrap
getSoftWrap: -> @state.get('softWrap')
# Deprecated: Use the softWrap property directly
getSoftWrap: -> @softWrap
# Set the number of characters that fit horizontally in the editor.
#
# editorWidthInChars - A {Number} of characters.
setEditorWidthInChars: (editorWidthInChars) ->
previousWidthInChars = @state.get('editorWidthInChars')
@state.set('editorWidthInChars', editorWidthInChars)
if editorWidthInChars isnt previousWidthInChars and @getSoftWrap()
previousWidthInChars = @editorWidthInChars
@editorWidthInChars = editorWidthInChars
if editorWidthInChars isnt previousWidthInChars and @softWrap
@updateWrappedScreenLines()
getSoftWrapColumn: ->
editorWidthInChars = @state.get('editorWidthInChars')
if atom.config.get('editor.softWrapAtPreferredLineLength')
Math.min(editorWidthInChars, atom.config.getPositiveInt('editor.preferredLineLength', editorWidthInChars))
Math.min(@editorWidthInChars, atom.config.getPositiveInt('editor.preferredLineLength', @editorWidthInChars))
else
editorWidthInChars
@editorWidthInChars
# Gets the screen line for the given screen row.
#
@@ -433,7 +424,7 @@ class DisplayBuffer
# Returns a {Number} representing the `line` position where the wrap would take place.
# Returns `null` if a wrap wouldn't occur.
findWrapColumn: (line, softWrapColumn=@getSoftWrapColumn()) ->
return unless @getSoftWrap()
return unless @softWrap
return unless line.length > softWrapColumn
if /\s/.test(line[softWrapColumn])
@@ -654,6 +645,7 @@ class DisplayBuffer
softWraps = 0
while wrapScreenColumn = @findWrapColumn(tokenizedLine.text)
[wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(wrapScreenColumn)
newScreenLines.push(wrappedLine)
softWraps++
newScreenLines.push(tokenizedLine)

View File

@@ -106,7 +106,7 @@ class EditorView extends View
@edit(editor)
else if @mini
@edit(new Editor
buffer: TextBuffer.createAsRoot()
buffer: atom.create(new TextBuffer)
softWrap: false
tabLength: 2
softTabs: true

View File

@@ -44,7 +44,7 @@ class Editor
atom.deserializers.add(this)
@version: 5
@version: 6
@deserialize: (state) ->
new Editor(state)
@@ -67,7 +67,8 @@ class Editor
if optionsOrState instanceof telepath.Document
@state = optionsOrState
@id = @state.get('id')
displayBuffer = atom.deserializers.deserialize(@state.get('displayBuffer'))
displayBuffer = @state.get('displayBuffer')
displayBuffer.created()
@setBuffer(displayBuffer.buffer)
@setDisplayBuffer(displayBuffer)
for marker in @findMarkers(@getSelectionMarkerAttributes())
@@ -79,12 +80,12 @@ class Editor
else
{buffer, displayBuffer, tabLength, softTabs, softWrap, suppressCursorCreation, initialLine} = optionsOrState
@id = guid.create().toString()
displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrap})
displayBuffer ?= atom.create(new DisplayBuffer({buffer, tabLength, softWrap}))
@state = atom.site.createDocument
deserializer: @constructor.name
version: @constructor.version
id: @id
displayBuffer: displayBuffer.getState()
displayBuffer: displayBuffer
softTabs: buffer.usesSoftTabs() ? softTabs ? atom.config.get('editor.softTabs') ? true
scrollTop: 0
scrollLeft: 0

View File

@@ -34,7 +34,7 @@ class Project extends telepath.Model
# Private: Called by telepath.
created: ->
for buffer in @buffers.getValues()
buffer.once 'destroyed', (buffer) => @removeBuffer(buffer)
buffer.once 'destroyed', (buffer) => @removeBuffer(buffer) if @isAlive()
@openers = []
@editors = []
@@ -64,7 +64,7 @@ class Project extends telepath.Model
# Private:
destroyed: ->
editor.destroy() for editor in @getEditors()
buffer.release() for buffer in @getBuffers()
buffer.destroy() for buffer in @getBuffers()
@destroyRepo()
# Private:
@@ -239,7 +239,7 @@ class Project extends telepath.Model
# Private:
addBufferAtIndex: (buffer, index, options={}) ->
buffer = @buffers.insert(index, buffer)
buffer.once 'destroyed', => @removeBuffer(buffer)
buffer.once 'destroyed', => @removeBuffer(buffer) if @isAlive()
@emit 'buffer-created', buffer
buffer

View File

@@ -24,41 +24,14 @@ tooltipDefaults =
placement: 'auto top'
viewportPadding: 2
modifiers =
cmd: ''
ctrl: ''
alt: ''
option: ''
shift: ''
enter: ''
left: ''
right: ''
up: ''
down: ''
replaceKey = (key) ->
if modifiers[key]
modifiers[key]
else if key.length == 1 and key == key.toUpperCase() and key.toUpperCase() != key.toLowerCase()
[modifiers.shift, key.toUpperCase()]
else if key.length == 1
key.toUpperCase()
else
key
replaceModifiersInSingleKeystroke = (keystroke) ->
keys = keystroke.split('-')
keys = _.flatten(replaceKey(key) for key in keys)
keys.join('')
replaceModifiers = (keystroke) ->
humanizeKeystrokes = (keystroke) ->
keystrokes = keystroke.split(' ')
keystrokes = (replaceModifiersInSingleKeystroke(stroke) for stroke in keystrokes)
keystrokes = (_.humanizeKeystroke(stroke) for stroke in keystrokes)
keystrokes.join(' ')
getKeystroke = (bindings) ->
if bindings?.length
"<span class=\"keystroke\">#{replaceModifiers(bindings[0].keystroke)}</span>"
"<span class=\"keystroke\">#{humanizeKeystrokes(bindings[0].keystroke)}</span>"
else
''
# options from http://getbootstrap.com/javascript/#tooltips
@@ -87,6 +60,6 @@ jQuery.fn.destroyTooltip = ->
@tooltip('destroy')
jQuery.fn.setTooltip.getKeystroke = getKeystroke
jQuery.fn.setTooltip.replaceModifiers = replaceModifiers
jQuery.fn.setTooltip.humanizeKeystrokes = humanizeKeystrokes
module.exports = spacePen

View File

@@ -81,12 +81,12 @@ class TextBuffer extends telepath.Model
@emit 'changed', bufferChangeEvent
@scheduleModifiedEvents()
destroy: ->
unless @destroyed
destroyed: ->
unless @alreadyDestroyed
@cancelStoppedChangingTimeout()
@file?.off()
@unsubscribe()
@destroyed = true
@alreadyDestroyed = true
@emit 'destroyed', this
isRetained: -> @refcount > 0

View File

@@ -1,16 +1,16 @@
_ = require 'underscore-plus'
{Model, Point, Range} = require 'telepath'
TokenizedLine = require './tokenized-line'
{Emitter, Subscriber} = require 'emissary'
Token = require './token'
telepath = require 'telepath'
{Point, Range} = telepath
### Internal ###
module.exports =
class TokenizedBuffer
Emitter.includeInto(this)
Subscriber.includeInto(this)
class TokenizedBuffer extends Model
@properties
bufferPath: null
tabLength: -> atom.config.get('editor.tabLength') ? 2
project: null
grammar: null
currentGrammarScore: null
@@ -20,24 +20,19 @@ class TokenizedBuffer
invalidRows: null
visible: false
@acceptsDocuments: true
atom.deserializers.add(this)
constructor: ->
super
@deserializing = @state?
@deserialize: (state) ->
new this(state)
created: ->
if @deserializing
@deserializing = false
return
constructor: (optionsOrState) ->
if optionsOrState instanceof telepath.Document
@state = optionsOrState
# TODO: This needs to be made async, but should wait until the new Telepath changes land
@buffer = atom.project.bufferForPathSync(optionsOrState.get('bufferPath'))
if @buffer? and @buffer.isAlive()
@bufferPath = @buffer.getPath()
else
{ @buffer, tabLength } = optionsOrState
@state = atom.site.createDocument
deserializer: @constructor.name
bufferPath: @buffer.getPath()
tabLength: tabLength ? atom.config.get('editor.tabLength') ? 2
@buffer = @project.bufferForPathSync(@bufferPath)
@subscribe atom.syntax, 'grammar-added grammar-updated', (grammar) =>
if grammar.injectionSelector?
@@ -48,15 +43,25 @@ class TokenizedBuffer
@on 'grammar-changed grammar-updated', => @resetTokenizedLines()
@subscribe @buffer, "changed", (e) => @handleBufferChange(e)
@subscribe @buffer, "path-changed", => @state.set('bufferPath', @buffer.getPath())
@subscribe @buffer, "path-changed", => @bufferPath = @buffer.getPath()
@subscribe @$tabLength.changes.onValue (tabLength) =>
lastRow = @buffer.getLastRow()
@tokenizedLines = @buildPlaceholderTokenizedLinesForRows(0, lastRow)
@invalidateRow(0)
@emit "changed", { start: 0, end: lastRow, delta: 0 }
@subscribe atom.config.observe 'editor.tabLength', callNow: false, =>
@setTabLength(atom.config.getPositiveInt('editor.tabLength'))
@reloadGrammar()
serialize: -> @state.clone()
getState: -> @state
# TODO: Remove when everything is a telepath model
destroy: ->
@destroyed()
destroyed: ->
@unsubscribe()
setGrammar: (grammar, score) ->
return if grammar is @grammar
@@ -90,24 +95,19 @@ class TokenizedBuffer
#
# Returns a {Number}.
getTabLength: ->
@state.get('tabLength')
@tabLength
# Specifies the tab length.
#
# tabLength - A {Number} that defines the new tab length.
setTabLength: (tabLength) ->
@state.set('tabLength', tabLength)
lastRow = @buffer.getLastRow()
@tokenizedLines = @buildPlaceholderTokenizedLinesForRows(0, lastRow)
@invalidateRow(0)
@emit "changed", { start: 0, end: lastRow, delta: 0 }
setTabLength: (@tabLength) ->
tokenizeInBackground: ->
return if not @visible or @pendingChunk or @destroyed
return if not @visible or @pendingChunk or not @isAlive()
@pendingChunk = true
_.defer =>
@pendingChunk = false
@tokenizeNextChunk() unless @destroyed
@tokenizeNextChunk() if @isAlive() and @buffer.isAlive()
tokenizeNextChunk: ->
rowsRemaining = @chunkSize
@@ -251,10 +251,6 @@ class TokenizedBuffer
endColumn = tokenizedLine.bufferColumnForToken(lastToken) + lastToken.bufferDelta
new Range([position.row, startColumn], [position.row, endColumn])
destroy: ->
@unsubscribe()
@destroyed = true
iterateTokensInBufferRange: (bufferRange, iterator) ->
bufferRange = Range.fromObject(bufferRange)
{ start, end } = bufferRange

View File

@@ -10,4 +10,5 @@ Atom = require './atom'
window.atom = new Atom()
atom.setUpEnvironment('editor')
atom.startEditorWindow()
console.log "Window load time: #{Date.now() - startTime}ms"
window.atom.loadTime = Date.now() - startTime
console.log "Window load time: #{atom.getWindowLoadTime()}ms"

View File

@@ -118,8 +118,6 @@ class WorkspaceView extends View
@command 'window:save-all', => @saveAll()
@command 'window:toggle-invisibles', =>
atom.config.toggle("editor.showInvisibles")
@command 'window:toggle-ignored-files', =>
atom.config.toggle("core.hideGitIgnoredFiles")
@command 'window:toggle-auto-indent', =>
atom.config.toggle("editor.autoIndent")