Initial 🔪 at extending telepath.Model in Project/TextBuffer

This commit is contained in:
Kevin Sawicki
2013-11-12 16:33:26 -08:00
parent 62feefd28d
commit 1808e5f991
6 changed files with 42 additions and 120 deletions

View File

@@ -35,7 +35,7 @@
"season": "0.14.0",
"semver": "1.1.4",
"space-pen": "2.0.0",
"telepath": "0.29.0",
"telepath": "0.31.0",
"temp": "0.5.0",
"underscore-plus": "0.3.0"
},

View File

@@ -121,10 +121,10 @@ class Atom
deserializeProject: ->
Project = require './project'
state = @getWindowState()
@project = deserialize(state.get('project'))
@project = state.get('project')
unless @project?
@project = new Project(@getLoadSettings().initialPath)
state.set('project', @project.getState())
@project = new Project(path: @getLoadSettings().initialPath)
state.set('project', @project)
deserializeRootView: ->
RootView = require './root-view'
@@ -295,6 +295,8 @@ class Atom
doc = Document.deserialize(documentState) if documentState?
doc ?= Document.create()
doc.registerModelClass(require('./project'))
doc.registerModelClass(require('./text-buffer'))
# TODO: Remove this when everything is using telepath models
if @site?
@site.setRootDocument(doc)

View File

@@ -139,10 +139,10 @@ class EditSession
@destroyed = true
@unsubscribe()
selection.destroy() for selection in @getSelections()
@buffer.release()
@displayBuffer.destroy()
@languageMode.destroy()
project?.removeEditSession(this)
@buffer.release()
@emit 'destroyed'
@off()

View File

@@ -5,7 +5,7 @@ _ = require 'underscore-plus'
fs = require 'fs-plus'
Q = require 'q'
telepath = require 'telepath'
{Range} = telepath
{Model, Range} = telepath
TextBuffer = require './text-buffer'
EditSession = require './edit-session'
@@ -19,16 +19,12 @@ Git = require './git'
# Ultimately, a project is a git directory that's been opened. It's a collection
# of directories and files that you can operate on.
module.exports =
class Project
class Project extends Model
Emitter.includeInto(this)
@acceptsDocuments: true
@version: 1
registerDeserializer(this)
# Private:
@deserialize: (state) -> new Project(state)
@properties
buffers: []
path: null
# Public: Find the local path for the given repository URL.
@pathForRepositoryUrl: (repoUrl) ->
@@ -36,10 +32,11 @@ class Project
repoName = repoName.replace(/\.git$/, '')
path.join(atom.config.get('core.projectHome'), repoName)
rootDirectory: null
editSessions: null
ignoredPathRegexes: null
openers: null
# Private:
attached: ->
@openers = []
@editSessions = []
@setPath(@path)
# Public:
registerOpener: (opener) -> @openers.push(opener)
@@ -59,51 +56,10 @@ class Project
@repo.destroy()
@repo = null
# Public: Establishes a new project at a given path.
#
# path - The {String} name of the path
constructor: (pathOrState) ->
@openers = []
@editSessions = []
@buffers = []
if pathOrState instanceof telepath.Document
@state = pathOrState
if projectPath = @state.remove('path')
@setPath(projectPath)
else
@setPath(@constructor.pathForRepositoryUrl(@state.get('repoUrl')))
@state.get('buffers').each (bufferState) =>
if buffer = deserialize(bufferState, project: this)
@addBuffer(buffer, updateState: false)
else
@state = atom.site.createDocument(deserializer: @constructor.name, version: @constructor.version, buffers: [])
@setPath(pathOrState)
@state.get('buffers').on 'changed', ({index, insertedValues, removedValues, siteId}) =>
return if siteId is @state.siteId
for removedBuffer in removedValues
@removeBufferAtIndex(index, updateState: false)
for insertedBuffer, i in insertedValues
@addBufferAtIndex(deserialize(insertedBuffer, project: this), index + i, updateState: false)
# Private:
serialize: ->
state = @state.clone()
state.set('path', @getPath())
@destroyUnretainedBuffers()
state.set('buffers', buffer.serialize() for buffer in @getBuffers())
state
# Private:
destroyUnretainedBuffers: ->
buffer.destroy() for buffer in @getBuffers() when not buffer.isRetained()
# Public: ?
getState: -> @state
# Public: Returns the {Git} repository if available.
getRepo: -> @repo
@@ -223,17 +179,15 @@ class Project
new Array(@buffers...)
isPathModified: (filePath) ->
absoluteFilePath = @resolve(filePath)
existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath
existingBuffer?.isModified()
@findBufferForPath(@resolve(filePath))?.isModified()
findBufferForPath: (filePath) ->
_.find @buffers.getValues(), (buffer) -> buffer.getPath() == filePath
# Private: Only to be used in specs
bufferForPathSync: (filePath) ->
absoluteFilePath = @resolve(filePath)
if filePath
existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath
existingBuffer = @findBufferForPath(absoluteFilePath) if filePath
existingBuffer ? @buildBufferSync(absoluteFilePath)
# Private: Given a file path, this retrieves or creates a new {TextBuffer}.
@@ -246,9 +200,7 @@ class Project
# Returns a promise that resolves to the {TextBuffer}.
bufferForPath: (filePath) ->
absoluteFilePath = @resolve(filePath)
if absoluteFilePath
existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath
existingBuffer = @findBufferForPath(absoluteFilePath) if absoluteFilePath
Q(existingBuffer ? @buildBuffer(absoluteFilePath))
# Private:
@@ -269,10 +221,11 @@ class Project
#
# Returns a promise that resolves to the {TextBuffer}.
buildBuffer: (absoluteFilePath) ->
buffer = new TextBuffer({project: this, filePath: absoluteFilePath})
buffer.load().then (buffer) =>
@addBuffer(buffer)
buffer
buffer = new TextBuffer({filePath: absoluteFilePath})
@addBuffer(buffer)
buffer.load()
.then((buffer) -> buffer)
.catch(=> @removeBuffer(buffer))
# Private:
addBuffer: (buffer, options={}) ->
@@ -280,8 +233,7 @@ class Project
# Private:
addBufferAtIndex: (buffer, index, options={}) ->
@buffers[index] = buffer
@state.get('buffers').insert(index, buffer.getState()) if options.updateState ? true
@buffers.insert(index, buffer)
@emit 'buffer-created', buffer
# Private: Removes a {TextBuffer} association from the project.
@@ -293,8 +245,9 @@ class Project
# Private:
removeBufferAtIndex: (index, options={}) ->
console.log 'removing buffer', index
console.trace()
[buffer] = @buffers.splice(index, 1)
@state.get('buffers')?.remove(index) if options.updateState ? true
buffer?.destroy()
# Public: Performs a search across all the files in the project.

