Merge branch 'project-refactor'

This commit is contained in:
Nathan Sobo
2012-06-20 16:41:54 -06:00
14 changed files with 219 additions and 213 deletions

View File

@@ -39,19 +39,6 @@ describe 'Buffer', ->
expect(eventHandler).toHaveBeenCalledWith(buffer)
describe ".isModified()", ->
describe "when deserialized", ->
it "returns false", ->
buffer = Buffer.deserialize(buffer.serialize(), new Project)
expect(buffer.isModified()).toBe false
buffer = Buffer.deserialize((new Buffer).serialize(), new Project)
expect(buffer.isModified()).toBe false
it "returns is true if buffer no path and had changes", ->
buffer = new Buffer
buffer.insert([0,0], "oh hi")
expect(buffer.isModified()).toBe true
it "returns true when user changes buffer", ->
expect(buffer.isModified()).toBeFalsy()
buffer.insert([0,0], "hi")
@@ -68,25 +55,6 @@ describe 'Buffer', ->
buffer.save()
expect(buffer.isModified()).toBe false
describe '.deserialize(state, project)', ->
project = null
beforeEach ->
project = new Project(fs.directory(filePath))
describe 'when the state has a path', ->
it 'use the project to open the path', ->
savedBuffer = project.open(filePath)
buffer = Buffer.deserialize(savedBuffer.serialize(), project)
expect(buffer).toBe savedBuffer
describe 'when the state has text (and no path)', ->
it 'creates a new empty buffer (does not serialze unsaved text)', ->
unsavedBuffer = project.open()
unsavedBuffer.setText("OMGWTFBBQ")
buffer = Buffer.deserialize(unsavedBuffer.serialize(), project)
expect(buffer.getText()).toBe ""
describe ".getLines()", ->
it "returns an array of lines in the text contents", ->
expect(buffer.getLines().length).toBe fileContents.split("\n").length

View File

@@ -6,12 +6,12 @@ describe "EditSession", ->
beforeEach ->
buffer = new Buffer(require.resolve('fixtures/sample.js'))
editSession = new EditSession(
editSession = new EditSession
buffer: buffer
tabText: ' '
autoIndent: false
softWrapColumn: Infinity
)
softWrap: false
lineLengths = buffer.getLines().map (line) -> line.length
describe "cursor movement", ->

View File

