diff --git a/spec/app/buffer-spec.coffee b/spec/app/buffer-spec.coffee index 676c90218..78b15ce55 100644 --- a/spec/app/buffer-spec.coffee +++ b/spec/app/buffer-spec.coffee @@ -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 diff --git a/spec/app/edit-session-spec.coffee b/spec/app/edit-session-spec.coffee index 557522cd6..5031eb9ba 100644 --- a/spec/app/edit-session-spec.coffee +++ b/spec/app/edit-session-spec.coffee @@ -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", -> diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index c629626c7..2128ec600 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -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", -> diff --git a/spec/app/project-spec.coffee b/spec/app/project-spec.coffee index 131f814f3..2cab3e5a1 100644 --- a/spec/app/project-spec.coffee +++ b/spec/app/project-spec.coffee @@ -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", -> diff --git a/spec/app/root-view-spec.coffee b/spec/app/root-view-spec.coffee index 1503e0879..eef34f027 100644 --- a/spec/app/root-view-spec.coffee +++ b/spec/app/root-view-spec.coffee @@ -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() diff --git a/spec/extensions/autocomplete-spec.coffee b/spec/extensions/autocomplete-spec.coffee index 56d835d44..6b70d24a9 100644 --- a/spec/extensions/autocomplete-spec.coffee +++ b/spec/extensions/autocomplete-spec.coffee @@ -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") diff --git a/spec/extensions/command-interpreter-spec.coffee b/spec/extensions/command-interpreter-spec.coffee index e68795ebe..cc9d4e731 100644 --- a/spec/extensions/command-interpreter-spec.coffee +++ b/spec/extensions/command-interpreter-spec.coffee @@ -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", -> diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index c8dc5d733..ad69ea9ad 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -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 = [] diff --git a/src/app/buffer.coffee b/src/app/buffer.coffee index 7fbf8792f..d35168063 100644 --- a/src/app/buffer.coffee +++ b/src/app/buffer.coffee @@ -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 diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index 7d71304a0..c38227b80 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -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) diff --git a/src/app/editor.coffee b/src/app/editor.coffee index ff6cf7abf..9c16bd265 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -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 diff --git a/src/app/project.coffee b/src/app/project.coffee index 673e3b704..1e66e163c 100644 --- a/src/app/project.coffee +++ b/src/app/project.coffee @@ -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 diff --git a/src/app/root-view.coffee b/src/app/root-view.coffee index eadf7bc7a..2799eb10b 100644 --- a/src/app/root-view.coffee +++ b/src/app/root-view.coffee @@ -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 diff --git a/src/extensions/strip-trailing-whitespace.coffee b/src/extensions/strip-trailing-whitespace.coffee index 86db0c10b..ebf482741 100644 --- a/src/extensions/strip-trailing-whitespace.coffee +++ b/src/extensions/strip-trailing-whitespace.coffee @@ -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) =>