mirror of
https://github.com/atom/atom.git
synced 2026-01-24 22:38:20 -05:00
Merge branch 'ns-teleditor'
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
"season": "0.14.0",
|
||||
"semver": "1.1.4",
|
||||
"space-pen": "2.0.1",
|
||||
"telepath": "0.65.0",
|
||||
"telepath": "0.66.0",
|
||||
"temp": "0.5.0",
|
||||
"underscore-plus": "0.5.0"
|
||||
},
|
||||
|
||||
@@ -21,20 +21,24 @@ describe "Editor", ->
|
||||
buffer = editor.buffer
|
||||
lineLengths = buffer.getLines().map (line) -> line.length
|
||||
|
||||
describe "@deserialize(state)", ->
|
||||
describe "when the editor is deserialized", ->
|
||||
it "restores selections and folds based on markers in the buffer", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [3, 4]])
|
||||
editor.addSelectionForBufferRange([[5, 6], [7, 5]], isReversed: true)
|
||||
editor.foldBufferRow(4)
|
||||
expect(editor.isFoldedAtBufferRow(4)).toBeTruthy()
|
||||
|
||||
editor2 = atom.deserializers.deserialize(editor.serialize())
|
||||
# Simulate serialization with replicate
|
||||
editor2 = editor.replicate()
|
||||
# FIXME: The created hook is called manually on deserialization because globals aren't ready otherwise
|
||||
editor2.created()
|
||||
|
||||
expect(editor2.id).toBe editor.id
|
||||
expect(editor2.getBuffer().getPath()).toBe editor.getBuffer().getPath()
|
||||
expect(editor2.getSelectedBufferRanges()).toEqual [[[1, 2], [3, 4]], [[5, 6], [7, 5]]]
|
||||
expect(editor2.getSelection(1).isReversed()).toBeTruthy()
|
||||
expect(editor2.isFoldedAtBufferRow(4)).toBeTruthy()
|
||||
editor2.destroy()
|
||||
|
||||
describe ".copy()", ->
|
||||
it "returns a different edit session with the same initial state", ->
|
||||
|
||||
@@ -59,22 +59,6 @@ describe "Project", ->
|
||||
editor.saveAs(tempFile)
|
||||
expect(atom.project.getPath()).toBe path.dirname(tempFile)
|
||||
|
||||
describe "when an edit session is deserialized", ->
|
||||
it "emits an 'editor-created' event and stores the edit session", ->
|
||||
handler = jasmine.createSpy('editorCreatedHandler')
|
||||
atom.project.on 'editor-created', handler
|
||||
|
||||
editor1 = atom.project.openSync("a")
|
||||
expect(handler.callCount).toBe 1
|
||||
expect(atom.project.getEditors().length).toBe 1
|
||||
expect(atom.project.getEditors()[0]).toBe editor1
|
||||
|
||||
editor2 = atom.deserializers.deserialize(editor1.serialize())
|
||||
expect(handler.callCount).toBe 2
|
||||
expect(atom.project.getEditors().length).toBe 2
|
||||
expect(atom.project.getEditors()[0]).toBe editor1
|
||||
expect(atom.project.getEditors()[1]).toBe editor2
|
||||
|
||||
describe "when an edit session is copied", ->
|
||||
it "emits an 'editor-created' event and stores the edit session", ->
|
||||
handler = jasmine.createSpy('editorCreatedHandler')
|
||||
|
||||
@@ -5,7 +5,7 @@ describe "Selection", ->
|
||||
|
||||
beforeEach ->
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
editor = new Editor(buffer: buffer, tabLength: 2)
|
||||
editor = atom.create(new Editor(buffer: buffer, tabLength: 2))
|
||||
selection = editor.getSelection()
|
||||
|
||||
afterEach ->
|
||||
|
||||
@@ -427,7 +427,13 @@ class Atom
|
||||
serializedWindowState = @loadSerializedWindowState()
|
||||
doc = Document.deserialize(serializedWindowState) if serializedWindowState?
|
||||
doc ?= Document.create()
|
||||
doc.registerModelClasses(require('./text-buffer'), require('./project'), require('./tokenized-buffer'), require('./display-buffer'))
|
||||
doc.registerModelClasses(
|
||||
require('./text-buffer'),
|
||||
require('./project'),
|
||||
require('./tokenized-buffer'),
|
||||
require('./display-buffer'),
|
||||
require('./editor')
|
||||
)
|
||||
# TODO: Remove this when everything is using telepath models
|
||||
if @site?
|
||||
@site.setRootDocument(doc)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{Document} = require 'telepath'
|
||||
{Document, Model} = require 'telepath'
|
||||
|
||||
# Public: Manages the deserializers used for serialized state
|
||||
#
|
||||
@@ -25,6 +25,8 @@ class DeserializerManager
|
||||
deserialize: (state, params) ->
|
||||
return unless state?
|
||||
|
||||
return state if state instanceof Model
|
||||
|
||||
if deserializer = @get(state)
|
||||
stateVersion = state.get?('version') ? state.version
|
||||
return if deserializer.version? and deserializer.version isnt stateVersion
|
||||
|
||||
@@ -105,12 +105,12 @@ class EditorView extends View
|
||||
if editor?
|
||||
@edit(editor)
|
||||
else if @mini
|
||||
@edit(new Editor
|
||||
@edit(atom.create(new Editor
|
||||
buffer: atom.create(new TextBuffer)
|
||||
softWrap: false
|
||||
tabLength: 2
|
||||
softTabs: true
|
||||
)
|
||||
))
|
||||
else
|
||||
throw new Error("Must supply an Editor or mini: true")
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
_ = require 'underscore-plus'
|
||||
path = require 'path'
|
||||
telepath = require 'telepath'
|
||||
guid = require 'guid'
|
||||
{Point, Range} = telepath
|
||||
{Model, Point, Range} = require 'telepath'
|
||||
LanguageMode = require './language-mode'
|
||||
DisplayBuffer = require './display-buffer'
|
||||
Cursor = require './cursor'
|
||||
Selection = require './selection'
|
||||
{Emitter, Subscriber} = require 'emissary'
|
||||
TextMateScopeSelector = require('first-mate').ScopeSelector
|
||||
|
||||
# Public: The core model of Atom.
|
||||
@@ -36,82 +34,70 @@ TextMateScopeSelector = require('first-mate').ScopeSelector
|
||||
# FIXME: Describe how there are both local and remote cursors and selections and
|
||||
# why that is.
|
||||
module.exports =
|
||||
class Editor
|
||||
Emitter.includeInto(this)
|
||||
Subscriber.includeInto(this)
|
||||
class Editor extends Model
|
||||
|
||||
@acceptsDocuments: true
|
||||
@properties
|
||||
displayBuffer: null
|
||||
softTabs: null
|
||||
scrollTop: 0
|
||||
scrollLeft: 0
|
||||
|
||||
atom.deserializers.add(this)
|
||||
|
||||
@version: 6
|
||||
|
||||
@deserialize: (state) ->
|
||||
new Editor(state)
|
||||
|
||||
id: null
|
||||
deserializing: false
|
||||
callDisplayBufferCreatedHook: false
|
||||
buffer: null
|
||||
languageMode: null
|
||||
displayBuffer: null
|
||||
cursors: null
|
||||
remoteCursors: null
|
||||
selections: null
|
||||
remoteSelections: null
|
||||
suppressSelectionMerging: false
|
||||
|
||||
# Private:
|
||||
constructor: (optionsOrState) ->
|
||||
constructor: ->
|
||||
super
|
||||
@deserializing = @state?
|
||||
|
||||
created: ->
|
||||
if @deserializing
|
||||
@deserializing = false
|
||||
@callDisplayBufferCreatedHook = true
|
||||
return
|
||||
|
||||
@cursors = []
|
||||
@remoteCursors = []
|
||||
@selections = []
|
||||
@remoteSelections = []
|
||||
if optionsOrState instanceof telepath.Document
|
||||
@state = optionsOrState
|
||||
@id = @state.get('id')
|
||||
displayBuffer = @state.get('displayBuffer')
|
||||
displayBuffer.created()
|
||||
@setBuffer(displayBuffer.buffer)
|
||||
@setDisplayBuffer(displayBuffer)
|
||||
for marker in @findMarkers(@getSelectionMarkerAttributes())
|
||||
marker.setAttributes(preserveFolds: true)
|
||||
@addSelection(marker)
|
||||
@setScrollTop(@state.get('scrollTop'))
|
||||
@setScrollLeft(@state.get('scrollLeft'))
|
||||
registerEditor = true
|
||||
else
|
||||
{buffer, displayBuffer, tabLength, softTabs, softWrap, suppressCursorCreation, initialLine} = optionsOrState
|
||||
@id = guid.create().toString()
|
||||
displayBuffer ?= atom.create(new DisplayBuffer({buffer, tabLength, softWrap}))
|
||||
@state = atom.site.createDocument
|
||||
deserializer: @constructor.name
|
||||
version: @constructor.version
|
||||
id: @id
|
||||
displayBuffer: displayBuffer
|
||||
softTabs: buffer.usesSoftTabs() ? softTabs ? atom.config.get('editor.softTabs') ? true
|
||||
scrollTop: 0
|
||||
scrollLeft: 0
|
||||
@setBuffer(buffer)
|
||||
@setDisplayBuffer(displayBuffer)
|
||||
|
||||
if @getCursors().length is 0 and not suppressCursorCreation
|
||||
if initialLine
|
||||
position = [initialLine, 0]
|
||||
unless @displayBuffer?
|
||||
@displayBuffer = new DisplayBuffer({@buffer, @tabLength, @softWrap})
|
||||
@softTabs = @buffer.usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true
|
||||
|
||||
@displayBuffer.created() if @callDisplayBufferCreatedHook
|
||||
@buffer = @displayBuffer.buffer
|
||||
|
||||
for marker in @findMarkers(@getSelectionMarkerAttributes())
|
||||
marker.setAttributes(preserveFolds: true)
|
||||
@addSelection(marker)
|
||||
|
||||
@subscribeToBuffer()
|
||||
@subscribeToDisplayBuffer()
|
||||
|
||||
if @getCursors().length is 0 and not @suppressCursorCreation
|
||||
if @initialLine
|
||||
position = [@initialLine, 0]
|
||||
else
|
||||
position = _.last(@getRemoteCursors())?.getBufferPosition() ? [0, 0]
|
||||
@addCursorAtBufferPosition(position)
|
||||
|
||||
@languageMode = new LanguageMode(this, @buffer.getExtension())
|
||||
@subscribe @state, 'changed', ({newValues}) =>
|
||||
for key, newValue of newValues
|
||||
switch key
|
||||
when 'scrollTop'
|
||||
@emit 'scroll-top-changed', newValue
|
||||
when 'scrollLeft'
|
||||
@emit 'scroll-left-changed', newValue
|
||||
|
||||
atom.project.addEditor(this) if registerEditor
|
||||
@subscribe @$scrollTop, 'value', (scrollTop) => @emit 'scroll-top-changed', scrollTop
|
||||
@subscribe @$scrollLeft, 'value', (scrollLeft) => @emit 'scroll-left-changed', scrollLeft
|
||||
|
||||
# Deprecated: The goal is a world where we don't call serialize explicitly
|
||||
serialize: -> this
|
||||
|
||||
# Private:
|
||||
setBuffer: (@buffer) ->
|
||||
subscribeToBuffer: ->
|
||||
@buffer.retain()
|
||||
@subscribe @buffer, "path-changed", =>
|
||||
unless atom.project.getPath()?
|
||||
@@ -124,7 +110,7 @@ class Editor
|
||||
@preserveCursorPositionOnBufferReload()
|
||||
|
||||
# Private:
|
||||
setDisplayBuffer: (@displayBuffer) ->
|
||||
subscribeToDisplayBuffer: ->
|
||||
@subscribe @displayBuffer, 'marker-created', @handleMarkerCreated
|
||||
@subscribe @displayBuffer, "changed", (e) => @emit 'screen-lines-changed', e
|
||||
@subscribe @displayBuffer, "markers-updated", => @mergeIntersectingSelections()
|
||||
@@ -148,18 +134,12 @@ class Editor
|
||||
@emit 'destroyed'
|
||||
@off()
|
||||
|
||||
# Private:
|
||||
serialize: -> @state.clone()
|
||||
|
||||
# Private:
|
||||
getState: -> @state
|
||||
|
||||
# Private: Creates an {Editor} with the same initial state
|
||||
copy: ->
|
||||
tabLength = @getTabLength()
|
||||
displayBuffer = @displayBuffer.copy()
|
||||
softTabs = @getSoftTabs()
|
||||
newEditor = new Editor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true})
|
||||
newEditor = @create(new Editor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true}))
|
||||
newEditor.setScrollTop(@getScrollTop())
|
||||
newEditor.setScrollLeft(@getScrollLeft())
|
||||
for marker in @findMarkers(editorId: @id)
|
||||
@@ -211,17 +191,17 @@ class Editor
|
||||
# Public: Controls visiblity based on the given Boolean.
|
||||
setVisible: (visible) -> @displayBuffer.setVisible(visible)
|
||||
|
||||
# Public: FIXME: I don't understand this.
|
||||
setScrollTop: (scrollTop) -> @state.set('scrollTop', scrollTop)
|
||||
# Deprecated: Use the ::scrollTop property directly
|
||||
setScrollTop: (@scrollTop) -> @scrollTop
|
||||
|
||||
# Public: Returns the current `scrollTop` value
|
||||
getScrollTop: -> @state.get('scrollTop') ? 0
|
||||
# Deprecated: Use the ::scrollTop property directly
|
||||
getScrollTop: -> @scrollTop
|
||||
|
||||
# Public: FIXME: I don't understand this.
|
||||
setScrollLeft: (scrollLeft) -> @state.set('scrollLeft', scrollLeft)
|
||||
# Deprecated: Use the ::scrollLeft property directly
|
||||
setScrollLeft: (@scrollLeft) -> @scrollLeft
|
||||
|
||||
# Public: Returns the current `scrollLeft` value
|
||||
getScrollLeft: -> @state.get('scrollLeft')
|
||||
# Deprecated: Use the ::scrollLeft property directly
|
||||
getScrollLeft: -> @scrollLeft
|
||||
|
||||
# Set the number of characters that can be displayed horizontally in the
|
||||
# editor that contains this edit session.
|
||||
@@ -233,12 +213,11 @@ class Editor
|
||||
# Public: Sets the column at which columsn will soft wrap
|
||||
getSoftWrapColumn: -> @displayBuffer.getSoftWrapColumn()
|
||||
|
||||
# Public: Returns whether soft tabs are enabled or not.
|
||||
getSoftTabs: -> @state.get('softTabs')
|
||||
# Deprecated: Use the ::softTabs property directly. Indicates whether soft tabs are enabled.
|
||||
getSoftTabs: -> @softTabs
|
||||
|
||||
# Public: Controls whether soft tabs are enabled or not.
|
||||
setSoftTabs: (softTabs) ->
|
||||
@state.set('softTabs', softTabs)
|
||||
# Deprecated: Use the ::softTabs property directly. Indicates whether soft tabs are enabled.
|
||||
setSoftTabs: (@softTabs) -> @softTabs
|
||||
|
||||
# Public: Returns whether soft wrap is enabled or not.
|
||||
getSoftWrap: -> @displayBuffer.getSoftWrap()
|
||||
|
||||
@@ -34,7 +34,9 @@ class Pane extends View
|
||||
if args[0] instanceof telepath.Document
|
||||
@state = args[0]
|
||||
@items = _.compact @state.get('items').map (item) ->
|
||||
atom.deserializers.deserialize(item)
|
||||
item = atom.deserializers.deserialize(item)
|
||||
item?.created?()
|
||||
item
|
||||
else
|
||||
@items = args
|
||||
@state = atom.site.createDocument
|
||||
|
||||
@@ -334,7 +334,7 @@ class Project extends telepath.Model
|
||||
|
||||
# Private:
|
||||
buildEditorForBuffer: (buffer, editorOptions) ->
|
||||
editor = new Editor(_.extend({buffer}, editorOptions))
|
||||
editor = @create(new Editor(_.extend({buffer}, editorOptions)))
|
||||
@addEditor(editor)
|
||||
editor
|
||||
|
||||
|
||||
Reference in New Issue
Block a user