@@ -1,4 +1,5 @@
RootView = require 'root-view'
EditSession = require 'edit-session'
Buffer = require 'buffer'
Editor = require 'editor'
Range = require 'range'
@@ -9,11 +10,11 @@ _ = require 'underscore'
fs = require 'fs'
describe "Editor", ->
[rootView, buffer, editor, cachedLineHeight] = []
[rootView, project, buffer, editor, cachedLineHeight] = []
getLineHeight = ->
return cachedLineHeight if cachedLineHeight?
editorForMeasurement = new Editor()
editorForMeasurement = new Editor(editSession: rootView.project.open('sample.js'))
editorForMeasurement.attachToDom()
cachedLineHeight = editorForMeasurement.lineHeight
editorForMeasurement.remove()
@@ -21,7 +22,6 @@ describe "Editor", ->
beforeEach ->
rootView = new RootView(require.resolve('fixtures/sample.js'))
project = rootView.project
editor = rootView.activeEditor()
buffer = editor.buffer
@@ -31,7 +31,7 @@ describe "Editor", ->
$('#jasmine-content').append(this)
editor.lineOverdraw = 2
editor.setAutoIndent(false)
rootView.project.setAutoIndent(false)
editor.enableKeymap()
editor.isFocused = true
@@ -39,13 +39,8 @@ describe "Editor", ->
editor.remove()
describe "construction", ->
it "assigns an empty buffer and correctly handles text input (regression coverage)", ->
editor = new Editor
editor.attachToDom()
expect(editor.buffer.getPath()).toBeUndefined()
expect(editor.renderedLines.find('.line').length).toBe 1
editor.insertText('x')
expect(editor.renderedLines.find('.line').length).toBe 1
it "throws an error if no editor session is given", ->
expect(-> new Editor).toThrow()
describe ".copy()", ->
it "builds a new editor with the same edit sessions, cursor position, and scroll position as the receiver", ->
@@ -66,6 +61,7 @@ describe "Editor", ->
expect(editor.serialize).toHaveBeenCalled()
expect(Editor.deserialize).toHaveBeenCalled()
expect(newEditor.buffer).toBe editor.buffer
expect(newEditor.getCursorScreenPosition()).toEqual editor.getCursorScreenPosition()
expect(newEditor.editSessions[0]).toEqual(editor.editSessions[0])
@@ -96,16 +92,15 @@ describe "Editor", ->
expect(editor).toMatchSelector ":has(:focus)"
it "unsubscribes from the buffer when it is removed from the dom", ->
buffer = new Buffer
previousSubscriptionCount = buffer.subscriptionCount()
editSession = rootView.project.open('sample.txt')
previousSubscriptionCount = editSession.buffer.subscriptionCount()
editor.attachToDom()
editor.setBuffer(buffer)
editor.edit(editSession)
expect(buffer.subscriptionCount()).toBeGreaterThan previousSubscriptionCount
expect(editSession.buffer.subscriptionCount()).toBeGreaterThan previousSubscriptionCount
expect($('.editor')).toExist()
editor.remove()
expect(buffer.subscriptionCount()).toBe previousSubscriptionCount
expect(editSession.buffer.subscriptionCount()).toBeLessThan previousSubscriptionCount
expect($('.editor')).not.toExist()
describe "when the editor recieves focus", ->
@@ -129,19 +124,20 @@ describe "Editor", ->
describe ".remove()", ->
it "removes subscriptions from all edit session buffers", ->
otherBuffer = new Buffer(require.resolve('fixtures/sample.txt'))
expect(buffer.subscriptionCount()).toBeGreaterThan 1
previousEditSession = editor.activeEditSession
otherEditSession = rootView.project.open('sample.txt')
expect(previousEditSession.buffer.subscriptionCount()).toBeGreaterThan 1
editor.setBuffer(otherBuffer)
expect(otherBuffer.subscriptionCount()).toBeGreaterThan 1
editor.edit(otherEditSession)
expect(otherEditSession.buffer.subscriptionCount()).toBeGreaterThan 1
editor.remove()
expect(buffer.subscriptionCount()).toBe 1
expect(otherBuffer.subscriptionCount()).toBe 1
expect(previousEditSession.buffer.subscriptionCount()).toBe 1
expect(otherEditSession.buffer.subscriptionCount()).toBe 1
describe "when 'close' is triggered", ->
it "closes active edit session and loads next edit session", ->
editor.setBuffer(new Buffer())
editor.edit(rootView.project.open())
spyOn(editor, "remove")
editor.trigger "close"
expect(editor.remove).not.toHaveBeenCalled()
@@ -170,62 +166,62 @@ describe "Editor", ->
expect(editor.remove).not.toHaveBeenCalled()
expect($native.alert).toHaveBeenCalled()
describe ".setBuffer(buffer)", ->
otherBuffer = null
describe ".edit(editSession)", ->
otherEditSession = null
beforeEach ->
otherBuffer = new Buffer
otherEditSession = rootView.project.open()
describe "when the buffer wasn't previously assigned to this editor", ->
it "creates a new EditSession for it", ->
editor.setBuffer(otherBuffer)
expect(editor.activeEditSession.buffer).toBe otherBuffer
describe "when the edit session wasn't previously assigned to this editor", ->
it "adds edit session to editor", ->
originalEditSessionCount = editor.editSessions.length
editor.edit(otherEditSession)
expect(editor.activeEditSession).toBe otherEditSession
expect(editor.editSessions.length).toBe originalEditSessionCount + 1
describe "when the buffer was previously assigned to this editor", ->
it "restores the previous edit session associated with the buffer", ->
describe "when the edit session was previously assigned to this editor", ->
it "restores the previous edit session associated with the editor", ->
previousEditSession = editor.activeEditSession
editor.setBuffer(otherBuffer)
editor.edit(otherEditSession)
expect(editor.activeEditSession).not.toBe previousEditSession
editor.setBuffer(buffer)
editor.edit(previousEditSession)
expect(editor.activeEditSession).toBe previousEditSession
it "unsubscribes from the previously assigned buffer", ->
editor.setBuffer(otherBuffer)
previousEditSession = editor.activeEditSession
previousSubscriptionCount = previousEditSession.buffer.subscriptionCount()
editor.edit(otherEditSession)
expect(previousEditSession.buffer.subscriptionCount()).toBe previousSubscriptionCount - 1
previousSubscriptionCount = buffer.subscriptionCount()
editor.edit(previousEditSession)
expect(previousEditSession.buffer.subscriptionCount()).toBe previousSubscriptionCount
editor.setBuffer(buffer)
editor.setBuffer(otherBuffer)
editor.edit(otherEditSession)
expect(previousEditSession.buffer.subscriptionCount()).toBe previousSubscriptionCount - 1
expect(buffer.subscriptionCount()).toBe previousSubscriptionCount
it "handles buffer manipulation correctly after switching to a new buffer", ->
it "handles buffer manipulation correctly after switching to a new edit session", ->
editor.attachToDom()
editor.insertText("abc\n")
expect(editor.lineElementForScreenRow(0).text()).toBe 'abc'
editor.setBuffer(otherBuffer)
editor.edit(otherEditSession)
expect(editor.lineElementForScreenRow(0).html()).toBe ' '
editor.insertText("def\n")
expect(editor.lineElementForScreenRow(0).text()).toBe 'def'
describe "switching edit sessions", ->
[buffer0, buffer1, buffer2] = []
[session0, session1, session2] = []
beforeEach ->
buffer0 = buffer
session0 = editor.activeEditSession
buffer1 = new Buffer(require.resolve('fixtures/sample.txt'))
editor.setBuffer(buffer1)
editor.edit(rootView.project.open('sample.txt'))
session1 = editor.activeEditSession
buffer2 = new Buffer(require.resolve('fixtures/two-hundred.txt'))
editor.setBuffer(buffer2)
editor.edit(rootView.project.open('two-hundred.txt'))
session2 = editor.activeEditSession
describe ".setActiveEditSessionIndex(index)", ->
@@ -238,10 +234,10 @@ describe "Editor", ->
expect(editor.scrollTop()).toBe 750
editor.setActiveEditSessionIndex(0)
expect(editor.buffer).toBe buffer0
expect(editor.buffer).toBe session0.buffer
editor.setActiveEditSessionIndex(2)
expect(editor.buffer).toBe buffer2
expect(editor.buffer).toBe session2.buffer
expect(editor.getCursorScreenPosition()).toEqual [43, 1]
expect(editor.verticalScrollbar.prop('scrollHeight')).toBe previousScrollHeight
expect(editor.scrollTop()).toBe 750
@@ -278,7 +274,10 @@ describe "Editor", ->
beforeEach ->
tempFilePath = '/tmp/atom-temp.txt'
editor.setBuffer new Buffer(tempFilePath)
rootView = new RootView(tempFilePath)
project = rootView.project
editor.edit(rootView.project.open(tempFilePath))
expect(editor.buffer.getPath()).toBe tempFilePath
afterEach ->
@@ -296,7 +295,8 @@ describe "Editor", ->
describe "when the current buffer has no path", ->
selectedFilePath = null
beforeEach ->
editor.setBuffer new Buffer()
editor.edit(rootView.project.open())
expect(editor.buffer.getPath()).toBeUndefined()
editor.buffer.setText 'Save me to a new path'
spyOn($native, 'saveDialog').andCallFake -> selectedFilePath
@@ -412,7 +412,7 @@ describe "Editor", ->
it "emits event when editor receives a new buffer", ->
eventHandler = jasmine.createSpy('eventHandler')
editor.on 'editor-path-change', eventHandler
editor.setBuffer(new Buffer("something.txt"))
editor.edit(rootView.project.open("something.txt"))
expect(eventHandler).toHaveBeenCalled()
it "stops listening to events on previously set buffers", ->
@@ -420,7 +420,7 @@ describe "Editor", ->
oldBuffer = editor.buffer
editor.on 'editor-path-change', eventHandler
editor.setBuffer(new Buffer("something.txt"))
editor.edit(rootView.project.open("something.txt"))
expect(eventHandler).toHaveBeenCalled()
eventHandler.reset()
@@ -1023,11 +1023,11 @@ describe "Editor", ->
expect(editor.renderedLines.find('.line:eq(5)').text()).toBe " while(items.length > 0) {"
expect(editor.bufferPositionForScreenPosition(editor.getCursorScreenPosition())).toEqual [3, 60]
it "wraps the lines of any newly assigned buffers", ->
otherBuffer = new Buffer
otherBuffer.setText([1..100].join(''))
editor.setBuffer(otherBuffer)
expect(editor.renderedLines.find('.line').length).toBeGreaterThan(1)
it "does not wrap the lines of any newly assigned buffers", ->
otherEditSession = rootView.project.open()
otherEditSession.buffer.setText([1..100].join(''))
editor.edit(otherEditSession)
expect(editor.renderedLines.find('.line').length).toBe(1)
it "unwraps lines and cancels window resize listener when softwrap is disabled", ->
editor.toggleSoftWrap()
@@ -1060,7 +1060,7 @@ describe "Editor", ->
expect(editor.getCursorScreenPosition()).toEqual [11, 0]
it "calls .setSoftWrapColumn() when the editor is attached because now its dimensions are available to calculate it", ->
otherEditor = new Editor()
otherEditor = new Editor(editSession: rootView.project.open('sample.js'))
spyOn(otherEditor, 'setSoftWrapColumn')
otherEditor.setSoftWrap(true)
@@ -1320,8 +1320,9 @@ describe "Editor", ->
describe "when autoscrolling at the end of the document", ->
it "renders lines properly", ->
editor.setBuffer(new Buffer(require.resolve 'fixtures/two-hundred.txt'))
editor.edit(rootView.project.open('two-hundred.txt'))
editor.attachToDom(heightInLines: 5.5)
expect(editor.renderedLines.find('.line').length).toBe 8
editor.moveCursorToBottom()
@@ -1485,7 +1486,9 @@ describe "Editor", ->
describe "folding", ->
beforeEach ->
editor.setBuffer(new Buffer(require.resolve('fixtures/two-hundred.txt')))
editSession = rootView.project.open('two-hundred.txt')
buffer = editSession.buffer
editor.edit(editSession)
editor.attachToDom()
describe "when a fold-selection event is triggered", ->