View File

@@ -1,4 +1,3 @@
crypto = require 'crypto'
{Emitter, Subscriber} = require 'emissary'
guid = require 'guid'
Q = require 'q'
@@ -8,25 +7,23 @@ telepath = require 'telepath'
_ = require 'underscore-plus'
File = require './file'
{Point, Range} = telepath
{Point, Range, Model} = telepath
# Private: Represents the contents of a file.
#
# The `Buffer` is often associated with a {File}. However, this is not always
# the case, as a `Buffer` could be an unsaved chunk of text.
module.exports =
class TextBuffer
class TextBuffer extends Model
Emitter.includeInto(this)
Subscriber.includeInto(this)
@acceptsDocuments: true
@version: 2
registerDeserializer(this)
@properties
text: -> new telepath.String('', replicated: false)
id: -> guid.create().toString()
filePath: null
@deserialize: (state, params) ->
buffer = new this(state, params)
buffer.load()
buffer
@::lazyGetter 'project', -> @grandparent
stoppedChangingDelay: 300
stoppedChangingTimeout: null
@@ -36,34 +33,14 @@ class TextBuffer
file: null
refcount: 0
# Creates a new buffer.
#
# * optionsOrState - An {Object} or a telepath.Document
# + filePath - A {String} representing the file path
constructor: (optionsOrState={}, params={}) ->
if optionsOrState instanceof telepath.Document
{@project} = params
@state = optionsOrState
@id = @state.get('id')
filePath = @state.get('relativePath')
@text = @state.get('text')
@useSerializedText = @state.get('isModified') != false
else
{@project, filePath} = optionsOrState
@text = new telepath.String(initialText ? '', replicated: false)
@id = guid.create().toString()
@state = atom.site.createDocument
id: @id
deserializer: @constructor.name
version: @constructor.version
text: @text
attached: ->
@loaded = false
@subscribe @text, 'changed', @handleTextChange
@subscribe @text, 'marker-created', (marker) => @emit 'marker-created', marker
@subscribe @text, 'markers-updated', => @emit 'markers-updated'
@setPath(@project.resolve(filePath)) if @project
@setPath(@project.resolve(@filePath)) if @project
loadSync: ->
@updateCachedDiskContentsSync()
@@ -109,16 +86,6 @@ class TextBuffer
@destroy() unless @isRetained()
this
serialize: ->
state = @state.clone()
state.set('isModified', @isModified())
state.set('diskContentsDigest', @file.getDigest()) if @file
for marker in state.get('text').getMarkers() when marker.isRemote()
marker.destroy()
state
getState: -> @state
subscribeToFile: ->
@file.on "contents-changed", =>
@conflict = true if @isModified()

View File

@@ -69,7 +69,7 @@ window.startEditorWindow = ->
window.unloadEditorWindow = ->
return if not atom.project and not atom.rootView
windowState = atom.getWindowState()
windowState.set('project', atom.project.serialize())
windowState.set('project', atom.project)
windowState.set('syntax', atom.syntax.serialize())
windowState.set('rootView', atom.rootView.serialize())
atom.packages.deactivatePackages()