View File

@@ -14,30 +14,30 @@ describe "Project", ->
project.on 'new-buffer', newBufferHandler
describe "when given an absolute path that hasn't been opened previously", ->
it "returns a new buffer for the given path and emits a 'new-buffer' event", ->
buffer = project.open(absolutePath)
expect(buffer.path).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith buffer
it "returns a new edit session for the given path and emits a 'new-buffer' event", ->
editSession = project.open(absolutePath)
expect(editSession.buffer.path).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer
describe "when given a relative path that hasn't been opened previously", ->
it "returns a buffer for the given path (relative to the project root) and emits a 'new-buffer' event", ->
buffer = project.open('a')
expect(buffer.path).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith buffer
it "returns a new edit session for the given path (relative to the project root) and emits a 'new-buffer' event", ->
editSession = project.open('a')
expect(editSession.buffer.path).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer
describe "when passed the path to a buffer that has already been opened", ->
it "returns the previously opened buffer", ->
buffer = project.open(absolutePath)
it "returns a new edit session containing previously opened buffer", ->
editSession = project.open(absolutePath)
newBufferHandler.reset()
expect(project.open(absolutePath)).toBe buffer
expect(project.open('a')).toBe buffer
expect(project.open(absolutePath).buffer).toBe editSession.buffer
expect(project.open('a').buffer).toBe editSession.buffer
expect(newBufferHandler).not.toHaveBeenCalled()
describe "when not passed a path", ->
it "returns a new buffer and emits a new-buffer event", ->
buffer = project.open()
expect(buffer.path).toBeUndefined()
expect(newBufferHandler).toHaveBeenCalledWith(buffer)
it "returns a new edit session and emits a new-buffer event", ->
editSession = project.open()
expect(editSession.buffer.getPath()).toBeUndefined()
expect(newBufferHandler).toHaveBeenCalledWith(editSession.buffer)
describe ".resolve(path)", ->
it "returns an absolute path based on the project's root", ->

View File

@@ -7,7 +7,6 @@ Editor = require 'editor'
describe "RootView", ->
rootView = null
project = null
path = null
beforeEach ->
@@ -15,7 +14,6 @@ describe "RootView", ->
rootView = new RootView(path)
rootView.enableKeymap()
rootView.focus()
project = rootView.project
describe "initialize(pathToOpen)", ->
describe "when called with a pathToOpen", ->
@@ -61,14 +59,18 @@ describe "RootView", ->
describe "when the serialized RootView has a project", ->
beforeEach ->
path = require.resolve 'fixtures'
rootView = new RootView(path)
rootView.open('dir/a')
editor1 = rootView.activeEditor()
editor2 = editor1.splitRight()
editor3 = editor2.splitRight()
editor4 = editor2.splitDown()
editor2.setBuffer(new Buffer(require.resolve 'fixtures/dir/b'))
editor3.setBuffer(new Buffer(require.resolve 'fixtures/sample.js'))
editor2.edit(rootView.project.open('dir/b'))
editor3.edit(rootView.project.open('sample.js'))
editor3.setCursorScreenPosition([2, 3])
editor4.setBuffer(new Buffer(require.resolve 'fixtures/sample.txt'))
editor4.edit(rootView.project.open('sample.txt'))
editor4.setCursorScreenPosition([0, 2])
rootView.attachToDom()
editor2.focus()
@@ -440,14 +442,14 @@ describe "RootView", ->
expect(document.title).toBe path
editor2 = rootView.activeEditor().splitLeft()
editor2.setBuffer(new Buffer("second.txt"))
editor2.edit(rootView.project.open("second.txt"))
expect(pathChangeHandler).toHaveBeenCalled()
expect(document.title).toBe "second.txt"
expect(document.title).toBe rootView.project.resolve("second.txt")
pathChangeHandler.reset()
editor1.buffer.setPath("should-not-be-title.txt")
expect(pathChangeHandler).not.toHaveBeenCalled()
expect(document.title).toBe "second.txt"
expect(document.title).toBe rootView.project.resolve("second.txt")
it "creates a project if there isn't one yet and the buffer was previously unsaved", ->
rootView = new RootView
@@ -475,7 +477,7 @@ describe "RootView", ->
rootView.focus()
expect(pathChangeHandler).not.toHaveBeenCalled()
editor2.setBuffer editor1.buffer
editor2.edit(editor1.activeEditSession)
editor2.focus()
expect(pathChangeHandler).not.toHaveBeenCalled()

View File

@@ -10,8 +10,7 @@ describe "Autocomplete", ->
miniEditor = null
beforeEach ->
editor = new Editor()
editor.setBuffer new Buffer(require.resolve('fixtures/sample.js'))
editor = new Editor(editSession: fixturesProject.open('sample.js'))
autocomplete = new Autocomplete(editor)
miniEditor = autocomplete.miniEditor
@@ -346,13 +345,13 @@ describe "Autocomplete", ->
autocomplete.attach()
expect(autocomplete.buildWordList).not.toHaveBeenCalled()
describe "when a new buffer is assigned on editor", ->
describe "when a new edit session is assigned on editor", ->
it 'creates and uses a new word list based on new buffer', ->
wordList = autocomplete.wordList
expect(wordList).toContain "quicksort"
expect(wordList).not.toContain "Some"
editor.setBuffer new Buffer(require.resolve('fixtures/sample.txt'))
editor.edit(fixturesProject.open('sample.txt'))
wordList = autocomplete.wordList
expect(wordList).not.toContain "quicksort"
@@ -360,7 +359,7 @@ describe "Autocomplete", ->
it 'stops listening to previous buffers change events', ->
previousBuffer = editor.buffer
editor.setBuffer new Buffer(require.resolve('fixtures/sample.txt'))
editor.edit(fixturesProject.open('sample.txt'))
spyOn(autocomplete, "buildWordList")
previousBuffer.change([[0,0],[0,1]], "sauron")

View File

@@ -1,13 +1,15 @@
CommandInterpreter = require 'command-interpreter'
Buffer = require 'buffer'
EditSession = require 'edit-session'
Editor = require 'editor'
describe "CommandInterpreter", ->
[interpreter, editor, buffer] = []
beforeEach ->
buffer = new Buffer(require.resolve 'fixtures/sample.js')
editor = new Editor({buffer})
editSession = fixturesProject.open('sample.js')
buffer = editSession.buffer
editor = new Editor(editSession: editSession)
interpreter = new CommandInterpreter()
describe "addresses", ->

View File

@@ -3,6 +3,7 @@ $ = require 'jquery'
_ = require 'underscore'
Keymap = require 'keymap'
Point = require 'point'
Project = require 'project'
Directory = require 'directory'
RootView = require 'root-view'
require 'window'
@@ -14,6 +15,7 @@ defaultTitle = document.title
directoriesWithSubscriptions = null
beforeEach ->
window.fixturesProject = new Project(require.resolve('fixtures'))
window.resetTimeouts()
directoriesWithSubscriptions = []

View File

@@ -12,9 +12,6 @@ class Buffer
lines: null
path: null
@deserialize: (state, project) ->
project.open(state.path)
constructor: (path) ->
@id = @constructor.idCounter++
@setPath(path)
@@ -26,9 +23,6 @@ class Buffer
@undoManager = new UndoManager(this)
@modified = false
serialize: ->
path: @getPath()
getPath: ->
@path

View File

@@ -11,13 +11,7 @@ class EditSession
@idCounter: 1
@deserialize: (state, editor, rootView) ->
buffer = Buffer.deserialize(state.buffer, rootView.project)
session = new EditSession(
buffer: buffer
tabText: editor.tabText
autoIndent: editor.autoIndent
softTabs: editor.softTabs
)
session = rootView.project.open(state.buffer)
session.setScrollTop(state.scrollTop)
session.setScrollLeft(state.scrollLeft)
session.setCursorScreenPosition(state.cursorScreenPosition)
@@ -30,11 +24,12 @@ class EditSession
selections: null
autoIndent: true
softTabs: true
softWrap: false
constructor: ({@buffer, @tabText, @autoIndent, @softTabs, @softWrapColumn}) ->
constructor: ({@buffer, @tabText, @autoIndent, @softTabs, @softWrap}) ->
@id = @constructor.idCounter++
@softTabs ?= true
@displayBuffer = new DisplayBuffer(@buffer, { @softWrapColumn, @tabText })
@displayBuffer = new DisplayBuffer(@buffer, { @tabText })
@tokenizedBuffer = @displayBuffer.tokenizedBuffer
@cursors = []
@selections = []
@@ -54,7 +49,7 @@ class EditSession
@displayBuffer.destroy()
serialize: ->
buffer: @buffer.serialize()
buffer: @buffer.getPath()
scrollTop: @getScrollTop()
scrollLeft: @getScrollLeft()
cursorScreenPosition: @getCursorScreenPosition().serialize()
@@ -76,6 +71,9 @@ class EditSession
setAutoIndent: (@autoIndent) ->
setSoftTabs: (@softTabs) ->
getSoftWrap: -> @softWrap
setSoftWrap: (@softWrap) ->
clipBufferPosition: (bufferPosition, options) ->
{ row, column } = Point.fromObject(bufferPosition)
row = 0 if row < 0
@@ -446,4 +444,7 @@ class EditSession
@mergeIntersectingSelections(options)
return
inspect: ->
JSON.stringify @serialize()
_.extend(EditSession.prototype, EventEmitter)

View File

@@ -33,30 +33,29 @@ class Editor extends View
vScrollMargin: 2
hScrollMargin: 10
softWrap: false
lineHeight: null
charWidth: null
charHeight: null
cursorViews: null
selectionViews: null
buffer: null
autoIndent: true
lineCache: null
isFocused: false
softTabs: true
tabText: ' '
activeEditSession: null
editSessions: null
attached: false
lineOverdraw: 100
@deserialize: (state, rootView) ->
editor = new Editor(suppressBufferCreation: true, mini: state.mini)
editor.editSessions = state.editSessions.map (state) -> EditSession.deserialize(state, editor, rootView)
editor.setActiveEditSessionIndex(state.activeEditSessionIndex)
editSessions = state.editSessions.map (state) -> EditSession.deserialize(state, editor, rootView)
editSession = editSessions[state.activeEditSessionIndex]
editor = new Editor(editSession: editSession, mini: state.mini)
editor.editSession = editSessions
editor.isFocused = state.isFocused
editor
initialize: ({buffer, suppressBufferCreation, @mini} = {}) ->
initialize: ({editSession, @mini} = {}) ->
requireStylesheet 'editor.css'
requireStylesheet 'theme/twilight.css'
@@ -68,15 +67,29 @@ class Editor extends View
@selectionViews = []
@editSessions = []
if buffer?
@setBuffer(buffer)
else if !suppressBufferCreation
@setBuffer(new Buffer)
if editSession?
@editSessions.push editSession
@setActiveEditSessionIndex(0)
else if @mini
editSession = new EditSession
buffer: new Buffer()
softWrap: false
tabText: " "
autoIndent: false
softTabs: true
@editSessions.push editSession
@setActiveEditSessionIndex(0)
else
throw new Error("Editor initialization requires an editSession")
serialize: ->
@saveActiveEditSession()
editSessions = @editSessions.map (session) -> session.serialize()
{ viewClass: "Editor", editSessions, @activeEditSessionIndex, @isFocused }
viewClass: "Editor"
editSessions: @editSessions.map (session) -> session.serialize()
activeEditSessionIndex: @getActiveEditSessionIndex()
isFocused: @isFocused
copy: ->
Editor.deserialize(@serialize(), @rootView())
@@ -216,15 +229,13 @@ class Editor extends View
isFoldedAtScreenRow: (screenRow) -> @activeEditSession.isFoldedAtScreenRow(screenRow)
unfoldCurrentRow: -> @activeEditSession.unfoldCurrentRow()
setAutoIndent: (@autoIndent) -> @activeEditSession.setAutoIndent(@autoIndent)
setSoftTabs: (@softTabs) -> @activeEditSession.setSoftTabs(@softTabs)
lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow)
linesForScreenRows: (start, end) -> @activeEditSession.linesForScreenRows(start, end)
screenLineCount: -> @activeEditSession.screenLineCount()
setSoftWrapColumn: (softWrapColumn) ->
softWrapColumn ?= @calcSoftWrapColumn()
@activeEditSession.setSoftWrapColumn(softWrapColumn) if softWrapColumn
lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow)
linesForScreenRows: (start, end) -> @activeEditSession.linesForScreenRows(start, end)
screenLineCount: -> @activeEditSession.screenLineCount()
maxScreenLineLength: -> @activeEditSession.maxScreenLineLength()
getLastScreenRow: -> @activeEditSession.getLastScreenRow()
clipScreenPosition: (screenPosition, options={}) -> @activeEditSession.clipScreenPosition(screenPosition, options)
@@ -325,7 +336,7 @@ class Editor extends View
@subscribeToFontSize()
@calculateDimensions()
@hiddenInput.width(@charWidth)
@setSoftWrapColumn() if @softWrap
@setSoftWrapColumn() if @activeEditSession.getSoftWrap()
$(window).on "resize.editor#{@id}", => @updateRenderedLines()
@focus() if @isFocused
@@ -333,28 +344,15 @@ class Editor extends View
@trigger 'editor-open', [this]
setBuffer: (buffer) ->
@activateEditSessionForBuffer(buffer)
edit: (editSession) ->
index = @editSessions.indexOf(editSession)
activateEditSessionForBuffer: (buffer) ->
index = @editSessionIndexForBuffer(buffer)
unless index?
if index == -1
index = @editSessions.length
@editSessions.push(new EditSession(
softWrapColumn: @calcSoftWrapColumn()
buffer: buffer
tabText: @tabText
autoIndent: @autoIndent
softTabs: @softTabs
))
@editSessions.push(editSession)
@setActiveEditSessionIndex(index)
editSessionIndexForBuffer: (buffer) ->
for editSession, index in @editSessions
return index if editSession.buffer == buffer
null
removeActiveEditSession: ->
if @editSessions.length == 1
@remove()
@@ -364,14 +362,17 @@ class Editor extends View
_.remove(@editSessions, editSession)
loadNextEditSession: ->
nextIndex = (@activeEditSessionIndex + 1) % @editSessions.length
nextIndex = (@getActiveEditSessionIndex() + 1) % @editSessions.length
@setActiveEditSessionIndex(nextIndex)
loadPreviousEditSession: ->
previousIndex = @activeEditSessionIndex - 1
previousIndex = @getActiveEditSessionIndex() - 1
previousIndex = @editSessions.length - 1 if previousIndex < 0
@setActiveEditSessionIndex(previousIndex)
getActiveEditSessionIndex: ->
return index for session, index in @editSessions when session == @activeEditSession
setActiveEditSessionIndex: (index) ->
throw new Error("Edit session not found") unless @editSessions[index]
@@ -380,11 +381,11 @@ class Editor extends View
@activeEditSession.off()
@activeEditSession = @editSessions[index]
@activeEditSessionIndex = index
@unsubscribeFromBuffer() if @buffer
@buffer = @activeEditSession.buffer
@buffer.on "path-change.editor#{@id}", => @trigger 'editor-path-change'
@trigger 'editor-path-change'
@renderWhenAttached()
@@ -434,7 +435,7 @@ class Editor extends View
@scrollTop(desiredTop)
scrollHorizontally: (pixelPosition) ->
return if @softWrap
return if @activeEditSession.getSoftWrap()
charsInView = @scrollView.width() / @charWidth
maxScrollMargin = Math.floor((charsInView - 1) / 2)
@@ -469,17 +470,18 @@ class Editor extends View
@activeEditSession.setScrollLeft(@scrollView.scrollLeft())
toggleSoftWrap: ->
@setSoftWrap(not @softWrap)
@setSoftWrap(not @activeEditSession.getSoftWrap())
calcSoftWrapColumn: ->
if @softWrap
if @activeEditSession.getSoftWrap()
Math.floor(@scrollView.width() / @charWidth)
else
Infinity
setSoftWrap: (@softWrap, softWrapColumn=undefined) ->
setSoftWrap: (softWrap, softWrapColumn=undefined) ->
@activeEditSession.setSoftWrap(softWrap)
@setSoftWrapColumn(softWrapColumn) if @attached
if @softWrap
if @activeEditSession.getSoftWrap()
@addClass 'soft-wrap'
@_setSoftWrapColumn = => @setSoftWrapColumn()
$(window).on 'resize', @_setSoftWrapColumn

View File

@@ -3,17 +3,25 @@ _ = require 'underscore'
$ = require 'jquery'
Buffer = require 'buffer'
EditSession = require 'edit-session'
EventEmitter = require 'event-emitter'
Directory = require 'directory'
module.exports =
class Project
rootDirectory: null
buffers: null
editSessions: null
tabText: null
autoIndent: null
softTabs: null
softWrap: null
constructor: (path) ->
@setPath(path)
@buffers = []
@editSessions = []
@setTabText(' ')
@setAutoIndent(true)
@setSoftTabs(true)
getPath: ->
@rootDirectory?.path
@@ -48,19 +56,6 @@ class Project
ignorePath: (path) ->
fs.base(path).match(/\.DS_Store/) or path.match(/(^|\/)\.git(\/|$)/)
open: (filePath) ->
if filePath?
filePath = @resolve(filePath)
@bufferWithPath(filePath) ? @buildBuffer(filePath)
else
@buildBuffer()
buildBuffer: (filePath) ->
buffer = new Buffer(filePath)
@buffers.push(buffer)
@trigger 'new-buffer', buffer
buffer
resolve: (filePath) ->
filePath = fs.join(@getPath(), filePath) unless filePath[0] == '/'
fs.absolute filePath
@@ -68,10 +63,48 @@ class Project
relativize: (fullPath) ->
fullPath.replace(@getPath(), "").replace(/^\//, '')
bufferWithId: (id) ->
return buffer for buffer in @buffers when buffer.id == id
getTabText: -> @tabText
setTabText: (@tabText) ->
getAutoIndent: -> @autoIndent
setAutoIndent: (@autoIndent) ->
getSoftTabs: -> @softTabs
setSoftTabs: (@softTabs) ->
getSoftWrap: -> @softWrap
setSoftWrap: (@softWrap) ->
open: (filePath) ->
if filePath?
filePath = @resolve(filePath)
buffer = @bufferWithPath(filePath) ? @buildBuffer(filePath)
else
buffer = @buildBuffer()
editSession = new EditSession
buffer: buffer
tabText: @getTabText()
autoIndent: @getAutoIndent()
softTabs: @getSoftTabs()
softWrap: @getSoftWrap()
@editSessions.push editSession
editSession
buildBuffer: (filePath) ->
buffer = new Buffer(filePath)
@trigger 'new-buffer', buffer
buffer
getBuffers: ->
buffers = []
for editSession in @editSessions when not _.include(buffers, editSession.buffer)
buffers.push editSession.buffer
buffers
bufferWithPath: (path) ->
return buffer for buffer in @buffers when buffer.path == path
return editSession.buffer for editSession in @editSessions when editSession.buffer.getPath() == path
_.extend Project.prototype, EventEmitter

View File

@@ -92,12 +92,12 @@ class RootView extends View
@remove()
open: (path, changeFocus=true) ->
buffer = @project.open(path)
editSession = @project.open(path)
if @activeEditor()
@activeEditor().setBuffer(buffer)
@activeEditor().edit(editSession)
else
editor = new Editor({ buffer })
editor = new Editor(editSession: editSession)
pane = new Pane(editor)
@panes.append(pane)
if changeFocus

View File

@@ -1,6 +1,6 @@
module.exports =
activate: (rootView) ->
for buffer in rootView.project.buffers
for buffer in rootView.project.getBuffers()
@stripTrailingWhitespaceBeforeSave(buffer)
rootView.project.on 'new-buffer', (buffer) =>