From aaa82e23dac586114a727317f41d4bd54fd89e42 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 14:34:20 -0800 Subject: [PATCH 01/15] Rename Editor to TextEditorView --- exports/atom.coffee | 3 ++- spec/editor-spec.coffee | 26 +++++++++---------- spec/spec-helper.coffee | 6 ++--- src/edit-session.coffee | 2 +- src/gutter.coffee | 6 ++--- src/pane.coffee | 2 +- src/root-view.coffee | 8 +++--- src/select-list.coffee | 4 +-- src/text-buffer.coffee | 2 +- ...{editor.coffee => text-editor-view.coffee} | 22 ++++++++-------- src/window.coffee | 2 +- 11 files changed, 42 insertions(+), 41 deletions(-) rename src/{editor.coffee => text-editor-view.coffee} (98%) diff --git a/exports/atom.coffee b/exports/atom.coffee index b68144665..049d3d9f1 100644 --- a/exports/atom.coffee +++ b/exports/atom.coffee @@ -20,7 +20,8 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE module.exports.$ = $ module.exports.$$ = $$ module.exports.$$$ = $$$ - module.exports.Editor = require '../src/editor' + module.exports.Editor = require '../src/text-editor-view' + module.exports.pathForRepositoryUrl = require('../src/project').pathForRepositoryUrl module.exports.RootView = require '../src/root-view' module.exports.SelectList = require '../src/select-list' module.exports.ScrollView = require '../src/scroll-view' diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index e2c8f5817..1d34730aa 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1,8 +1,8 @@ -{_, $, $$, fs, Editor, Range, RootView} = require 'atom' +{_, $, $$, fs, TextEditorView, Range, RootView} = require 'atom' path = require 'path' temp = require 'temp' -describe "Editor", -> +describe "TextEditorView", -> [buffer, editor, editSession, cachedLineHeight, cachedCharWidth] = [] beforeEach -> @@ -10,7 +10,7 @@ describe "Editor", -> atom.activatePackage('language-javascript', sync: true) editSession = project.openSync('sample.js') buffer = editSession.buffer - editor = new Editor(editSession) + editor = new TextEditorView(editSession) editor.lineOverdraw = 2 editor.isFocused = true editor.enableKeymap() @@ -33,7 +33,7 @@ describe "Editor", -> cachedCharWidth calcDimensions = -> - editorForMeasurement = new Editor(editSession: project.openSync('sample.js')) + editorForMeasurement = new TextEditorView(editSession: project.openSync('sample.js')) editorForMeasurement.attachToDom() cachedLineHeight = editorForMeasurement.lineHeight cachedCharWidth = editorForMeasurement.charWidth @@ -41,7 +41,7 @@ describe "Editor", -> describe "construction", -> it "throws an error if no edit session is given", -> - expect(-> new Editor).toThrow() + expect(-> new TextEditorView).toThrow() describe "when the editor is attached to the dom", -> it "calculates line height and char width and updates the pixel position of the cursor", -> @@ -325,7 +325,7 @@ describe "Editor", -> expect(editor.charWidth).not.toBe charWidthBefore expect(editor.getCursorView().position()).toEqual { top: 5 * editor.lineHeight, left: 6 * editor.charWidth } - newEditor = new Editor(editor.activeEditSession.copy()) + newEditor = new TextEditorView(editor.activeEditSession.copy()) newEditor.attachToDom() expect(newEditor.css('font-family')).toBe fontFamily @@ -353,7 +353,7 @@ describe "Editor", -> expect(editor.renderedLines.outerHeight()).toBe buffer.getLineCount() * editor.lineHeight expect(editor.verticalScrollbarContent.height()).toBe buffer.getLineCount() * editor.lineHeight - newEditor = new Editor(editor.activeEditSession.copy()) + newEditor = new TextEditorView(editor.activeEditSession.copy()) editor.remove() newEditor.attachToDom() expect(newEditor.css('font-size')).toBe '30px' @@ -1764,7 +1764,7 @@ describe "Editor", -> expect(editor.getCursorScreenPosition()).toEqual [11, 0] it "calls .setWidthInChars() when the editor is attached because now its dimensions are available to calculate it", -> - otherEditor = new Editor(editSession: project.openSync('sample.js')) + otherEditor = new TextEditorView(editSession: project.openSync('sample.js')) spyOn(otherEditor, 'setWidthInChars') otherEditor.activeEditSession.setSoftWrap(true) @@ -1902,19 +1902,19 @@ describe "Editor", -> describe "when the editor is mini", -> it "hides the gutter", -> - miniEditor = new Editor(mini: true) + miniEditor = new TextEditorView(mini: true) miniEditor.attachToDom() expect(miniEditor.gutter).toBeHidden() it "doesn't highlight the only line", -> - miniEditor = new Editor(mini: true) + miniEditor = new TextEditorView(mini: true) miniEditor.attachToDom() expect(miniEditor.getCursorBufferPosition().row).toBe 0 expect(miniEditor.find('.line.cursor-line').length).toBe 0 it "doesn't show the end of line invisible", -> atom.config.set "editor.showInvisibles", true - miniEditor = new Editor(mini: true) + miniEditor = new TextEditorView(mini: true) miniEditor.attachToDom() space = miniEditor.invisibles?.space expect(space).toBeTruthy() @@ -1925,14 +1925,14 @@ describe "Editor", -> it "doesn't show the indent guide", -> atom.config.set "editor.showIndentGuide", true - miniEditor = new Editor(mini: true) + miniEditor = new TextEditorView(mini: true) miniEditor.attachToDom() miniEditor.setText(" and indented line") expect(miniEditor.renderedLines.find('.indent-guide').length).toBe 0 it "lets you set the grammar", -> - miniEditor = new Editor(mini: true) + miniEditor = new TextEditorView(mini: true) miniEditor.setText("var something") previousTokens = miniEditor.lineForScreenRow(0).tokens miniEditor.setGrammar(atom.syntax.selectGrammar('something.js')) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 0c07dd1af..bd8cc5e75 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -9,7 +9,7 @@ Keymap = require '../src/keymap' Config = require '../src/config' {Point} = require 'telepath' Project = require '../src/project' -Editor = require '../src/editor' +TextEditorView = require '../src/text-editor-view' TokenizedBuffer = require '../src/tokenized-buffer' pathwatcher = require 'pathwatcher' platform = require './spec-helper-platform' @@ -75,7 +75,7 @@ beforeEach -> spyOn(config, 'load') spyOn(config, 'save') config.setDefaults('core', RootView.configDefaults) - config.setDefaults('editor', Editor.configDefaults) + config.setDefaults('editor', TextEditorView.configDefaults) config.set "editor.fontFamily", "Courier" config.set "editor.fontSize", 16 config.set "editor.autoIndent", false @@ -86,7 +86,7 @@ beforeEach -> window.config = config # make editor display updates synchronous - spyOn(Editor.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay() + spyOn(TextEditorView.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay() spyOn(RootView.prototype, 'setTitle').andCallFake (@title) -> spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout diff --git a/src/edit-session.coffee b/src/edit-session.coffee index b12628ba0..ef892a187 100644 --- a/src/edit-session.coffee +++ b/src/edit-session.coffee @@ -131,7 +131,7 @@ class EditSession # Private: getViewClass: -> - require './editor' + require './text-editor-view' # Private: destroy: -> diff --git a/src/gutter.coffee b/src/gutter.coffee index a776bf447..1d021b9e4 100644 --- a/src/gutter.coffee +++ b/src/gutter.coffee @@ -2,7 +2,7 @@ {Range} = require 'telepath' _ = require 'underscore-plus' -# Private: Represents the portion of the {Editor} containing row numbers. +# Private: Represents the portion of the {TextEditorView} containing row numbers. # # The gutter also indicates if rows are folded. module.exports = @@ -52,9 +52,9 @@ class Gutter extends View ### Public ### - # Retrieves the containing {Editor}. + # Retrieves the containing {TextEditorView}. # - # Returns an {Editor}. + # Returns an {TextEditorView}. getEditor: -> @parentView diff --git a/src/pane.coffee b/src/pane.coffee index 514e37e93..b91ed926e 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -7,7 +7,7 @@ PaneColumn = require './pane-column' # Public: A container which can contains multiple items to be switched between. # -# Items can be almost anything however most commonly they're {Editor}s. +# Items can be almost anything however most commonly they're {TextEditorView}s. # # Most packages won't need to use this class, unless you're interested in # building a package that deals with switching between panes or tiems. diff --git a/src/root-view.coffee b/src/root-view.coffee index d1d071272..fd8e00b6e 100644 --- a/src/root-view.coffee +++ b/src/root-view.coffee @@ -5,7 +5,7 @@ Q = require 'q' _ = require 'underscore-plus' fs = require 'fs-plus' telepath = require 'telepath' -Editor = require './editor' +TextEditorView = require './text-editor-view' Pane = require './pane' PaneColumn = require './pane-column' PaneRow = require './pane-row' @@ -38,7 +38,7 @@ EditSession = require './edit-session' # module.exports = class RootView extends View - registerDeserializers(this, Pane, PaneRow, PaneColumn, Editor) + registerDeserializers(this, Pane, PaneRow, PaneColumn, TextEditorView) @version: 1 @@ -249,7 +249,7 @@ class RootView extends View setTitle: (title) -> document.title = title - # Private: Returns an Array of all of the application's {Editor}s. + # Private: Returns an Array of all of the application's {TextEditorView}s. getEditors: -> @panes.find('.pane > .item-views > .editor').map(-> $(this).view()).toArray() @@ -308,7 +308,7 @@ class RootView extends View indexOfPane: (pane) -> @panes.indexOfPane(pane) - # Private: Fires a callback on each open {Editor}. + # Private: Fires a callback on each open {TextEditorView}. eachEditor: (callback) -> callback(editor) for editor in @getEditors() attachedCallback = (e, editor) -> callback(editor) diff --git a/src/select-list.coffee b/src/select-list.coffee index 78a305945..aafe2ca58 100644 --- a/src/select-list.coffee +++ b/src/select-list.coffee @@ -1,5 +1,5 @@ {$, View} = require './space-pen-extensions' -Editor = require './editor' +TextEditorView = require './text-editor-view' fuzzyFilter = require('fuzzaldrin').filter # Public: Provides a widget for users to make a selection from a list of @@ -10,7 +10,7 @@ class SelectList extends View # Private: @content: -> @div class: @viewClass(), => - @subview 'miniEditor', new Editor(mini: true) + @subview 'miniEditor', new TextEditorView(mini: true) @div class: 'error-message', outlet: 'error' @div class: 'loading', outlet: 'loadingArea', => @span class: 'loading-message', outlet: 'loading' diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index 52d494fb0..fa7a4a86a 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -126,7 +126,7 @@ class TextBuffer extends telepath.Model # Identifies if the buffer belongs to multiple editors. # - # For example, if the {Editor} was split. + # For example, if the {TextEditorView} was split. # # Returns a {Boolean}. hasMultipleEditors: -> @refcount > 1 diff --git a/src/editor.coffee b/src/text-editor-view.coffee similarity index 98% rename from src/editor.coffee rename to src/text-editor-view.coffee index ed14e6e9a..9015c94a6 100644 --- a/src/editor.coffee +++ b/src/text-editor-view.coffee @@ -15,9 +15,9 @@ LongLineLength = 1000 # Private: Represents the entire visual pane in Atom. # -# The Editor manages the {EditSession}, which manages the file buffers. +# The TextEditorView manages the {EditSession}, which manages the file buffers. module.exports = -class Editor extends View +class TextEditorView extends View @characterWidthCache: {} @configDefaults: fontSize: 20 @@ -75,7 +75,7 @@ class Editor extends View ### Public ### - # The constructor for setting up an `Editor` instance. + # The constructor for setting up an `TextEditorView` instance. # # editSessionOrOptions - Either an {EditSession}, or an object with one property, `mini`. # If `mini` is `true`, a "miniature" `EditSession` is constructed. @@ -88,7 +88,7 @@ class Editor extends View else {editSession, @mini} = editSessionOrOptions ? {} - @id = Editor.nextEditorId++ + @id = TextEditorView.nextEditorId++ @lineCache = [] @configure() @bindKeys() @@ -1038,7 +1038,7 @@ class Editor extends View pane = @getPane() pane?.splitDown(pane?.copyActiveItem()).activeView - # Retrieve's the `Editor`'s pane. + # Retrieve's the `TextEditorView`'s pane. # # Returns a {Pane}. getPane: -> @@ -1480,9 +1480,9 @@ class Editor extends View eolInvisibles = @getEndOfLineInvisibles(screenLine) htmlEolInvisibles = @buildHtmlEndOfLineInvisibles(screenLine) - indentation = Editor.buildIndentation(screenRow, @activeEditSession) + indentation = TextEditorView.buildIndentation(screenRow, @activeEditSession) - Editor.buildLineHtml({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, @showIndentGuide, indentation, @activeEditSession, @mini}) + TextEditorView.buildLineHtml({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, @showIndentGuide, indentation, @activeEditSession, @mini}) @buildIndentation: (screenRow, activeEditSession) -> bufferRow = activeEditSession.bufferPositionForScreenPosition([screenRow]).row @@ -1639,7 +1639,7 @@ class Editor extends View getCharacterWidthCache: (scopes, char) -> scopes ?= NoScope - obj = Editor.characterWidthCache + obj = TextEditorView.characterWidthCache for scope in scopes obj = obj[scope] return null unless obj? @@ -1647,14 +1647,14 @@ class Editor extends View setCharacterWidthCache: (scopes, char, val) -> scopes ?= NoScope - obj = Editor.characterWidthCache + obj = TextEditorView.characterWidthCache for scope in scopes obj[scope] ?= {} obj = obj[scope] obj[char] = val clearCharacterWidthCache: -> - Editor.characterWidthCache = {} + TextEditorView.characterWidthCache = {} pixelOffsetForScreenPosition: (position) -> {top, left} = @pixelPositionForScreenPosition(position) @@ -1734,7 +1734,7 @@ class Editor extends View line.push("
") if text == '' - html = Editor.buildEmptyLineHtml(showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini) + html = TextEditorView.buildEmptyLineHtml(showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini) line.push(html) if html else firstNonWhitespacePosition = text.search(/\S/) diff --git a/src/window.coffee b/src/window.coffee index 34a0d80ee..3d34342c7 100644 --- a/src/window.coffee +++ b/src/window.coffee @@ -49,7 +49,7 @@ window.startEditorWindow = -> atom.restoreDimensions() atom.config.load() atom.config.setDefaults('core', require('./root-view').configDefaults) - atom.config.setDefaults('editor', require('./editor').configDefaults) + atom.config.setDefaults('editor', require('./text-editor-view').configDefaults) atom.keymap.loadBundledKeymaps() atom.themes.loadBaseStylesheets() atom.packages.loadPackages() From 311155ac0db57807db15fbd3fe187e8afc28b581 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Mon, 18 Nov 2013 16:02:16 -0800 Subject: [PATCH 02/15] Rename editor-spec to text-editor-view-spec --- spec/{editor-spec.coffee => text-editor-view-spec.coffee} | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename spec/{editor-spec.coffee => text-editor-view-spec.coffee} (99%) diff --git a/spec/editor-spec.coffee b/spec/text-editor-view-spec.coffee similarity index 99% rename from spec/editor-spec.coffee rename to spec/text-editor-view-spec.coffee index 1d34730aa..4b9a18b2f 100644 --- a/spec/editor-spec.coffee +++ b/spec/text-editor-view-spec.coffee @@ -1,4 +1,5 @@ -{_, $, $$, fs, TextEditorView, Range, RootView} = require 'atom' +{_, $, $$, fs, Range, RootView} = require 'atom' +TextEditorView = require '../src/text-editor-view' path = require 'path' temp = require 'temp' From 95e4ac903cbb37b1705f766b9e5d28dc583bf6d3 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Mon, 18 Nov 2013 16:12:22 -0800 Subject: [PATCH 03/15] Use Range literals --- spec/text-editor-view-spec.coffee | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/spec/text-editor-view-spec.coffee b/spec/text-editor-view-spec.coffee index 4b9a18b2f..853cbfdbf 100644 --- a/spec/text-editor-view-spec.coffee +++ b/spec/text-editor-view-spec.coffee @@ -748,7 +748,7 @@ describe "TextEditorView", -> describe "when a selection changes", -> describe "when the selection is within a single line", -> it "covers the selection's range with a single region", -> - selection.setBufferRange(new Range({row: 2, column: 7}, {row: 2, column: 25})) + selection.setBufferRange([[2, 7], [2, 25]]) expect(selectionView.regions.length).toBe 1 region = selectionView.regions[0] @@ -759,7 +759,7 @@ describe "TextEditorView", -> describe "when the selection spans 2 lines", -> it "covers the selection's range with 2 regions", -> - selection.setBufferRange(new Range({row: 2, column: 7}, {row: 3, column: 25})) + selection.setBufferRange([[2,7],[3,25]]) expect(selectionView.regions.length).toBe 2 @@ -777,7 +777,7 @@ describe "TextEditorView", -> describe "when the selection spans more than 2 lines", -> it "covers the selection's range with 3 regions", -> - selection.setBufferRange(new Range({row: 2, column: 7}, {row: 6, column: 25})) + selection.setBufferRange([[2,7],[6,25]]) expect(selectionView.regions.length).toBe 3 @@ -808,7 +808,7 @@ describe "TextEditorView", -> expect(region3.width()).toBeCloseTo(25 * charWidth) it "clears previously drawn regions before creating new ones", -> - selection.setBufferRange(new Range({row: 2, column: 7}, {row: 4, column: 25})) + selection.setBufferRange([[2,7],[4,25]]) expect(selectionView.regions.length).toBe 3 expect(selectionView.find('.region').length).toBe 3 @@ -1713,7 +1713,7 @@ describe "TextEditorView", -> editor.setCursorBufferPosition([4, 0]) expect(editor.find('.cursor').offset()).toEqual(editor.renderedLines.find('.line:eq(5)').offset()) - editor.getSelection().setBufferRange(new Range([6, 30], [6, 55])) + editor.getSelection().setBufferRange([[6, 30], [6, 55]]) [region1, region2] = editor.getSelectionView().regions expect(region1.offset().top).toBeCloseTo(editor.renderedLines.find('.line:eq(7)').offset().top) expect(region2.offset().top).toBeCloseTo(editor.renderedLines.find('.line:eq(8)').offset().top) @@ -2030,17 +2030,17 @@ describe "TextEditorView", -> editor.attachToDom(30) it "highlights the foreground of the gutter", -> - editor.getSelection().setBufferRange(new Range([0,0],[2,2])) + editor.getSelection().setBufferRange([[0,0],[2,2]]) expect(editor.getSelection().isSingleScreenLine()).toBe false expect(editor.find('.line-number.cursor-line').length).toBe 3 it "doesn't highlight the background of the gutter", -> - editor.getSelection().setBufferRange(new Range([0,0],[2,0])) + editor.getSelection().setBufferRange([[0,0],[2,0]]) expect(editor.getSelection().isSingleScreenLine()).toBe false expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 0 it "doesn't highlight the last line if it ends at the beginning of a line", -> - editor.getSelection().setBufferRange(new Range([0,0],[1,0])) + editor.getSelection().setBufferRange([[0,0],[1,0]]) expect(editor.getSelection().isSingleScreenLine()).toBe false expect(editor.find('.line-number.cursor-line').length).toBe 1 expect(editor.find('.line-number.cursor-line').intValue()).toBe 1 @@ -2102,7 +2102,7 @@ describe "TextEditorView", -> describe "when a fold-selection event is triggered", -> it "folds the lines covered by the selection into a single line with a fold class and marker", -> - editor.getSelection().setBufferRange(new Range([4, 29], [7, 4])) + editor.getSelection().setBufferRange([[4,29],[7,4]]) editor.trigger 'editor:fold-selection' expect(editor.renderedLines.find('.line:eq(4)')).toHaveClass('fold') @@ -2113,7 +2113,7 @@ describe "TextEditorView", -> expect(editor.getCursorScreenPosition()).toEqual [5, 0] it "keeps the gutter line and the editor line the same heights (regression)", -> - editor.getSelection().setBufferRange(new Range([4, 29], [7, 4])) + editor.getSelection().setBufferRange([[4,29],[7,4]]) editor.trigger 'editor:fold-selection' expect(editor.gutter.find('.line-number:eq(4)').height()).toBe editor.renderedLines.find('.line:eq(4)').height() From 89212e599f368991c82f20ce5971fc24e29cf205 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Mon, 18 Nov 2013 16:25:59 -0800 Subject: [PATCH 04/15] Update requires --- spec/text-editor-view-spec.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/text-editor-view-spec.coffee b/spec/text-editor-view-spec.coffee index 853cbfdbf..b58aaac1b 100644 --- a/spec/text-editor-view-spec.coffee +++ b/spec/text-editor-view-spec.coffee @@ -1,5 +1,8 @@ -{_, $, $$, fs, Range, RootView} = require 'atom' +RootView = require '../src/root-view' TextEditorView = require '../src/text-editor-view' +{$, $$} = require '../src/space-pen-extensions' +_ = require 'underscore' +fs = require 'fs-plus' path = require 'path' temp = require 'temp' From 955d379e0e74d546280d2cf97cd9ee9ec5dc7bb1 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 14:56:09 -0800 Subject: [PATCH 05/15] Rename EditSession to TextEditor --- src/cursor.coffee | 10 +- src/language-mode.coffee | 4 +- src/project.coffee | 18 +- src/root-view.coffee | 8 +- src/selection.coffee | 6 +- src/text-buffer.coffee | 2 +- src/text-editor-view.coffee | 240 +++++++++--------- ...edit-session.coffee => text-editor.coffee} | 22 +- 8 files changed, 155 insertions(+), 155 deletions(-) rename src/{edit-session.coffee => text-editor.coffee} (98%) diff --git a/src/cursor.coffee b/src/cursor.coffee index 551edef0e..dcf3d6429 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -5,7 +5,7 @@ _ = require 'underscore-plus' # Public: The `Cursor` class represents the little blinking line identifying # where text can be inserted. # -# Cursors belong to {EditSession}s and have some metadata attached in the form +# Cursors belong to {TextEditor}s and have some metadata attached in the form # of a {StringMarker}. module.exports = class Cursor @@ -17,7 +17,7 @@ class Cursor visible: true needsAutoscroll: null - # Private: Instantiated by an {EditSession} + # Private: Instantiated by an {TextEditor} constructor: ({@editSession, @marker}) -> @updateVisibility() @marker.on 'changed', (e) => @@ -62,7 +62,7 @@ class Cursor # An {Array} of two numbers: the screen row, and the screen column. # * options: # + autoscroll: - # A Boolean which, if `true`, scrolls the {EditSession} to wherever the + # A Boolean which, if `true`, scrolls the {TextEditor} to wherever the # cursor moves to. setScreenPosition: (screenPosition, options={}) -> @changePosition options, => @@ -78,7 +78,7 @@ class Cursor # An {Array} of two numbers: the buffer row, and the buffer column. # * options: # + autoscroll: - # A Boolean which, if `true`, scrolls the {EditSession} to wherever the + # A Boolean which, if `true`, scrolls the {TextEditor} to wherever the # cursor moves to. setBufferPosition: (bufferPosition, options={}) -> @changePosition options, => @@ -118,7 +118,7 @@ class Cursor segments.push("[#{_.escapeRegExp(nonWordCharacters)}]+") new RegExp(segments.join("|"), "g") - # Public: Identifies if this cursor is the last in the {EditSession}. + # Public: Identifies if this cursor is the last in the {TextEditor}. # # "Last" is defined as the most recently added cursor. # diff --git a/src/language-mode.coffee b/src/language-mode.coffee index 1947de408..194e32099 100644 --- a/src/language-mode.coffee +++ b/src/language-mode.coffee @@ -22,9 +22,9 @@ class LanguageMode ### Public ### - # Sets up a `LanguageMode` for the given {EditSession}. + # Sets up a `LanguageMode` for the given {TextEditor}. # - # editSession - The {EditSession} to associate with + # editSession - The {TextEditor} to associate with constructor: (@editSession) -> @buffer = @editSession.buffer diff --git a/src/project.coffee b/src/project.coffee index 4ad5065ae..df17e5bad 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -7,7 +7,7 @@ Q = require 'q' telepath = require 'telepath' TextBuffer = require './text-buffer' -EditSession = require './edit-session' +TextEditor = require './text-editor' {Emitter} = require 'emissary' Directory = require './directory' Task = require './task' @@ -133,14 +133,14 @@ class Project extends telepath.Model @rootDirectory?.contains(pathToCheck) ? false # Public: Given a path to a file, this constructs and associates a new - # {EditSession}, showing the file. + # {TextEditor}, showing the file. # # * filePath: # The {String} path of the file to associate with # * editSessionOptions: - # Options that you can pass to the {EditSession} constructor + # Options that you can pass to the {TextEditor} constructor # - # Returns a promise that resolves to an {EditSession}. + # Returns a promise that resolves to an {TextEditor}. open: (filePath, options={}) -> filePath = @resolve(filePath) resource = null @@ -160,18 +160,18 @@ class Project extends telepath.Model @buildEditSessionForBuffer(@bufferForPathSync(filePath), options) - # Public: Retrieves all {EditSession}s for all open files. + # Public: Retrieves all {TextEditor}s for all open files. # - # Returns an {Array} of {EditSession}s. + # Returns an {Array} of {TextEditor}s. getEditSessions: -> new Array(@editSessions...) - # Public: Add the given {EditSession}. + # Public: Add the given {TextEditor}. addEditSession: (editSession) -> @editSessions.push editSession @emit 'edit-session-created', editSession - # Public: Return and removes the given {EditSession}. + # Public: Return and removes the given {TextEditor}. removeEditSession: (editSession) -> _.remove(@editSessions, editSession) @@ -332,7 +332,7 @@ class Project extends telepath.Model # Private: buildEditSessionForBuffer: (buffer, editSessionOptions) -> - editSession = new EditSession(_.extend({buffer}, editSessionOptions)) + editSession = new TextEditor(_.extend({buffer}, editSessionOptions)) @addEditSession(editSession) editSession diff --git a/src/root-view.coffee b/src/root-view.coffee index fd8e00b6e..806048e27 100644 --- a/src/root-view.coffee +++ b/src/root-view.coffee @@ -10,7 +10,7 @@ Pane = require './pane' PaneColumn = require './pane-column' PaneRow = require './pane-row' PaneContainer = require './pane-container' -EditSession = require './edit-session' +TextEditor = require './text-editor' # Public: The container for the entire Atom application. # @@ -169,7 +169,7 @@ class RootView extends View # * options # + initialLine: The buffer line number to open to. # - # Returns a promise that resolves to the {EditSession} for the file URI. + # Returns a promise that resolves to the {TextEditor} for the file URI. open: (filePath, options={}) -> changeFocus = options.changeFocus ? true filePath = project.resolve(filePath) @@ -259,7 +259,7 @@ class RootView extends View getModifiedBuffers: -> modifiedBuffers = [] for pane in @getPanes() - for item in pane.getItems() when item instanceof EditSession + for item in pane.getItems() when item instanceof TextEditor modifiedBuffers.push item.buffer if item.buffer.isModified() modifiedBuffers @@ -315,7 +315,7 @@ class RootView extends View @on('editor:attached', attachedCallback) off: => @off('editor:attached', attachedCallback) - # Public: Fires a callback on each open {EditSession}. + # Public: Fires a callback on each open {TextEditor}. eachEditSession: (callback) -> project.eachEditSession(callback) diff --git a/src/selection.coffee b/src/selection.coffee index f0a0dc623..e42864209 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -2,7 +2,7 @@ {Emitter} = require 'emissary' {pick} = require 'underscore-plus' -# Public: Represents a selection in the {EditSession}. +# Public: Represents a selection in the {TextEditor}. module.exports = class Selection Emitter.includeInto(this) @@ -79,7 +79,7 @@ class Selection # + preserveFolds: # if `true`, the fold settings are preserved after the selection moves # + autoscroll: - # if `true`, the {EditSession} scrolls to the new selection + # if `true`, the {TextEditor} scrolls to the new selection setBufferRange: (bufferRange, options={}) -> bufferRange = Range.fromObject(bufferRange) @needsAutoscroll = options.autoscroll @@ -361,7 +361,7 @@ class Selection # * options - A hash with one key, # + autoIndent: # If `true`, the indentation is performed appropriately. Otherwise, - # {EditSession.getTabText} is used + # {TextEditor.getTabText} is used indent: ({ autoIndent }={})-> { row, column } = @cursor.getBufferPosition() diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index fa7a4a86a..e91d059e8 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -131,7 +131,7 @@ class TextBuffer extends telepath.Model # Returns a {Boolean}. hasMultipleEditors: -> @refcount > 1 - # Reloads a file in the {EditSession}. + # Reloads a file in the {TextEditor}. # # Sets the buffer's content to the cached disk contents reload: -> diff --git a/src/text-editor-view.coffee b/src/text-editor-view.coffee index 9015c94a6..1086bde85 100644 --- a/src/text-editor-view.coffee +++ b/src/text-editor-view.coffee @@ -2,7 +2,7 @@ TextBuffer = require './text-buffer' Gutter = require './gutter' {Point, Range} = require 'telepath' -EditSession = require './edit-session' +TextEditor = require './text-editor' CursorView = require './cursor-view' SelectionView = require './selection-view' fs = require 'fs-plus' @@ -15,7 +15,7 @@ LongLineLength = 1000 # Private: Represents the entire visual pane in Atom. # -# The TextEditorView manages the {EditSession}, which manages the file buffers. +# The TextEditorView manages the {TextEditor}, which manages the file buffers. module.exports = class TextEditorView extends View @characterWidthCache: {} @@ -77,13 +77,13 @@ class TextEditorView extends View # The constructor for setting up an `TextEditorView` instance. # - # editSessionOrOptions - Either an {EditSession}, or an object with one property, `mini`. - # If `mini` is `true`, a "miniature" `EditSession` is constructed. + # editSessionOrOptions - Either an {TextEditor}, or an object with one property, `mini`. + # If `mini` is `true`, a "miniature" `TextEditor` is constructed. # Typically, this is ideal for scenarios where you need an Atom editor, # but without all the chrome, like scrollbars, gutter, _e.t.c._. # initialize: (editSessionOrOptions) -> - if editSessionOrOptions instanceof EditSession + if editSessionOrOptions instanceof TextEditor editSession = editSessionOrOptions else {editSession, @mini} = editSessionOrOptions ? {} @@ -103,14 +103,14 @@ class TextEditorView extends View if editSession? @edit(editSession) else if @mini - @edit(new EditSession + @edit(new TextEditor buffer: TextBuffer.createAsRoot() softWrap: false tabLength: 2 softTabs: true ) else - throw new Error("Must supply an EditSession or mini: true") + throw new Error("Must supply an TextEditor or mini: true") # Internal: Sets up the core Atom commands. # @@ -213,294 +213,294 @@ class TextEditorView extends View do (name, method) => @command name, (e) => method.call(this, e); false - # {Delegates to: EditSession.getCursor} + # {Delegates to: TextEditor.getCursor} getCursor: -> @activeEditSession.getCursor() - # {Delegates to: EditSession.getCursors} + # {Delegates to: TextEditor.getCursors} getCursors: -> @activeEditSession.getCursors() - # {Delegates to: EditSession.addCursorAtScreenPosition} + # {Delegates to: TextEditor.addCursorAtScreenPosition} addCursorAtScreenPosition: (screenPosition) -> @activeEditSession.addCursorAtScreenPosition(screenPosition) - # {Delegates to: EditSession.addCursorAtBufferPosition} + # {Delegates to: TextEditor.addCursorAtBufferPosition} addCursorAtBufferPosition: (bufferPosition) -> @activeEditSession.addCursorAtBufferPosition(bufferPosition) - # {Delegates to: EditSession.moveCursorUp} + # {Delegates to: TextEditor.moveCursorUp} moveCursorUp: -> @activeEditSession.moveCursorUp() - # {Delegates to: EditSession.moveCursorDown} + # {Delegates to: TextEditor.moveCursorDown} moveCursorDown: -> @activeEditSession.moveCursorDown() - # {Delegates to: EditSession.moveCursorLeft} + # {Delegates to: TextEditor.moveCursorLeft} moveCursorLeft: -> @activeEditSession.moveCursorLeft() - # {Delegates to: EditSession.moveCursorRight} + # {Delegates to: TextEditor.moveCursorRight} moveCursorRight: -> @activeEditSession.moveCursorRight() - # {Delegates to: EditSession.moveCursorToBeginningOfWord} + # {Delegates to: TextEditor.moveCursorToBeginningOfWord} moveCursorToBeginningOfWord: -> @activeEditSession.moveCursorToBeginningOfWord() - # {Delegates to: EditSession.moveCursorToEndOfWord} + # {Delegates to: TextEditor.moveCursorToEndOfWord} moveCursorToEndOfWord: -> @activeEditSession.moveCursorToEndOfWord() - # {Delegates to: EditSession.moveCursorToBeginningOfNextWord} + # {Delegates to: TextEditor.moveCursorToBeginningOfNextWord} moveCursorToBeginningOfNextWord: -> @activeEditSession.moveCursorToBeginningOfNextWord() - # {Delegates to: EditSession.moveCursorToTop} + # {Delegates to: TextEditor.moveCursorToTop} moveCursorToTop: -> @activeEditSession.moveCursorToTop() - # {Delegates to: EditSession.moveCursorToBottom} + # {Delegates to: TextEditor.moveCursorToBottom} moveCursorToBottom: -> @activeEditSession.moveCursorToBottom() - # {Delegates to: EditSession.moveCursorToBeginningOfLine} + # {Delegates to: TextEditor.moveCursorToBeginningOfLine} moveCursorToBeginningOfLine: -> @activeEditSession.moveCursorToBeginningOfLine() - # {Delegates to: EditSession.moveCursorToFirstCharacterOfLine} + # {Delegates to: TextEditor.moveCursorToFirstCharacterOfLine} moveCursorToFirstCharacterOfLine: -> @activeEditSession.moveCursorToFirstCharacterOfLine() - # {Delegates to: EditSession.moveCursorToPreviousWordBoundary} + # {Delegates to: TextEditor.moveCursorToPreviousWordBoundary} moveCursorToPreviousWordBoundary: -> @activeEditSession.moveCursorToPreviousWordBoundary() - # {Delegates to: EditSession.moveCursorToNextWordBoundary} + # {Delegates to: TextEditor.moveCursorToNextWordBoundary} moveCursorToNextWordBoundary: -> @activeEditSession.moveCursorToNextWordBoundary() - # {Delegates to: EditSession.moveCursorToEndOfLine} + # {Delegates to: TextEditor.moveCursorToEndOfLine} moveCursorToEndOfLine: -> @activeEditSession.moveCursorToEndOfLine() - # {Delegates to: EditSession.moveLineUp} + # {Delegates to: TextEditor.moveLineUp} moveLineUp: -> @activeEditSession.moveLineUp() - # {Delegates to: EditSession.moveLineDown} + # {Delegates to: TextEditor.moveLineDown} moveLineDown: -> @activeEditSession.moveLineDown() - # {Delegates to: EditSession.setCursorScreenPosition} + # {Delegates to: TextEditor.setCursorScreenPosition} setCursorScreenPosition: (position, options) -> @activeEditSession.setCursorScreenPosition(position, options) - # {Delegates to: EditSession.duplicateLine} + # {Delegates to: TextEditor.duplicateLine} duplicateLine: -> @activeEditSession.duplicateLine() - # {Delegates to: EditSession.joinLine} + # {Delegates to: TextEditor.joinLine} joinLine: -> @activeEditSession.joinLine() - # {Delegates to: EditSession.getCursorScreenPosition} + # {Delegates to: TextEditor.getCursorScreenPosition} getCursorScreenPosition: -> @activeEditSession.getCursorScreenPosition() - # {Delegates to: EditSession.getCursorScreenRow} + # {Delegates to: TextEditor.getCursorScreenRow} getCursorScreenRow: -> @activeEditSession.getCursorScreenRow() - # {Delegates to: EditSession.setCursorBufferPosition} + # {Delegates to: TextEditor.setCursorBufferPosition} setCursorBufferPosition: (position, options) -> @activeEditSession.setCursorBufferPosition(position, options) - # {Delegates to: EditSession.getCursorBufferPosition} + # {Delegates to: TextEditor.getCursorBufferPosition} getCursorBufferPosition: -> @activeEditSession.getCursorBufferPosition() - # {Delegates to: EditSession.getCurrentParagraphBufferRange} + # {Delegates to: TextEditor.getCurrentParagraphBufferRange} getCurrentParagraphBufferRange: -> @activeEditSession.getCurrentParagraphBufferRange() - # {Delegates to: EditSession.getWordUnderCursor} + # {Delegates to: TextEditor.getWordUnderCursor} getWordUnderCursor: (options) -> @activeEditSession.getWordUnderCursor(options) - # {Delegates to: EditSession.getSelection} + # {Delegates to: TextEditor.getSelection} getSelection: (index) -> @activeEditSession.getSelection(index) - # {Delegates to: EditSession.getSelections} + # {Delegates to: TextEditor.getSelections} getSelections: -> @activeEditSession.getSelections() - # {Delegates to: EditSession.getSelectionsOrderedByBufferPosition} + # {Delegates to: TextEditor.getSelectionsOrderedByBufferPosition} getSelectionsOrderedByBufferPosition: -> @activeEditSession.getSelectionsOrderedByBufferPosition() - # {Delegates to: EditSession.getLastSelectionInBuffer} + # {Delegates to: TextEditor.getLastSelectionInBuffer} getLastSelectionInBuffer: -> @activeEditSession.getLastSelectionInBuffer() - # {Delegates to: EditSession.getSelectedText} + # {Delegates to: TextEditor.getSelectedText} getSelectedText: -> @activeEditSession.getSelectedText() - # {Delegates to: EditSession.getSelectedBufferRanges} + # {Delegates to: TextEditor.getSelectedBufferRanges} getSelectedBufferRanges: -> @activeEditSession.getSelectedBufferRanges() - # {Delegates to: EditSession.getSelectedBufferRange} + # {Delegates to: TextEditor.getSelectedBufferRange} getSelectedBufferRange: -> @activeEditSession.getSelectedBufferRange() - # {Delegates to: EditSession.setSelectedBufferRange} + # {Delegates to: TextEditor.setSelectedBufferRange} setSelectedBufferRange: (bufferRange, options) -> @activeEditSession.setSelectedBufferRange(bufferRange, options) - # {Delegates to: EditSession.setSelectedBufferRanges} + # {Delegates to: TextEditor.setSelectedBufferRanges} setSelectedBufferRanges: (bufferRanges, options) -> @activeEditSession.setSelectedBufferRanges(bufferRanges, options) - # {Delegates to: EditSession.addSelectionForBufferRange} + # {Delegates to: TextEditor.addSelectionForBufferRange} addSelectionForBufferRange: (bufferRange, options) -> @activeEditSession.addSelectionForBufferRange(bufferRange, options) - # {Delegates to: EditSession.selectRight} + # {Delegates to: TextEditor.selectRight} selectRight: -> @activeEditSession.selectRight() - # {Delegates to: EditSession.selectLeft} + # {Delegates to: TextEditor.selectLeft} selectLeft: -> @activeEditSession.selectLeft() - # {Delegates to: EditSession.selectUp} + # {Delegates to: TextEditor.selectUp} selectUp: -> @activeEditSession.selectUp() - # {Delegates to: EditSession.selectDown} + # {Delegates to: TextEditor.selectDown} selectDown: -> @activeEditSession.selectDown() - # {Delegates to: EditSession.selectToTop} + # {Delegates to: TextEditor.selectToTop} selectToTop: -> @activeEditSession.selectToTop() - # {Delegates to: EditSession.selectToBottom} + # {Delegates to: TextEditor.selectToBottom} selectToBottom: -> @activeEditSession.selectToBottom() - # {Delegates to: EditSession.selectAll} + # {Delegates to: TextEditor.selectAll} selectAll: -> @activeEditSession.selectAll() - # {Delegates to: EditSession.selectToBeginningOfLine} + # {Delegates to: TextEditor.selectToBeginningOfLine} selectToBeginningOfLine: -> @activeEditSession.selectToBeginningOfLine() - # {Delegates to: EditSession.selectToFirstCharacterOfLine} + # {Delegates to: TextEditor.selectToFirstCharacterOfLine} selectToFirstCharacterOfLine: -> @activeEditSession.selectToFirstCharacterOfLine() - # {Delegates to: EditSession.selectToEndOfLine} + # {Delegates to: TextEditor.selectToEndOfLine} selectToEndOfLine: -> @activeEditSession.selectToEndOfLine() - # {Delegates to: EditSession.selectToPreviousWordBoundary} + # {Delegates to: TextEditor.selectToPreviousWordBoundary} selectToPreviousWordBoundary: -> @activeEditSession.selectToPreviousWordBoundary() - # {Delegates to: EditSession.selectToNextWordBoundary} + # {Delegates to: TextEditor.selectToNextWordBoundary} selectToNextWordBoundary: -> @activeEditSession.selectToNextWordBoundary() - # {Delegates to: EditSession.addSelectionBelow} + # {Delegates to: TextEditor.addSelectionBelow} addSelectionBelow: -> @activeEditSession.addSelectionBelow() - # {Delegates to: EditSession.addSelectionAbove} + # {Delegates to: TextEditor.addSelectionAbove} addSelectionAbove: -> @activeEditSession.addSelectionAbove() - # {Delegates to: EditSession.selectToBeginningOfWord} + # {Delegates to: TextEditor.selectToBeginningOfWord} selectToBeginningOfWord: -> @activeEditSession.selectToBeginningOfWord() - # {Delegates to: EditSession.selectToEndOfWord} + # {Delegates to: TextEditor.selectToEndOfWord} selectToEndOfWord: -> @activeEditSession.selectToEndOfWord() - # {Delegates to: EditSession.selectToBeginningOfNextWord} + # {Delegates to: TextEditor.selectToBeginningOfNextWord} selectToBeginningOfNextWord: -> @activeEditSession.selectToBeginningOfNextWord() - # {Delegates to: EditSession.selectWord} + # {Delegates to: TextEditor.selectWord} selectWord: -> @activeEditSession.selectWord() - # {Delegates to: EditSession.selectLine} + # {Delegates to: TextEditor.selectLine} selectLine: -> @activeEditSession.selectLine() - # {Delegates to: EditSession.selectToScreenPosition} + # {Delegates to: TextEditor.selectToScreenPosition} selectToScreenPosition: (position) -> @activeEditSession.selectToScreenPosition(position) - # {Delegates to: EditSession.transpose} + # {Delegates to: TextEditor.transpose} transpose: -> @activeEditSession.transpose() - # {Delegates to: EditSession.upperCase} + # {Delegates to: TextEditor.upperCase} upperCase: -> @activeEditSession.upperCase() - # {Delegates to: EditSession.lowerCase} + # {Delegates to: TextEditor.lowerCase} lowerCase: -> @activeEditSession.lowerCase() - # {Delegates to: EditSession.clearSelections} + # {Delegates to: TextEditor.clearSelections} clearSelections: -> @activeEditSession.clearSelections() - # {Delegates to: EditSession.backspace} + # {Delegates to: TextEditor.backspace} backspace: -> @activeEditSession.backspace() - # {Delegates to: EditSession.backspaceToBeginningOfWord} + # {Delegates to: TextEditor.backspaceToBeginningOfWord} backspaceToBeginningOfWord: -> @activeEditSession.backspaceToBeginningOfWord() - # {Delegates to: EditSession.backspaceToBeginningOfLine} + # {Delegates to: TextEditor.backspaceToBeginningOfLine} backspaceToBeginningOfLine: -> @activeEditSession.backspaceToBeginningOfLine() - # {Delegates to: EditSession.delete} + # {Delegates to: TextEditor.delete} delete: -> @activeEditSession.delete() - # {Delegates to: EditSession.deleteToEndOfWord} + # {Delegates to: TextEditor.deleteToEndOfWord} deleteToEndOfWord: -> @activeEditSession.deleteToEndOfWord() - # {Delegates to: EditSession.deleteLine} + # {Delegates to: TextEditor.deleteLine} deleteLine: -> @activeEditSession.deleteLine() - # {Delegates to: EditSession.cutToEndOfLine} + # {Delegates to: TextEditor.cutToEndOfLine} cutToEndOfLine: -> @activeEditSession.cutToEndOfLine() - # {Delegates to: EditSession.insertText} + # {Delegates to: TextEditor.insertText} insertText: (text, options) -> @activeEditSession.insertText(text, options) - # {Delegates to: EditSession.insertNewline} + # {Delegates to: TextEditor.insertNewline} insertNewline: -> @activeEditSession.insertNewline() - # {Delegates to: EditSession.insertNewlineBelow} + # {Delegates to: TextEditor.insertNewlineBelow} insertNewlineBelow: -> @activeEditSession.insertNewlineBelow() - # {Delegates to: EditSession.insertNewlineAbove} + # {Delegates to: TextEditor.insertNewlineAbove} insertNewlineAbove: -> @activeEditSession.insertNewlineAbove() - # {Delegates to: EditSession.indent} + # {Delegates to: TextEditor.indent} indent: (options) -> @activeEditSession.indent(options) - # {Delegates to: EditSession.autoIndentSelectedRows} + # {Delegates to: TextEditor.autoIndentSelectedRows} autoIndent: (options) -> @activeEditSession.autoIndentSelectedRows() - # {Delegates to: EditSession.indentSelectedRows} + # {Delegates to: TextEditor.indentSelectedRows} indentSelectedRows: -> @activeEditSession.indentSelectedRows() - # {Delegates to: EditSession.outdentSelectedRows} + # {Delegates to: TextEditor.outdentSelectedRows} outdentSelectedRows: -> @activeEditSession.outdentSelectedRows() - # {Delegates to: EditSession.cutSelectedText} + # {Delegates to: TextEditor.cutSelectedText} cutSelection: -> @activeEditSession.cutSelectedText() - # {Delegates to: EditSession.copySelectedText} + # {Delegates to: TextEditor.copySelectedText} copySelection: -> @activeEditSession.copySelectedText() - # {Delegates to: EditSession.pasteText} + # {Delegates to: TextEditor.pasteText} paste: (options) -> @activeEditSession.pasteText(options) - # {Delegates to: EditSession.undo} + # {Delegates to: TextEditor.undo} undo: -> @activeEditSession.undo() - # {Delegates to: EditSession.redo} + # {Delegates to: TextEditor.redo} redo: -> @activeEditSession.redo() - # {Delegates to: EditSession.createFold} + # {Delegates to: TextEditor.createFold} createFold: (startRow, endRow) -> @activeEditSession.createFold(startRow, endRow) - # {Delegates to: EditSession.foldCurrentRow} + # {Delegates to: TextEditor.foldCurrentRow} foldCurrentRow: -> @activeEditSession.foldCurrentRow() - # {Delegates to: EditSession.unfoldCurrentRow} + # {Delegates to: TextEditor.unfoldCurrentRow} unfoldCurrentRow: -> @activeEditSession.unfoldCurrentRow() - # {Delegates to: EditSession.foldAll} + # {Delegates to: TextEditor.foldAll} foldAll: -> @activeEditSession.foldAll() - # {Delegates to: EditSession.unfoldAll} + # {Delegates to: TextEditor.unfoldAll} unfoldAll: -> @activeEditSession.unfoldAll() - # {Delegates to: EditSession.foldSelection} + # {Delegates to: TextEditor.foldSelection} foldSelection: -> @activeEditSession.foldSelection() - # {Delegates to: EditSession.destroyFoldsContainingBufferRow} + # {Delegates to: TextEditor.destroyFoldsContainingBufferRow} destroyFoldsContainingBufferRow: (bufferRow) -> @activeEditSession.destroyFoldsContainingBufferRow(bufferRow) - # {Delegates to: EditSession.isFoldedAtScreenRow} + # {Delegates to: TextEditor.isFoldedAtScreenRow} isFoldedAtScreenRow: (screenRow) -> @activeEditSession.isFoldedAtScreenRow(screenRow) - # {Delegates to: EditSession.isFoldedAtBufferRow} + # {Delegates to: TextEditor.isFoldedAtBufferRow} isFoldedAtBufferRow: (bufferRow) -> @activeEditSession.isFoldedAtBufferRow(bufferRow) - # {Delegates to: EditSession.isFoldedAtCursorRow} + # {Delegates to: TextEditor.isFoldedAtCursorRow} isFoldedAtCursorRow: -> @activeEditSession.isFoldedAtCursorRow() foldAllAtIndentLevel: (indentLevel) -> @activeEditSession.foldAllAtIndentLevel(indentLevel) - # {Delegates to: EditSession.lineForScreenRow} + # {Delegates to: TextEditor.lineForScreenRow} lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow) - # {Delegates to: EditSession.linesForScreenRows} + # {Delegates to: TextEditor.linesForScreenRows} linesForScreenRows: (start, end) -> @activeEditSession.linesForScreenRows(start, end) - # {Delegates to: EditSession.getScreenLineCount} + # {Delegates to: TextEditor.getScreenLineCount} getScreenLineCount: -> @activeEditSession.getScreenLineCount() # Private: @@ -508,33 +508,33 @@ class TextEditorView extends View heightInLines ?= @calculateHeightInLines() @heightInLines = heightInLines if heightInLines - # {Delegates to: EditSession.setEditorWidthInChars} + # {Delegates to: TextEditor.setEditorWidthInChars} setWidthInChars: (widthInChars) -> widthInChars ?= @calculateWidthInChars() @activeEditSession.setEditorWidthInChars(widthInChars) if widthInChars - # {Delegates to: EditSession.getMaxScreenLineLength} + # {Delegates to: TextEditor.getMaxScreenLineLength} getMaxScreenLineLength: -> @activeEditSession.getMaxScreenLineLength() - # {Delegates to: EditSession.getLastScreenRow} + # {Delegates to: TextEditor.getLastScreenRow} getLastScreenRow: -> @activeEditSession.getLastScreenRow() - # {Delegates to: EditSession.clipScreenPosition} + # {Delegates to: TextEditor.clipScreenPosition} clipScreenPosition: (screenPosition, options={}) -> @activeEditSession.clipScreenPosition(screenPosition, options) - # {Delegates to: EditSession.screenPositionForBufferPosition} + # {Delegates to: TextEditor.screenPositionForBufferPosition} screenPositionForBufferPosition: (position, options) -> @activeEditSession.screenPositionForBufferPosition(position, options) - # {Delegates to: EditSession.bufferPositionForScreenPosition} + # {Delegates to: TextEditor.bufferPositionForScreenPosition} bufferPositionForScreenPosition: (position, options) -> @activeEditSession.bufferPositionForScreenPosition(position, options) - # {Delegates to: EditSession.screenRangeForBufferRange} + # {Delegates to: TextEditor.screenRangeForBufferRange} screenRangeForBufferRange: (range) -> @activeEditSession.screenRangeForBufferRange(range) - # {Delegates to: EditSession.bufferRangeForScreenRange} + # {Delegates to: TextEditor.bufferRangeForScreenRange} bufferRangeForScreenRange: (range) -> @activeEditSession.bufferRangeForScreenRange(range) - # {Delegates to: EditSession.bufferRowsForScreenRows} + # {Delegates to: TextEditor.bufferRowsForScreenRows} bufferRowsForScreenRows: (startRow, endRow) -> @activeEditSession.bufferRowsForScreenRows(startRow, endRow) # Public: Emulates the "page down" key, where the last row of a buffer scrolls to become the first. @@ -591,13 +591,13 @@ class TextEditorView extends View if path = @getPath() atom.project.getRepo()?.checkoutHead(path) - # {Delegates to: EditSession.setText} + # {Delegates to: TextEditor.setText} setText: (text) -> @activeEditSession.setText(text) - # {Delegates to: EditSession.getText} + # {Delegates to: TextEditor.getText} getText: -> @activeEditSession.getText() - # {Delegates to: EditSession.getPath} + # {Delegates to: TextEditor.getPath} getPath: -> @activeEditSession?.getPath() # {Delegates to: TextBuffer.getLineCount} @@ -888,7 +888,7 @@ class TextEditorView extends View ### Public ### - # Retrieves the {EditSession}'s buffer. + # Retrieves the {TextEditor}'s buffer. # # Returns the current {TextBuffer}. getBuffer: -> @activeEditSession.buffer @@ -1701,20 +1701,20 @@ class TextEditorView extends View else @highlightedLine = null - # {Delegates to: EditSession.getGrammar} + # {Delegates to: TextEditor.getGrammar} getGrammar: -> @activeEditSession.getGrammar() - # {Delegates to: EditSession.setGrammar} + # {Delegates to: TextEditor.setGrammar} setGrammar: (grammar) -> throw new Error("Only mini-editors can explicity set their grammar") unless @mini @activeEditSession.setGrammar(grammar) - # {Delegates to: EditSession.reloadGrammar} + # {Delegates to: TextEditor.reloadGrammar} reloadGrammar: -> @activeEditSession.reloadGrammar() - # {Delegates to: EditSession.scopesForBufferPosition} + # {Delegates to: TextEditor.scopesForBufferPosition} scopesForBufferPosition: (bufferPosition) -> @activeEditSession.scopesForBufferPosition(bufferPosition) diff --git a/src/edit-session.coffee b/src/text-editor.coffee similarity index 98% rename from src/edit-session.coffee rename to src/text-editor.coffee index ef892a187..80cfa2be9 100644 --- a/src/edit-session.coffee +++ b/src/text-editor.coffee @@ -12,18 +12,18 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # Public: The core model of Atom. # -# An {EditSession} represents a unique view of each document, with it's own +# An {TextEditor} represents a unique view of each document, with it's own # {Cursor}s and scroll position. # -# For instance if a user creates a split, Atom creates a second {EditSession} -# but both {EditSession}s interact with the same buffer underlying buffer. So +# For instance if a user creates a split, Atom creates a second {TextEditor} +# but both {TextEditor}s interact with the same buffer underlying buffer. So # if you type in either buffer it immediately appears in both but if you scroll # in one it doesn't scroll the other. # # Almost all extension will interact primiarily with this class as it provides # access to objects you'll most commonly interact with. To access it you'll # want to register a callback on {RootView} which will be fired once for every -# existing {EditSession} as well as any future {EditSession}s. +# existing {TextEditor} as well as any future {TextEditor}s. # # ## Example # ```coffeescript @@ -36,7 +36,7 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # FIXME: Describe how there are both local and remote cursors and selections and # why that is. module.exports = -class EditSession +class TextEditor Emitter.includeInto(this) Subscriber.includeInto(this) @@ -47,7 +47,7 @@ class EditSession @version: 5 @deserialize: (state) -> - new EditSession(state) + new TextEditor(state) id: null languageMode: null @@ -152,12 +152,12 @@ class EditSession # Private: getState: -> @state - # Private: Creates an {EditSession} with the same initial state + # Private: Creates an {TextEditor} with the same initial state copy: -> tabLength = @getTabLength() displayBuffer = @displayBuffer.copy() softTabs = @getSoftTabs() - newEditSession = new EditSession({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true}) + newEditSession = new TextEditor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true}) newEditSession.setScrollTop(@getScrollTop()) newEditSession.setScrollLeft(@getScrollLeft()) for marker in @findMarkers(editSessionId: @id) @@ -190,7 +190,7 @@ class EditSession else 'untitled' - # Public: Compares two `EditSession`s to determine equality. + # Public: Compares two `TextEditor`s to determine equality. # # Equality is based on the condition that: # @@ -200,7 +200,7 @@ class EditSession # # Returns a {Boolean}. isEqual: (other) -> - return false unless other instanceof EditSession + return false unless other instanceof TextEditor @buffer == other.buffer and @getScrollTop() == other.getScrollTop() and @getScrollLeft() == other.getScrollLeft() and @@ -876,7 +876,7 @@ class EditSession @emit 'cursor-added', cursor cursor - # Public: Removes and returns a cursor from the `EditSession`. + # Public: Removes and returns a cursor from the `TextEditor`. removeCursor: (cursor) -> _.remove(@cursors, cursor) From 625fcaffc800cedba83d156b3c095b45bff4d20f Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 14:57:31 -0800 Subject: [PATCH 06/15] Update TextEditor specs --- spec/selection-spec.coffee | 4 ++-- spec/{edit-session-spec.coffee => text-editor-spec.coffee} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename spec/{edit-session-spec.coffee => text-editor-spec.coffee} (99%) diff --git a/spec/selection-spec.coffee b/spec/selection-spec.coffee index e5aa2c055..7503ddbec 100644 --- a/spec/selection-spec.coffee +++ b/spec/selection-spec.coffee @@ -1,11 +1,11 @@ -EditSession = require '../src/edit-session' +TextEditor = require '../src/text-editor' describe "Selection", -> [buffer, editSession, selection] = [] beforeEach -> buffer = project.bufferForPathSync('sample.js') - editSession = new EditSession(buffer: buffer, tabLength: 2) + editSession = new TextEditor(buffer: buffer, tabLength: 2) selection = editSession.getSelection() afterEach -> diff --git a/spec/edit-session-spec.coffee b/spec/text-editor-spec.coffee similarity index 99% rename from spec/edit-session-spec.coffee rename to spec/text-editor-spec.coffee index 2107c3928..9db47ce42 100644 --- a/spec/edit-session-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -1,6 +1,6 @@ clipboard = require 'clipboard' -describe "EditSession", -> +describe "TextEditor", -> [buffer, editSession, lineLengths] = [] convertToHardTabs = (buffer) -> From 6fdd4f775bc59c605e4f00f7d9d137542936f769 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 11:04:07 -0800 Subject: [PATCH 07/15] Rename TextEditor and TextEditorView to Editor and EditorView --- spec/editor-view-spec.coffee | 2825 ++++++++++++++++++++++++++++++++++ src/editor-view.coffee | 1853 ++++++++++++++++++++++ 2 files changed, 4678 insertions(+) create mode 100644 spec/editor-view-spec.coffee create mode 100644 src/editor-view.coffee diff --git a/spec/editor-view-spec.coffee b/spec/editor-view-spec.coffee new file mode 100644 index 000000000..86672b996 --- /dev/null +++ b/spec/editor-view-spec.coffee @@ -0,0 +1,2825 @@ +RootView = require '../src/root-view' +EditorView = require '../src/editor-view' +{$, $$} = require '../src/space-pen-extensions' +_ = require 'underscore-plus' +fs = require 'fs-plus' +path = require 'path' +temp = require 'temp' + +describe "EditorView", -> + [buffer, editorView, editSession, cachedLineHeight, cachedCharWidth] = [] + + beforeEach -> + atom.activatePackage('language-text', sync: true) + atom.activatePackage('language-javascript', sync: true) + editSession = project.openSync('sample.js') + buffer = editSession.buffer + editorView = new EditorView(editSession) + editorView.lineOverdraw = 2 + editorView.isFocused = true + editorView.enableKeymap() + editorView.calculateHeightInLines = -> + Math.ceil(@height() / @lineHeight) + editorView.attachToDom = ({ heightInLines, widthInChars } = {}) -> + heightInLines ?= @getBuffer().getLineCount() + @height(getLineHeight() * heightInLines) + @width(getCharWidth() * widthInChars) if widthInChars + $('#jasmine-content').append(this) + + getLineHeight = -> + return cachedLineHeight if cachedLineHeight? + calcDimensions() + cachedLineHeight + + getCharWidth = -> + return cachedCharWidth if cachedCharWidth? + calcDimensions() + cachedCharWidth + + calcDimensions = -> + editorForMeasurement = new EditorView(editSession: project.openSync('sample.js')) + editorForMeasurement.attachToDom() + cachedLineHeight = editorForMeasurement.lineHeight + cachedCharWidth = editorForMeasurement.charWidth + editorForMeasurement.remove() + + describe "construction", -> + it "throws an error if no edit session is given", -> + expect(-> new EditorView).toThrow() + + describe "when the editor view view is attached to the dom", -> + it "calculates line height and char width and updates the pixel position of the cursor", -> + expect(editorView.lineHeight).toBeNull() + expect(editorView.charWidth).toBeNull() + editorView.setCursorScreenPosition(row: 2, column: 2) + + editorView.attachToDom() + + expect(editorView.lineHeight).not.toBeNull() + expect(editorView.charWidth).not.toBeNull() + expect(editorView.find('.cursor').offset()).toEqual pagePixelPositionForPoint(editorView, [2, 2]) + + it "is focused", -> + editorView.attachToDom() + expect(editorView).toMatchSelector ":has(:focus)" + + describe "when the editor view view receives focus", -> + it "focuses the hidden input", -> + editorView.attachToDom() + editorView.focus() + expect(editorView).not.toMatchSelector ':focus' + expect(editorView.hiddenInput).toMatchSelector ':focus' + + it "does not scroll the editor view (regression)", -> + editorView.attachToDom(heightInLines: 2) + editorView.selectAll() + editorView.hiddenInput.blur() + editorView.focus() + + expect(editorView.hiddenInput).toMatchSelector ':focus' + expect($(editorView[0]).scrollTop()).toBe 0 + expect($(editorView.scrollView[0]).scrollTop()).toBe 0 + + editorView.moveCursorToBottom() + editorView.hiddenInput.blur() + editorView.scrollTop(0) + editorView.focus() + + expect(editorView.hiddenInput).toMatchSelector ':focus' + expect($(editorView[0]).scrollTop()).toBe 0 + expect($(editorView.scrollView[0]).scrollTop()).toBe 0 + + describe "when the hidden input is focused / unfocused", -> + it "assigns the isFocused flag on the editor view view and also adds/removes the .focused css class", -> + editorView.attachToDom() + editorView.isFocused = false + editorView.hiddenInput.focus() + expect(editorView.isFocused).toBeTruthy() + + editorView.hiddenInput.focusout() + expect(editorView.isFocused).toBeFalsy() + + describe "when the activeEditSession's file is modified on disk", -> + it "triggers an alert", -> + filePath = path.join(temp.dir, 'atom-changed-file.txt') + fs.writeFileSync(filePath, "") + editSession = project.openSync(filePath) + editorView.edit(editSession) + editorView.insertText("now the buffer is modified") + + fileChangeHandler = jasmine.createSpy('fileChange') + editSession.buffer.file.on 'contents-changed', fileChangeHandler + + spyOn(atom, "confirm") + + fs.writeFileSync(filePath, "a file change") + + waitsFor "file to trigger contents-changed event", -> + fileChangeHandler.callCount > 0 + + runs -> + expect(atom.confirm).toHaveBeenCalled() + + describe ".remove()", -> + it "destroys the edit session", -> + editorView.remove() + expect(editorView.activeEditSession.destroyed).toBeTruthy() + + describe ".edit(editSession)", -> + [newEditSession, newBuffer] = [] + + beforeEach -> + newEditSession = project.openSync('two-hundred.txt') + newBuffer = newEditSession.buffer + + it "updates the rendered lines, cursors, selections, scroll position, and event subscriptions to match the given edit session", -> + editorView.attachToDom(heightInLines: 5, widthInChars: 30) + editorView.setCursorBufferPosition([6, 13]) + editorView.scrollToBottom() + editorView.scrollLeft(150) + previousScrollHeight = editorView.verticalScrollbar.prop('scrollHeight') + previousScrollTop = editorView.scrollTop() + previousScrollLeft = editorView.scrollLeft() + + newEditSession.setScrollTop(900) + newEditSession.setSelectedBufferRange([[40, 0], [43, 1]]) + + editorView.edit(newEditSession) + { firstRenderedScreenRow, lastRenderedScreenRow } = editorView + expect(editorView.lineElementForScreenRow(firstRenderedScreenRow).text()).toBe newBuffer.lineForRow(firstRenderedScreenRow) + expect(editorView.lineElementForScreenRow(lastRenderedScreenRow).text()).toBe newBuffer.lineForRow(editorView.lastRenderedScreenRow) + expect(editorView.scrollTop()).toBe 900 + expect(editorView.scrollLeft()).toBe 0 + expect(editorView.getSelectionView().regions[0].position().top).toBe 40 * editorView.lineHeight + editorView.insertText("hello") + expect(editorView.lineElementForScreenRow(40).text()).toBe "hello3" + + editorView.edit(editSession) + { firstRenderedScreenRow, lastRenderedScreenRow } = editorView + expect(editorView.lineElementForScreenRow(firstRenderedScreenRow).text()).toBe buffer.lineForRow(firstRenderedScreenRow) + expect(editorView.lineElementForScreenRow(lastRenderedScreenRow).text()).toBe buffer.lineForRow(editorView.lastRenderedScreenRow) + expect(editorView.verticalScrollbar.prop('scrollHeight')).toBe previousScrollHeight + expect(editorView.scrollTop()).toBe previousScrollTop + expect(editorView.scrollLeft()).toBe previousScrollLeft + expect(editorView.getCursorView().position()).toEqual { top: 6 * editorView.lineHeight, left: 13 * editorView.charWidth } + editorView.insertText("goodbye") + expect(editorView.lineElementForScreenRow(6).text()).toMatch /^ currentgoodbye/ + + it "triggers alert if edit session's buffer goes into conflict with changes on disk", -> + filePath = path.join(temp.dir, 'atom-changed-file.txt') + fs.writeFileSync(filePath, "") + tempEditSession = project.openSync(filePath) + editorView.edit(tempEditSession) + tempEditSession.insertText("a buffer change") + + spyOn(atom, "confirm") + + contentsConflictedHandler = jasmine.createSpy("contentsConflictedHandler") + tempEditSession.on 'contents-conflicted', contentsConflictedHandler + fs.writeFileSync(filePath, "a file change") + waitsFor -> + contentsConflictedHandler.callCount > 0 + + runs -> + expect(atom.confirm).toHaveBeenCalled() + + describe ".scrollTop(n)", -> + beforeEach -> + editorView.attachToDom(heightInLines: 5) + expect(editorView.verticalScrollbar.scrollTop()).toBe 0 + + describe "when called with a scroll top argument", -> + it "sets the scrollTop of the vertical scrollbar and sets scrollTop on the line numbers and lines", -> + editorView.scrollTop(100) + expect(editorView.verticalScrollbar.scrollTop()).toBe 100 + expect(editorView.scrollView.scrollTop()).toBe 0 + expect(editorView.renderedLines.css('top')).toBe "-100px" + expect(editorView.gutter.lineNumbers.css('top')).toBe "-100px" + + editorView.scrollTop(120) + expect(editorView.verticalScrollbar.scrollTop()).toBe 120 + expect(editorView.scrollView.scrollTop()).toBe 0 + expect(editorView.renderedLines.css('top')).toBe "-120px" + expect(editorView.gutter.lineNumbers.css('top')).toBe "-120px" + + it "does not allow negative scrollTops to be assigned", -> + editorView.scrollTop(-100) + expect(editorView.scrollTop()).toBe 0 + + it "doesn't do anything if the scrollTop hasn't changed", -> + editorView.scrollTop(100) + spyOn(editorView.verticalScrollbar, 'scrollTop') + spyOn(editorView.renderedLines, 'css') + spyOn(editorView.gutter.lineNumbers, 'css') + + editorView.scrollTop(100) + expect(editorView.verticalScrollbar.scrollTop).not.toHaveBeenCalled() + expect(editorView.renderedLines.css).not.toHaveBeenCalled() + expect(editorView.gutter.lineNumbers.css).not.toHaveBeenCalled() + + describe "when the 'adjustVerticalScrollbar' option is false (defaults to true)", -> + it "doesn't adjust the scrollTop of the vertical scrollbar", -> + editorView.scrollTop(100, adjustVerticalScrollbar: false) + expect(editorView.verticalScrollbar.scrollTop()).toBe 0 + expect(editorView.renderedLines.css('top')).toBe "-100px" + expect(editorView.gutter.lineNumbers.css('top')).toBe "-100px" + + describe "when called with no argument", -> + it "returns the last assigned value or 0 if none has been assigned", -> + expect(editorView.scrollTop()).toBe 0 + editorView.scrollTop(50) + expect(editorView.scrollTop()).toBe 50 + + it "sets the new scroll top position on the active edit session", -> + expect(editorView.activeEditSession.getScrollTop()).toBe 0 + editorView.scrollTop(123) + expect(editorView.activeEditSession.getScrollTop()).toBe 123 + + describe ".scrollHorizontally(pixelPosition)", -> + it "sets the new scroll left position on the active edit session", -> + editorView.attachToDom(heightInLines: 5) + setEditorWidthInChars(editorView, 5) + expect(editorView.activeEditSession.getScrollLeft()).toBe 0 + editorView.scrollHorizontally(left: 50) + expect(editorView.activeEditSession.getScrollLeft()).toBeGreaterThan 0 + expect(editorView.activeEditSession.getScrollLeft()).toBe editorView.scrollLeft() + + describe "editor:attached event", -> + it 'only triggers an editor:attached event when it is first added to the DOM', -> + openHandler = jasmine.createSpy('openHandler') + editorView.on 'editor:attached', openHandler + + editorView.attachToDom() + expect(openHandler).toHaveBeenCalled() + [event, eventEditor] = openHandler.argsForCall[0] + expect(eventEditor).toBe editorView + + openHandler.reset() + editorView.attachToDom() + expect(openHandler).not.toHaveBeenCalled() + + describe "editor:path-changed event", -> + filePath = null + + beforeEach -> + filePath = path.join(temp.dir, 'something.txt') + fs.writeFileSync(filePath, filePath) + + afterEach -> + fs.removeSync(filePath) if fs.existsSync(filePath) + + it "emits event when buffer's path is changed", -> + eventHandler = jasmine.createSpy('eventHandler') + editorView.on 'editor:path-changed', eventHandler + editorView.getBuffer().saveAs(filePath) + expect(eventHandler).toHaveBeenCalled() + + it "emits event when editor view view receives a new buffer", -> + eventHandler = jasmine.createSpy('eventHandler') + editorView.on 'editor:path-changed', eventHandler + editorView.edit(project.openSync(filePath)) + expect(eventHandler).toHaveBeenCalled() + + it "stops listening to events on previously set buffers", -> + eventHandler = jasmine.createSpy('eventHandler') + oldBuffer = editorView.getBuffer() + editorView.on 'editor:path-changed', eventHandler + + editorView.edit(project.openSync(filePath)) + expect(eventHandler).toHaveBeenCalled() + + eventHandler.reset() + oldBuffer.saveAs(path.join(temp.dir, 'atom-bad.txt')) + expect(eventHandler).not.toHaveBeenCalled() + + eventHandler.reset() + editorView.getBuffer().saveAs(path.join(temp.dir, 'atom-new.txt')) + expect(eventHandler).toHaveBeenCalled() + + it "loads the grammar for the new path", -> + expect(editorView.getGrammar().name).toBe 'JavaScript' + editorView.getBuffer().saveAs(filePath) + expect(editorView.getGrammar().name).toBe 'Plain Text' + + describe "font family", -> + beforeEach -> + expect(editorView.css('font-family')).toBe 'Courier' + + it "when there is no config in fontFamily don't set it", -> + atom.config.set('editor.fontFamily', null) + expect(editorView.css('font-family')).toBe '' + + describe "when the font family changes", -> + [fontFamily] = [] + + beforeEach -> + if process.platform is 'darwin' + fontFamily = "PCMyungjo" + else + fontFamily = "Consolas" + + it "updates the font family of editors and recalculates dimensions critical to cursor positioning", -> + editorView.attachToDom(12) + lineHeightBefore = editorView.lineHeight + charWidthBefore = editorView.charWidth + editorView.setCursorScreenPosition [5, 6] + + atom.config.set("editor.fontFamily", fontFamily) + expect(editorView.css('font-family')).toBe fontFamily + expect(editorView.charWidth).not.toBe charWidthBefore + expect(editorView.getCursorView().position()).toEqual { top: 5 * editorView.lineHeight, left: 6 * editorView.charWidth } + + newEditor = new EditorView(editorView.activeEditSession.copy()) + newEditor.attachToDom() + expect(newEditor.css('font-family')).toBe fontFamily + + describe "font size", -> + beforeEach -> + expect(editorView.css('font-size')).not.toBe "20px" + expect(editorView.css('font-size')).not.toBe "10px" + + it "sets the initial font size based on the value from config", -> + expect(editorView.css('font-size')).toBe "#{atom.config.get('editor.fontSize')}px" + + describe "when the font size changes", -> + it "updates the font sizes of editors and recalculates dimensions critical to cursor positioning", -> + atom.config.set("editor.fontSize", 10) + editorView.attachToDom() + lineHeightBefore = editorView.lineHeight + charWidthBefore = editorView.charWidth + editorView.setCursorScreenPosition [5, 6] + + atom.config.set("editor.fontSize", 30) + expect(editorView.css('font-size')).toBe '30px' + expect(editorView.lineHeight).toBeGreaterThan lineHeightBefore + expect(editorView.charWidth).toBeGreaterThan charWidthBefore + expect(editorView.getCursorView().position()).toEqual { top: 5 * editorView.lineHeight, left: 6 * editorView.charWidth } + expect(editorView.renderedLines.outerHeight()).toBe buffer.getLineCount() * editorView.lineHeight + expect(editorView.verticalScrollbarContent.height()).toBe buffer.getLineCount() * editorView.lineHeight + + newEditor = new EditorView(editorView.activeEditSession.copy()) + editorView.remove() + newEditor.attachToDom() + expect(newEditor.css('font-size')).toBe '30px' + + it "updates the position and size of selection regions", -> + atom.config.set("editor.fontSize", 10) + editorView.setSelectedBufferRange([[5, 2], [5, 7]]) + editorView.attachToDom() + + atom.config.set("editor.fontSize", 30) + selectionRegion = editorView.find('.region') + expect(selectionRegion.position().top).toBe 5 * editorView.lineHeight + expect(selectionRegion.position().left).toBe 2 * editorView.charWidth + expect(selectionRegion.height()).toBe editorView.lineHeight + expect(selectionRegion.width()).toBe 5 * editorView.charWidth + + it "updates lines if there are unrendered lines", -> + editorView.attachToDom(heightInLines: 5) + originalLineCount = editorView.renderedLines.find(".line").length + expect(originalLineCount).toBeGreaterThan 0 + + atom.config.set("editor.fontSize", 10) + expect(editorView.renderedLines.find(".line").length).toBeGreaterThan originalLineCount + + describe "when the font size changes while editor view view is detached", -> + it "redraws the editor view view according to the new font size when it is reattached", -> + editorView.setCursorScreenPosition([4, 2]) + editorView.attachToDom() + initialLineHeight = editorView.lineHeight + initialCharWidth = editorView.charWidth + initialCursorPosition = editorView.getCursorView().position() + initialScrollbarHeight = editorView.verticalScrollbarContent.height() + editorView.detach() + + atom.config.set("editor.fontSize", 10) + expect(editorView.lineHeight).toBe initialLineHeight + expect(editorView.charWidth).toBe initialCharWidth + + editorView.attachToDom() + expect(editorView.lineHeight).not.toBe initialLineHeight + expect(editorView.charWidth).not.toBe initialCharWidth + expect(editorView.getCursorView().position()).not.toEqual initialCursorPosition + expect(editorView.verticalScrollbarContent.height()).not.toBe initialScrollbarHeight + + describe "mouse events", -> + beforeEach -> + editorView.attachToDom() + editorView.css(position: 'absolute', top: 10, left: 10, width: 400) + + describe "single-click", -> + it "re-positions the cursor to the clicked row / column", -> + expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [3, 10]) + expect(editorView.getCursorScreenPosition()).toEqual(row: 3, column: 10) + + describe "when the lines are scrolled to the right", -> + it "re-positions the cursor on the clicked location", -> + setEditorWidthInChars(editorView, 30) + expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [3, 30]) # scrolls lines to the right + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [3, 50]) + expect(editorView.getCursorBufferPosition()).toEqual(row: 3, column: 50) + + describe "when the editor view view is using a variable-width font", -> + beforeEach -> + editorView.setFontFamily('sans-serif') + + it "positions the cursor to the clicked row and column", -> + {top, left} = editorView.pixelOffsetForScreenPosition([3, 30]) + editorView.renderedLines.trigger mousedownEvent(pageX: left, pageY: top) + expect(editorView.getCursorScreenPosition()).toEqual [3, 30] + + describe "double-click", -> + it "selects the word under the cursor, and expands the selection wordwise in either direction on a subsequent shift-click", -> + expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [8, 24], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [8, 24], originalEvent: {detail: 2}) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedText()).toBe "concat" + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [8, 7], shiftKey: true) + editorView.renderedLines.trigger 'mouseup' + + expect(editorView.getSelectedText()).toBe "return sort(left).concat" + + it "stops selecting by word when the selection is emptied", -> + expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 8], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 8], originalEvent: {detail: 2}) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedText()).toBe "quicksort" + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [3, 10]) + editorView.renderedLines.trigger 'mouseup' + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [3, 12], originalEvent: {detail: 1}, shiftKey: true) + expect(editorView.getSelectedBufferRange()).toEqual [[3, 10], [3, 12]] + + describe "when clicking between a word and a non-word", -> + it "selects the word", -> + expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 21], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 21], originalEvent: {detail: 2}) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedText()).toBe "function" + + editorView.setCursorBufferPosition([0, 0]) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 22], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 22], originalEvent: {detail: 2}) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedText()).toBe "items" + + editorView.setCursorBufferPosition([0, 0]) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 28], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 28], originalEvent: {detail: 2}) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedText()).toBe "{" + + describe "triple/quardruple/etc-click", -> + it "selects the line under the cursor", -> + expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0) + + # Triple click + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 8], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 8], originalEvent: {detail: 2}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 8], originalEvent: {detail: 3}) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedText()).toBe " var sort = function(items) {\n" + + # Quad click + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [2, 3], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [2, 3], originalEvent: {detail: 2}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [2, 3], originalEvent: {detail: 3}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [2, 3], originalEvent: {detail: 4}) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedText()).toBe " if (items.length <= 1) return items;\n" + + it "expands the selection linewise in either direction on a subsequent shift-click, but stops selecting linewise once the selection is emptied", -> + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 8], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 8], originalEvent: {detail: 2}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 8], originalEvent: {detail: 3}) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedBufferRange()).toEqual [[4, 0], [5, 0]] + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 8], originalEvent: {detail: 1}, shiftKey: true) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedBufferRange()).toEqual [[1, 0], [5, 0]] + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [2, 8], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelection().isEmpty()).toBeTruthy() + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [3, 8], originalEvent: {detail: 1}, shiftKey: true) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedBufferRange()).toEqual [[2, 8], [3, 8]] + + describe "shift-click", -> + it "selects from the cursor's current location to the clicked location", -> + editorView.setCursorScreenPosition([4, 7]) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [5, 24], shiftKey: true) + expect(editorView.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] + + describe "shift-double-click", -> + it "expands the selection on the first click and ignores the second click", -> + editorView.setCursorScreenPosition([4, 7]) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [5, 24], shiftKey: true, originalEvent: { detail: 1 }) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [5, 24], shiftKey: true, originalEvent: { detail: 2 }) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] + + describe "shift-triple-click", -> + it "expands the selection on the first click and ignores the second click", -> + editorView.setCursorScreenPosition([4, 7]) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [5, 24], shiftKey: true, originalEvent: { detail: 1 }) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [5, 24], shiftKey: true, originalEvent: { detail: 2 }) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [5, 24], shiftKey: true, originalEvent: { detail: 3 }) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] + + describe "meta-click", -> + it "places an additional cursor", -> + editorView.attachToDom() + setEditorHeightInLines(editorView, 5) + editorView.setCursorBufferPosition([3, 0]) + editorView.scrollTop(editorView.lineHeight * 6) + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [6, 0], metaKey: true) + expect(editorView.scrollTop()).toBe editorView.lineHeight * (6 - editorView.vScrollMargin) + + [cursor1, cursor2] = editorView.getCursorViews() + expect(cursor1.position()).toEqual(top: 3 * editorView.lineHeight, left: 0) + expect(cursor1.getBufferPosition()).toEqual [3, 0] + expect(cursor2.position()).toEqual(top: 6 * editorView.lineHeight, left: 0) + expect(cursor2.getBufferPosition()).toEqual [6, 0] + + describe "click and drag", -> + it "creates a selection from the initial click to mouse cursor's location ", -> + editorView.attachToDom() + editorView.css(position: 'absolute', top: 10, left: 10) + + # start + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 10]) + + # moving changes selection + $(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27]) + + range = editorView.getSelection().getScreenRange() + expect(range.start).toEqual({row: 4, column: 10}) + expect(range.end).toEqual({row: 5, column: 27}) + expect(editorView.getCursorScreenPosition()).toEqual(row: 5, column: 27) + + # mouse up may occur outside of editorView, but still need to halt selection + $(document).trigger 'mouseup' + + # moving after mouse up should not change selection + editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [8, 8]) + + range = editorView.getSelection().getScreenRange() + expect(range.start).toEqual({row: 4, column: 10}) + expect(range.end).toEqual({row: 5, column: 27}) + expect(editorView.getCursorScreenPosition()).toEqual(row: 5, column: 27) + + it "selects and scrolls if the mouse is dragged outside of the editor view view itself", -> + editorView.vScrollMargin = 0 + editorView.attachToDom(heightInLines: 5) + editorView.scrollToBottom() + + spyOn(window, 'setInterval').andCallFake -> + + # start + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [12, 0]) + originalScrollTop = editorView.scrollTop() + + # moving changes selection + $(document).trigger mousemoveEvent(editorView: editorView, pageX: 0, pageY: -1) + expect(editorView.scrollTop()).toBe originalScrollTop - editorView.lineHeight + + # every mouse move selects more text + for x in [0..10] + $(document).trigger mousemoveEvent(editorView: editorView, pageX: 0, pageY: -1) + + expect(editorView.scrollTop()).toBe 0 + + it "ignores non left-click and drags", -> + editorView.attachToDom() + editorView.css(position: 'absolute', top: 10, left: 10) + + event = mousedownEvent(editorView: editorView, point: [4, 10]) + event.originalEvent.which = 2 + editorView.renderedLines.trigger(event) + $(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27]) + $(document).trigger 'mouseup' + + range = editorView.getSelection().getScreenRange() + expect(range.start).toEqual({row: 4, column: 10}) + expect(range.end).toEqual({row: 4, column: 10}) + + it "ignores ctrl-click and drags", -> + editorView.attachToDom() + editorView.css(position: 'absolute', top: 10, left: 10) + + event = mousedownEvent(editorView: editorView, point: [4, 10]) + event.ctrlKey = true + editorView.renderedLines.trigger(event) + $(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27]) + $(document).trigger 'mouseup' + + range = editorView.getSelection().getScreenRange() + expect(range.start).toEqual({row: 4, column: 10}) + expect(range.end).toEqual({row: 4, column: 10}) + + describe "double-click and drag", -> + it "selects the word under the cursor, then continues to select by word in either direction as the mouse is dragged", -> + expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0) + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 8], originalEvent: {detail: 1}) + editorView.renderedLines.trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 8], originalEvent: {detail: 2}) + expect(editorView.getSelectedText()).toBe "quicksort" + + editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [1, 8]) + expect(editorView.getSelectedBufferRange()).toEqual [[0, 4], [1, 10]] + expect(editorView.getCursorBufferPosition()).toEqual [1, 10] + + editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [0, 1]) + expect(editorView.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]] + expect(editorView.getCursorBufferPosition()).toEqual [0, 0] + + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]] + + # shift-clicking still selects by word, but does not preserve the initial range + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [5, 25], originalEvent: {detail: 1}, shiftKey: true) + editorView.renderedLines.trigger 'mouseup' + expect(editorView.getSelectedBufferRange()).toEqual [[0, 13], [5, 27]] + + describe "triple-click and drag", -> + it "expands the initial selection linewise in either direction", -> + editorView.attachToDom() + + # triple click + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 7], originalEvent: {detail: 1}) + $(document).trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 7], originalEvent: {detail: 2}) + $(document).trigger 'mouseup' + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 7], originalEvent: {detail: 3}) + expect(editorView.getSelectedBufferRange()).toEqual [[4, 0], [5, 0]] + + # moving changes selection linewise + editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [5, 27]) + expect(editorView.getSelectedBufferRange()).toEqual [[4, 0], [6, 0]] + expect(editorView.getCursorBufferPosition()).toEqual [6, 0] + + # moving changes selection linewise + editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [2, 27]) + expect(editorView.getSelectedBufferRange()).toEqual [[2, 0], [5, 0]] + expect(editorView.getCursorBufferPosition()).toEqual [2, 0] + + # mouse up may occur outside of editorView, but still need to halt selection + $(document).trigger 'mouseup' + + describe "meta-click and drag", -> + it "adds an additional selection", -> + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 10]) + editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [5, 27]) + editorView.renderedLines.trigger 'mouseup' + + editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [6, 10], metaKey: true) + editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [8, 27], metaKey: true) + editorView.renderedLines.trigger 'mouseup' + + selections = editorView.getSelections() + expect(selections.length).toBe 2 + [selection1, selection2] = selections + expect(selection1.getScreenRange()).toEqual [[4, 10], [5, 27]] + expect(selection2.getScreenRange()).toEqual [[6, 10], [8, 27]] + + describe "when text input events are triggered on the hidden input element", -> + it "inserts the typed character at the cursor position, both in the buffer and the pre element", -> + editorView.attachToDom() + editorView.setCursorScreenPosition(row: 1, column: 6) + + expect(buffer.lineForRow(1).charAt(6)).not.toBe 'q' + + editorView.hiddenInput.textInput 'q' + + expect(buffer.lineForRow(1).charAt(6)).toBe 'q' + expect(editorView.getCursorScreenPosition()).toEqual(row: 1, column: 7) + expect(editorView.renderedLines.find('.line:eq(1)')).toHaveText buffer.lineForRow(1) + + describe "selection rendering", -> + [charWidth, lineHeight, selection, selectionView] = [] + + beforeEach -> + editorView.attachToDom() + editorView.width(500) + { charWidth, lineHeight } = editorView + selection = editorView.getSelection() + selectionView = editorView.getSelectionView() + + describe "when a selection is added", -> + it "adds a selection view for it with the proper regions", -> + editorView.activeEditSession.addSelectionForBufferRange([[2, 7], [2, 25]]) + selectionViews = editorView.getSelectionViews() + expect(selectionViews.length).toBe 2 + expect(selectionViews[1].regions.length).toBe 1 + region = selectionViews[1].regions[0] + expect(region.position().top).toBeCloseTo(2 * lineHeight) + expect(region.position().left).toBeCloseTo(7 * charWidth) + expect(region.height()).toBeCloseTo lineHeight + expect(region.width()).toBeCloseTo((25 - 7) * charWidth) + + describe "when a selection changes", -> + describe "when the selection is within a single line", -> + it "covers the selection's range with a single region", -> + selection.setBufferRange([[2, 7], [2, 25]]) + + expect(selectionView.regions.length).toBe 1 + region = selectionView.regions[0] + expect(region.position().top).toBeCloseTo(2 * lineHeight) + expect(region.position().left).toBeCloseTo(7 * charWidth) + expect(region.height()).toBeCloseTo lineHeight + expect(region.width()).toBeCloseTo((25 - 7) * charWidth) + + describe "when the selection spans 2 lines", -> + it "covers the selection's range with 2 regions", -> + selection.setBufferRange([[2,7],[3,25]]) + + expect(selectionView.regions.length).toBe 2 + + region1 = selectionView.regions[0] + expect(region1.position().top).toBeCloseTo(2 * lineHeight) + expect(region1.position().left).toBeCloseTo(7 * charWidth) + expect(region1.height()).toBeCloseTo lineHeight + + expect(region1.width()).toBeCloseTo(editorView.renderedLines.outerWidth() - region1.position().left) + region2 = selectionView.regions[1] + expect(region2.position().top).toBeCloseTo(3 * lineHeight) + expect(region2.position().left).toBeCloseTo(0) + expect(region2.height()).toBeCloseTo lineHeight + expect(region2.width()).toBeCloseTo(25 * charWidth) + + describe "when the selection spans more than 2 lines", -> + it "covers the selection's range with 3 regions", -> + selection.setBufferRange([[2,7],[6,25]]) + + expect(selectionView.regions.length).toBe 3 + + region1 = selectionView.regions[0] + expect(region1.position().top).toBeCloseTo(2 * lineHeight) + expect(region1.position().left).toBeCloseTo(7 * charWidth) + expect(region1.height()).toBeCloseTo lineHeight + + expect(region1.width()).toBeCloseTo(editorView.renderedLines.outerWidth() - region1.position().left) + region2 = selectionView.regions[1] + expect(region2.position().top).toBeCloseTo(3 * lineHeight) + expect(region2.position().left).toBeCloseTo(0) + expect(region2.height()).toBeCloseTo(3 * lineHeight) + expect(region2.width()).toBeCloseTo(editorView.renderedLines.outerWidth()) + + # resizes with the editorView + expect(editorView.width()).toBeLessThan(800) + editorView.width(800) + editorView.resize() # call to trigger the resize event. + + region2 = selectionView.regions[1] + expect(region2.width()).toBe(editorView.renderedLines.outerWidth()) + + region3 = selectionView.regions[2] + expect(region3.position().top).toBeCloseTo(6 * lineHeight) + expect(region3.position().left).toBeCloseTo(0) + expect(region3.height()).toBeCloseTo lineHeight + expect(region3.width()).toBeCloseTo(25 * charWidth) + + it "clears previously drawn regions before creating new ones", -> + selection.setBufferRange([[2,7],[4,25]]) + expect(selectionView.regions.length).toBe 3 + expect(selectionView.find('.region').length).toBe 3 + + selectionView.updateDisplay() + expect(selectionView.regions.length).toBe 3 + expect(selectionView.find('.region').length).toBe 3 + + describe "when a selection merges with another selection", -> + it "removes the merged selection view", -> + editSession = editorView.activeEditSession + editSession.setCursorScreenPosition([4, 10]) + editSession.selectToScreenPosition([5, 27]) + editSession.addCursorAtScreenPosition([3, 10]) + editSession.selectToScreenPosition([6, 27]) + + expect(editorView.getSelectionViews().length).toBe 1 + expect(editorView.find('.region').length).toBe 3 + + describe "when a selection is added and removed before the display is updated", -> + it "does not attempt to render the selection", -> + # don't update display until we request it + jasmine.unspy(editorView, 'requestDisplayUpdate') + spyOn(editorView, 'requestDisplayUpdate') + + editSession = editorView.activeEditSession + selection = editSession.addSelectionForBufferRange([[3, 0], [3, 4]]) + selection.destroy() + editorView.updateDisplay() + expect(editorView.getSelectionViews().length).toBe 1 + + describe "when the selection is created with the selectAll event", -> + it "does not scroll to the end of the buffer", -> + editorView.height(150) + editorView.selectAll() + expect(editorView.scrollTop()).toBe 0 + + # regression: does not scroll the scroll view when the editorView is refocused + editorView.hiddenInput.blur() + editorView.hiddenInput.focus() + expect(editorView.scrollTop()).toBe 0 + expect(editorView.scrollView.scrollTop()).toBe 0 + + # does autoscroll when the selection is cleared + editorView.moveCursorDown() + expect(editorView.scrollTop()).toBeGreaterThan(0) + + describe "selection autoscrolling and highlighting when setting selected buffer range", -> + beforeEach -> + setEditorHeightInLines(editorView, 4) + + describe "if autoscroll is true", -> + it "centers the viewport on the selection if its vertical center is currently offscreen", -> + editorView.setSelectedBufferRange([[2, 0], [4, 0]], autoscroll: true) + expect(editorView.scrollTop()).toBe 0 + + editorView.setSelectedBufferRange([[6, 0], [8, 0]], autoscroll: true) + expect(editorView.scrollTop()).toBe 5 * editorView.lineHeight + + it "highlights the selection if autoscroll is true", -> + editorView.setSelectedBufferRange([[2, 0], [4, 0]], autoscroll: true) + expect(editorView.getSelectionView()).toHaveClass 'highlighted' + advanceClock(1000) + expect(editorView.getSelectionView()).not.toHaveClass 'highlighted' + + editorView.setSelectedBufferRange([[3, 0], [5, 0]], autoscroll: true) + expect(editorView.getSelectionView()).toHaveClass 'highlighted' + + advanceClock(500) + spyOn(editorView.getSelectionView(), 'removeClass').andCallThrough() + editorView.setSelectedBufferRange([[2, 0], [4, 0]], autoscroll: true) + expect(editorView.getSelectionView().removeClass).toHaveBeenCalledWith('highlighted') + expect(editorView.getSelectionView()).toHaveClass 'highlighted' + + advanceClock(500) + expect(editorView.getSelectionView()).toHaveClass 'highlighted' + + describe "if autoscroll is false", -> + it "does not scroll to the selection or the cursor", -> + editorView.scrollToBottom() + scrollTopBefore = editorView.scrollTop() + editorView.setSelectedBufferRange([[0, 0], [1, 0]], autoscroll: false) + expect(editorView.scrollTop()).toBe scrollTopBefore + + describe "if autoscroll is not specified", -> + it "autoscrolls to the cursor as normal", -> + editorView.scrollToBottom() + editorView.setSelectedBufferRange([[0, 0], [1, 0]]) + expect(editorView.scrollTop()).toBe 0 + + describe "cursor rendering", -> + describe "when the cursor moves", -> + charWidth = null + + beforeEach -> + editorView.attachToDom() + editorView.vScrollMargin = 3 + editorView.hScrollMargin = 5 + {charWidth} = editorView + + it "repositions the cursor's view on screen", -> + editorView.setCursorScreenPosition(row: 2, column: 2) + expect(editorView.getCursorView().position()).toEqual(top: 2 * editorView.lineHeight, left: 2 * editorView.charWidth) + + it "hides the cursor when the selection is non-empty, and shows it otherwise", -> + cursorView = editorView.getCursorView() + expect(editorView.getSelection().isEmpty()).toBeTruthy() + expect(cursorView).toBeVisible() + + editorView.setSelectedBufferRange([[0, 0], [3, 0]]) + expect(editorView.getSelection().isEmpty()).toBeFalsy() + expect(cursorView).toBeHidden() + + editorView.setCursorBufferPosition([1, 3]) + expect(editorView.getSelection().isEmpty()).toBeTruthy() + expect(cursorView).toBeVisible() + + it "moves the hiddenInput to the same position with cursor's view", -> + editorView.setCursorScreenPosition(row: 2, column: 2) + expect(editorView.getCursorView().offset()).toEqual(editorView.hiddenInput.offset()) + + describe "when the editor view is using a variable-width font", -> + beforeEach -> + editorView.setFontFamily('sans-serif') + + describe "on #darwin or #linux", -> + it "correctly positions the cursor", -> + editorView.setCursorBufferPosition([3, 30]) + expect(editorView.getCursorView().position()).toEqual {top: 3 * editorView.lineHeight, left: 178} + editorView.setCursorBufferPosition([3, Infinity]) + expect(editorView.getCursorView().position()).toEqual {top: 3 * editorView.lineHeight, left: 353} + + describe "on #win32", -> + it "correctly positions the cursor", -> + editorView.setCursorBufferPosition([3, 30]) + expect(editorView.getCursorView().position()).toEqual {top: 3 * editorView.lineHeight, left: 175} + editorView.setCursorBufferPosition([3, Infinity]) + expect(editorView.getCursorView().position()).toEqual {top: 3 * editorView.lineHeight, left: 346} + + describe "autoscrolling", -> + it "only autoscrolls when the last cursor is moved", -> + editorView.setCursorBufferPosition([11,0]) + editorView.addCursorAtBufferPosition([6,50]) + [cursor1, cursor2] = editorView.getCursors() + + spyOn(editorView, 'scrollToPixelPosition') + cursor1.setScreenPosition([10, 10]) + expect(editorView.scrollToPixelPosition).not.toHaveBeenCalled() + + cursor2.setScreenPosition([11, 11]) + expect(editorView.scrollToPixelPosition).toHaveBeenCalled() + + it "does not autoscroll if the 'autoscroll' option is false", -> + editorView.setCursorBufferPosition([11,0]) + spyOn(editorView, 'scrollToPixelPosition') + editorView.setCursorScreenPosition([10, 10], autoscroll: false) + expect(editorView.scrollToPixelPosition).not.toHaveBeenCalled() + + it "autoscrolls to cursor if autoscroll is true, even if the position does not change", -> + spyOn(editorView, 'scrollToPixelPosition') + editorView.setCursorScreenPosition([4, 10], autoscroll: false) + editorView.setCursorScreenPosition([4, 10]) + expect(editorView.scrollToPixelPosition).toHaveBeenCalled() + editorView.scrollToPixelPosition.reset() + + editorView.setCursorBufferPosition([4, 10]) + expect(editorView.scrollToPixelPosition).toHaveBeenCalled() + + it "does not autoscroll the cursor based on a buffer change, unless the buffer change was initiated by the cursor", -> + lastVisibleRow = editorView.getLastVisibleScreenRow() + editorView.addCursorAtBufferPosition([lastVisibleRow, 0]) + spyOn(editorView, 'scrollToPixelPosition') + buffer.insert([lastVisibleRow, 0], "\n\n") + expect(editorView.scrollToPixelPosition).not.toHaveBeenCalled() + editorView.insertText('\n\n') + expect(editorView.scrollToPixelPosition.callCount).toBe 1 + + it "autoscrolls on undo/redo", -> + spyOn(editorView, 'scrollToPixelPosition') + editorView.insertText('\n\n') + expect(editorView.scrollToPixelPosition.callCount).toBe 1 + editorView.undo() + expect(editorView.scrollToPixelPosition.callCount).toBe 2 + editorView.redo() + expect(editorView.scrollToPixelPosition.callCount).toBe 3 + + describe "when the last cursor exceeds the upper or lower scroll margins", -> + describe "when the editor view is taller than twice the vertical scroll margin", -> + it "sets the scrollTop so the cursor remains within the scroll margin", -> + setEditorHeightInLines(editorView, 10) + + _.times 6, -> editorView.moveCursorDown() + expect(editorView.scrollTop()).toBe(0) + + editorView.moveCursorDown() + expect(editorView.scrollTop()).toBe(editorView.lineHeight) + + editorView.moveCursorDown() + expect(editorView.scrollTop()).toBe(editorView.lineHeight * 2) + + _.times 3, -> editorView.moveCursorUp() + + editorView.moveCursorUp() + expect(editorView.scrollTop()).toBe(editorView.lineHeight) + + editorView.moveCursorUp() + expect(editorView.scrollTop()).toBe(0) + + describe "when the editor view is shorter than twice the vertical scroll margin", -> + it "sets the scrollTop based on a reduced scroll margin, which prevents a jerky tug-of-war between upper and lower scroll margins", -> + setEditorHeightInLines(editorView, 5) + + _.times 3, -> editorView.moveCursorDown() + + expect(editorView.scrollTop()).toBe(editorView.lineHeight) + + editorView.moveCursorUp() + expect(editorView.renderedLines.css('top')).toBe "0px" + + describe "when the last cursor exceeds the right or left scroll margins", -> + describe "when soft-wrap is disabled", -> + describe "when the editor view is wider than twice the horizontal scroll margin", -> + it "sets the scrollView's scrollLeft so the cursor remains within the scroll margin", -> + setEditorWidthInChars(editorView, 30) + + # moving right + editorView.setCursorScreenPosition([2, 24]) + expect(editorView.scrollLeft()).toBe 0 + + editorView.setCursorScreenPosition([2, 25]) + expect(editorView.scrollLeft()).toBe charWidth + + editorView.setCursorScreenPosition([2, 28]) + expect(editorView.scrollLeft()).toBe charWidth * 4 + + # moving left + editorView.setCursorScreenPosition([2, 9]) + expect(editorView.scrollLeft()).toBe charWidth * 4 + + editorView.setCursorScreenPosition([2, 8]) + expect(editorView.scrollLeft()).toBe charWidth * 3 + + editorView.setCursorScreenPosition([2, 5]) + expect(editorView.scrollLeft()).toBe 0 + + describe "when the editor view is narrower than twice the horizontal scroll margin", -> + it "sets the scrollView's scrollLeft based on a reduced horizontal scroll margin, to prevent a jerky tug-of-war between right and left scroll margins", -> + editorView.hScrollMargin = 6 + setEditorWidthInChars(editorView, 7) + + editorView.setCursorScreenPosition([2, 3]) + window.advanceClock() + expect(editorView.scrollLeft()).toBe(0) + + editorView.setCursorScreenPosition([2, 4]) + window.advanceClock() + expect(editorView.scrollLeft()).toBe(charWidth) + + editorView.setCursorScreenPosition([2, 3]) + window.advanceClock() + expect(editorView.scrollLeft()).toBe(0) + + describe "when soft-wrap is enabled", -> + beforeEach -> + editSession.setSoftWrap(true) + + it "does not scroll the buffer horizontally", -> + editorView.width(charWidth * 30) + + # moving right + editorView.setCursorScreenPosition([2, 24]) + expect(editorView.scrollLeft()).toBe 0 + + editorView.setCursorScreenPosition([2, 25]) + expect(editorView.scrollLeft()).toBe 0 + + editorView.setCursorScreenPosition([2, 28]) + expect(editorView.scrollLeft()).toBe 0 + + # moving left + editorView.setCursorScreenPosition([2, 9]) + expect(editorView.scrollLeft()).toBe 0 + + editorView.setCursorScreenPosition([2, 8]) + expect(editorView.scrollLeft()).toBe 0 + + editorView.setCursorScreenPosition([2, 5]) + expect(editorView.scrollLeft()).toBe 0 + + describe "when editor:toggle-soft-wrap is toggled", -> + describe "when the text exceeds the editor view width and the scroll-view is horizontally scrolled", -> + it "wraps the text and renders properly", -> + editorView.attachToDom(heightInLines: 30, widthInChars: 30) + editorView.setWidthInChars(100) + editorView.setText("Fashion axe umami jean shorts retro hashtag carles mumblecore. Photo booth skateboard Austin gentrify occupy ethical. Food truck gastropub keffiyeh, squid deep v pinterest literally sustainable salvia scenester messenger bag. Neutra messenger bag flexitarian four loko, shoreditch VHS pop-up tumblr seitan synth master cleanse. Marfa selvage ugh, raw denim authentic try-hard mcsweeney's trust fund fashion axe actually polaroid viral sriracha. Banh mi marfa plaid single-origin coffee. Pickled mumblecore lomo ugh bespoke.") + editorView.scrollLeft(editorView.charWidth * 30) + editorView.trigger "editor:toggle-soft-wrap" + expect(editorView.scrollLeft()).toBe 0 + expect(editorView.activeEditSession.getSoftWrapColumn()).not.toBe 100 + + describe "text rendering", -> + describe "when all lines in the buffer are visible on screen", -> + beforeEach -> + editorView.attachToDom() + expect(editorView.trueHeight()).toBeCloseTo buffer.getLineCount() * editorView.lineHeight + + it "creates a line element for each line in the buffer with the html-escaped text of the line", -> + expect(editorView.renderedLines.find('.line').length).toEqual(buffer.getLineCount()) + expect(buffer.lineForRow(2)).toContain('<') + expect(editorView.renderedLines.find('.line:eq(2)').html()).toContain '<' + + # renders empty lines with a non breaking space + expect(buffer.lineForRow(10)).toBe '' + expect(editorView.renderedLines.find('.line:eq(10)').html()).toBe ' ' + + it "syntax highlights code based on the file type", -> + line0 = editorView.renderedLines.find('.line:first') + span0 = line0.children('span:eq(0)') + expect(span0).toMatchSelector '.source.js' + expect(span0.children('span:eq(0)')).toMatchSelector '.storage.modifier.js' + expect(span0.children('span:eq(0)').text()).toBe 'var' + + span0_1 = span0.children('span:eq(1)') + expect(span0_1).toMatchSelector '.meta.function.js' + expect(span0_1.text()).toBe 'quicksort = function ()' + expect(span0_1.children('span:eq(0)')).toMatchSelector '.entity.name.function.js' + expect(span0_1.children('span:eq(0)').text()).toBe "quicksort" + expect(span0_1.children('span:eq(1)')).toMatchSelector '.keyword.operator.js' + expect(span0_1.children('span:eq(1)').text()).toBe "=" + expect(span0_1.children('span:eq(2)')).toMatchSelector '.storage.type.function.js' + expect(span0_1.children('span:eq(2)').text()).toBe "function" + expect(span0_1.children('span:eq(3)')).toMatchSelector '.punctuation.definition.parameters.begin.js' + expect(span0_1.children('span:eq(3)').text()).toBe "(" + expect(span0_1.children('span:eq(4)')).toMatchSelector '.punctuation.definition.parameters.end.js' + expect(span0_1.children('span:eq(4)').text()).toBe ")" + + expect(span0.children('span:eq(2)')).toMatchSelector '.meta.brace.curly.js' + expect(span0.children('span:eq(2)').text()).toBe "{" + + line12 = editorView.renderedLines.find('.line:eq(11)').children('span:eq(0)') + expect(line12.children('span:eq(1)')).toMatchSelector '.keyword' + + it "wraps hard tabs in a span", -> + editorView.setText('\t<- hard tab') + line0 = editorView.renderedLines.find('.line:first') + span0_0 = line0.children('span:eq(0)').children('span:eq(0)') + expect(span0_0).toMatchSelector '.hard-tab' + expect(span0_0.text()).toBe ' ' + + it "wraps leading whitespace in a span", -> + line1 = editorView.renderedLines.find('.line:eq(1)') + span0_0 = line1.children('span:eq(0)').children('span:eq(0)') + expect(span0_0).toMatchSelector '.leading-whitespace' + expect(span0_0.text()).toBe ' ' + + describe "when the line has trailing whitespace", -> + it "wraps trailing whitespace in a span", -> + editorView.setText('trailing whitespace -> ') + line0 = editorView.renderedLines.find('.line:first') + span0_last = line0.children('span:eq(0)').children('span:last') + expect(span0_last).toMatchSelector '.trailing-whitespace' + expect(span0_last.text()).toBe ' ' + + describe "when lines are updated in the buffer", -> + it "syntax highlights the updated lines", -> + expect(editorView.renderedLines.find('.line:eq(0) > span:first > span:first')).toMatchSelector '.storage.modifier.js' + buffer.insert([0, 0], "q") + expect(editorView.renderedLines.find('.line:eq(0) > span:first > span:first')).not.toMatchSelector '.storage.modifier.js' + + # verify that re-highlighting can occur below the changed line + buffer.insert([5,0], "/* */") + buffer.insert([1,0], "/*") + expect(editorView.renderedLines.find('.line:eq(2) > span:first > span:first')).toMatchSelector '.comment' + + describe "when some lines at the end of the buffer are not visible on screen", -> + beforeEach -> + editorView.attachToDom(heightInLines: 5.5) + + it "only renders the visible lines plus the overdrawn lines, setting the padding-bottom of the lines element to account for the missing lines", -> + expect(editorView.renderedLines.find('.line').length).toBe 8 + expectedPaddingBottom = (buffer.getLineCount() - 8) * editorView.lineHeight + expect(editorView.renderedLines.css('padding-bottom')).toBe "#{expectedPaddingBottom}px" + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) + + it "renders additional lines when the editor view is resized", -> + setEditorHeightInLines(editorView, 10) + $(window).trigger 'resize' + + expect(editorView.renderedLines.find('.line').length).toBe 12 + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(11) + + it "renders correctly when scrolling after text is added to the buffer", -> + editorView.insertText("1\n") + _.times 4, -> editorView.moveCursorDown() + expect(editorView.renderedLines.find('.line:eq(2)').text()).toBe editorView.lineForBufferRow(2) + expect(editorView.renderedLines.find('.line:eq(7)').text()).toBe editorView.lineForBufferRow(7) + + it "renders correctly when scrolling after text is removed from buffer", -> + editorView.getBuffer().delete([[0,0],[1,0]]) + expect(editorView.renderedLines.find('.line:eq(0)').text()).toBe editorView.lineForBufferRow(0) + expect(editorView.renderedLines.find('.line:eq(5)').text()).toBe editorView.lineForBufferRow(5) + + editorView.scrollTop(3 * editorView.lineHeight) + expect(editorView.renderedLines.find('.line:first').text()).toBe editorView.lineForBufferRow(1) + expect(editorView.renderedLines.find('.line:last').text()).toBe editorView.lineForBufferRow(10) + + describe "when creating and destroying folds that are longer than the visible lines", -> + describe "when the cursor precedes the fold when it is destroyed", -> + it "renders lines and line numbers correctly", -> + scrollHeightBeforeFold = editorView.scrollView.prop('scrollHeight') + fold = editorView.createFold(1, 9) + fold.destroy() + expect(editorView.scrollView.prop('scrollHeight')).toBe scrollHeightBeforeFold + + expect(editorView.renderedLines.find('.line').length).toBe 8 + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) + + expect(editorView.gutter.find('.line-number').length).toBe 8 + expect(editorView.gutter.find('.line-number:last').intValue()).toBe 8 + + editorView.scrollTop(4 * editorView.lineHeight) + expect(editorView.renderedLines.find('.line').length).toBe 10 + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(11) + + describe "when the cursor follows the fold when it is destroyed", -> + it "renders lines and line numbers correctly", -> + fold = editorView.createFold(1, 9) + editorView.setCursorBufferPosition([10, 0]) + fold.destroy() + + expect(editorView.renderedLines.find('.line').length).toBe 8 + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(12) + + expect(editorView.gutter.find('.line-number').length).toBe 8 + expect(editorView.gutter.find('.line-number:last').text()).toBe '13' + + editorView.scrollTop(4 * editorView.lineHeight) + + expect(editorView.renderedLines.find('.line').length).toBe 10 + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(11) + + describe "when scrolling vertically", -> + describe "when scrolling less than the editor view's height", -> + it "draws new lines and removes old lines when the last visible line will exceed the last rendered line", -> + expect(editorView.renderedLines.find('.line').length).toBe 8 + + editorView.scrollTop(editorView.lineHeight * 1.5) + expect(editorView.renderedLines.find('.line').length).toBe 8 + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) + + editorView.scrollTop(editorView.lineHeight * 3.5) # first visible row will be 3, last will be 8 + expect(editorView.renderedLines.find('.line').length).toBe 10 + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(1) + expect(editorView.renderedLines.find('.line:last').html()).toBe ' ' # line 10 is blank + expect(editorView.gutter.find('.line-number:first').intValue()).toBe 2 + expect(editorView.gutter.find('.line-number:last').intValue()).toBe 11 + + # here we don't scroll far enough to trigger additional rendering + editorView.scrollTop(editorView.lineHeight * 5.5) # first visible row will be 5, last will be 10 + expect(editorView.renderedLines.find('.line').length).toBe 10 + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(1) + expect(editorView.renderedLines.find('.line:last').html()).toBe ' ' # line 10 is blank + expect(editorView.gutter.find('.line-number:first').intValue()).toBe 2 + expect(editorView.gutter.find('.line-number:last').intValue()).toBe 11 + + editorView.scrollTop(editorView.lineHeight * 7.5) # first visible row is 7, last will be 12 + expect(editorView.renderedLines.find('.line').length).toBe 8 + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(5) + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(12) + + editorView.scrollTop(editorView.lineHeight * 3.5) # first visible row will be 3, last will be 8 + expect(editorView.renderedLines.find('.line').length).toBe 10 + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(1) + expect(editorView.renderedLines.find('.line:last').html()).toBe ' ' # line 10 is blank + + editorView.scrollTop(0) + expect(editorView.renderedLines.find('.line').length).toBe 8 + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) + + describe "when scrolling more than the editors height", -> + it "removes lines that are offscreen and not in range of the overdraw and builds lines that become visible", -> + editorView.scrollTop(editorView.layerHeight - editorView.scrollView.height()) + expect(editorView.renderedLines.find('.line').length).toBe 8 + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(5) + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(12) + + editorView.verticalScrollbar.scrollBottom(0) + editorView.verticalScrollbar.trigger 'scroll' + expect(editorView.renderedLines.find('.line').length).toBe 8 + expect(editorView.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) + expect(editorView.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) + + it "adjusts the vertical padding of the lines element to account for non-rendered lines", -> + editorView.scrollTop(editorView.lineHeight * 3) + firstVisibleBufferRow = 3 + expectedPaddingTop = (firstVisibleBufferRow - editorView.lineOverdraw) * editorView.lineHeight + expect(editorView.renderedLines.css('padding-top')).toBe "#{expectedPaddingTop}px" + + lastVisibleBufferRow = Math.ceil(3 + 5.5) # scroll top in lines + height in lines + lastOverdrawnRow = lastVisibleBufferRow + editorView.lineOverdraw + expectedPaddingBottom = ((buffer.getLineCount() - lastOverdrawnRow) * editorView.lineHeight) + expect(editorView.renderedLines.css('padding-bottom')).toBe "#{expectedPaddingBottom}px" + + editorView.scrollToBottom() + # scrolled to bottom, first visible row is 5 and first rendered row is 3 + firstVisibleBufferRow = Math.floor(buffer.getLineCount() - 5.5) + firstOverdrawnBufferRow = firstVisibleBufferRow - editorView.lineOverdraw + expectedPaddingTop = firstOverdrawnBufferRow * editorView.lineHeight + expect(editorView.renderedLines.css('padding-top')).toBe "#{expectedPaddingTop}px" + expect(editorView.renderedLines.css('padding-bottom')).toBe "0px" + + describe "when lines are added", -> + beforeEach -> + editorView.attachToDom(heightInLines: 5) + + describe "when the change precedes the first rendered row", -> + it "inserts and removes rendered lines to account for upstream change", -> + editorView.scrollToBottom() + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) + + buffer.change([[1,0], [3,0]], "1\n2\n3\n") + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) + + describe "when the change straddles the first rendered row", -> + it "doesn't render rows that were not previously rendered", -> + editorView.scrollToBottom() + + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) + + buffer.change([[2,0], [7,0]], "2\n3\n4\n5\n6\n7\n8\n9\n") + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) + + describe "when the change straddles the last rendered row", -> + it "doesn't render rows that were not previously rendered", -> + buffer.change([[2,0], [7,0]], "2\n3\n4\n5\n6\n7\n8\n") + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6) + + describe "when the change the follows the last rendered row", -> + it "does not change the rendered lines", -> + buffer.change([[12,0], [12,0]], "12\n13\n14\n") + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6) + + it "increases the width of the rendered lines element to be either the width of the longest line or the width of the scrollView (whichever is longer)", -> + maxLineLength = editorView.getMaxScreenLineLength() + setEditorWidthInChars(editorView, maxLineLength) + widthBefore = editorView.renderedLines.width() + expect(widthBefore).toBe editorView.scrollView.width() + 20 + buffer.change([[12,0], [12,0]], [1..maxLineLength*2].join('')) + expect(editorView.renderedLines.width()).toBeGreaterThan widthBefore + + describe "when lines are removed", -> + beforeEach -> + editorView.attachToDom(heightInLines: 5) + + it "sets the rendered screen line's width to either the max line length or the scollView's width (whichever is greater)", -> + maxLineLength = editorView.getMaxScreenLineLength() + setEditorWidthInChars(editorView, maxLineLength) + buffer.change([[12,0], [12,0]], [1..maxLineLength*2].join('')) + expect(editorView.renderedLines.width()).toBeGreaterThan editorView.scrollView.width() + widthBefore = editorView.renderedLines.width() + buffer.delete([[12, 0], [12, Infinity]]) + expect(editorView.renderedLines.width()).toBe editorView.scrollView.width() + 20 + + describe "when the change the precedes the first rendered row", -> + it "removes rendered lines to account for upstream change", -> + editorView.scrollToBottom() + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) + + buffer.change([[1,0], [2,0]], "") + expect(editorView.renderedLines.find(".line").length).toBe 6 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(11) + + describe "when the change straddles the first rendered row", -> + it "renders the correct rows", -> + editorView.scrollToBottom() + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) + + buffer.change([[7,0], [11,0]], "1\n2\n") + expect(editorView.renderedLines.find(".line").length).toBe 5 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(10) + + describe "when the change straddles the last rendered row", -> + it "renders the correct rows", -> + buffer.change([[2,0], [7,0]], "") + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6) + + describe "when the change the follows the last rendered row", -> + it "does not change the rendered lines", -> + buffer.change([[10,0], [12,0]], "") + expect(editorView.renderedLines.find(".line").length).toBe 7 + expect(editorView.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0) + expect(editorView.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6) + + describe "when the last line is removed when the editor view is scrolled to the bottom", -> + it "reduces the editor view's scrollTop (due to the reduced total scroll height) and renders the correct screen lines", -> + editorView.setCursorScreenPosition([Infinity, Infinity]) + editorView.insertText('\n\n\n') + editorView.scrollToBottom() + + expect(buffer.getLineCount()).toBe 16 + + initialScrollTop = editorView.scrollTop() + expect(editorView.firstRenderedScreenRow).toBe 9 + expect(editorView.lastRenderedScreenRow).toBe 15 + + editorView.backspace() + + expect(editorView.scrollTop()).toBeLessThan initialScrollTop + expect(editorView.firstRenderedScreenRow).toBe 9 + expect(editorView.lastRenderedScreenRow).toBe 14 + + expect(editorView.find('.line').length).toBe 6 + + editorView.backspace() + expect(editorView.firstRenderedScreenRow).toBe 9 + expect(editorView.lastRenderedScreenRow).toBe 13 + + expect(editorView.find('.line').length).toBe 5 + + editorView.backspace() + expect(editorView.firstRenderedScreenRow).toBe 6 + expect(editorView.lastRenderedScreenRow).toBe 12 + + expect(editorView.find('.line').length).toBe 7 + + describe "when folding leaves less then a screen worth of text (regression)", -> + it "renders lines properly", -> + editorView.lineOverdraw = 1 + editorView.attachToDom(heightInLines: 5) + editorView.activeEditSession.foldBufferRow(4) + editorView.activeEditSession.foldBufferRow(0) + + expect(editorView.renderedLines.find('.line').length).toBe 1 + expect(editorView.renderedLines.find('.line').text()).toBe buffer.lineForRow(0) + + describe "when folding leaves fewer screen lines than the first rendered screen line (regression)", -> + it "clears all screen lines and does not throw any exceptions", -> + editorView.lineOverdraw = 1 + editorView.attachToDom(heightInLines: 5) + editorView.scrollToBottom() + editorView.activeEditSession.foldBufferRow(0) + expect(editorView.renderedLines.find('.line').length).toBe 1 + expect(editorView.renderedLines.find('.line').text()).toBe buffer.lineForRow(0) + + describe "when autoscrolling at the end of the document", -> + it "renders lines properly", -> + editorView.edit(project.openSync('two-hundred.txt')) + editorView.attachToDom(heightInLines: 5.5) + + expect(editorView.renderedLines.find('.line').length).toBe 8 + + editorView.moveCursorToBottom() + + expect(editorView.renderedLines.find('.line').length).toBe 8 + + describe "when line has a character that could push it to be too tall (regression)", -> + it "does renders the line at a consistent height", -> + editorView.attachToDom() + buffer.insert([0, 0], "–") + expect(editorView.find('.line:eq(0)').outerHeight()).toBe editorView.find('.line:eq(1)').outerHeight() + + describe "when editor.showInvisibles config is set to true", -> + it "displays spaces, tabs, and newlines using visible non-empty values", -> + editorView.setText " a line with tabs\tand spaces " + editorView.attachToDom() + + expect(atom.config.get("editor.showInvisibles")).toBeFalsy() + expect(editorView.renderedLines.find('.line').text()).toBe " a line with tabs and spaces " + + atom.config.set("editor.showInvisibles", true) + space = editorView.invisibles?.space + expect(space).toBeTruthy() + tab = editorView.invisibles?.tab + expect(tab).toBeTruthy() + eol = editorView.invisibles?.eol + expect(eol).toBeTruthy() + expect(editorView.renderedLines.find('.line').text()).toBe "#{space}a line with tabs#{tab} and spaces#{space}#{eol}" + + atom.config.set("editor.showInvisibles", false) + expect(editorView.renderedLines.find('.line').text()).toBe " a line with tabs and spaces " + + it "displays newlines as their own token outside of the other tokens scope", -> + editorView.setShowInvisibles(true) + editorView.attachToDom() + editorView.setText "var" + expect(editorView.find('.line').html()).toBe 'var¬' + + it "allows invisible glyphs to be customized via the editor.invisibles config", -> + editorView.setText(" \t ") + editorView.attachToDom() + atom.config.set("editor.showInvisibles", true) + atom.config.set("editor.invisibles", eol: ";", space: "_", tab: "tab") + expect(editorView.find(".line:first").text()).toBe "_tab _;" + + it "displays trailing carriage return using a visible non-empty value", -> + editorView.setText "a line that ends with a carriage return\r\n" + editorView.attachToDom() + + expect(atom.config.get("editor.showInvisibles")).toBeFalsy() + expect(editorView.renderedLines.find('.line:first').text()).toBe "a line that ends with a carriage return" + + atom.config.set("editor.showInvisibles", true) + cr = editorView.invisibles?.cr + expect(cr).toBeTruthy() + eol = editorView.invisibles?.eol + expect(eol).toBeTruthy() + expect(editorView.renderedLines.find('.line:first').text()).toBe "a line that ends with a carriage return#{cr}#{eol}" + + describe "when wrapping is on", -> + beforeEach -> + editSession.setSoftWrap(true) + + it "doesn't show the end of line invisible at the end of lines broken due to wrapping", -> + editorView.setText "a line that wraps" + editorView.attachToDom() + editorView.setWidthInChars(6) + atom.config.set "editor.showInvisibles", true + space = editorView.invisibles?.space + expect(space).toBeTruthy() + eol = editorView.invisibles?.eol + expect(eol).toBeTruthy() + expect(editorView.renderedLines.find('.line:first').text()).toBe "a line#{space}" + expect(editorView.renderedLines.find('.line:last').text()).toBe "wraps#{eol}" + + it "displays trailing carriage return using a visible non-empty value", -> + editorView.setText "a line that\r\n" + editorView.attachToDom() + editorView.setWidthInChars(6) + atom.config.set "editor.showInvisibles", true + space = editorView.invisibles?.space + expect(space).toBeTruthy() + cr = editorView.invisibles?.cr + expect(cr).toBeTruthy() + eol = editorView.invisibles?.eol + expect(eol).toBeTruthy() + expect(editorView.renderedLines.find('.line:first').text()).toBe "a line#{space}" + expect(editorView.renderedLines.find('.line:eq(1)').text()).toBe "that#{cr}#{eol}" + expect(editorView.renderedLines.find('.line:last').text()).toBe "#{eol}" + + describe "when editor.showIndentGuide is set to true", -> + it "adds an indent-guide class to each leading whitespace span", -> + editorView.attachToDom() + + expect(atom.config.get("editor.showIndentGuide")).toBeFalsy() + atom.config.set("editor.showIndentGuide", true) + expect(editorView.showIndentGuide).toBeTruthy() + + expect(editorView.renderedLines.find('.line:eq(0) .indent-guide').length).toBe 0 + + expect(editorView.renderedLines.find('.line:eq(1) .indent-guide').length).toBe 1 + expect(editorView.renderedLines.find('.line:eq(1) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(2) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(2) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(3) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(3) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(4) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(4) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(5) .indent-guide').length).toBe 3 + expect(editorView.renderedLines.find('.line:eq(5) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(6) .indent-guide').length).toBe 3 + expect(editorView.renderedLines.find('.line:eq(6) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(7) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(7) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(8) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(8) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(9) .indent-guide').length).toBe 1 + expect(editorView.renderedLines.find('.line:eq(9) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1 + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(11) .indent-guide').length).toBe 1 + expect(editorView.renderedLines.find('.line:eq(11) .indent-guide').text()).toBe ' ' + + expect(editorView.renderedLines.find('.line:eq(12) .indent-guide').length).toBe 0 + + describe "when the indentation level on a line before an empty line is changed", -> + it "updates the indent guide on the empty line", -> + editorView.attachToDom() + atom.config.set("editor.showIndentGuide", true) + + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1 + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' + + editorView.setCursorBufferPosition([9]) + editorView.indentSelectedRows() + + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' + + describe "when the indentation level on a line after an empty line is changed", -> + it "updates the indent guide on the empty line", -> + editorView.attachToDom() + atom.config.set("editor.showIndentGuide", true) + + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1 + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' + + editorView.setCursorBufferPosition([11]) + editorView.indentSelectedRows() + + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' + + describe "when a line contains only whitespace", -> + it "displays an indent guide on the line", -> + editorView.attachToDom() + atom.config.set("editor.showIndentGuide", true) + + editorView.setCursorBufferPosition([10]) + editorView.indent() + editorView.indent() + expect(editorView.getCursorBufferPosition()).toEqual [10, 4] + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' + + it "uses the highest indent guide level from the next or previous non-empty line", -> + editorView.attachToDom() + atom.config.set("editor.showIndentGuide", true) + + editorView.setCursorBufferPosition([1, Infinity]) + editorView.insertNewline() + expect(editorView.getCursorBufferPosition()).toEqual [2, 0] + expect(editorView.renderedLines.find('.line:eq(2) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(2) .indent-guide').text()).toBe ' ' + + describe "when the line has leading and trailing whitespace", -> + it "does not display the indent guide in the trailing whitespace", -> + editorView.attachToDom() + atom.config.set("editor.showIndentGuide", true) + + editorView.insertText("/*\n * \n*/") + expect(editorView.renderedLines.find('.line:eq(1) .indent-guide').length).toBe 1 + expect(editorView.renderedLines.find('.line:eq(1) .indent-guide')).toHaveClass('leading-whitespace') + + describe "when the line is empty and end of show invisibles are enabled", -> + it "renders the indent guides interleaved with the end of line invisibles", -> + editorView.attachToDom() + atom.config.set("editor.showIndentGuide", true) + atom.config.set("editor.showInvisibles", true) + eol = editorView.invisibles?.eol + + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1 + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} " + expect(editorView.renderedLines.find('.line:eq(10) .invisible-character').text()).toBe eol + + editorView.setCursorBufferPosition([9]) + editorView.indent() + + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 + expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} " + expect(editorView.renderedLines.find('.line:eq(10) .invisible-character').text()).toBe eol + + describe "when soft-wrap is enabled", -> + beforeEach -> + jasmine.unspy(window, 'setTimeout') + editSession.setSoftWrap(true) + editorView.attachToDom() + setEditorHeightInLines(editorView, 20) + setEditorWidthInChars(editorView, 50) + expect(editorView.activeEditSession.getSoftWrapColumn()).toBe 50 + + it "wraps lines that are too long to fit within the editor view's width, adjusting cursor positioning accordingly", -> + expect(editorView.renderedLines.find('.line').length).toBe 16 + expect(editorView.renderedLines.find('.line:eq(3)').text()).toBe " var pivot = items.shift(), current, left = [], " + expect(editorView.renderedLines.find('.line:eq(4)').text()).toBe "right = [];" + + editorView.setCursorBufferPosition([3, 51], wrapAtSoftNewlines: true) + expect(editorView.find('.cursor').offset()).toEqual(editorView.renderedLines.find('.line:eq(4)').offset()) + + editorView.setCursorBufferPosition([4, 0]) + expect(editorView.find('.cursor').offset()).toEqual(editorView.renderedLines.find('.line:eq(5)').offset()) + + editorView.getSelection().setBufferRange([[6, 30], [6, 55]]) + [region1, region2] = editorView.getSelectionView().regions + expect(region1.offset().top).toBeCloseTo(editorView.renderedLines.find('.line:eq(7)').offset().top) + expect(region2.offset().top).toBeCloseTo(editorView.renderedLines.find('.line:eq(8)').offset().top) + + it "handles changes to wrapped lines correctly", -> + buffer.insert([6, 28], '1234567') + expect(editorView.renderedLines.find('.line:eq(7)').text()).toBe ' current < pivot ? left1234567.push(current) ' + expect(editorView.renderedLines.find('.line:eq(8)').text()).toBe ': right.push(current);' + expect(editorView.renderedLines.find('.line:eq(9)').text()).toBe ' }' + + it "changes the max line length and repositions the cursor when the window size changes", -> + editorView.setCursorBufferPosition([3, 60]) + setEditorWidthInChars(editorView, 40) + expect(editorView.renderedLines.find('.line').length).toBe 19 + expect(editorView.renderedLines.find('.line:eq(4)').text()).toBe "left = [], right = [];" + expect(editorView.renderedLines.find('.line:eq(5)').text()).toBe " while(items.length > 0) {" + expect(editorView.bufferPositionForScreenPosition(editorView.getCursorScreenPosition())).toEqual [3, 60] + + it "does not wrap the lines of any newly assigned buffers", -> + otherEditSession = project.openSync() + otherEditSession.buffer.setText([1..100].join('')) + editorView.edit(otherEditSession) + expect(editorView.renderedLines.find('.line').length).toBe(1) + + it "unwraps lines when softwrap is disabled", -> + editorView.toggleSoftWrap() + expect(editorView.renderedLines.find('.line:eq(3)').text()).toBe ' var pivot = items.shift(), current, left = [], right = [];' + + it "allows the cursor to move down to the last line", -> + _.times editorView.getLastScreenRow(), -> editorView.moveCursorDown() + expect(editorView.getCursorScreenPosition()).toEqual [editorView.getLastScreenRow(), 0] + editorView.moveCursorDown() + expect(editorView.getCursorScreenPosition()).toEqual [editorView.getLastScreenRow(), 2] + + it "allows the cursor to move up to a shorter soft wrapped line", -> + editorView.setCursorScreenPosition([11, 15]) + editorView.moveCursorUp() + expect(editorView.getCursorScreenPosition()).toEqual [10, 10] + editorView.moveCursorUp() + editorView.moveCursorUp() + expect(editorView.getCursorScreenPosition()).toEqual [8, 15] + + it "it allows the cursor to wrap when moving horizontally past the beginning / end of a wrapped line", -> + editorView.setCursorScreenPosition([11, 0]) + editorView.moveCursorLeft() + expect(editorView.getCursorScreenPosition()).toEqual [10, 10] + + editorView.moveCursorRight() + expect(editorView.getCursorScreenPosition()).toEqual [11, 0] + + it "calls .setWidthInChars() when the editor view is attached because now its dimensions are available to calculate it", -> + otherEditor = new EditorView(editSession: project.openSync('sample.js')) + spyOn(otherEditor, 'setWidthInChars') + + otherEditor.activeEditSession.setSoftWrap(true) + expect(otherEditor.setWidthInChars).not.toHaveBeenCalled() + + otherEditor.simulateDomAttachment() + expect(otherEditor.setWidthInChars).toHaveBeenCalled() + otherEditor.remove() + + describe "when the editor view's width changes", -> + it "updates the width in characters on the edit session", -> + previousSoftWrapColumn = editSession.getSoftWrapColumn() + + spyOn(editorView, 'setWidthInChars').andCallThrough() + editorView.width(editorView.width() / 2) + + waitsFor -> + editorView.setWidthInChars.callCount > 0 + + runs -> + expect(editSession.getSoftWrapColumn()).toBeLessThan previousSoftWrapColumn + + describe "gutter rendering", -> + beforeEach -> + editorView.attachToDom(heightInLines: 5.5) + + it "creates a line number element for each visible line with   padding to the left of the number", -> + expect(editorView.gutter.find('.line-number').length).toBe 8 + expect(editorView.find('.line-number:first').html()).toBe " 1" + expect(editorView.gutter.find('.line-number:last').html()).toBe " 8" + + # here we don't scroll far enough to trigger additional rendering + editorView.scrollTop(editorView.lineHeight * 1.5) + expect(editorView.renderedLines.find('.line').length).toBe 8 + expect(editorView.gutter.find('.line-number:first').html()).toBe " 1" + expect(editorView.gutter.find('.line-number:last').html()).toBe " 8" + + editorView.scrollTop(editorView.lineHeight * 3.5) + expect(editorView.renderedLines.find('.line').length).toBe 10 + expect(editorView.gutter.find('.line-number:first').html()).toBe " 2" + expect(editorView.gutter.find('.line-number:last').html()).toBe "11" + + describe "when lines are inserted", -> + it "re-renders the correct line number range in the gutter", -> + editorView.scrollTop(3 * editorView.lineHeight) + expect(editorView.gutter.find('.line-number:first').intValue()).toBe 2 + expect(editorView.gutter.find('.line-number:last').intValue()).toBe 11 + + buffer.insert([6, 0], '\n') + + expect(editorView.gutter.find('.line-number:first').intValue()).toBe 2 + expect(editorView.gutter.find('.line-number:last').intValue()).toBe 11 + + it "re-renders the correct line number range when there are folds", -> + editorView.activeEditSession.foldBufferRow(1) + expect(editorView.gutter.find('.line-number-1')).toHaveClass 'fold' + + buffer.insert([0, 0], '\n') + + expect(editorView.gutter.find('.line-number-2')).toHaveClass 'fold' + + describe "when wrapping is on", -> + it "renders a • instead of line number for wrapped portions of lines", -> + editSession.setSoftWrap(true) + editorView.setWidthInChars(50) + expect(editorView.gutter.find('.line-number').length).toEqual(8) + expect(editorView.gutter.find('.line-number:eq(3)').intValue()).toBe 4 + expect(editorView.gutter.find('.line-number:eq(4)').html()).toBe ' â€¢' + expect(editorView.gutter.find('.line-number:eq(5)').intValue()).toBe 5 + + describe "when there are folds", -> + it "skips line numbers covered by the fold and updates them when the fold changes", -> + editorView.createFold(3, 5) + expect(editorView.gutter.find('.line-number:eq(3)').intValue()).toBe 4 + expect(editorView.gutter.find('.line-number:eq(4)').intValue()).toBe 7 + + buffer.insert([4,0], "\n\n") + expect(editorView.gutter.find('.line-number:eq(3)').intValue()).toBe 4 + expect(editorView.gutter.find('.line-number:eq(4)').intValue()).toBe 9 + + buffer.delete([[3,0], [6,0]]) + expect(editorView.gutter.find('.line-number:eq(3)').intValue()).toBe 4 + expect(editorView.gutter.find('.line-number:eq(4)').intValue()).toBe 6 + + it "redraws gutter numbers when lines are unfolded", -> + setEditorHeightInLines(editorView, 20) + fold = editorView.createFold(2, 12) + expect(editorView.gutter.find('.line-number').length).toBe 3 + + fold.destroy() + expect(editorView.gutter.find('.line-number').length).toBe 13 + + it "styles folded line numbers", -> + editorView.createFold(3, 5) + expect(editorView.gutter.find('.line-number.fold').length).toBe 1 + expect(editorView.gutter.find('.line-number.fold:eq(0)').intValue()).toBe 4 + + describe "when the scrollView is scrolled to the right", -> + it "adds a drop shadow to the gutter", -> + editorView.attachToDom() + editorView.width(100) + + expect(editorView.gutter).not.toHaveClass('drop-shadow') + + editorView.scrollLeft(10) + editorView.scrollView.trigger('scroll') + + expect(editorView.gutter).toHaveClass('drop-shadow') + + editorView.scrollLeft(0) + editorView.scrollView.trigger('scroll') + + expect(editorView.gutter).not.toHaveClass('drop-shadow') + + describe "when the editor view is scrolled vertically", -> + it "adjusts the padding-top to account for non-rendered line numbers", -> + editorView.scrollTop(editorView.lineHeight * 3.5) + expect(editorView.gutter.lineNumbers.css('padding-top')).toBe "#{editorView.lineHeight * 1}px" + expect(editorView.gutter.lineNumbers.css('padding-bottom')).toBe "#{editorView.lineHeight * 2}px" + expect(editorView.renderedLines.find('.line').length).toBe 10 + expect(editorView.gutter.find('.line-number:first').intValue()).toBe 2 + expect(editorView.gutter.find('.line-number:last').intValue()).toBe 11 + + describe "when the switching from an edit session for a long buffer to an edit session for a short buffer", -> + it "updates the line numbers to reflect the shorter buffer", -> + emptyEditSession = project.openSync(null) + editorView.edit(emptyEditSession) + expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1 + + editorView.edit(editSession) + expect(editorView.gutter.lineNumbers.find('.line-number').length).toBeGreaterThan 1 + + editorView.edit(emptyEditSession) + expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1 + + describe "when the editor view is mini", -> + it "hides the gutter", -> + miniEditor = new EditorView(mini: true) + miniEditor.attachToDom() + expect(miniEditor.gutter).toBeHidden() + + it "doesn't highlight the only line", -> + miniEditor = new EditorView(mini: true) + miniEditor.attachToDom() + expect(miniEditor.getCursorBufferPosition().row).toBe 0 + expect(miniEditor.find('.line.cursor-line').length).toBe 0 + + it "doesn't show the end of line invisible", -> + atom.config.set "editor.showInvisibles", true + miniEditor = new EditorView(mini: true) + miniEditor.attachToDom() + space = miniEditor.invisibles?.space + expect(space).toBeTruthy() + tab = miniEditor.invisibles?.tab + expect(tab).toBeTruthy() + miniEditor.setText(" a line with tabs\tand spaces ") + expect(miniEditor.renderedLines.find('.line').text()).toBe "#{space}a line with tabs#{tab} and spaces#{space}" + + it "doesn't show the indent guide", -> + atom.config.set "editor.showIndentGuide", true + miniEditor = new EditorView(mini: true) + miniEditor.attachToDom() + miniEditor.setText(" and indented line") + expect(miniEditor.renderedLines.find('.indent-guide').length).toBe 0 + + + it "lets you set the grammar", -> + miniEditor = new EditorView(mini: true) + miniEditor.setText("var something") + previousTokens = miniEditor.lineForScreenRow(0).tokens + miniEditor.setGrammar(atom.syntax.selectGrammar('something.js')) + expect(miniEditor.getGrammar().name).toBe "JavaScript" + expect(previousTokens).not.toEqual miniEditor.lineForScreenRow(0).tokens + + # doesn't allow regular editors to set grammars + expect(-> editorView.setGrammar()).toThrow() + + describe "when the editor.showLineNumbers config is false", -> + it "doesn't render any line numbers", -> + expect(editorView.gutter.lineNumbers).toBeVisible() + atom.config.set("editor.showLineNumbers", false) + expect(editorView.gutter.lineNumbers).not.toBeVisible() + + describe "using gutter's api", -> + it "can get all the line number elements", -> + elements = editorView.gutter.getLineNumberElements() + len = editorView.gutter.lastScreenRow - editorView.gutter.firstScreenRow + 1 + expect(elements).toHaveLength(len) + + it "can get a single line number element", -> + element = editorView.gutter.getLineNumberElement(3) + expect(element).toBeTruthy() + + it "returns falsy when there is no line element", -> + expect(editorView.gutter.getLineNumberElement(42)).toHaveLength 0 + + it "can add and remove classes to all the line numbers", -> + wasAdded = editorView.gutter.addClassToAllLines('heyok') + expect(wasAdded).toBe true + + elements = editorView.gutter.getLineNumberElementsForClass('heyok') + expect($(elements)).toHaveClass('heyok') + + editorView.gutter.removeClassFromAllLines('heyok') + expect($(editorView.gutter.getLineNumberElements())).not.toHaveClass('heyok') + + it "can add and remove classes from a single line number", -> + wasAdded = editorView.gutter.addClassToLine(3, 'heyok') + expect(wasAdded).toBe true + + element = editorView.gutter.getLineNumberElement(2) + expect($(element)).not.toHaveClass('heyok') + + it "can fetch line numbers by their class", -> + editorView.gutter.addClassToLine(1, 'heyok') + editorView.gutter.addClassToLine(3, 'heyok') + + elements = editorView.gutter.getLineNumberElementsForClass('heyok') + expect(elements.length).toBe 2 + + expect($(elements[0])).toHaveClass 'line-number-1' + expect($(elements[0])).toHaveClass 'heyok' + + expect($(elements[1])).toHaveClass 'line-number-3' + expect($(elements[1])).toHaveClass 'heyok' + + describe "gutter line highlighting", -> + beforeEach -> + editorView.attachToDom(heightInLines: 5.5) + + describe "when there is no wrapping", -> + it "highlights the line where the initial cursor position is", -> + expect(editorView.getCursorBufferPosition().row).toBe 0 + expect(editorView.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 1 + expect(editorView.find('.line-number.cursor-line.cursor-line-no-selection').intValue()).toBe 1 + + it "updates the highlighted line when the cursor position changes", -> + editorView.setCursorBufferPosition([1,0]) + expect(editorView.getCursorBufferPosition().row).toBe 1 + expect(editorView.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 1 + expect(editorView.find('.line-number.cursor-line.cursor-line-no-selection').intValue()).toBe 2 + + describe "when there is wrapping", -> + beforeEach -> + editorView.attachToDom(30) + editSession.setSoftWrap(true) + setEditorWidthInChars(editorView, 20) + + it "highlights the line where the initial cursor position is", -> + expect(editorView.getCursorBufferPosition().row).toBe 0 + expect(editorView.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 1 + expect(editorView.find('.line-number.cursor-line.cursor-line-no-selection').intValue()).toBe 1 + + it "updates the highlighted line when the cursor position changes", -> + editorView.setCursorBufferPosition([1,0]) + expect(editorView.getCursorBufferPosition().row).toBe 1 + expect(editorView.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 1 + expect(editorView.find('.line-number.cursor-line.cursor-line-no-selection').intValue()).toBe 2 + + describe "when the selection spans multiple lines", -> + beforeEach -> + editorView.attachToDom(30) + + it "highlights the foreground of the gutter", -> + editorView.getSelection().setBufferRange([[0,0],[2,2]]) + expect(editorView.getSelection().isSingleScreenLine()).toBe false + expect(editorView.find('.line-number.cursor-line').length).toBe 3 + + it "doesn't highlight the background of the gutter", -> + editorView.getSelection().setBufferRange([[0,0],[2,0]]) + expect(editorView.getSelection().isSingleScreenLine()).toBe false + expect(editorView.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 0 + + it "doesn't highlight the last line if it ends at the beginning of a line", -> + editorView.getSelection().setBufferRange([[0,0],[1,0]]) + expect(editorView.getSelection().isSingleScreenLine()).toBe false + expect(editorView.find('.line-number.cursor-line').length).toBe 1 + expect(editorView.find('.line-number.cursor-line').intValue()).toBe 1 + + it "when a newline is deleted with backspace, the line number of the new cursor position is highlighted", -> + editorView.setCursorScreenPosition([1,0]) + editorView.backspace() + expect(editorView.find('.line-number.cursor-line').length).toBe 1 + expect(editorView.find('.line-number.cursor-line').intValue()).toBe 1 + + describe "line highlighting", -> + beforeEach -> + editorView.attachToDom(30) + + describe "when there is no wrapping", -> + it "highlights the line where the initial cursor position is", -> + expect(editorView.getCursorBufferPosition().row).toBe 0 + expect(editorView.find('.line.cursor-line').length).toBe 1 + expect(editorView.find('.line.cursor-line').text()).toBe buffer.lineForRow(0) + + it "updates the highlighted line when the cursor position changes", -> + editorView.setCursorBufferPosition([1,0]) + expect(editorView.getCursorBufferPosition().row).toBe 1 + expect(editorView.find('.line.cursor-line').length).toBe 1 + expect(editorView.find('.line.cursor-line').text()).toBe buffer.lineForRow(1) + + it "when a newline is deleted with backspace, the line of the new cursor position is highlighted", -> + editorView.setCursorScreenPosition([1,0]) + editorView.backspace() + expect(editorView.find('.line.cursor-line').length).toBe 1 + + describe "when there is wrapping", -> + beforeEach -> + editSession.setSoftWrap(true) + setEditorWidthInChars(editorView, 20) + + it "highlights the line where the initial cursor position is", -> + expect(editorView.getCursorBufferPosition().row).toBe 0 + expect(editorView.find('.line.cursor-line').length).toBe 1 + expect(editorView.find('.line.cursor-line').text()).toBe 'var quicksort = ' + + it "updates the highlighted line when the cursor position changes", -> + editorView.setCursorBufferPosition([1,0]) + expect(editorView.getCursorBufferPosition().row).toBe 1 + expect(editorView.find('.line.cursor-line').length).toBe 1 + expect(editorView.find('.line.cursor-line').text()).toBe ' var sort = ' + + describe "when there is a non-empty selection", -> + it "does not highlight the line", -> + editorView.setSelectedBufferRange([[1, 0], [1, 1]]) + expect(editorView.find('.line.cursor-line').length).toBe 0 + + describe "folding", -> + beforeEach -> + editSession = project.openSync('two-hundred.txt') + buffer = editSession.buffer + editorView.edit(editSession) + editorView.attachToDom() + + describe "when a fold-selection event is triggered", -> + it "folds the lines covered by the selection into a single line with a fold class and marker", -> + editorView.getSelection().setBufferRange([[4,29],[7,4]]) + editorView.trigger 'editor:fold-selection' + + expect(editorView.renderedLines.find('.line:eq(4)')).toHaveClass('fold') + expect(editorView.renderedLines.find('.line:eq(4) > .fold-marker')).toExist() + expect(editorView.renderedLines.find('.line:eq(5)').text()).toBe '8' + + expect(editorView.getSelection().isEmpty()).toBeTruthy() + expect(editorView.getCursorScreenPosition()).toEqual [5, 0] + + it "keeps the gutter line and the editor view line the same heights (regression)", -> + editorView.getSelection().setBufferRange([[4,29],[7,4]]) + editorView.trigger 'editor:fold-selection' + + expect(editorView.gutter.find('.line-number:eq(4)').height()).toBe editorView.renderedLines.find('.line:eq(4)').height() + + describe "when a fold placeholder line is clicked", -> + it "removes the associated fold and places the cursor at its beginning", -> + editorView.setCursorBufferPosition([3,0]) + editSession.createFold(3, 5) + + foldLine = editorView.find('.line.fold') + expect(foldLine).toExist() + foldLine.mousedown() + + expect(editorView.find('.fold')).not.toExist() + expect(editorView.find('.fold-marker')).not.toExist() + expect(editorView.renderedLines.find('.line:eq(4)').text()).toMatch /4-+/ + expect(editorView.renderedLines.find('.line:eq(5)').text()).toMatch /5/ + + expect(editorView.getCursorBufferPosition()).toEqual [3, 0] + + describe "when the unfold-current-row event is triggered when the cursor is on a fold placeholder line", -> + it "removes the associated fold and places the cursor at its beginning", -> + editorView.setCursorBufferPosition([3,0]) + editorView.trigger 'editor:fold-current-row' + + editorView.setCursorBufferPosition([3,0]) + editorView.trigger 'editor:unfold-current-row' + + expect(editorView.find('.fold')).not.toExist() + expect(editorView.renderedLines.find('.line:eq(4)').text()).toMatch /4-+/ + expect(editorView.renderedLines.find('.line:eq(5)').text()).toMatch /5/ + + expect(editorView.getCursorBufferPosition()).toEqual [3, 0] + + describe "when a selection starts/stops intersecting a fold", -> + it "adds/removes the 'fold-selected' class to the fold's line element and hides the cursor if it is on the fold line", -> + editorView.createFold(2, 4) + + editorView.setSelectedBufferRange([[1, 0], [2, 0]], preserveFolds: true, isReversed: true) + expect(editorView.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected') + + editorView.setSelectedBufferRange([[1, 0], [1, 1]], preserveFolds: true) + expect(editorView.lineElementForScreenRow(2)).not.toMatchSelector('.fold.fold-selected') + + editorView.setSelectedBufferRange([[1, 0], [5, 0]], preserveFolds: true) + expect(editorView.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected') + + editorView.setCursorScreenPosition([3,0]) + expect(editorView.lineElementForScreenRow(2)).not.toMatchSelector('.fold.fold-selected') + + editorView.setCursorScreenPosition([2,0]) + expect(editorView.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected') + expect(editorView.find('.cursor')).toBeHidden() + + editorView.setCursorScreenPosition([3,0]) + expect(editorView.find('.cursor')).toBeVisible() + + describe "when a selected fold is scrolled into view (and the fold line was not previously rendered)", -> + it "renders the fold's line element with the 'fold-selected' class", -> + setEditorHeightInLines(editorView, 5) + editorView.resetDisplay() + + editorView.createFold(2, 4) + editorView.setSelectedBufferRange([[1, 0], [5, 0]], preserveFolds: true) + expect(editorView.renderedLines.find('.fold.fold-selected')).toExist() + + editorView.scrollToBottom() + expect(editorView.renderedLines.find('.fold.fold-selected')).not.toExist() + + editorView.scrollTop(0) + expect(editorView.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected') + + describe "paging up and down", -> + beforeEach -> + editorView.attachToDom() + + it "moves to the last line when page down is repeated from the first line", -> + rows = editorView.getLineCount() - 1 + expect(rows).toBeGreaterThan(0) + row = editorView.getCursor().getScreenPosition().row + expect(row).toBe(0) + while row < rows + editorView.pageDown() + newRow = editorView.getCursor().getScreenPosition().row + expect(newRow).toBeGreaterThan(row) + if (newRow <= row) + break + row = newRow + expect(row).toBe(rows) + expect(editorView.getLastVisibleScreenRow()).toBe(rows) + + it "moves to the first line when page up is repeated from the last line", -> + editorView.moveCursorToBottom() + row = editorView.getCursor().getScreenPosition().row + expect(row).toBeGreaterThan(0) + while row > 0 + editorView.pageUp() + newRow = editorView.getCursor().getScreenPosition().row + expect(newRow).toBeLessThan(row) + if (newRow >= row) + break + row = newRow + expect(row).toBe(0) + expect(editorView.getFirstVisibleScreenRow()).toBe(0) + + it "resets to original position when down is followed by up", -> + expect(editorView.getCursor().getScreenPosition().row).toBe(0) + editorView.pageDown() + expect(editorView.getCursor().getScreenPosition().row).toBeGreaterThan(0) + editorView.pageUp() + expect(editorView.getCursor().getScreenPosition().row).toBe(0) + expect(editorView.getFirstVisibleScreenRow()).toBe(0) + + describe ".checkoutHead()", -> + [filePath, originalPathText] = [] + + beforeEach -> + filePath = project.resolve('git/working-dir/file.txt') + originalPathText = fs.readFileSync(filePath, 'utf8') + editorView.edit(project.openSync(filePath)) + + afterEach -> + fs.writeFileSync(filePath, originalPathText) + + it "restores the contents of the editor view to the HEAD revision", -> + editorView.setText('') + editorView.getBuffer().save() + + fileChangeHandler = jasmine.createSpy('fileChange') + editorView.getBuffer().file.on 'contents-changed', fileChangeHandler + + editorView.checkoutHead() + + waitsFor "file to trigger contents-changed event", -> + fileChangeHandler.callCount > 0 + + runs -> + expect(editorView.getText()).toBe(originalPathText) + + describe ".pixelPositionForBufferPosition(position)", -> + describe "when the editor view is detached", -> + it "returns top and left values of 0", -> + expect(editorView.isOnDom()).toBeFalsy() + expect(editorView.pixelPositionForBufferPosition([2,7])).toEqual top: 0, left: 0 + + describe "when the editor view is invisible", -> + it "returns top and left values of 0", -> + editorView.attachToDom() + editorView.hide() + expect(editorView.isVisible()).toBeFalsy() + expect(editorView.pixelPositionForBufferPosition([2,7])).toEqual top: 0, left: 0 + + describe "when the editor view is attached and visible", -> + beforeEach -> + editorView.attachToDom() + + it "returns the top and left pixel positions", -> + expect(editorView.pixelPositionForBufferPosition([2,7])).toEqual top: 40, left: 70 + + it "caches the left position", -> + editorView.renderedLines.css('font-size', '16px') + expect(editorView.pixelPositionForBufferPosition([2,8])).toEqual top: 40, left: 80 + + # make characters smaller + editorView.renderedLines.css('font-size', '15px') + + expect(editorView.pixelPositionForBufferPosition([2,8])).toEqual top: 40, left: 80 + + describe "when clicking in the gutter", -> + beforeEach -> + editorView.attachToDom() + + describe "when single clicking", -> + it "moves the cursor to the start of the selected line", -> + expect(editorView.getCursorScreenPosition()).toEqual [0,0] + event = $.Event("mousedown") + event.pageY = editorView.gutter.find(".line-number:eq(1)").offset().top + event.originalEvent = {detail: 1} + editorView.gutter.find(".line-number:eq(1)").trigger event + expect(editorView.getCursorScreenPosition()).toEqual [1,0] + + describe "when shift-clicking", -> + it "selects to the start of the selected line", -> + expect(editorView.getSelection().getScreenRange()).toEqual [[0,0], [0,0]] + event = $.Event("mousedown") + event.pageY = editorView.gutter.find(".line-number:eq(1)").offset().top + event.originalEvent = {detail: 1} + event.shiftKey = true + editorView.gutter.find(".line-number:eq(1)").trigger event + expect(editorView.getSelection().getScreenRange()).toEqual [[0,0], [2,0]] + + describe "when mousing down and then moving across multiple lines before mousing up", -> + describe "when selecting from top to bottom", -> + it "selects the lines", -> + mousedownEvent = $.Event("mousedown") + mousedownEvent.pageY = editorView.gutter.find(".line-number:eq(1)").offset().top + mousedownEvent.originalEvent = {detail: 1} + editorView.gutter.find(".line-number:eq(1)").trigger mousedownEvent + + mousemoveEvent = $.Event("mousemove") + mousemoveEvent.pageY = editorView.gutter.find(".line-number:eq(5)").offset().top + mousemoveEvent.originalEvent = {detail: 1} + editorView.gutter.find(".line-number:eq(5)").trigger mousemoveEvent + + $(document).trigger 'mouseup' + + expect(editorView.getSelection().getScreenRange()).toEqual [[1,0], [6,0]] + + describe "when selecting from bottom to top", -> + it "selects the lines", -> + mousedownEvent = $.Event("mousedown") + mousedownEvent.pageY = editorView.gutter.find(".line-number:eq(5)").offset().top + mousedownEvent.originalEvent = {detail: 1} + editorView.gutter.find(".line-number:eq(5)").trigger mousedownEvent + + mousemoveEvent = $.Event("mousemove") + mousemoveEvent.pageY = editorView.gutter.find(".line-number:eq(1)").offset().top + mousemoveEvent.originalEvent = {detail: 1} + editorView.gutter.find(".line-number:eq(1)").trigger mousemoveEvent + + $(document).trigger 'mouseup' + + expect(editorView.getSelection().getScreenRange()).toEqual [[1,0], [6,0]] + + describe "when clicking below the last line", -> + beforeEach -> + editorView.attachToDom() + + it "move the cursor to the end of the file", -> + expect(editorView.getCursorScreenPosition()).toEqual [0,0] + event = mousedownEvent(editorView: editorView, point: [Infinity, 10]) + editorView.underlayer.trigger event + expect(editorView.getCursorScreenPosition()).toEqual [12,2] + + it "selects to the end of the files when shift is pressed", -> + expect(editorView.getSelection().getScreenRange()).toEqual [[0,0], [0,0]] + event = mousedownEvent(editorView: editorView, point: [Infinity, 10], shiftKey: true) + editorView.underlayer.trigger event + expect(editorView.getSelection().getScreenRange()).toEqual [[0,0], [12,2]] + + describe ".reloadGrammar()", -> + [filePath] = [] + + beforeEach -> + tmpdir = fs.absolute(temp.dir) + filePath = path.join(tmpdir, "grammar-change.txt") + fs.writeFileSync(filePath, "var i;") + + afterEach -> + fs.removeSync(filePath) if fs.existsSync(filePath) + + it "updates all the rendered lines when the grammar changes", -> + editorView.edit(project.openSync(filePath)) + expect(editorView.getGrammar().name).toBe 'Plain Text' + atom.syntax.setGrammarOverrideForPath(filePath, 'source.js') + editorView.reloadGrammar() + expect(editorView.getGrammar().name).toBe 'JavaScript' + + tokenizedBuffer = editorView.activeEditSession.displayBuffer.tokenizedBuffer + line0 = tokenizedBuffer.lineForScreenRow(0) + expect(line0.tokens.length).toBe 3 + expect(line0.tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.modifier.js']) + + it "doesn't update the rendered lines when the grammar doesn't change", -> + expect(editorView.getGrammar().name).toBe 'JavaScript' + spyOn(editorView, 'updateDisplay').andCallThrough() + editorView.reloadGrammar() + expect(editorView.reloadGrammar()).toBeFalsy() + expect(editorView.updateDisplay).not.toHaveBeenCalled() + expect(editorView.getGrammar().name).toBe 'JavaScript' + + it "emits an editor:grammar-changed event when updated", -> + editorView.edit(project.openSync(filePath)) + + eventHandler = jasmine.createSpy('eventHandler') + editorView.on('editor:grammar-changed', eventHandler) + editorView.reloadGrammar() + + expect(eventHandler).not.toHaveBeenCalled() + + atom.syntax.setGrammarOverrideForPath(filePath, 'source.js') + editorView.reloadGrammar() + expect(eventHandler).toHaveBeenCalled() + + describe ".replaceSelectedText()", -> + it "doesn't call the replace function when the selection is empty", -> + replaced = false + edited = false + replacer = (text) -> + replaced = true + 'new' + + editorView.moveCursorToTop() + edited = editorView.replaceSelectedText(replacer) + expect(replaced).toBe false + expect(edited).toBe false + + it "returns true when transformed text is non-empty", -> + replaced = false + edited = false + replacer = (text) -> + replaced = true + 'new' + + editorView.moveCursorToTop() + editorView.selectToEndOfLine() + edited = editorView.replaceSelectedText(replacer) + expect(replaced).toBe true + expect(edited).toBe true + + it "returns false when transformed text is null", -> + replaced = false + edited = false + replacer = (text) -> + replaced = true + null + + editorView.moveCursorToTop() + editorView.selectToEndOfLine() + edited = editorView.replaceSelectedText(replacer) + expect(replaced).toBe true + expect(edited).toBe false + + it "returns false when transformed text is undefined", -> + replaced = false + edited = false + replacer = (text) -> + replaced = true + undefined + + editorView.moveCursorToTop() + editorView.selectToEndOfLine() + edited = editorView.replaceSelectedText(replacer) + expect(replaced).toBe true + expect(edited).toBe false + + describe "when editor:copy-path is triggered", -> + it "copies the absolute path to the editor view's file to the pasteboard", -> + editorView.trigger 'editor:copy-path' + expect(atom.pasteboard.read()[0]).toBe editorView.getPath() + + describe "when editor:move-line-up is triggered", -> + describe "when there is no selection", -> + it "moves the line where the cursor is up", -> + editorView.setCursorBufferPosition([1,0]) + editorView.trigger 'editor:move-line-up' + expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {' + expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {' + + it "moves the cursor to the new row and the same column", -> + editorView.setCursorBufferPosition([1,2]) + editorView.trigger 'editor:move-line-up' + expect(editorView.getCursorBufferPosition()).toEqual [0,2] + + describe "where there is a selection", -> + describe "when the selection falls inside the line", -> + it "maintains the selection", -> + editorView.setSelectedBufferRange([[1, 2], [1, 5]]) + expect(editorView.getSelectedText()).toBe 'var' + editorView.trigger 'editor:move-line-up' + expect(editorView.getSelectedBufferRange()).toEqual [[0, 2], [0, 5]] + expect(editorView.getSelectedText()).toBe 'var' + + describe "where there are multiple lines selected", -> + it "moves the selected lines up", -> + editorView.setSelectedBufferRange([[2, 0], [3, Infinity]]) + editorView.trigger 'editor:move-line-up' + expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {' + expect(buffer.lineForRow(1)).toBe ' if (items.length <= 1) return items;' + expect(buffer.lineForRow(2)).toBe ' var pivot = items.shift(), current, left = [], right = [];' + expect(buffer.lineForRow(3)).toBe ' var sort = function(items) {' + + it "maintains the selection", -> + editorView.setSelectedBufferRange([[2, 0], [3, 62]]) + editorView.trigger 'editor:move-line-up' + expect(editorView.getSelectedBufferRange()).toEqual [[1, 0], [2, 62]] + + describe "when the last line is selected", -> + it "moves the selected line up", -> + editorView.setSelectedBufferRange([[12, 0], [12, Infinity]]) + editorView.trigger 'editor:move-line-up' + expect(buffer.lineForRow(11)).toBe '};' + expect(buffer.lineForRow(12)).toBe ' return sort(Array.apply(this, arguments));' + + describe "when the last two lines are selected", -> + it "moves the selected lines up", -> + editorView.setSelectedBufferRange([[11, 0], [12, Infinity]]) + editorView.trigger 'editor:move-line-up' + expect(buffer.lineForRow(10)).toBe ' return sort(Array.apply(this, arguments));' + expect(buffer.lineForRow(11)).toBe '};' + expect(buffer.lineForRow(12)).toBe '' + + describe "when the cursor is on the first line", -> + it "does not move the line", -> + editorView.setCursorBufferPosition([0,0]) + originalText = editorView.getText() + editorView.trigger 'editor:move-line-up' + expect(editorView.getText()).toBe originalText + + describe "when the cursor is on the trailing newline", -> + it "does not move the line", -> + editorView.moveCursorToBottom() + editorView.insertNewline() + editorView.moveCursorToBottom() + originalText = editorView.getText() + editorView.trigger 'editor:move-line-up' + expect(editorView.getText()).toBe originalText + + describe "when the cursor is on a folded line", -> + it "moves all lines in the fold up and preserves the fold", -> + editorView.setCursorBufferPosition([4, 0]) + editorView.foldCurrentRow() + editorView.trigger 'editor:move-line-up' + expect(buffer.lineForRow(3)).toBe ' while(items.length > 0) {' + expect(buffer.lineForRow(7)).toBe ' var pivot = items.shift(), current, left = [], right = [];' + expect(editorView.getSelectedBufferRange()).toEqual [[3, 0], [3, 0]] + expect(editorView.isFoldedAtScreenRow(3)).toBeTruthy() + + describe "when the selection contains a folded and unfolded line", -> + it "moves the selected lines up and preserves the fold", -> + editorView.setCursorBufferPosition([4, 0]) + editorView.foldCurrentRow() + editorView.setCursorBufferPosition([3, 4]) + editorView.selectDown() + expect(editorView.isFoldedAtScreenRow(4)).toBeTruthy() + editorView.trigger 'editor:move-line-up' + expect(buffer.lineForRow(2)).toBe ' var pivot = items.shift(), current, left = [], right = [];' + expect(buffer.lineForRow(3)).toBe ' while(items.length > 0) {' + expect(editorView.getSelectedBufferRange()).toEqual [[2, 4], [3, 0]] + expect(editorView.isFoldedAtScreenRow(3)).toBeTruthy() + + describe "when an entire line is selected including the newline", -> + it "moves the selected line up", -> + editorView.setCursorBufferPosition([1]) + editorView.selectToEndOfLine() + editorView.selectRight() + editorView.trigger 'editor:move-line-up' + expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {' + expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {' + + describe "when editor:move-line-down is triggered", -> + describe "when there is no selection", -> + it "moves the line where the cursor is down", -> + editorView.setCursorBufferPosition([0, 0]) + editorView.trigger 'editor:move-line-down' + expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {' + expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {' + + it "moves the cursor to the new row and the same column", -> + editorView.setCursorBufferPosition([0, 2]) + editorView.trigger 'editor:move-line-down' + expect(editorView.getCursorBufferPosition()).toEqual [1, 2] + + describe "when the cursor is on the last line", -> + it "does not move the line", -> + editorView.moveCursorToBottom() + editorView.trigger 'editor:move-line-down' + expect(buffer.lineForRow(12)).toBe '};' + expect(editorView.getSelectedBufferRange()).toEqual [[12, 2], [12, 2]] + + describe "when the cursor is on the second to last line", -> + it "moves the line down", -> + editorView.setCursorBufferPosition([11, 0]) + editorView.trigger 'editor:move-line-down' + expect(buffer.lineForRow(11)).toBe '};' + expect(buffer.lineForRow(12)).toBe ' return sort(Array.apply(this, arguments));' + expect(buffer.lineForRow(13)).toBeUndefined() + + describe "when the cursor is on the second to last line and the last line is empty", -> + it "does not move the line", -> + editorView.moveCursorToBottom() + editorView.insertNewline() + editorView.setCursorBufferPosition([12, 2]) + editorView.trigger 'editor:move-line-down' + expect(buffer.lineForRow(12)).toBe '};' + expect(buffer.lineForRow(13)).toBe '' + expect(editorView.getSelectedBufferRange()).toEqual [[12, 2], [12, 2]] + + describe "where there is a selection", -> + describe "when the selection falls inside the line", -> + it "maintains the selection", -> + editorView.setSelectedBufferRange([[1, 2], [1, 5]]) + expect(editorView.getSelectedText()).toBe 'var' + editorView.trigger 'editor:move-line-down' + expect(editorView.getSelectedBufferRange()).toEqual [[2, 2], [2, 5]] + expect(editorView.getSelectedText()).toBe 'var' + + describe "where there are multiple lines selected", -> + it "moves the selected lines down", -> + editorView.setSelectedBufferRange([[2, 0], [3, Infinity]]) + editorView.trigger 'editor:move-line-down' + expect(buffer.lineForRow(2)).toBe ' while(items.length > 0) {' + expect(buffer.lineForRow(3)).toBe ' if (items.length <= 1) return items;' + expect(buffer.lineForRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];' + expect(buffer.lineForRow(5)).toBe ' current = items.shift();' + + it "maintains the selection", -> + editorView.setSelectedBufferRange([[2, 0], [3, 62]]) + editorView.trigger 'editor:move-line-down' + expect(editorView.getSelectedBufferRange()).toEqual [[3, 0], [4, 62]] + + describe "when the cursor is on a folded line", -> + it "moves all lines in the fold down and preserves the fold", -> + editorView.setCursorBufferPosition([4, 0]) + editorView.foldCurrentRow() + editorView.trigger 'editor:move-line-down' + expect(buffer.lineForRow(4)).toBe ' return sort(left).concat(pivot).concat(sort(right));' + expect(buffer.lineForRow(5)).toBe ' while(items.length > 0) {' + expect(editorView.getSelectedBufferRange()).toEqual [[5, 0], [5, 0]] + expect(editorView.isFoldedAtScreenRow(5)).toBeTruthy() + + describe "when the selection contains a folded and unfolded line", -> + it "moves the selected lines down and preserves the fold", -> + editorView.setCursorBufferPosition([4, 0]) + editorView.foldCurrentRow() + editorView.setCursorBufferPosition([3, 4]) + editorView.selectDown() + expect(editorView.isFoldedAtScreenRow(4)).toBeTruthy() + editorView.trigger 'editor:move-line-down' + expect(buffer.lineForRow(3)).toBe ' return sort(left).concat(pivot).concat(sort(right));' + expect(buffer.lineForRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];' + expect(buffer.lineForRow(5)).toBe ' while(items.length > 0) {' + expect(editorView.getSelectedBufferRange()).toEqual [[4, 4], [5, 0]] + expect(editorView.isFoldedAtScreenRow(5)).toBeTruthy() + + describe "when an entire line is selected including the newline", -> + it "moves the selected line down", -> + editorView.setCursorBufferPosition([1]) + editorView.selectToEndOfLine() + editorView.selectRight() + editorView.trigger 'editor:move-line-down' + expect(buffer.lineForRow(1)).toBe ' if (items.length <= 1) return items;' + expect(buffer.lineForRow(2)).toBe ' var sort = function(items) {' + + describe "when editor:duplicate-line is triggered", -> + describe "where there is no selection", -> + describe "when the cursor isn't on a folded line", -> + it "duplicates the current line below and moves the cursor down one row", -> + editorView.setCursorBufferPosition([0, 5]) + editorView.trigger 'editor:duplicate-line' + expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {' + expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {' + expect(editorView.getCursorBufferPosition()).toEqual [1, 5] + + describe "when the cursor is on a folded line", -> + it "duplicates the entire fold before and moves the cursor to the new fold", -> + editorView.setCursorBufferPosition([4]) + editorView.foldCurrentRow() + editorView.trigger 'editor:duplicate-line' + expect(editorView.getCursorScreenPosition()).toEqual [5] + expect(editorView.isFoldedAtScreenRow(4)).toBeTruthy() + expect(editorView.isFoldedAtScreenRow(5)).toBeTruthy() + expect(buffer.lineForRow(8)).toBe ' while(items.length > 0) {' + expect(buffer.lineForRow(9)).toBe ' current = items.shift();' + expect(buffer.lineForRow(10)).toBe ' current < pivot ? left.push(current) : right.push(current);' + expect(buffer.lineForRow(11)).toBe ' }' + + describe "when the cursor is on the last line and it doesn't have a trailing newline", -> + it "inserts a newline and the duplicated line", -> + editorView.moveCursorToBottom() + editorView.trigger 'editor:duplicate-line' + expect(buffer.lineForRow(12)).toBe '};' + expect(buffer.lineForRow(13)).toBe '};' + expect(buffer.lineForRow(14)).toBeUndefined() + expect(editorView.getCursorBufferPosition()).toEqual [13, 2] + + describe "when the cursor in on the last line and it is only a newline", -> + it "duplicates the current line below and moves the cursor down one row", -> + editorView.moveCursorToBottom() + editorView.insertNewline() + editorView.moveCursorToBottom() + editorView.trigger 'editor:duplicate-line' + expect(buffer.lineForRow(13)).toBe '' + expect(buffer.lineForRow(14)).toBe '' + expect(buffer.lineForRow(15)).toBeUndefined() + expect(editorView.getCursorBufferPosition()).toEqual [14, 0] + + describe "when the cursor is on the second to last line and the last line only a newline", -> + it "duplicates the current line below and moves the cursor down one row", -> + editorView.moveCursorToBottom() + editorView.insertNewline() + editorView.setCursorBufferPosition([12]) + editorView.trigger 'editor:duplicate-line' + expect(buffer.lineForRow(12)).toBe '};' + expect(buffer.lineForRow(13)).toBe '};' + expect(buffer.lineForRow(14)).toBe '' + expect(buffer.lineForRow(15)).toBeUndefined() + expect(editorView.getCursorBufferPosition()).toEqual [13, 0] + + describe "editor:save-debug-snapshot", -> + it "saves the state of the rendered lines, the display buffer, and the buffer to a file of the user's choosing", -> + saveDialogCallback = null + spyOn(atom, 'showSaveDialog').andCallFake (callback) -> saveDialogCallback = callback + spyOn(fs, 'writeFileSync') + + editorView.trigger 'editor:save-debug-snapshot' + + statePath = path.join(temp.dir, 'state') + expect(atom.showSaveDialog).toHaveBeenCalled() + saveDialogCallback(statePath) + expect(fs.writeFileSync).toHaveBeenCalled() + expect(fs.writeFileSync.argsForCall[0][0]).toBe statePath + expect(typeof fs.writeFileSync.argsForCall[0][1]).toBe 'string' + + describe "when the escape key is pressed on the editor view", -> + it "clears multiple selections if there are any, and otherwise allows other bindings to be handled", -> + keymap.bindKeys 'name', '.editor', 'escape': 'test-event' + testEventHandler = jasmine.createSpy("testEventHandler") + + editorView.on 'test-event', testEventHandler + editorView.activeEditSession.addSelectionForBufferRange([[3, 0], [3, 0]]) + expect(editorView.activeEditSession.getSelections().length).toBe 2 + + editorView.trigger(keydownEvent('escape')) + expect(editorView.activeEditSession.getSelections().length).toBe 1 + expect(testEventHandler).not.toHaveBeenCalled() + + editorView.trigger(keydownEvent('escape')) + expect(testEventHandler).toHaveBeenCalled() + + describe "when the editor view is attached but invisible", -> + describe "when the editor view's text is changed", -> + it "redraws the editor view when it is next shown", -> + window.rootView = new RootView + rootView.openSync('sample.js') + rootView.attachToDom() + editorView = rootView.getActiveView() + + view = $$ -> @div id: 'view', tabindex: -1, 'View' + editorView.getPane().showItem(view) + expect(editorView.isVisible()).toBeFalsy() + + editorView.setText('hidden changes') + editorView.setCursorBufferPosition([0,4]) + + displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler") + editorView.on 'editor:display-updated', displayUpdatedHandler + editorView.getPane().showItem(editorView.getModel()) + expect(editorView.isVisible()).toBeTruthy() + + waitsFor -> + displayUpdatedHandler.callCount is 1 + + runs -> + expect(editorView.renderedLines.find('.line').text()).toBe 'hidden changes' + + it "redraws the editor view when it is next reattached", -> + editorView.attachToDom() + editorView.hide() + editorView.setText('hidden changes') + editorView.setCursorBufferPosition([0,4]) + editorView.detach() + + displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler") + editorView.on 'editor:display-updated', displayUpdatedHandler + editorView.show() + editorView.attachToDom() + + waitsFor -> + displayUpdatedHandler.callCount is 1 + + runs -> + expect(editorView.renderedLines.find('.line').text()).toBe 'hidden changes' + + describe "editor:scroll-to-cursor", -> + it "scrolls to and centers the editor view on the cursor's position", -> + editorView.attachToDom(heightInLines: 3) + editorView.setCursorBufferPosition([1, 2]) + editorView.scrollToBottom() + expect(editorView.getFirstVisibleScreenRow()).not.toBe 0 + expect(editorView.getLastVisibleScreenRow()).not.toBe 2 + editorView.trigger('editor:scroll-to-cursor') + expect(editorView.getFirstVisibleScreenRow()).toBe 0 + expect(editorView.getLastVisibleScreenRow()).toBe 2 + + describe "when the editor view is removed", -> + it "fires a editor:will-be-removed event", -> + window.rootView = new RootView + rootView.openSync('sample.js') + rootView.attachToDom() + editorView = rootView.getActiveView() + + willBeRemovedHandler = jasmine.createSpy('fileChange') + editorView.on 'editor:will-be-removed', willBeRemovedHandler + editorView.getPane().destroyActiveItem() + expect(willBeRemovedHandler).toHaveBeenCalled() + + describe "when setInvisibles is toggled (regression)", -> + it "renders inserted newlines properly", -> + editorView.setShowInvisibles(true) + editorView.setCursorBufferPosition([0, 0]) + editorView.attachToDom(heightInLines: 20) + editorView.setShowInvisibles(false) + editorView.insertText("\n") + + for rowNumber in [1..5] + expect(editorView.lineElementForScreenRow(rowNumber).text()).toBe buffer.lineForRow(rowNumber) + + describe "when the window is resized", -> + it "updates the active edit session with the current soft wrap column", -> + editorView.attachToDom() + setEditorWidthInChars(editorView, 50) + expect(editorView.activeEditSession.getSoftWrapColumn()).toBe 50 + setEditorWidthInChars(editorView, 100) + $(window).trigger 'resize' + expect(editorView.activeEditSession.getSoftWrapColumn()).toBe 100 diff --git a/src/editor-view.coffee b/src/editor-view.coffee new file mode 100644 index 000000000..28aeba67d --- /dev/null +++ b/src/editor-view.coffee @@ -0,0 +1,1853 @@ +{View, $, $$} = require './space-pen-extensions' +TextBuffer = require './text-buffer' +Gutter = require './gutter' +{Point, Range} = require 'telepath' +Editor = require './editor' +CursorView = require './cursor-view' +SelectionView = require './selection-view' +fs = require 'fs-plus' +_ = require 'underscore-plus' + +MeasureRange = document.createRange() +TextNodeFilter = { acceptNode: -> NodeFilter.FILTER_ACCEPT } +NoScope = ['no-scope'] +LongLineLength = 1000 + +# Private: Represents the entire visual pane in Atom. +# +# The EditorView manages the {Editor}, which manages the file buffers. +module.exports = +class EditorView extends View + @characterWidthCache: {} + @configDefaults: + fontSize: 20 + showInvisibles: false + showIndentGuide: false + showLineNumbers: true + autoIndent: true + normalizeIndentOnPaste: true + nonWordCharacters: "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`~?-" + preferredLineLength: 80 + tabLength: 2 + softWrap: false + softTabs: true + softWrapAtPreferredLineLength: false + + @nextEditorId: 1 + + ### Internal ### + + @content: (params) -> + attributes = { class: @classes(params), tabindex: -1 } + _.extend(attributes, params.attributes) if params.attributes + @div attributes, => + @subview 'gutter', new Gutter + @div class: 'scroll-view', outlet: 'scrollView', => + @div class: 'overlayer', outlet: 'overlayer' + @div class: 'lines', outlet: 'renderedLines' + @div class: 'underlayer', outlet: 'underlayer', => + @input class: 'hidden-input', outlet: 'hiddenInput' + @div class: 'vertical-scrollbar', outlet: 'verticalScrollbar', => + @div outlet: 'verticalScrollbarContent' + + @classes: ({mini} = {}) -> + classes = ['editor', 'editor-colors'] + classes.push 'mini' if mini + classes.join(' ') + + vScrollMargin: 2 + hScrollMargin: 10 + lineHeight: null + charWidth: null + charHeight: null + cursorViews: null + selectionViews: null + lineCache: null + isFocused: false + activeEditSession: null + attached: false + lineOverdraw: 10 + pendingChanges: null + newCursors: null + newSelections: null + redrawOnReattach: false + bottomPaddingInLines: 10 + + ### Public ### + + # The constructor for setting up an `EditorView` instance. + # + # editSessionOrOptions - Either an {Editor}, or an object with one property, `mini`. + # If `mini` is `true`, a "miniature" `Editor` is constructed. + # Typically, this is ideal for scenarios where you need an Atom editor, + # but without all the chrome, like scrollbars, gutter, _e.t.c._. + # + initialize: (editSessionOrOptions) -> + if editSessionOrOptions instanceof Editor + editSession = editSessionOrOptions + else + {editSession, @mini} = editSessionOrOptions ? {} + + @id = EditorView.nextEditorId++ + @lineCache = [] + @configure() + @bindKeys() + @handleEvents() + @handleInputEvents() + @cursorViews = [] + @selectionViews = [] + @pendingChanges = [] + @newCursors = [] + @newSelections = [] + + if editSession? + @edit(editSession) + else if @mini + @edit(new Editor + buffer: TextBuffer.createAsRoot() + softWrap: false + tabLength: 2 + softTabs: true + ) + else + throw new Error("Must supply an Editor or mini: true") + + # Internal: Sets up the core Atom commands. + # + # Some commands are excluded from mini-editors. + bindKeys: -> + editorBindings = + 'core:move-left': @moveCursorLeft + 'core:move-right': @moveCursorRight + 'core:select-left': @selectLeft + 'core:select-right': @selectRight + 'core:select-all': @selectAll + 'core:backspace': @backspace + 'core:delete': @delete + 'core:undo': @undo + 'core:redo': @redo + 'core:cut': @cutSelection + 'core:copy': @copySelection + 'core:paste': @paste + 'editor:move-to-previous-word': @moveCursorToPreviousWord + 'editor:select-word': @selectWord + 'editor:consolidate-selections': @consolidateSelections + 'editor:backspace-to-beginning-of-word': @backspaceToBeginningOfWord + 'editor:backspace-to-beginning-of-line': @backspaceToBeginningOfLine + 'editor:delete-to-end-of-word': @deleteToEndOfWord + 'editor:delete-line': @deleteLine + 'editor:cut-to-end-of-line': @cutToEndOfLine + 'editor:move-to-beginning-of-line': @moveCursorToBeginningOfLine + 'editor:move-to-end-of-line': @moveCursorToEndOfLine + 'editor:move-to-first-character-of-line': @moveCursorToFirstCharacterOfLine + 'editor:move-to-beginning-of-word': @moveCursorToBeginningOfWord + 'editor:move-to-end-of-word': @moveCursorToEndOfWord + 'editor:move-to-beginning-of-next-word': @moveCursorToBeginningOfNextWord + 'editor:move-to-previous-word-boundary': @moveCursorToPreviousWordBoundary + 'editor:move-to-next-word-boundary': @moveCursorToNextWordBoundary + 'editor:select-to-end-of-line': @selectToEndOfLine + 'editor:select-to-beginning-of-line': @selectToBeginningOfLine + 'editor:select-to-end-of-word': @selectToEndOfWord + 'editor:select-to-beginning-of-word': @selectToBeginningOfWord + 'editor:select-to-beginning-of-next-word': @selectToBeginningOfNextWord + 'editor:select-to-next-word-boundary': @selectToNextWordBoundary + 'editor:select-to-previous-word-boundary': @selectToPreviousWordBoundary + 'editor:select-to-first-character-of-line': @selectToFirstCharacterOfLine + 'editor:select-line': @selectLine + 'editor:transpose': @transpose + 'editor:upper-case': @upperCase + 'editor:lower-case': @lowerCase + + unless @mini + _.extend editorBindings, + 'core:move-up': @moveCursorUp + 'core:move-down': @moveCursorDown + 'core:move-to-top': @moveCursorToTop + 'core:move-to-bottom': @moveCursorToBottom + 'core:page-down': @pageDown + 'core:page-up': @pageUp + 'core:select-up': @selectUp + 'core:select-down': @selectDown + 'core:select-to-top': @selectToTop + 'core:select-to-bottom': @selectToBottom + 'editor:indent': @indent + 'editor:auto-indent': @autoIndent + 'editor:indent-selected-rows': @indentSelectedRows + 'editor:outdent-selected-rows': @outdentSelectedRows + 'editor:newline': @insertNewline + 'editor:newline-below': @insertNewlineBelow + 'editor:newline-above': @insertNewlineAbove + 'editor:add-selection-below': @addSelectionBelow + 'editor:add-selection-above': @addSelectionAbove + 'editor:toggle-soft-tabs': @toggleSoftTabs + 'editor:toggle-soft-wrap': @toggleSoftWrap + 'editor:fold-all': @foldAll + 'editor:unfold-all': @unfoldAll + 'editor:fold-current-row': @foldCurrentRow + 'editor:unfold-current-row': @unfoldCurrentRow + 'editor:fold-selection': @foldSelection + 'editor:fold-at-indent-level-1': => @foldAllAtIndentLevel(0) + 'editor:fold-at-indent-level-2': => @foldAllAtIndentLevel(1) + 'editor:fold-at-indent-level-3': => @foldAllAtIndentLevel(2) + 'editor:fold-at-indent-level-4': => @foldAllAtIndentLevel(3) + 'editor:fold-at-indent-level-5': => @foldAllAtIndentLevel(4) + 'editor:fold-at-indent-level-6': => @foldAllAtIndentLevel(5) + 'editor:fold-at-indent-level-7': => @foldAllAtIndentLevel(6) + 'editor:fold-at-indent-level-8': => @foldAllAtIndentLevel(7) + 'editor:fold-at-indent-level-9': => @foldAllAtIndentLevel(8) + 'editor:toggle-line-comments': @toggleLineCommentsInSelection + 'editor:log-cursor-scope': @logCursorScope + 'editor:checkout-head-revision': @checkoutHead + 'editor:copy-path': @copyPathToPasteboard + 'editor:move-line-up': @moveLineUp + 'editor:move-line-down': @moveLineDown + 'editor:duplicate-line': @duplicateLine + 'editor:join-line': @joinLine + 'editor:toggle-indent-guide': => atom.config.toggle('editor.showIndentGuide') + 'editor:save-debug-snapshot': @saveDebugSnapshot + 'editor:toggle-line-numbers': => atom.config.toggle('editor.showLineNumbers') + 'editor:scroll-to-cursor': @scrollToCursorPosition + + documentation = {} + for name, method of editorBindings + do (name, method) => + @command name, (e) => method.call(this, e); false + + # {Delegates to: Editor.getCursor} + getCursor: -> @activeEditSession.getCursor() + + # {Delegates to: Editor.getCursors} + getCursors: -> @activeEditSession.getCursors() + + # {Delegates to: Editor.addCursorAtScreenPosition} + addCursorAtScreenPosition: (screenPosition) -> @activeEditSession.addCursorAtScreenPosition(screenPosition) + + # {Delegates to: Editor.addCursorAtBufferPosition} + addCursorAtBufferPosition: (bufferPosition) -> @activeEditSession.addCursorAtBufferPosition(bufferPosition) + + # {Delegates to: Editor.moveCursorUp} + moveCursorUp: -> @activeEditSession.moveCursorUp() + + # {Delegates to: Editor.moveCursorDown} + moveCursorDown: -> @activeEditSession.moveCursorDown() + + # {Delegates to: Editor.moveCursorLeft} + moveCursorLeft: -> @activeEditSession.moveCursorLeft() + + # {Delegates to: Editor.moveCursorRight} + moveCursorRight: -> @activeEditSession.moveCursorRight() + + # {Delegates to: Editor.moveCursorToBeginningOfWord} + moveCursorToBeginningOfWord: -> @activeEditSession.moveCursorToBeginningOfWord() + + # {Delegates to: Editor.moveCursorToEndOfWord} + moveCursorToEndOfWord: -> @activeEditSession.moveCursorToEndOfWord() + + # {Delegates to: Editor.moveCursorToBeginningOfNextWord} + moveCursorToBeginningOfNextWord: -> @activeEditSession.moveCursorToBeginningOfNextWord() + + # {Delegates to: Editor.moveCursorToTop} + moveCursorToTop: -> @activeEditSession.moveCursorToTop() + + # {Delegates to: Editor.moveCursorToBottom} + moveCursorToBottom: -> @activeEditSession.moveCursorToBottom() + + # {Delegates to: Editor.moveCursorToBeginningOfLine} + moveCursorToBeginningOfLine: -> @activeEditSession.moveCursorToBeginningOfLine() + + # {Delegates to: Editor.moveCursorToFirstCharacterOfLine} + moveCursorToFirstCharacterOfLine: -> @activeEditSession.moveCursorToFirstCharacterOfLine() + + # {Delegates to: Editor.moveCursorToPreviousWordBoundary} + moveCursorToPreviousWordBoundary: -> @activeEditSession.moveCursorToPreviousWordBoundary() + + # {Delegates to: Editor.moveCursorToNextWordBoundary} + moveCursorToNextWordBoundary: -> @activeEditSession.moveCursorToNextWordBoundary() + + # {Delegates to: Editor.moveCursorToEndOfLine} + moveCursorToEndOfLine: -> @activeEditSession.moveCursorToEndOfLine() + + # {Delegates to: Editor.moveLineUp} + moveLineUp: -> @activeEditSession.moveLineUp() + + # {Delegates to: Editor.moveLineDown} + moveLineDown: -> @activeEditSession.moveLineDown() + + # {Delegates to: Editor.setCursorScreenPosition} + setCursorScreenPosition: (position, options) -> @activeEditSession.setCursorScreenPosition(position, options) + + # {Delegates to: Editor.duplicateLine} + duplicateLine: -> @activeEditSession.duplicateLine() + + # {Delegates to: Editor.joinLine} + joinLine: -> @activeEditSession.joinLine() + + # {Delegates to: Editor.getCursorScreenPosition} + getCursorScreenPosition: -> @activeEditSession.getCursorScreenPosition() + + # {Delegates to: Editor.getCursorScreenRow} + getCursorScreenRow: -> @activeEditSession.getCursorScreenRow() + + # {Delegates to: Editor.setCursorBufferPosition} + setCursorBufferPosition: (position, options) -> @activeEditSession.setCursorBufferPosition(position, options) + + # {Delegates to: Editor.getCursorBufferPosition} + getCursorBufferPosition: -> @activeEditSession.getCursorBufferPosition() + + # {Delegates to: Editor.getCurrentParagraphBufferRange} + getCurrentParagraphBufferRange: -> @activeEditSession.getCurrentParagraphBufferRange() + + # {Delegates to: Editor.getWordUnderCursor} + getWordUnderCursor: (options) -> @activeEditSession.getWordUnderCursor(options) + + # {Delegates to: Editor.getSelection} + getSelection: (index) -> @activeEditSession.getSelection(index) + + # {Delegates to: Editor.getSelections} + getSelections: -> @activeEditSession.getSelections() + + # {Delegates to: Editor.getSelectionsOrderedByBufferPosition} + getSelectionsOrderedByBufferPosition: -> @activeEditSession.getSelectionsOrderedByBufferPosition() + + # {Delegates to: Editor.getLastSelectionInBuffer} + getLastSelectionInBuffer: -> @activeEditSession.getLastSelectionInBuffer() + + # {Delegates to: Editor.getSelectedText} + getSelectedText: -> @activeEditSession.getSelectedText() + + # {Delegates to: Editor.getSelectedBufferRanges} + getSelectedBufferRanges: -> @activeEditSession.getSelectedBufferRanges() + + # {Delegates to: Editor.getSelectedBufferRange} + getSelectedBufferRange: -> @activeEditSession.getSelectedBufferRange() + + # {Delegates to: Editor.setSelectedBufferRange} + setSelectedBufferRange: (bufferRange, options) -> @activeEditSession.setSelectedBufferRange(bufferRange, options) + + # {Delegates to: Editor.setSelectedBufferRanges} + setSelectedBufferRanges: (bufferRanges, options) -> @activeEditSession.setSelectedBufferRanges(bufferRanges, options) + + # {Delegates to: Editor.addSelectionForBufferRange} + addSelectionForBufferRange: (bufferRange, options) -> @activeEditSession.addSelectionForBufferRange(bufferRange, options) + + # {Delegates to: Editor.selectRight} + selectRight: -> @activeEditSession.selectRight() + + # {Delegates to: Editor.selectLeft} + selectLeft: -> @activeEditSession.selectLeft() + + # {Delegates to: Editor.selectUp} + selectUp: -> @activeEditSession.selectUp() + + # {Delegates to: Editor.selectDown} + selectDown: -> @activeEditSession.selectDown() + + # {Delegates to: Editor.selectToTop} + selectToTop: -> @activeEditSession.selectToTop() + + # {Delegates to: Editor.selectToBottom} + selectToBottom: -> @activeEditSession.selectToBottom() + + # {Delegates to: Editor.selectAll} + selectAll: -> @activeEditSession.selectAll() + + # {Delegates to: Editor.selectToBeginningOfLine} + selectToBeginningOfLine: -> @activeEditSession.selectToBeginningOfLine() + + # {Delegates to: Editor.selectToFirstCharacterOfLine} + selectToFirstCharacterOfLine: -> @activeEditSession.selectToFirstCharacterOfLine() + + # {Delegates to: Editor.selectToEndOfLine} + selectToEndOfLine: -> @activeEditSession.selectToEndOfLine() + + # {Delegates to: Editor.selectToPreviousWordBoundary} + selectToPreviousWordBoundary: -> @activeEditSession.selectToPreviousWordBoundary() + + # {Delegates to: Editor.selectToNextWordBoundary} + selectToNextWordBoundary: -> @activeEditSession.selectToNextWordBoundary() + + # {Delegates to: Editor.addSelectionBelow} + addSelectionBelow: -> @activeEditSession.addSelectionBelow() + + # {Delegates to: Editor.addSelectionAbove} + addSelectionAbove: -> @activeEditSession.addSelectionAbove() + + # {Delegates to: Editor.selectToBeginningOfWord} + selectToBeginningOfWord: -> @activeEditSession.selectToBeginningOfWord() + + # {Delegates to: Editor.selectToEndOfWord} + selectToEndOfWord: -> @activeEditSession.selectToEndOfWord() + + # {Delegates to: Editor.selectToBeginningOfNextWord} + selectToBeginningOfNextWord: -> @activeEditSession.selectToBeginningOfNextWord() + + # {Delegates to: Editor.selectWord} + selectWord: -> @activeEditSession.selectWord() + + # {Delegates to: Editor.selectLine} + selectLine: -> @activeEditSession.selectLine() + + # {Delegates to: Editor.selectToScreenPosition} + selectToScreenPosition: (position) -> @activeEditSession.selectToScreenPosition(position) + + # {Delegates to: Editor.transpose} + transpose: -> @activeEditSession.transpose() + + # {Delegates to: Editor.upperCase} + upperCase: -> @activeEditSession.upperCase() + + # {Delegates to: Editor.lowerCase} + lowerCase: -> @activeEditSession.lowerCase() + + # {Delegates to: Editor.clearSelections} + clearSelections: -> @activeEditSession.clearSelections() + + # {Delegates to: Editor.backspace} + backspace: -> @activeEditSession.backspace() + + # {Delegates to: Editor.backspaceToBeginningOfWord} + backspaceToBeginningOfWord: -> @activeEditSession.backspaceToBeginningOfWord() + + # {Delegates to: Editor.backspaceToBeginningOfLine} + backspaceToBeginningOfLine: -> @activeEditSession.backspaceToBeginningOfLine() + + # {Delegates to: Editor.delete} + delete: -> @activeEditSession.delete() + + # {Delegates to: Editor.deleteToEndOfWord} + deleteToEndOfWord: -> @activeEditSession.deleteToEndOfWord() + + # {Delegates to: Editor.deleteLine} + deleteLine: -> @activeEditSession.deleteLine() + + # {Delegates to: Editor.cutToEndOfLine} + cutToEndOfLine: -> @activeEditSession.cutToEndOfLine() + + # {Delegates to: Editor.insertText} + insertText: (text, options) -> @activeEditSession.insertText(text, options) + + # {Delegates to: Editor.insertNewline} + insertNewline: -> @activeEditSession.insertNewline() + + # {Delegates to: Editor.insertNewlineBelow} + insertNewlineBelow: -> @activeEditSession.insertNewlineBelow() + + # {Delegates to: Editor.insertNewlineAbove} + insertNewlineAbove: -> @activeEditSession.insertNewlineAbove() + + # {Delegates to: Editor.indent} + indent: (options) -> @activeEditSession.indent(options) + + # {Delegates to: Editor.autoIndentSelectedRows} + autoIndent: (options) -> @activeEditSession.autoIndentSelectedRows() + + # {Delegates to: Editor.indentSelectedRows} + indentSelectedRows: -> @activeEditSession.indentSelectedRows() + + # {Delegates to: Editor.outdentSelectedRows} + outdentSelectedRows: -> @activeEditSession.outdentSelectedRows() + + # {Delegates to: Editor.cutSelectedText} + cutSelection: -> @activeEditSession.cutSelectedText() + + # {Delegates to: Editor.copySelectedText} + copySelection: -> @activeEditSession.copySelectedText() + + # {Delegates to: Editor.pasteText} + paste: (options) -> @activeEditSession.pasteText(options) + + # {Delegates to: Editor.undo} + undo: -> @activeEditSession.undo() + + # {Delegates to: Editor.redo} + redo: -> @activeEditSession.redo() + + # {Delegates to: Editor.createFold} + createFold: (startRow, endRow) -> @activeEditSession.createFold(startRow, endRow) + + # {Delegates to: Editor.foldCurrentRow} + foldCurrentRow: -> @activeEditSession.foldCurrentRow() + + # {Delegates to: Editor.unfoldCurrentRow} + unfoldCurrentRow: -> @activeEditSession.unfoldCurrentRow() + + # {Delegates to: Editor.foldAll} + foldAll: -> @activeEditSession.foldAll() + + # {Delegates to: Editor.unfoldAll} + unfoldAll: -> @activeEditSession.unfoldAll() + + # {Delegates to: Editor.foldSelection} + foldSelection: -> @activeEditSession.foldSelection() + + # {Delegates to: Editor.destroyFoldsContainingBufferRow} + destroyFoldsContainingBufferRow: (bufferRow) -> @activeEditSession.destroyFoldsContainingBufferRow(bufferRow) + + # {Delegates to: Editor.isFoldedAtScreenRow} + isFoldedAtScreenRow: (screenRow) -> @activeEditSession.isFoldedAtScreenRow(screenRow) + + # {Delegates to: Editor.isFoldedAtBufferRow} + isFoldedAtBufferRow: (bufferRow) -> @activeEditSession.isFoldedAtBufferRow(bufferRow) + + # {Delegates to: Editor.isFoldedAtCursorRow} + isFoldedAtCursorRow: -> @activeEditSession.isFoldedAtCursorRow() + + foldAllAtIndentLevel: (indentLevel) -> @activeEditSession.foldAllAtIndentLevel(indentLevel) + + # {Delegates to: Editor.lineForScreenRow} + lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow) + + # {Delegates to: Editor.linesForScreenRows} + linesForScreenRows: (start, end) -> @activeEditSession.linesForScreenRows(start, end) + + # {Delegates to: Editor.getScreenLineCount} + getScreenLineCount: -> @activeEditSession.getScreenLineCount() + + # Private: + setHeightInLines: (heightInLines)-> + heightInLines ?= @calculateHeightInLines() + @heightInLines = heightInLines if heightInLines + + # {Delegates to: Editor.setEditorWidthInChars} + setWidthInChars: (widthInChars) -> + widthInChars ?= @calculateWidthInChars() + @activeEditSession.setEditorWidthInChars(widthInChars) if widthInChars + + # {Delegates to: Editor.getMaxScreenLineLength} + getMaxScreenLineLength: -> @activeEditSession.getMaxScreenLineLength() + + # {Delegates to: Editor.getLastScreenRow} + getLastScreenRow: -> @activeEditSession.getLastScreenRow() + + # {Delegates to: Editor.clipScreenPosition} + clipScreenPosition: (screenPosition, options={}) -> @activeEditSession.clipScreenPosition(screenPosition, options) + + # {Delegates to: Editor.screenPositionForBufferPosition} + screenPositionForBufferPosition: (position, options) -> @activeEditSession.screenPositionForBufferPosition(position, options) + + # {Delegates to: Editor.bufferPositionForScreenPosition} + bufferPositionForScreenPosition: (position, options) -> @activeEditSession.bufferPositionForScreenPosition(position, options) + + # {Delegates to: Editor.screenRangeForBufferRange} + screenRangeForBufferRange: (range) -> @activeEditSession.screenRangeForBufferRange(range) + + # {Delegates to: Editor.bufferRangeForScreenRange} + bufferRangeForScreenRange: (range) -> @activeEditSession.bufferRangeForScreenRange(range) + + # {Delegates to: Editor.bufferRowsForScreenRows} + bufferRowsForScreenRows: (startRow, endRow) -> @activeEditSession.bufferRowsForScreenRows(startRow, endRow) + + # Public: Emulates the "page down" key, where the last row of a buffer scrolls to become the first. + pageDown: -> + newScrollTop = @scrollTop() + @scrollView[0].clientHeight + @activeEditSession.moveCursorDown(@getPageRows()) + @scrollTop(newScrollTop, adjustVerticalScrollbar: true) + + # Public: Emulates the "page up" key, where the frst row of a buffer scrolls to become the last. + pageUp: -> + newScrollTop = @scrollTop() - @scrollView[0].clientHeight + @activeEditSession.moveCursorUp(@getPageRows()) + @scrollTop(newScrollTop, adjustVerticalScrollbar: true) + + # Gets the number of actual page rows existing in an editor. + # + # Returns a {Number}. + getPageRows: -> + Math.max(1, Math.ceil(@scrollView[0].clientHeight / @lineHeight)) + + # Set whether invisible characters are shown. + # + # showInvisibles - A {Boolean} which, if `true`, show invisible characters + setShowInvisibles: (showInvisibles) -> + return if showInvisibles == @showInvisibles + @showInvisibles = showInvisibles + @resetDisplay() + + # Defines which characters are invisible. + # + # invisibles - A hash defining the invisible characters: The defaults are: + # eol: `\u00ac` + # space: `\u00b7` + # tab: `\u00bb` + # cr: `\u00a4` + setInvisibles: (@invisibles={}) -> + _.defaults @invisibles, + eol: '\u00ac' + space: '\u00b7' + tab: '\u00bb' + cr: '\u00a4' + @resetDisplay() + + # Sets whether you want to show the indentation guides. + # + # showIndentGuide - A {Boolean} you can set to `true` if you want to see the indentation guides. + setShowIndentGuide: (showIndentGuide) -> + return if showIndentGuide == @showIndentGuide + @showIndentGuide = showIndentGuide + @resetDisplay() + + # Checkout the HEAD revision of this editor's file. + checkoutHead: -> + if path = @getPath() + atom.project.getRepo()?.checkoutHead(path) + + # {Delegates to: Editor.setText} + setText: (text) -> @activeEditSession.setText(text) + + # {Delegates to: Editor.getText} + getText: -> @activeEditSession.getText() + + # {Delegates to: Editor.getPath} + getPath: -> @activeEditSession?.getPath() + + # {Delegates to: TextBuffer.getLineCount} + getLineCount: -> @getBuffer().getLineCount() + + # {Delegates to: TextBuffer.getLastRow} + getLastBufferRow: -> @getBuffer().getLastRow() + + # {Delegates to: TextBuffer.getTextInRange} + getTextInRange: (range) -> @getBuffer().getTextInRange(range) + + # {Delegates to: TextBuffer.getEofPosition} + getEofPosition: -> @getBuffer().getEofPosition() + + # {Delegates to: TextBuffer.lineForRow} + lineForBufferRow: (row) -> @getBuffer().lineForRow(row) + + # {Delegates to: TextBuffer.lineLengthForRow} + lineLengthForBufferRow: (row) -> @getBuffer().lineLengthForRow(row) + + # {Delegates to: TextBuffer.rangeForRow} + rangeForBufferRow: (row) -> @getBuffer().rangeForRow(row) + + # {Delegates to: TextBuffer.scanInRange} + scanInBufferRange: (args...) -> @getBuffer().scanInRange(args...) + + # {Delegates to: TextBuffer.backwardsScanInRange} + backwardsScanInBufferRange: (args...) -> @getBuffer().backwardsScanInRange(args...) + + ### Internal ### + + configure: -> + @observeConfig 'editor.showLineNumbers', (showLineNumbers) => @gutter.setShowLineNumbers(showLineNumbers) + @observeConfig 'editor.showInvisibles', (showInvisibles) => @setShowInvisibles(showInvisibles) + @observeConfig 'editor.showIndentGuide', (showIndentGuide) => @setShowIndentGuide(showIndentGuide) + @observeConfig 'editor.invisibles', (invisibles) => @setInvisibles(invisibles) + @observeConfig 'editor.fontSize', (fontSize) => @setFontSize(fontSize) + @observeConfig 'editor.fontFamily', (fontFamily) => @setFontFamily(fontFamily) + + handleEvents: -> + @on 'focus', => + @hiddenInput.focus() + false + + @hiddenInput.on 'focus', => + @bringHiddenInputIntoView() + @isFocused = true + @addClass 'is-focused' + + @hiddenInput.on 'focusout', => + @bringHiddenInputIntoView() + @isFocused = false + @removeClass 'is-focused' + + @underlayer.on 'mousedown', (e) => + @renderedLines.trigger(e) + false if @isFocused + + @overlayer.on 'mousedown', (e) => + @overlayer.hide() + clickedElement = document.elementFromPoint(e.pageX, e.pageY) + @overlayer.show() + e.target = clickedElement + $(clickedElement).trigger(e) + false if @isFocused + + @renderedLines.on 'mousedown', '.fold.line', (e) => + id = $(e.currentTarget).attr('fold-id') + marker = @activeEditSession.displayBuffer.getMarker(id) + @activeEditSession.setCursorBufferPosition(marker.getBufferRange().start) + @activeEditSession.destroyFoldWithId(id) + false + + @renderedLines.on 'mousedown', (e) => + clickCount = e.originalEvent.detail + + screenPosition = @screenPositionFromMouseEvent(e) + if clickCount == 1 + if e.metaKey + @addCursorAtScreenPosition(screenPosition) + else if e.shiftKey + @selectToScreenPosition(screenPosition) + else + @setCursorScreenPosition(screenPosition) + else if clickCount == 2 + @activeEditSession.selectWord() unless e.shiftKey + else if clickCount == 3 + @activeEditSession.selectLine() unless e.shiftKey + + @selectOnMousemoveUntilMouseup() unless e.ctrlKey or e.originalEvent.which > 1 + + unless @mini + @scrollView.on 'mousewheel', (e) => + if delta = e.originalEvent.wheelDeltaY + @scrollTop(@scrollTop() - delta) + false + + @verticalScrollbar.on 'scroll', => + @scrollTop(@verticalScrollbar.scrollTop(), adjustVerticalScrollbar: false) + + @scrollView.on 'scroll', => + if @scrollLeft() == 0 + @gutter.removeClass('drop-shadow') + else + @gutter.addClass('drop-shadow') + + # Listen for overflow events to detect when the editor's width changes + # to update the soft wrap column. + updateWidthInChars = _.debounce((=> @setWidthInChars()), 100) + @scrollView.on 'overflowchanged', => + updateWidthInChars() if @[0].classList.contains('soft-wrap') + + handleInputEvents: -> + @on 'cursor:moved', => + return unless @isFocused + cursorView = @getCursorView() + + if cursorView.isVisible() + # This is an order of magnitude faster than checking .offset(). + style = cursorView[0].style + @hiddenInput[0].style.top = style.top + @hiddenInput[0].style.left = style.left + + selectedText = null + @hiddenInput.on 'compositionstart', => + selectedText = @getSelectedText() + @hiddenInput.css('width', '100%') + @hiddenInput.on 'compositionupdate', (e) => + @insertText(e.originalEvent.data, {select: true, undo: 'skip'}) + @hiddenInput.on 'compositionend', => + @insertText(selectedText, {select: true, undo: 'skip'}) + @hiddenInput.css('width', '1px') + + lastInput = '' + @on "textInput", (e) => + # Work around of the accented character suggestion feature in OS X. + selectedLength = @hiddenInput[0].selectionEnd - @hiddenInput[0].selectionStart + if selectedLength is 1 and lastInput is @hiddenInput.val() + @selectLeft() + + lastInput = e.originalEvent.data + @insertText(lastInput) + @hiddenInput.val(lastInput) + false + + bringHiddenInputIntoView: -> + @hiddenInput.css(top: @scrollTop(), left: @scrollLeft()) + + selectOnMousemoveUntilMouseup: -> + lastMoveEvent = null + moveHandler = (event = lastMoveEvent) => + if event + @selectToScreenPosition(@screenPositionFromMouseEvent(event)) + lastMoveEvent = event + + $(document).on "mousemove.editor-#{@id}", moveHandler + interval = setInterval(moveHandler, 20) + + $(document).one "mouseup.editor-#{@id}", => + clearInterval(interval) + $(document).off 'mousemove', moveHandler + @activeEditSession.mergeIntersectingSelections(isReversed: @activeEditSession.getLastSelection().isReversed()) + @activeEditSession.finalizeSelections() + @syncCursorAnimations() + + afterAttach: (onDom) -> + return unless onDom + @redraw() if @redrawOnReattach + return if @attached + @attached = true + @calculateDimensions() + @setWidthInChars() + @subscribe $(window), "resize.editor-#{@id}", => + @setHeightInLines() + @setWidthInChars() + @updateLayerDimensions() + @requestDisplayUpdate() + @focus() if @isFocused + + if pane = @getPane() + @active = @is(pane.activeView) + @subscribe pane, 'pane:active-item-changed', (event, item) => + wasActive = @active + @active = @is(pane.activeView) + @redraw() if @active and not wasActive + + @resetDisplay() + + @trigger 'editor:attached', [this] + + edit: (editSession) -> + return if editSession is @activeEditSession + + if @activeEditSession + @saveScrollPositionForActiveEditSession() + @activeEditSession.off(".editor") + + @activeEditSession = editSession + + return unless @activeEditSession? + + @activeEditSession.setVisible(true) + + @activeEditSession.on "contents-conflicted.editor", => + @showBufferConflictAlert(@activeEditSession) + + @activeEditSession.on "path-changed.editor", => + @reloadGrammar() + @trigger 'editor:path-changed' + + @activeEditSession.on "grammar-changed.editor", => + @trigger 'editor:grammar-changed' + + @activeEditSession.on 'selection-added.editor', (selection) => + @newCursors.push(selection.cursor) + @newSelections.push(selection) + @requestDisplayUpdate() + + @activeEditSession.on 'screen-lines-changed.editor', (e) => + @handleScreenLinesChange(e) + + @activeEditSession.on 'scroll-top-changed.editor', (scrollTop) => + @scrollTop(scrollTop) + + @activeEditSession.on 'scroll-left-changed.editor', (scrollLeft) => + @scrollLeft(scrollLeft) + + @activeEditSession.on 'soft-wrap-changed.editor', (softWrap) => + @setSoftWrap(softWrap) + + @trigger 'editor:path-changed' + @resetDisplay() + + if @attached and @activeEditSession.buffer.isInConflict() + _.defer => @showBufferConflictAlert(@activeEditSession) # Display after editSession has a chance to display + + getModel: -> + @activeEditSession + + setModel: (editSession) -> + @edit(editSession) + + showBufferConflictAlert: (editSession) -> + atom.confirm( + editSession.getPath(), + "Has changed on disk. Do you want to reload it?", + "Reload", (=> editSession.buffer.reload()), + "Cancel" + ) + + scrollTop: (scrollTop, options={}) -> + return @cachedScrollTop or 0 unless scrollTop? + maxScrollTop = @verticalScrollbar.prop('scrollHeight') - @verticalScrollbar.height() + scrollTop = Math.floor(Math.max(0, Math.min(maxScrollTop, scrollTop))) + return if scrollTop == @cachedScrollTop + @cachedScrollTop = scrollTop + + @updateDisplay() if @attached + + @renderedLines.css('top', -scrollTop) + @underlayer.css('top', -scrollTop) + @overlayer.css('top', -scrollTop) + @gutter.lineNumbers.css('top', -scrollTop) + + if options?.adjustVerticalScrollbar ? true + @verticalScrollbar.scrollTop(scrollTop) + @activeEditSession.setScrollTop(@scrollTop()) + + scrollBottom: (scrollBottom) -> + if scrollBottom? + @scrollTop(scrollBottom - @scrollView.height()) + else + @scrollTop() + @scrollView.height() + + scrollLeft: (scrollLeft) -> + if scrollLeft? + @scrollView.scrollLeft(scrollLeft) + @activeEditSession.setScrollLeft(@scrollLeft()) + else + @scrollView.scrollLeft() + + scrollRight: (scrollRight) -> + if scrollRight? + @scrollView.scrollRight(scrollRight) + @activeEditSession.setScrollLeft(@scrollLeft()) + else + @scrollView.scrollRight() + + ### Public ### + + # Retrieves the {Editor}'s buffer. + # + # Returns the current {TextBuffer}. + getBuffer: -> @activeEditSession.buffer + + # Scrolls the editor to the bottom. + scrollToBottom: -> + @scrollBottom(@getScreenLineCount() * @lineHeight) + + # Scrolls the editor to the position of the most recently added cursor. + # + # The editor is also centered. + scrollToCursorPosition: -> + @scrollToBufferPosition(@getCursorBufferPosition(), center: true) + + # Scrolls the editor to the given buffer position. + # + # bufferPosition - An object that represents a buffer position. It can be either + # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} + # options - A hash matching the options available to {.scrollToPixelPosition} + scrollToBufferPosition: (bufferPosition, options) -> + @scrollToPixelPosition(@pixelPositionForBufferPosition(bufferPosition), options) + + # Scrolls the editor to the given screen position. + # + # screenPosition - An object that represents a buffer position. It can be either + # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} + # options - A hash matching the options available to {.scrollToPixelPosition} + scrollToScreenPosition: (screenPosition, options) -> + @scrollToPixelPosition(@pixelPositionForScreenPosition(screenPosition), options) + + # Scrolls the editor to the given pixel position. + # + # pixelPosition - An object that represents a pixel position. It can be either + # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} + # options - A hash with the following keys: + # center: if `true`, the position is scrolled such that it's in the center of the editor + scrollToPixelPosition: (pixelPosition, options) -> + return unless @attached + @scrollVertically(pixelPosition, options) + @scrollHorizontally(pixelPosition) + + # Highlight all the folds within the given buffer range. + # + # "Highlighting" essentially just adds the `fold-selected` class to the line's + # DOM element. + # + # bufferRange - The {Range} to check. + highlightFoldsContainingBufferRange: (bufferRange) -> + screenLines = @linesForScreenRows(@firstRenderedScreenRow, @lastRenderedScreenRow) + for screenLine, i in screenLines + if fold = screenLine.fold + screenRow = @firstRenderedScreenRow + i + element = @lineElementForScreenRow(screenRow) + + if bufferRange.intersectsWith(fold.getBufferRange()) + element.addClass('fold-selected') + else + element.removeClass('fold-selected') + + saveScrollPositionForActiveEditSession: -> + if @attached + @activeEditSession.setScrollTop(@scrollTop()) + @activeEditSession.setScrollLeft(@scrollLeft()) + + # Toggle soft tabs on the edit session. + toggleSoftTabs: -> + @activeEditSession.setSoftTabs(not @activeEditSession.getSoftTabs()) + + # Toggle soft wrap on the edit session. + toggleSoftWrap: -> + @setWidthInChars() + @activeEditSession.setSoftWrap(not @activeEditSession.getSoftWrap()) + + calculateWidthInChars: -> + Math.floor(@scrollView.width() / @charWidth) + + calculateHeightInLines: -> + Math.ceil($(window).height() / @lineHeight) + + # Enables/disables soft wrap on the editor. + # + # softWrap - A {Boolean} which, if `true`, enables soft wrap + setSoftWrap: (softWrap) -> + if softWrap + @addClass 'soft-wrap' + @scrollLeft(0) + else + @removeClass 'soft-wrap' + + # Sets the font size for the editor. + # + # fontSize - A {Number} indicating the font size in pixels. + setFontSize: (fontSize) -> + @css('font-size', "#{fontSize}px}") + + @clearCharacterWidthCache() + + if @isOnDom() + @redraw() + else + @redrawOnReattach = @attached + + # Retrieves the font size for the editor. + # + # Returns a {Number} indicating the font size in pixels. + getFontSize: -> + parseInt(@css("font-size")) + + # Sets the font family for the editor. + # + # fontFamily - A {String} identifying the CSS `font-family`, + setFontFamily: (fontFamily='') -> + @css('font-family', fontFamily) + + @clearCharacterWidthCache() + + @redraw() + + # Gets the font family for the editor. + # + # Returns a {String} identifying the CSS `font-family`, + getFontFamily: -> @css("font-family") + + # Redraw the editor + redraw: -> + return unless @hasParent() + return unless @attached + @redrawOnReattach = false + @calculateDimensions() + @updatePaddingOfRenderedLines() + @updateLayerDimensions() + @requestDisplayUpdate() + + splitLeft: -> + pane = @getPane() + pane?.splitLeft(pane?.copyActiveItem()).activeView + + splitRight: -> + pane = @getPane() + pane?.splitRight(pane?.copyActiveItem()).activeView + + splitUp: -> + pane = @getPane() + pane?.splitUp(pane?.copyActiveItem()).activeView + + splitDown: -> + pane = @getPane() + pane?.splitDown(pane?.copyActiveItem()).activeView + + # Retrieve's the `EditorView`'s pane. + # + # Returns a {Pane}. + getPane: -> + @parent('.item-views').parent('.pane').view() + + remove: (selector, keepData) -> + return super if keepData or @removed + super + rootView?.focus() + + beforeRemove: -> + @trigger 'editor:will-be-removed' + @removed = true + @activeEditSession?.destroy() + $(window).off(".editor-#{@id}") + $(document).off(".editor-#{@id}") + + getCursorView: (index) -> + index ?= @cursorViews.length - 1 + @cursorViews[index] + + getCursorViews: -> + new Array(@cursorViews...) + + addCursorView: (cursor, options) -> + cursorView = new CursorView(cursor, this, options) + @cursorViews.push(cursorView) + @overlayer.append(cursorView) + cursorView + + removeCursorView: (cursorView) -> + _.remove(@cursorViews, cursorView) + + getSelectionView: (index) -> + index ?= @selectionViews.length - 1 + @selectionViews[index] + + getSelectionViews: -> + new Array(@selectionViews...) + + addSelectionView: (selection) -> + selectionView = new SelectionView({editorView: this, selection}) + @selectionViews.push(selectionView) + @underlayer.append(selectionView) + selectionView + + removeSelectionView: (selectionView) -> + _.remove(@selectionViews, selectionView) + + removeAllCursorAndSelectionViews: -> + cursorView.remove() for cursorView in @getCursorViews() + selectionView.remove() for selectionView in @getSelectionViews() + + appendToLinesView: (view) -> + @overlayer.append(view) + + ### Internal ### + + # Scrolls the editor vertically to a given position. + scrollVertically: (pixelPosition, {center}={}) -> + scrollViewHeight = @scrollView.height() + scrollTop = @scrollTop() + scrollBottom = scrollTop + scrollViewHeight + + if center + unless scrollTop < pixelPosition.top < scrollBottom + @scrollTop(pixelPosition.top - (scrollViewHeight / 2)) + else + linesInView = @scrollView.height() / @lineHeight + maxScrollMargin = Math.floor((linesInView - 1) / 2) + scrollMargin = Math.min(@vScrollMargin, maxScrollMargin) + margin = scrollMargin * @lineHeight + desiredTop = pixelPosition.top - margin + desiredBottom = pixelPosition.top + @lineHeight + margin + if desiredBottom > scrollBottom + @scrollTop(desiredBottom - scrollViewHeight) + else if desiredTop < scrollTop + @scrollTop(desiredTop) + + # Scrolls the editor horizontally to a given position. + scrollHorizontally: (pixelPosition) -> + return if @activeEditSession.getSoftWrap() + + charsInView = @scrollView.width() / @charWidth + maxScrollMargin = Math.floor((charsInView - 1) / 2) + scrollMargin = Math.min(@hScrollMargin, maxScrollMargin) + margin = scrollMargin * @charWidth + desiredRight = pixelPosition.left + @charWidth + margin + desiredLeft = pixelPosition.left - margin + + if desiredRight > @scrollRight() + @scrollRight(desiredRight) + else if desiredLeft < @scrollLeft() + @scrollLeft(desiredLeft) + @saveScrollPositionForActiveEditSession() + + calculateDimensions: -> + fragment = $('') + @renderedLines.append(fragment) + + lineRect = fragment[0].getBoundingClientRect() + charRect = fragment.find('span')[0].getBoundingClientRect() + @lineHeight = lineRect.height + @charWidth = charRect.width + @charHeight = charRect.height + fragment.remove() + @setHeightInLines() + + updateLayerDimensions: -> + height = @lineHeight * @getScreenLineCount() + unless @layerHeight == height + @layerHeight = height + @underlayer.height(@layerHeight) + @renderedLines.height(@layerHeight) + @overlayer.height(@layerHeight) + @verticalScrollbarContent.height(@layerHeight) + @scrollBottom(height) if @scrollBottom() > height + + minWidth = Math.max(@charWidth * @getMaxScreenLineLength() + 20, @scrollView.width()) + unless @layerMinWidth == minWidth + @renderedLines.css('min-width', minWidth) + @underlayer.css('min-width', minWidth) + @overlayer.css('min-width', minWidth) + @layerMinWidth = minWidth + @trigger 'editor:min-width-changed' + + # Override for speed. The base function checks computedStyle, unnecessary here. + isHidden: -> + style = this[0].style + if style.display == 'none' or not @isOnDom() + true + else + false + + clearRenderedLines: -> + @renderedLines.empty() + @firstRenderedScreenRow = null + @lastRenderedScreenRow = null + + resetDisplay: -> + return unless @attached + + @clearRenderedLines() + @removeAllCursorAndSelectionViews() + editSessionScrollTop = @activeEditSession.getScrollTop() ? 0 + editSessionScrollLeft = @activeEditSession.getScrollLeft() ? 0 + @updateLayerDimensions() + @scrollTop(editSessionScrollTop) + @scrollLeft(editSessionScrollLeft) + @setSoftWrap(@activeEditSession.getSoftWrap()) + @newCursors = @activeEditSession.getAllCursors() + @newSelections = @activeEditSession.getAllSelections() + @updateDisplay(suppressAutoScroll: true) + + requestDisplayUpdate: -> + return if @pendingDisplayUpdate + return unless @isVisible() + @pendingDisplayUpdate = true + setImmediate => + @updateDisplay() + @pendingDisplayUpdate = false + + updateDisplay: (options={}) -> + return unless @attached and @activeEditSession + return if @activeEditSession.destroyed + unless @isOnDom() and @isVisible() + @redrawOnReattach = true + return + + @updateRenderedLines() + @highlightCursorLine() + @updateCursorViews() + @updateSelectionViews() + @autoscroll(options) + @trigger 'editor:display-updated' + + updateCursorViews: -> + if @newCursors.length > 0 + @addCursorView(cursor) for cursor in @newCursors when not cursor.destroyed + @syncCursorAnimations() + @newCursors = [] + + for cursorView in @getCursorViews() + if cursorView.needsRemoval + cursorView.remove() + else if @shouldUpdateCursor(cursorView) + cursorView.updateDisplay() + + shouldUpdateCursor: (cursorView) -> + return false unless cursorView.needsUpdate + + pos = cursorView.getScreenPosition() + pos.row >= @firstRenderedScreenRow and pos.row <= @lastRenderedScreenRow + + updateSelectionViews: -> + if @newSelections.length > 0 + @addSelectionView(selection) for selection in @newSelections when not selection.destroyed + @newSelections = [] + + for selectionView in @getSelectionViews() + if selectionView.needsRemoval + selectionView.remove() + else if @shouldUpdateSelection(selectionView) + selectionView.updateDisplay() + + shouldUpdateSelection: (selectionView) -> + screenRange = selectionView.getScreenRange() + startRow = screenRange.start.row + endRow = screenRange.end.row + (startRow >= @firstRenderedScreenRow and startRow <= @lastRenderedScreenRow) or # startRow in range + (endRow >= @firstRenderedScreenRow and endRow <= @lastRenderedScreenRow) or # endRow in range + (startRow <= @firstRenderedScreenRow and endRow >= @lastRenderedScreenRow) # selection surrounds the rendered items + + syncCursorAnimations: -> + for cursorView in @getCursorViews() + do (cursorView) -> cursorView.resetBlinking() + + autoscroll: (options={}) -> + for cursorView in @getCursorViews() + if !options.suppressAutoScroll and cursorView.needsAutoscroll() + @scrollToPixelPosition(cursorView.getPixelPosition()) + cursorView.clearAutoscroll() + + for selectionView in @getSelectionViews() + if !options.suppressAutoScroll and selectionView.needsAutoscroll() + @scrollToPixelPosition(selectionView.getCenterPixelPosition(), center: true) + selectionView.highlight() + selectionView.clearAutoscroll() + + updateRenderedLines: -> + firstVisibleScreenRow = @getFirstVisibleScreenRow() + lastScreenRowToRender = firstVisibleScreenRow + @heightInLines - 1 + lastScreenRow = @getLastScreenRow() + + if @firstRenderedScreenRow? and firstVisibleScreenRow >= @firstRenderedScreenRow and lastScreenRowToRender <= @lastRenderedScreenRow + renderFrom = Math.min(lastScreenRow, @firstRenderedScreenRow) + renderTo = Math.min(lastScreenRow, @lastRenderedScreenRow) + else + renderFrom = Math.min(lastScreenRow, Math.max(0, firstVisibleScreenRow - @lineOverdraw)) + renderTo = Math.min(lastScreenRow, lastScreenRowToRender + @lineOverdraw) + + if @pendingChanges.length == 0 and @firstRenderedScreenRow and @firstRenderedScreenRow <= renderFrom and renderTo <= @lastRenderedScreenRow + return + + changes = @pendingChanges + intactRanges = @computeIntactRanges(renderFrom, renderTo) + + @gutter.updateLineNumbers(changes, renderFrom, renderTo) + + @clearDirtyRanges(intactRanges) + @fillDirtyRanges(intactRanges, renderFrom, renderTo) + @firstRenderedScreenRow = renderFrom + @lastRenderedScreenRow = renderTo + @updateLayerDimensions() + @updatePaddingOfRenderedLines() + + computeSurroundingEmptyLineChanges: (change) -> + emptyLineChanges = [] + + if change.bufferDelta? + afterStart = change.end + change.bufferDelta + 1 + if @lineForBufferRow(afterStart) is '' + afterEnd = afterStart + afterEnd++ while @lineForBufferRow(afterEnd + 1) is '' + emptyLineChanges.push({start: afterStart, end: afterEnd, screenDelta: 0}) + + beforeEnd = change.start - 1 + if @lineForBufferRow(beforeEnd) is '' + beforeStart = beforeEnd + beforeStart-- while @lineForBufferRow(beforeStart - 1) is '' + emptyLineChanges.push({start: beforeStart, end: beforeEnd, screenDelta: 0}) + + emptyLineChanges + + computeIntactRanges: (renderFrom, renderTo) -> + return [] if !@firstRenderedScreenRow? and !@lastRenderedScreenRow? + + intactRanges = [{start: @firstRenderedScreenRow, end: @lastRenderedScreenRow, domStart: 0}] + + if not @mini and @showIndentGuide + emptyLineChanges = [] + for change in @pendingChanges + emptyLineChanges.push(@computeSurroundingEmptyLineChanges(change)...) + @pendingChanges.push(emptyLineChanges...) + + for change in @pendingChanges + newIntactRanges = [] + for range in intactRanges + if change.end < range.start and change.screenDelta != 0 + newIntactRanges.push( + start: range.start + change.screenDelta + end: range.end + change.screenDelta + domStart: range.domStart + ) + else if change.end < range.start or change.start > range.end + newIntactRanges.push(range) + else + if change.start > range.start + newIntactRanges.push( + start: range.start + end: change.start - 1 + domStart: range.domStart) + if change.end < range.end + newIntactRanges.push( + start: change.end + change.screenDelta + 1 + end: range.end + change.screenDelta + domStart: range.domStart + change.end + 1 - range.start + ) + intactRanges = newIntactRanges + + @truncateIntactRanges(intactRanges, renderFrom, renderTo) + + @pendingChanges = [] + + intactRanges + + truncateIntactRanges: (intactRanges, renderFrom, renderTo) -> + i = 0 + while i < intactRanges.length + range = intactRanges[i] + if range.start < renderFrom + range.domStart += renderFrom - range.start + range.start = renderFrom + if range.end > renderTo + range.end = renderTo + if range.start >= range.end + intactRanges.splice(i--, 1) + i++ + intactRanges.sort (a, b) -> a.domStart - b.domStart + + clearDirtyRanges: (intactRanges) -> + if intactRanges.length == 0 + @renderedLines[0].innerHTML = '' + else if currentLine = @renderedLines[0].firstChild + domPosition = 0 + for intactRange in intactRanges + while intactRange.domStart > domPosition + currentLine = @clearLine(currentLine) + domPosition++ + for i in [intactRange.start..intactRange.end] + currentLine = currentLine.nextSibling + domPosition++ + while currentLine + currentLine = @clearLine(currentLine) + + clearLine: (lineElement) -> + next = lineElement.nextSibling + @renderedLines[0].removeChild(lineElement) + next + + fillDirtyRanges: (intactRanges, renderFrom, renderTo) -> + i = 0 + nextIntact = intactRanges[i] + currentLine = @renderedLines[0].firstChild + + row = renderFrom + while row <= renderTo + if row == nextIntact?.end + 1 + nextIntact = intactRanges[++i] + + if !nextIntact or row < nextIntact.start + if nextIntact + dirtyRangeEnd = nextIntact.start - 1 + else + dirtyRangeEnd = renderTo + + for lineElement in @buildLineElementsForScreenRows(row, dirtyRangeEnd) + @renderedLines[0].insertBefore(lineElement, currentLine) + row++ + else + currentLine = currentLine.nextSibling + row++ + + updatePaddingOfRenderedLines: -> + paddingTop = @firstRenderedScreenRow * @lineHeight + @renderedLines.css('padding-top', paddingTop) + @gutter.lineNumbers.css('padding-top', paddingTop) + + paddingBottom = (@getLastScreenRow() - @lastRenderedScreenRow) * @lineHeight + @renderedLines.css('padding-bottom', paddingBottom) + @gutter.lineNumbers.css('padding-bottom', paddingBottom) + + ### Public ### + + # Retrieves the number of the row that is visible and currently at the top of the editor. + # + # Returns a {Number}. + getFirstVisibleScreenRow: -> + screenRow = Math.floor(@scrollTop() / @lineHeight) + screenRow = 0 if isNaN(screenRow) + screenRow + + # Retrieves the number of the row that is visible and currently at the bottom of the editor. + # + # Returns a {Number}. + getLastVisibleScreenRow: -> + calculatedRow = Math.ceil((@scrollTop() + @scrollView.height()) / @lineHeight) - 1 + screenRow = Math.max(0, Math.min(@getScreenLineCount() - 1, calculatedRow)) + screenRow = 0 if isNaN(screenRow) + screenRow + + # Given a row number, identifies if it is currently visible. + # + # row - A row {Number} to check + # + # Returns a {Boolean}. + isScreenRowVisible: (row) -> + @getFirstVisibleScreenRow() <= row <= @getLastVisibleScreenRow() + + ### Internal ### + + handleScreenLinesChange: (change) -> + @pendingChanges.push(change) + @requestDisplayUpdate() + + buildLineElementForScreenRow: (screenRow) -> + @buildLineElementsForScreenRows(screenRow, screenRow)[0] + + buildLineElementsForScreenRows: (startRow, endRow) -> + div = document.createElement('div') + div.innerHTML = @htmlForScreenRows(startRow, endRow) + new Array(div.children...) + + htmlForScreenRows: (startRow, endRow) -> + htmlLines = '' + screenRow = startRow + for line in @activeEditSession.linesForScreenRows(startRow, endRow) + htmlLines += @htmlForScreenLine(line, screenRow++) + htmlLines + + htmlForScreenLine: (screenLine, screenRow) -> + { tokens, text, lineEnding, fold, isSoftWrapped } = screenLine + if fold + attributes = { class: 'fold line', 'fold-id': fold.id } + else + attributes = { class: 'line' } + + invisibles = @invisibles if @showInvisibles + eolInvisibles = @getEndOfLineInvisibles(screenLine) + htmlEolInvisibles = @buildHtmlEndOfLineInvisibles(screenLine) + + indentation = EditorView.buildIndentation(screenRow, @activeEditSession) + + EditorView.buildLineHtml({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, @showIndentGuide, indentation, @activeEditSession, @mini}) + + @buildIndentation: (screenRow, activeEditSession) -> + bufferRow = activeEditSession.bufferPositionForScreenPosition([screenRow]).row + bufferLine = activeEditSession.lineForBufferRow(bufferRow) + if bufferLine is '' + indentation = 0 + nextRow = screenRow + 1 + while nextRow < activeEditSession.getBuffer().getLineCount() + bufferRow = activeEditSession.bufferPositionForScreenPosition([nextRow]).row + bufferLine = activeEditSession.lineForBufferRow(bufferRow) + if bufferLine isnt '' + indentation = Math.ceil(activeEditSession.indentLevelForLine(bufferLine)) + break + nextRow++ + + previousRow = screenRow - 1 + while previousRow >= 0 + bufferRow = activeEditSession.bufferPositionForScreenPosition([previousRow]).row + bufferLine = activeEditSession.lineForBufferRow(bufferRow) + if bufferLine isnt '' + indentation = Math.max(indentation, Math.ceil(activeEditSession.indentLevelForLine(bufferLine))) + break + previousRow-- + + indentation + else + Math.ceil(activeEditSession.indentLevelForLine(bufferLine)) + + buildHtmlEndOfLineInvisibles: (screenLine) -> + invisibles = [] + for invisible in @getEndOfLineInvisibles(screenLine) + invisibles.push("#{invisible}") + invisibles.join('') + + getEndOfLineInvisibles: (screenLine) -> + return [] unless @showInvisibles and @invisibles + return [] if @mini or screenLine.isSoftWrapped() + + invisibles = [] + invisibles.push(@invisibles.cr) if @invisibles.cr and screenLine.lineEnding is '\r\n' + invisibles.push(@invisibles.eol) if @invisibles.eol + invisibles + + lineElementForScreenRow: (screenRow) -> + @renderedLines.children(":eq(#{screenRow - @firstRenderedScreenRow})") + + toggleLineCommentsInSelection: -> + @activeEditSession.toggleLineCommentsInSelection() + + ### Public ### + + # Converts a buffer position to a pixel position. + # + # position - An object that represents a buffer position. It can be either + # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} + # + # Returns an object with two values: `top` and `left`, representing the pixel positions. + pixelPositionForBufferPosition: (position) -> + @pixelPositionForScreenPosition(@screenPositionForBufferPosition(position)) + + # Converts a screen position to a pixel position. + # + # position - An object that represents a screen position. It can be either + # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} + # + # Returns an object with two values: `top` and `left`, representing the pixel positions. + pixelPositionForScreenPosition: (position) -> + return { top: 0, left: 0 } unless @isOnDom() and @isVisible() + {row, column} = Point.fromObject(position) + actualRow = Math.floor(row) + + lineElement = existingLineElement = @lineElementForScreenRow(actualRow)[0] + unless existingLineElement + lineElement = @buildLineElementForScreenRow(actualRow) + @renderedLines.append(lineElement) + left = @positionLeftForLineAndColumn(lineElement, actualRow, column) + unless existingLineElement + @renderedLines[0].removeChild(lineElement) + { top: row * @lineHeight, left } + + positionLeftForLineAndColumn: (lineElement, screenRow, column) -> + return 0 if column == 0 + + bufferRow = @bufferRowsForScreenRows(screenRow, screenRow)[0] ? screenRow + tokenizedLine = @activeEditSession.displayBuffer.tokenizedBuffer.tokenizedLines[bufferRow] + + left = 0 + index = 0 + for token in tokenizedLine.tokens + for char in token.value + return left if index >= column + + val = @getCharacterWidthCache(token.scopes, char) + if val? + left += val + else + return @measureToColumn(lineElement, tokenizedLine, column) + + index++ + left + + scopesForColumn: (tokenizedLine, column) -> + index = 0 + for token in tokenizedLine.tokens + for char in token.value + return token.scopes if index == column + index++ + null + + measureToColumn: (lineElement, tokenizedLine, column) -> + left = oldLeft = index = 0 + iterator = document.createNodeIterator(lineElement, NodeFilter.SHOW_TEXT, TextNodeFilter) + + returnLeft = null + + offsetLeft = @scrollView.offset().left + paddingLeft = parseInt(@scrollView.css('padding-left')) + + while textNode = iterator.nextNode() + content = textNode.textContent + + for char, i in content + # Don't continue caching long lines :racehorse: + break if index > LongLineLength and column < index + + # Dont return right away, finish caching the whole line + returnLeft = left if index == column + oldLeft = left + + scopes = @scopesForColumn(tokenizedLine, index) + cachedCharWidth = @getCharacterWidthCache(scopes, char) + + if cachedCharWidth? + left = oldLeft + cachedCharWidth + else + # i + 1 to measure to the end of the current character + MeasureRange.setEnd(textNode, i + 1) + MeasureRange.collapse() + rects = MeasureRange.getClientRects() + return 0 if rects.length == 0 + left = rects[0].left - Math.floor(offsetLeft) + Math.floor(@scrollLeft()) - paddingLeft + + if scopes? + cachedCharWidth = left - oldLeft + @setCharacterWidthCache(scopes, char, cachedCharWidth) + + # Assume all the characters are the same width when dealing with long + # lines :racehorse: + return column * cachedCharWidth if index > LongLineLength + + index++ + + returnLeft ? left + + getCharacterWidthCache: (scopes, char) -> + scopes ?= NoScope + obj = EditorView.characterWidthCache + for scope in scopes + obj = obj[scope] + return null unless obj? + obj[char] + + setCharacterWidthCache: (scopes, char, val) -> + scopes ?= NoScope + obj = EditorView.characterWidthCache + for scope in scopes + obj[scope] ?= {} + obj = obj[scope] + obj[char] = val + + clearCharacterWidthCache: -> + EditorView.characterWidthCache = {} + + pixelOffsetForScreenPosition: (position) -> + {top, left} = @pixelPositionForScreenPosition(position) + offset = @renderedLines.offset() + {top: top + offset.top, left: left + offset.left} + + screenPositionFromMouseEvent: (e) -> + { pageX, pageY } = e + offset = @scrollView.offset() + + editorRelativeTop = pageY - offset.top + @scrollTop() + row = Math.floor(editorRelativeTop / @lineHeight) + column = 0 + + if pageX > offset.left and lineElement = @lineElementForScreenRow(row)[0] + range = document.createRange() + iterator = document.createNodeIterator(lineElement, NodeFilter.SHOW_TEXT, acceptNode: -> NodeFilter.FILTER_ACCEPT) + while node = iterator.nextNode() + range.selectNodeContents(node) + column += node.textContent.length + {left, right} = range.getClientRects()[0] + break if left <= pageX <= right + + if node + for characterPosition in [node.textContent.length...0] + range.setStart(node, characterPosition - 1) + range.setEnd(node, characterPosition) + {left, right, width} = range.getClientRects()[0] + break if left <= pageX - width / 2 <= right + column-- + + range.detach() + + new Point(row, column) + + # Highlights the current line the cursor is on. + highlightCursorLine: -> + return if @mini + + @highlightedLine?.removeClass('cursor-line') + if @getSelection().isEmpty() + @highlightedLine = @lineElementForScreenRow(@getCursorScreenRow()) + @highlightedLine.addClass('cursor-line') + else + @highlightedLine = null + + # {Delegates to: Editor.getGrammar} + getGrammar: -> + @activeEditSession.getGrammar() + + # {Delegates to: Editor.setGrammar} + setGrammar: (grammar) -> + throw new Error("Only mini-editors can explicity set their grammar") unless @mini + @activeEditSession.setGrammar(grammar) + + # {Delegates to: Editor.reloadGrammar} + reloadGrammar: -> + @activeEditSession.reloadGrammar() + + # {Delegates to: Editor.scopesForBufferPosition} + scopesForBufferPosition: (bufferPosition) -> + @activeEditSession.scopesForBufferPosition(bufferPosition) + + # Copies the current file path to the native clipboard. + copyPathToPasteboard: -> + path = @getPath() + pasteboard.write(path) if path? + + ### Internal ### + + @buildLineHtml: ({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, showIndentGuide, indentation, activeEditSession, mini}) -> + scopeStack = [] + line = [] + + attributePairs = '' + attributePairs += " #{attributeName}=\"#{value}\"" for attributeName, value of attributes + line.push("
") + + if text == '' + html = EditorView.buildEmptyLineHtml(showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini) + line.push(html) if html + else + firstNonWhitespacePosition = text.search(/\S/) + firstTrailingWhitespacePosition = text.search(/\s*$/) + lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0 + position = 0 + for token in tokens + @updateScopeStack(line, scopeStack, token.scopes) + hasLeadingWhitespace = position < firstNonWhitespacePosition + hasTrailingWhitespace = position + token.value.length > firstTrailingWhitespacePosition + hasIndentGuide = not mini and showIndentGuide and (hasLeadingWhitespace or lineIsWhitespaceOnly) + line.push(token.getValueAsHtml({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide})) + position += token.value.length + + @popScope(line, scopeStack) while scopeStack.length > 0 + line.push(htmlEolInvisibles) unless text == '' + line.push("") if fold + + line.push('
') + line.join('') + + @updateScopeStack: (line, scopeStack, desiredScopes) -> + excessScopes = scopeStack.length - desiredScopes.length + if excessScopes > 0 + @popScope(line, scopeStack) while excessScopes-- + + # pop until common prefix + for i in [scopeStack.length..0] + break if _.isEqual(scopeStack[0...i], desiredScopes[0...i]) + @popScope(line, scopeStack) + + # push on top of common prefix until scopeStack == desiredScopes + for j in [i...desiredScopes.length] + @pushScope(line, scopeStack, desiredScopes[j]) + + null + + @pushScope: (line, scopeStack, scope) -> + scopeStack.push(scope) + line.push("") + + @popScope: (line, scopeStack) -> + scopeStack.pop() + line.push("") + + @buildEmptyLineHtml: (showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini) -> + indentCharIndex = 0 + if not mini and showIndentGuide + if indentation > 0 + tabLength = activeEditSession.getTabLength() + indentGuideHtml = '' + for level in [0...indentation] + indentLevelHtml = "" + for characterPosition in [0...tabLength] + if invisible = eolInvisibles[indentCharIndex++] + indentLevelHtml += "#{invisible}" + else + indentLevelHtml += ' ' + indentLevelHtml += "" + indentGuideHtml += indentLevelHtml + + while indentCharIndex < eolInvisibles.length + indentGuideHtml += "#{eolInvisibles[indentCharIndex++]}" + + return indentGuideHtml + + if htmlEolInvisibles.length > 0 + htmlEolInvisibles + else + ' ' + + replaceSelectedText: (replaceFn) -> + selection = @getSelection() + return false if selection.isEmpty() + + text = replaceFn(@getTextInRange(selection.getBufferRange())) + return false if text is null or text is undefined + + @insertText(text, select: true) + true + + consolidateSelections: (e) -> e.abortKeyBinding() unless @activeEditSession.consolidateSelections() + + logCursorScope: -> + console.log @activeEditSession.getCursorScopes() + + transact: (fn) -> @activeEditSession.transact(fn) + beginTransaction: -> @activeEditSession.beginTransaction() + commitTransaction: -> @activeEditSession.commitTransaction() + abortTransaction: -> @activeEditSession.abortTransaction() + + saveDebugSnapshot: -> + atom.showSaveDialog (path) => + fs.writeFileSync(path, @getDebugSnapshot()) if path + + getDebugSnapshot: -> + [ + "Debug Snapshot: #{@getPath()}" + @getRenderedLinesDebugSnapshot() + @activeEditSession.getDebugSnapshot() + @getBuffer().getDebugSnapshot() + ].join('\n\n') + + getRenderedLinesDebugSnapshot: -> + lines = ['Rendered Lines:'] + firstRenderedScreenRow = @firstRenderedScreenRow + @renderedLines.find('.line').each (n) -> + lines.push "#{firstRenderedScreenRow + n}: #{$(this).text()}" + lines.join('\n') + + logScreenLines: (start, end) -> + @activeEditSession.logScreenLines(start, end) + + logRenderedLines: -> + @renderedLines.find('.line').each (n) -> + console.log n, $(this).text() From 756c2be64a6cfc08d783df305c10d8843bd80000 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 12:26:41 -0800 Subject: [PATCH 08/15] Replace editor instance variables with editorView --- spec/atom-spec.coffee | 8 ++++---- spec/pane-spec.coffee | 12 ++++++------ spec/root-view-spec.coffee | 4 ++-- spec/spec-helper.coffee | 22 +++++++++++----------- src/cursor-view.coffee | 12 ++++++------ src/gutter.coffee | 38 +++++++++++++++++++------------------- src/root-view.coffee | 4 ++-- src/selection-view.coffee | 18 +++++++++--------- 8 files changed, 59 insertions(+), 59 deletions(-) diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee index 1e8c5dda8..ddc1507d8 100644 --- a/spec/atom-spec.coffee +++ b/spec/atom-spec.coffee @@ -95,14 +95,14 @@ describe "the `atom` global", -> it "triggers the activation event on all handlers registered during activation", -> rootView.openSync() - editor = rootView.getActiveView() + editorView = rootView.getActiveView() eventHandler = jasmine.createSpy("activation-event") - editor.command 'activation-event', eventHandler - editor.trigger 'activation-event' + editorView.command 'activation-event', eventHandler + editorView.trigger 'activation-event' expect(mainModule.activate.callCount).toBe 1 expect(mainModule.activationEventCallCount).toBe 1 expect(eventHandler.callCount).toBe 1 - editor.trigger 'activation-event' + editorView.trigger 'activation-event' expect(mainModule.activationEventCallCount).toBe 2 expect(eventHandler.callCount).toBe 2 expect(mainModule.activate.callCount).toBe 1 diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index b892995c7..5f50b7251 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -90,18 +90,18 @@ describe "Pane", -> describe "when no view has yet been appended for that item", -> it "appends and shows a view to display the item based on its `.getViewClass` method", -> pane.showItem(editSession1) - editor = pane.activeView - expect(editor.css('display')).not.toBe 'none' - expect(editor.activeEditSession).toBe editSession1 + editorView = pane.activeView + expect(editorView.css('display')).not.toBe 'none' + expect(editorView.activeEditSession).toBe editSession1 describe "when a valid view has already been appended for another item", -> it "multiple views are created for multiple items", -> pane.showItem(editSession1) pane.showItem(editSession2) expect(pane.itemViews.find('.editor').length).toBe 2 - editor = pane.activeView - expect(editor.css('display')).not.toBe 'none' - expect(editor.activeEditSession).toBe editSession2 + editorView = pane.activeView + expect(editorView.css('display')).not.toBe 'none' + expect(editorView.activeEditSession).toBe editSession2 it "creates a new view with the item", -> initialViewCount = pane.itemViews.find('.test-view').length diff --git a/spec/root-view-spec.coffee b/spec/root-view-spec.coffee index 29396f67a..fa3add1f1 100644 --- a/spec/root-view-spec.coffee +++ b/spec/root-view-spec.coffee @@ -100,9 +100,9 @@ describe "RootView", -> describe "when there is an active view", -> it "hands off focus to the active view", -> editor = rootView.getActiveView() - editor.isFocused = false + editorView.isFocused = false rootView.focus() - expect(editor.isFocused).toBeTruthy() + expect(editorView.isFocused).toBeTruthy() describe "when there is no active view", -> beforeEach -> diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index bd8cc5e75..3338fb0b8 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -174,8 +174,8 @@ window.keydownEvent = (key, properties={}) -> window.mouseEvent = (type, properties) -> if properties.point - {point, editor} = properties - {top, left} = @pagePixelPositionForPoint(editor, point) + {point, editorView} = properties + {top, left} = @pagePixelPositionForPoint(editorView, point) properties.pageX = left + 1 properties.pageY = top + 1 properties.originalEvent ?= {detail: 1} @@ -236,22 +236,22 @@ window.advanceClock = (delta=1) -> callback() for callback in callbacks -window.pagePixelPositionForPoint = (editor, point) -> +window.pagePixelPositionForPoint = (editorView, point) -> point = Point.fromObject point - top = editor.renderedLines.offset().top + point.row * editor.lineHeight - left = editor.renderedLines.offset().left + point.column * editor.charWidth - editor.renderedLines.scrollLeft() + top = editorView.renderedLines.offset().top + point.row * editorView.lineHeight + left = editorView.renderedLines.offset().left + point.column * editorView.charWidth - editorView.renderedLines.scrollLeft() { top, left } window.tokensText = (tokens) -> _.pluck(tokens, 'value').join('') -window.setEditorWidthInChars = (editor, widthInChars, charWidth=editor.charWidth) -> - editor.width(charWidth * widthInChars + editor.gutter.outerWidth()) - $(window).trigger 'resize' # update width of editor's on-screen lines +window.setEditorWidthInChars = (editorView, widthInChars, charWidth=editorView.charWidth) -> + editorView.width(charWidth * widthInChars + editorView.gutter.outerWidth()) + $(window).trigger 'resize' # update width of editor view's on-screen lines -window.setEditorHeightInLines = (editor, heightInChars, charHeight=editor.lineHeight) -> - editor.height(charHeight * heightInChars + editor.renderedLines.position().top) - $(window).trigger 'resize' # update editor's on-screen lines +window.setEditorHeightInLines = (editorView, heightInChars, charHeight=editorView.lineHeight) -> + editorView.height(charHeight * heightInChars + editorView.renderedLines.position().top) + $(window).trigger 'resize' # update editor view's on-screen lines $.fn.resultOfTrigger = (type) -> event = $.Event(type) diff --git a/src/cursor-view.coffee b/src/cursor-view.coffee index 5276965b5..1af9e2204 100644 --- a/src/cursor-view.coffee +++ b/src/cursor-view.coffee @@ -9,14 +9,14 @@ class CursorView extends View @div class: 'cursor idle', => @raw ' ' blinkPeriod: 800 - editor: null + editorView: null visible: true needsUpdate: true needsRemoval: false shouldPauseBlinking: false - initialize: (@cursor, @editor) -> + initialize: (@cursor, @editorView) -> @cursor.on 'moved.cursor-view', => @needsUpdate = true @shouldPauseBlinking = true @@ -25,7 +25,7 @@ class CursorView extends View @needsUpdate = true @cursor.on 'autoscrolled.cursor-view', => - @editor.requestDisplayUpdate() + @editorView.requestDisplayUpdate() @cursor.on 'destroyed.cursor-view', => @needsRemoval = true @@ -34,7 +34,7 @@ class CursorView extends View @addClass("site-#{@cursor.marker.getOriginSiteId()}") beforeRemove: -> - @editor.removeCursorView(this) + @editorView.removeCursorView(this) @cursor.off('.cursor-view') @stopBlinking() @@ -52,7 +52,7 @@ class CursorView extends View else if !@startBlinkingTimeout @startBlinking() - @setVisible(@cursor.isVisible() and not @editor.isFoldedAtScreenRow(screenPosition.row)) + @setVisible(@cursor.isVisible() and not @editorView.isFoldedAtScreenRow(screenPosition.row)) # Override for speed. The base function checks the computedStyle isHidden: -> @@ -69,7 +69,7 @@ class CursorView extends View @cursor.clearAutoscroll() getPixelPosition: -> - @editor.pixelPositionForScreenPosition(@getScreenPosition()) + @editorView.pixelPositionForScreenPosition(@getScreenPosition()) setVisible: (visible) -> unless @visible == visible diff --git a/src/gutter.coffee b/src/gutter.coffee index 1d021b9e4..040c244ba 100644 --- a/src/gutter.coffee +++ b/src/gutter.coffee @@ -25,37 +25,37 @@ class Gutter extends View @attached = true highlightLines = => @highlightLines() - @getEditor().on 'cursor:moved', highlightLines - @getEditor().on 'selection:changed', highlightLines + @getEditorView().on 'cursor:moved', highlightLines + @getEditorView().on 'selection:changed', highlightLines @on 'mousedown', (e) => @handleMouseEvents(e) beforeRemove: -> - $(document).off(".gutter-#{@getEditor().id}") + $(document).off(".gutter-#{@getEditorView().id}") handleMouseEvents: (e) -> - editor = @getEditor() - startRow = editor.screenPositionFromMouseEvent(e).row + editorView = @getEditorView() + startRow = editorView.screenPositionFromMouseEvent(e).row if e.shiftKey - editor.selectToScreenPosition([startRow + 1, 0]) + editorView.selectToScreenPosition([startRow + 1, 0]) return else - editor.getSelection().setScreenRange([[startRow, 0], [startRow, 0]]) + editorView.getSelection().setScreenRange([[startRow, 0], [startRow, 0]]) moveHandler = (e) => start = startRow - end = editor.screenPositionFromMouseEvent(e).row + end = editorView.screenPositionFromMouseEvent(e).row if end > start then end++ else start++ - editor.getSelection().setScreenRange([[start, 0], [end, 0]]) + editorView.getSelection().setScreenRange([[start, 0], [end, 0]]) - $(document).on "mousemove.gutter-#{@getEditor().id}", moveHandler - $(document).one "mouseup.gutter-#{@getEditor().id}", => $(document).off 'mousemove', moveHandler + $(document).on "mousemove.gutter-#{@getEditorView().id}", moveHandler + $(document).one "mouseup.gutter-#{@getEditorView().id}", => $(document).off 'mousemove', moveHandler ### Public ### # Retrieves the containing {TextEditorView}. # # Returns an {TextEditorView}. - getEditor: -> + getEditorView: -> @parentView # Defines whether to show the gutter or not. @@ -192,9 +192,9 @@ class Gutter extends View @elementBuilder.children buildLineElementsHtml: (startScreenRow, endScreenRow) => - editor = @getEditor() - maxDigits = editor.getLineCount().toString().length - rows = editor.bufferRowsForScreenRows(startScreenRow, endScreenRow) + editorView = @getEditorView() + maxDigits = editorView.getLineCount().toString().length + rows = editorView.bufferRowsForScreenRows(startScreenRow, endScreenRow) html = '' for row in rows @@ -204,7 +204,7 @@ class Gutter extends View rowValue = (row + 1).toString() classes = "line-number line-number-#{row}" - classes += ' fold' if editor.isFoldedAtBufferRow(row) + classes += ' fold' if editorView.isFoldedAtBufferRow(row) rowValuePadding = _.multiplyString(' ', maxDigits - rowValue.length) @@ -230,8 +230,8 @@ class Gutter extends View @highlightedLineNumbers.push(highlightedLineNumber) highlightLines: -> - if @getEditor().getSelection().isEmpty() - row = @getEditor().getCursorScreenPosition().row + if @getEditorView().getSelection().isEmpty() + row = @getEditorView().getCursorScreenPosition().row rowRange = new Range([row, 0], [row, 0]) return if @selectionEmpty and @highlightedRows?.isEqual(rowRange) @@ -240,7 +240,7 @@ class Gutter extends View @highlightedRows = rowRange @selectionEmpty = true else - selectedRows = @getEditor().getSelection().getScreenRange() + selectedRows = @getEditorView().getSelection().getScreenRange() endRow = selectedRows.end.row endRow-- if selectedRows.end.column is 0 selectedRows = new Range([selectedRows.start.row, 0], [endRow, 0]) diff --git a/src/root-view.coffee b/src/root-view.coffee index 806048e27..b9556eaaa 100644 --- a/src/root-view.coffee +++ b/src/root-view.coffee @@ -267,7 +267,7 @@ class RootView extends View # # Returns an {Array} of {String}s. getOpenBufferPaths: -> - _.uniq(_.flatten(@getEditors().map (editor) -> editor.getOpenBufferPaths())) + _.uniq(_.flatten(@getEditors().map (editorView) -> editorView.getOpenBufferPaths())) # Public: Returns the currently focused {Pane}. getActivePane: -> @@ -325,6 +325,6 @@ class RootView extends View # Private: Destroys everything. remove: -> - editor.remove() for editor in @getEditors() + editorView.remove() for editorView in @getEditors() project?.destroy() super diff --git a/src/selection-view.coffee b/src/selection-view.coffee index e01ea384d..6dc301bab 100644 --- a/src/selection-view.coffee +++ b/src/selection-view.coffee @@ -11,12 +11,12 @@ class SelectionView extends View regions: null needsRemoval: false - initialize: ({@editor, @selection} = {}) -> + initialize: ({@editorView, @selection} = {}) -> @regions = [] - @selection.on 'screen-range-changed', => @editor.requestDisplayUpdate() + @selection.on 'screen-range-changed', => @editorView.requestDisplayUpdate() @selection.on 'destroyed', => @needsRemoval = true - @editor.requestDisplayUpdate() + @editorView.requestDisplayUpdate() if @selection.marker.isRemote() @addClass("site-#{@selection.marker.getOriginSiteId()}") @@ -26,7 +26,7 @@ class SelectionView extends View range = @getScreenRange() @trigger 'selection:changed' - @editor.highlightFoldsContainingBufferRange(@getBufferRange()) + @editorView.highlightFoldsContainingBufferRange(@getBufferRange()) return if range.isEmpty() rowSpan = range.end.row - range.start.row @@ -40,11 +40,11 @@ class SelectionView extends View @appendRegion(1, { row: range.end.row, column: 0 }, range.end) appendRegion: (rows, start, end) -> - { lineHeight, charWidth } = @editor - css = @editor.pixelPositionForScreenPosition(start) + { lineHeight, charWidth } = @editorView + css = @editorView.pixelPositionForScreenPosition(start) css.height = lineHeight * rows if end - css.width = @editor.pixelPositionForScreenPosition(end).left - css.left + css.width = @editorView.pixelPositionForScreenPosition(end).left - css.left else css.right = 0 @@ -57,7 +57,7 @@ class SelectionView extends View startRow = start.row endRow = end.row endRow-- if end.column == 0 - @editor.pixelPositionForScreenPosition([((startRow + endRow + 1) / 2), start.column]) + @editorView.pixelPositionForScreenPosition([((startRow + endRow + 1) / 2), start.column]) clearRegions: -> region.remove() for region in @regions @@ -85,5 +85,5 @@ class SelectionView extends View @removeClass('highlighted') remove: -> - @editor.removeSelectionView(this) + @editorView.removeSelectionView(this) super From bf05ddb958e5328839a5c300cd523168c7a6befe Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 14:59:37 -0800 Subject: [PATCH 09/15] :gun: I screwed up a rebase, this nasty commit is the result. --- exports/atom.coffee | 2 +- ...-editor-spec.coffee => editor-spec.coffee} | 2 +- spec/root-view-spec.coffee | 2 +- spec/selection-spec.coffee | 4 +- spec/spec-helper.coffee | 6 +- spec/text-editor-view-spec.coffee | 2825 ----------------- src/cursor.coffee | 10 +- src/editor-view.coffee | 2 +- src/{text-editor.coffee => editor.coffee} | 24 +- src/gutter.coffee | 6 +- src/language-mode.coffee | 4 +- src/pane.coffee | 2 +- src/project.coffee | 18 +- src/root-view.coffee | 16 +- src/select-list.coffee | 4 +- src/selection.coffee | 6 +- src/text-buffer.coffee | 4 +- src/text-editor-view.coffee | 1853 ----------- src/window.coffee | 2 +- test.coffee | 7 + 20 files changed, 64 insertions(+), 4735 deletions(-) rename spec/{text-editor-spec.coffee => editor-spec.coffee} (99%) delete mode 100644 spec/text-editor-view-spec.coffee rename src/{text-editor.coffee => editor.coffee} (98%) delete mode 100644 src/text-editor-view.coffee create mode 100644 test.coffee diff --git a/exports/atom.coffee b/exports/atom.coffee index 049d3d9f1..580e11961 100644 --- a/exports/atom.coffee +++ b/exports/atom.coffee @@ -20,7 +20,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE module.exports.$ = $ module.exports.$$ = $$ module.exports.$$$ = $$$ - module.exports.Editor = require '../src/text-editor-view' + module.exports.Editor = require '../src/editor-view' module.exports.pathForRepositoryUrl = require('../src/project').pathForRepositoryUrl module.exports.RootView = require '../src/root-view' module.exports.SelectList = require '../src/select-list' diff --git a/spec/text-editor-spec.coffee b/spec/editor-spec.coffee similarity index 99% rename from spec/text-editor-spec.coffee rename to spec/editor-spec.coffee index 9db47ce42..8f7400dc4 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1,6 +1,6 @@ clipboard = require 'clipboard' -describe "TextEditor", -> +describe "Editor", -> [buffer, editSession, lineLengths] = [] convertToHardTabs = (buffer) -> diff --git a/spec/root-view-spec.coffee b/spec/root-view-spec.coffee index fa3add1f1..b9086026b 100644 --- a/spec/root-view-spec.coffee +++ b/spec/root-view-spec.coffee @@ -99,7 +99,7 @@ describe "RootView", -> describe "when there is an active view", -> it "hands off focus to the active view", -> - editor = rootView.getActiveView() + editorView = rootView.getActiveView() editorView.isFocused = false rootView.focus() expect(editorView.isFocused).toBeTruthy() diff --git a/spec/selection-spec.coffee b/spec/selection-spec.coffee index 7503ddbec..e73f19345 100644 --- a/spec/selection-spec.coffee +++ b/spec/selection-spec.coffee @@ -1,11 +1,11 @@ -TextEditor = require '../src/text-editor' +Editor = require '../src/editor' describe "Selection", -> [buffer, editSession, selection] = [] beforeEach -> buffer = project.bufferForPathSync('sample.js') - editSession = new TextEditor(buffer: buffer, tabLength: 2) + editSession = new Editor(buffer: buffer, tabLength: 2) selection = editSession.getSelection() afterEach -> diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 3338fb0b8..4bab88b58 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -9,7 +9,7 @@ Keymap = require '../src/keymap' Config = require '../src/config' {Point} = require 'telepath' Project = require '../src/project' -TextEditorView = require '../src/text-editor-view' +EditorView = require '../src/editor-view' TokenizedBuffer = require '../src/tokenized-buffer' pathwatcher = require 'pathwatcher' platform = require './spec-helper-platform' @@ -75,7 +75,7 @@ beforeEach -> spyOn(config, 'load') spyOn(config, 'save') config.setDefaults('core', RootView.configDefaults) - config.setDefaults('editor', TextEditorView.configDefaults) + config.setDefaults('editor', EditorView.configDefaults) config.set "editor.fontFamily", "Courier" config.set "editor.fontSize", 16 config.set "editor.autoIndent", false @@ -86,7 +86,7 @@ beforeEach -> window.config = config # make editor display updates synchronous - spyOn(TextEditorView.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay() + spyOn(EditorView.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay() spyOn(RootView.prototype, 'setTitle').andCallFake (@title) -> spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout diff --git a/spec/text-editor-view-spec.coffee b/spec/text-editor-view-spec.coffee deleted file mode 100644 index b58aaac1b..000000000 --- a/spec/text-editor-view-spec.coffee +++ /dev/null @@ -1,2825 +0,0 @@ -RootView = require '../src/root-view' -TextEditorView = require '../src/text-editor-view' -{$, $$} = require '../src/space-pen-extensions' -_ = require 'underscore' -fs = require 'fs-plus' -path = require 'path' -temp = require 'temp' - -describe "TextEditorView", -> - [buffer, editor, editSession, cachedLineHeight, cachedCharWidth] = [] - - beforeEach -> - atom.activatePackage('language-text', sync: true) - atom.activatePackage('language-javascript', sync: true) - editSession = project.openSync('sample.js') - buffer = editSession.buffer - editor = new TextEditorView(editSession) - editor.lineOverdraw = 2 - editor.isFocused = true - editor.enableKeymap() - editor.calculateHeightInLines = -> - Math.ceil(@height() / @lineHeight) - editor.attachToDom = ({ heightInLines, widthInChars } = {}) -> - heightInLines ?= @getBuffer().getLineCount() - @height(getLineHeight() * heightInLines) - @width(getCharWidth() * widthInChars) if widthInChars - $('#jasmine-content').append(this) - - getLineHeight = -> - return cachedLineHeight if cachedLineHeight? - calcDimensions() - cachedLineHeight - - getCharWidth = -> - return cachedCharWidth if cachedCharWidth? - calcDimensions() - cachedCharWidth - - calcDimensions = -> - editorForMeasurement = new TextEditorView(editSession: project.openSync('sample.js')) - editorForMeasurement.attachToDom() - cachedLineHeight = editorForMeasurement.lineHeight - cachedCharWidth = editorForMeasurement.charWidth - editorForMeasurement.remove() - - describe "construction", -> - it "throws an error if no edit session is given", -> - expect(-> new TextEditorView).toThrow() - - describe "when the editor is attached to the dom", -> - it "calculates line height and char width and updates the pixel position of the cursor", -> - expect(editor.lineHeight).toBeNull() - expect(editor.charWidth).toBeNull() - editor.setCursorScreenPosition(row: 2, column: 2) - - editor.attachToDom() - - expect(editor.lineHeight).not.toBeNull() - expect(editor.charWidth).not.toBeNull() - expect(editor.find('.cursor').offset()).toEqual pagePixelPositionForPoint(editor, [2, 2]) - - it "is focused", -> - editor.attachToDom() - expect(editor).toMatchSelector ":has(:focus)" - - describe "when the editor receives focus", -> - it "focuses the hidden input", -> - editor.attachToDom() - editor.focus() - expect(editor).not.toMatchSelector ':focus' - expect(editor.hiddenInput).toMatchSelector ':focus' - - it "does not scroll the editor (regression)", -> - editor.attachToDom(heightInLines: 2) - editor.selectAll() - editor.hiddenInput.blur() - editor.focus() - - expect(editor.hiddenInput).toMatchSelector ':focus' - expect($(editor[0]).scrollTop()).toBe 0 - expect($(editor.scrollView[0]).scrollTop()).toBe 0 - - editor.moveCursorToBottom() - editor.hiddenInput.blur() - editor.scrollTop(0) - editor.focus() - - expect(editor.hiddenInput).toMatchSelector ':focus' - expect($(editor[0]).scrollTop()).toBe 0 - expect($(editor.scrollView[0]).scrollTop()).toBe 0 - - describe "when the hidden input is focused / unfocused", -> - it "assigns the isFocused flag on the editor and also adds/removes the .focused css class", -> - editor.attachToDom() - editor.isFocused = false - editor.hiddenInput.focus() - expect(editor.isFocused).toBeTruthy() - - editor.hiddenInput.focusout() - expect(editor.isFocused).toBeFalsy() - - describe "when the activeEditSession's file is modified on disk", -> - it "triggers an alert", -> - filePath = path.join(temp.dir, 'atom-changed-file.txt') - fs.writeFileSync(filePath, "") - editSession = project.openSync(filePath) - editor.edit(editSession) - editor.insertText("now the buffer is modified") - - fileChangeHandler = jasmine.createSpy('fileChange') - editSession.buffer.file.on 'contents-changed', fileChangeHandler - - spyOn(atom, "confirm") - - fs.writeFileSync(filePath, "a file change") - - waitsFor "file to trigger contents-changed event", -> - fileChangeHandler.callCount > 0 - - runs -> - expect(atom.confirm).toHaveBeenCalled() - - describe ".remove()", -> - it "destroys the edit session", -> - editor.remove() - expect(editor.activeEditSession.destroyed).toBeTruthy() - - describe ".edit(editSession)", -> - [newEditSession, newBuffer] = [] - - beforeEach -> - newEditSession = project.openSync('two-hundred.txt') - newBuffer = newEditSession.buffer - - it "updates the rendered lines, cursors, selections, scroll position, and event subscriptions to match the given edit session", -> - editor.attachToDom(heightInLines: 5, widthInChars: 30) - editor.setCursorBufferPosition([6, 13]) - editor.scrollToBottom() - editor.scrollLeft(150) - previousScrollHeight = editor.verticalScrollbar.prop('scrollHeight') - previousScrollTop = editor.scrollTop() - previousScrollLeft = editor.scrollLeft() - - newEditSession.setScrollTop(900) - newEditSession.setSelectedBufferRange([[40, 0], [43, 1]]) - - editor.edit(newEditSession) - { firstRenderedScreenRow, lastRenderedScreenRow } = editor - expect(editor.lineElementForScreenRow(firstRenderedScreenRow).text()).toBe newBuffer.lineForRow(firstRenderedScreenRow) - expect(editor.lineElementForScreenRow(lastRenderedScreenRow).text()).toBe newBuffer.lineForRow(editor.lastRenderedScreenRow) - expect(editor.scrollTop()).toBe 900 - expect(editor.scrollLeft()).toBe 0 - expect(editor.getSelectionView().regions[0].position().top).toBe 40 * editor.lineHeight - editor.insertText("hello") - expect(editor.lineElementForScreenRow(40).text()).toBe "hello3" - - editor.edit(editSession) - { firstRenderedScreenRow, lastRenderedScreenRow } = editor - expect(editor.lineElementForScreenRow(firstRenderedScreenRow).text()).toBe buffer.lineForRow(firstRenderedScreenRow) - expect(editor.lineElementForScreenRow(lastRenderedScreenRow).text()).toBe buffer.lineForRow(editor.lastRenderedScreenRow) - expect(editor.verticalScrollbar.prop('scrollHeight')).toBe previousScrollHeight - expect(editor.scrollTop()).toBe previousScrollTop - expect(editor.scrollLeft()).toBe previousScrollLeft - expect(editor.getCursorView().position()).toEqual { top: 6 * editor.lineHeight, left: 13 * editor.charWidth } - editor.insertText("goodbye") - expect(editor.lineElementForScreenRow(6).text()).toMatch /^ currentgoodbye/ - - it "triggers alert if edit session's buffer goes into conflict with changes on disk", -> - filePath = path.join(temp.dir, 'atom-changed-file.txt') - fs.writeFileSync(filePath, "") - tempEditSession = project.openSync(filePath) - editor.edit(tempEditSession) - tempEditSession.insertText("a buffer change") - - spyOn(atom, "confirm") - - contentsConflictedHandler = jasmine.createSpy("contentsConflictedHandler") - tempEditSession.on 'contents-conflicted', contentsConflictedHandler - fs.writeFileSync(filePath, "a file change") - waitsFor -> - contentsConflictedHandler.callCount > 0 - - runs -> - expect(atom.confirm).toHaveBeenCalled() - - describe ".scrollTop(n)", -> - beforeEach -> - editor.attachToDom(heightInLines: 5) - expect(editor.verticalScrollbar.scrollTop()).toBe 0 - - describe "when called with a scroll top argument", -> - it "sets the scrollTop of the vertical scrollbar and sets scrollTop on the line numbers and lines", -> - editor.scrollTop(100) - expect(editor.verticalScrollbar.scrollTop()).toBe 100 - expect(editor.scrollView.scrollTop()).toBe 0 - expect(editor.renderedLines.css('top')).toBe "-100px" - expect(editor.gutter.lineNumbers.css('top')).toBe "-100px" - - editor.scrollTop(120) - expect(editor.verticalScrollbar.scrollTop()).toBe 120 - expect(editor.scrollView.scrollTop()).toBe 0 - expect(editor.renderedLines.css('top')).toBe "-120px" - expect(editor.gutter.lineNumbers.css('top')).toBe "-120px" - - it "does not allow negative scrollTops to be assigned", -> - editor.scrollTop(-100) - expect(editor.scrollTop()).toBe 0 - - it "doesn't do anything if the scrollTop hasn't changed", -> - editor.scrollTop(100) - spyOn(editor.verticalScrollbar, 'scrollTop') - spyOn(editor.renderedLines, 'css') - spyOn(editor.gutter.lineNumbers, 'css') - - editor.scrollTop(100) - expect(editor.verticalScrollbar.scrollTop).not.toHaveBeenCalled() - expect(editor.renderedLines.css).not.toHaveBeenCalled() - expect(editor.gutter.lineNumbers.css).not.toHaveBeenCalled() - - describe "when the 'adjustVerticalScrollbar' option is false (defaults to true)", -> - it "doesn't adjust the scrollTop of the vertical scrollbar", -> - editor.scrollTop(100, adjustVerticalScrollbar: false) - expect(editor.verticalScrollbar.scrollTop()).toBe 0 - expect(editor.renderedLines.css('top')).toBe "-100px" - expect(editor.gutter.lineNumbers.css('top')).toBe "-100px" - - describe "when called with no argument", -> - it "returns the last assigned value or 0 if none has been assigned", -> - expect(editor.scrollTop()).toBe 0 - editor.scrollTop(50) - expect(editor.scrollTop()).toBe 50 - - it "sets the new scroll top position on the active edit session", -> - expect(editor.activeEditSession.getScrollTop()).toBe 0 - editor.scrollTop(123) - expect(editor.activeEditSession.getScrollTop()).toBe 123 - - describe ".scrollHorizontally(pixelPosition)", -> - it "sets the new scroll left position on the active edit session", -> - editor.attachToDom(heightInLines: 5) - setEditorWidthInChars(editor, 5) - expect(editor.activeEditSession.getScrollLeft()).toBe 0 - editor.scrollHorizontally(left: 50) - expect(editor.activeEditSession.getScrollLeft()).toBeGreaterThan 0 - expect(editor.activeEditSession.getScrollLeft()).toBe editor.scrollLeft() - - describe "editor:attached event", -> - it 'only triggers an editor:attached event when it is first added to the DOM', -> - openHandler = jasmine.createSpy('openHandler') - editor.on 'editor:attached', openHandler - - editor.attachToDom() - expect(openHandler).toHaveBeenCalled() - [event, eventEditor] = openHandler.argsForCall[0] - expect(eventEditor).toBe editor - - openHandler.reset() - editor.attachToDom() - expect(openHandler).not.toHaveBeenCalled() - - describe "editor:path-changed event", -> - filePath = null - - beforeEach -> - filePath = path.join(temp.dir, 'something.txt') - fs.writeFileSync(filePath, filePath) - - afterEach -> - fs.removeSync(filePath) if fs.existsSync(filePath) - - it "emits event when buffer's path is changed", -> - eventHandler = jasmine.createSpy('eventHandler') - editor.on 'editor:path-changed', eventHandler - editor.getBuffer().saveAs(filePath) - expect(eventHandler).toHaveBeenCalled() - - it "emits event when editor receives a new buffer", -> - eventHandler = jasmine.createSpy('eventHandler') - editor.on 'editor:path-changed', eventHandler - editor.edit(project.openSync(filePath)) - expect(eventHandler).toHaveBeenCalled() - - it "stops listening to events on previously set buffers", -> - eventHandler = jasmine.createSpy('eventHandler') - oldBuffer = editor.getBuffer() - editor.on 'editor:path-changed', eventHandler - - editor.edit(project.openSync(filePath)) - expect(eventHandler).toHaveBeenCalled() - - eventHandler.reset() - oldBuffer.saveAs(path.join(temp.dir, 'atom-bad.txt')) - expect(eventHandler).not.toHaveBeenCalled() - - eventHandler.reset() - editor.getBuffer().saveAs(path.join(temp.dir, 'atom-new.txt')) - expect(eventHandler).toHaveBeenCalled() - - it "loads the grammar for the new path", -> - expect(editor.getGrammar().name).toBe 'JavaScript' - editor.getBuffer().saveAs(filePath) - expect(editor.getGrammar().name).toBe 'Plain Text' - - describe "font family", -> - beforeEach -> - expect(editor.css('font-family')).toBe 'Courier' - - it "when there is no config in fontFamily don't set it", -> - atom.config.set('editor.fontFamily', null) - expect(editor.css('font-family')).toBe '' - - describe "when the font family changes", -> - [fontFamily] = [] - - beforeEach -> - if process.platform is 'darwin' - fontFamily = "PCMyungjo" - else - fontFamily = "Consolas" - - it "updates the font family of editors and recalculates dimensions critical to cursor positioning", -> - editor.attachToDom(12) - lineHeightBefore = editor.lineHeight - charWidthBefore = editor.charWidth - editor.setCursorScreenPosition [5, 6] - - atom.config.set("editor.fontFamily", fontFamily) - expect(editor.css('font-family')).toBe fontFamily - expect(editor.charWidth).not.toBe charWidthBefore - expect(editor.getCursorView().position()).toEqual { top: 5 * editor.lineHeight, left: 6 * editor.charWidth } - - newEditor = new TextEditorView(editor.activeEditSession.copy()) - newEditor.attachToDom() - expect(newEditor.css('font-family')).toBe fontFamily - - describe "font size", -> - beforeEach -> - expect(editor.css('font-size')).not.toBe "20px" - expect(editor.css('font-size')).not.toBe "10px" - - it "sets the initial font size based on the value from config", -> - expect(editor.css('font-size')).toBe "#{atom.config.get('editor.fontSize')}px" - - describe "when the font size changes", -> - it "updates the font sizes of editors and recalculates dimensions critical to cursor positioning", -> - atom.config.set("editor.fontSize", 10) - editor.attachToDom() - lineHeightBefore = editor.lineHeight - charWidthBefore = editor.charWidth - editor.setCursorScreenPosition [5, 6] - - atom.config.set("editor.fontSize", 30) - expect(editor.css('font-size')).toBe '30px' - expect(editor.lineHeight).toBeGreaterThan lineHeightBefore - expect(editor.charWidth).toBeGreaterThan charWidthBefore - expect(editor.getCursorView().position()).toEqual { top: 5 * editor.lineHeight, left: 6 * editor.charWidth } - expect(editor.renderedLines.outerHeight()).toBe buffer.getLineCount() * editor.lineHeight - expect(editor.verticalScrollbarContent.height()).toBe buffer.getLineCount() * editor.lineHeight - - newEditor = new TextEditorView(editor.activeEditSession.copy()) - editor.remove() - newEditor.attachToDom() - expect(newEditor.css('font-size')).toBe '30px' - - it "updates the position and size of selection regions", -> - atom.config.set("editor.fontSize", 10) - editor.setSelectedBufferRange([[5, 2], [5, 7]]) - editor.attachToDom() - - atom.config.set("editor.fontSize", 30) - selectionRegion = editor.find('.region') - expect(selectionRegion.position().top).toBe 5 * editor.lineHeight - expect(selectionRegion.position().left).toBe 2 * editor.charWidth - expect(selectionRegion.height()).toBe editor.lineHeight - expect(selectionRegion.width()).toBe 5 * editor.charWidth - - it "updates lines if there are unrendered lines", -> - editor.attachToDom(heightInLines: 5) - originalLineCount = editor.renderedLines.find(".line").length - expect(originalLineCount).toBeGreaterThan 0 - - atom.config.set("editor.fontSize", 10) - expect(editor.renderedLines.find(".line").length).toBeGreaterThan originalLineCount - - describe "when the font size changes while editor is detached", -> - it "redraws the editor according to the new font size when it is reattached", -> - editor.setCursorScreenPosition([4, 2]) - editor.attachToDom() - initialLineHeight = editor.lineHeight - initialCharWidth = editor.charWidth - initialCursorPosition = editor.getCursorView().position() - initialScrollbarHeight = editor.verticalScrollbarContent.height() - editor.detach() - - atom.config.set("editor.fontSize", 10) - expect(editor.lineHeight).toBe initialLineHeight - expect(editor.charWidth).toBe initialCharWidth - - editor.attachToDom() - expect(editor.lineHeight).not.toBe initialLineHeight - expect(editor.charWidth).not.toBe initialCharWidth - expect(editor.getCursorView().position()).not.toEqual initialCursorPosition - expect(editor.verticalScrollbarContent.height()).not.toBe initialScrollbarHeight - - describe "mouse events", -> - beforeEach -> - editor.attachToDom() - editor.css(position: 'absolute', top: 10, left: 10, width: 400) - - describe "single-click", -> - it "re-positions the cursor to the clicked row / column", -> - expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 10]) - expect(editor.getCursorScreenPosition()).toEqual(row: 3, column: 10) - - describe "when the lines are scrolled to the right", -> - it "re-positions the cursor on the clicked location", -> - setEditorWidthInChars(editor, 30) - expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 30]) # scrolls lines to the right - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 50]) - expect(editor.getCursorBufferPosition()).toEqual(row: 3, column: 50) - - describe "when the editor is using a variable-width font", -> - beforeEach -> - editor.setFontFamily('sans-serif') - - it "positions the cursor to the clicked row and column", -> - {top, left} = editor.pixelOffsetForScreenPosition([3, 30]) - editor.renderedLines.trigger mousedownEvent(pageX: left, pageY: top) - expect(editor.getCursorScreenPosition()).toEqual [3, 30] - - describe "double-click", -> - it "selects the word under the cursor, and expands the selection wordwise in either direction on a subsequent shift-click", -> - expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [8, 24], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [8, 24], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedText()).toBe "concat" - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [8, 7], shiftKey: true) - editor.renderedLines.trigger 'mouseup' - - expect(editor.getSelectedText()).toBe "return sort(left).concat" - - it "stops selecting by word when the selection is emptied", -> - expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedText()).toBe "quicksort" - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 10]) - editor.renderedLines.trigger 'mouseup' - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 12], originalEvent: {detail: 1}, shiftKey: true) - expect(editor.getSelectedBufferRange()).toEqual [[3, 10], [3, 12]] - - describe "when clicking between a word and a non-word", -> - it "selects the word", -> - expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 21], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 21], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedText()).toBe "function" - - editor.setCursorBufferPosition([0, 0]) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 22], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 22], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedText()).toBe "items" - - editor.setCursorBufferPosition([0, 0]) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 28], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 28], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedText()).toBe "{" - - describe "triple/quardruple/etc-click", -> - it "selects the line under the cursor", -> - expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - - # Triple click - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 3}) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedText()).toBe " var sort = function(items) {\n" - - # Quad click - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 3}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 3], originalEvent: {detail: 4}) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedText()).toBe " if (items.length <= 1) return items;\n" - - it "expands the selection linewise in either direction on a subsequent shift-click, but stops selecting linewise once the selection is emptied", -> - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 8], originalEvent: {detail: 2}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 8], originalEvent: {detail: 3}) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [5, 0]] - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [1, 8], originalEvent: {detail: 1}, shiftKey: true) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedBufferRange()).toEqual [[1, 0], [5, 0]] - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [2, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelection().isEmpty()).toBeTruthy() - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 8], originalEvent: {detail: 1}, shiftKey: true) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedBufferRange()).toEqual [[2, 8], [3, 8]] - - describe "shift-click", -> - it "selects from the cursor's current location to the clicked location", -> - editor.setCursorScreenPosition([4, 7]) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true) - expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] - - describe "shift-double-click", -> - it "expands the selection on the first click and ignores the second click", -> - editor.setCursorScreenPosition([4, 7]) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 1 }) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 2 }) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] - - describe "shift-triple-click", -> - it "expands the selection on the first click and ignores the second click", -> - editor.setCursorScreenPosition([4, 7]) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 1 }) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 2 }) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 24], shiftKey: true, originalEvent: { detail: 3 }) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]] - - describe "meta-click", -> - it "places an additional cursor", -> - editor.attachToDom() - setEditorHeightInLines(editor, 5) - editor.setCursorBufferPosition([3, 0]) - editor.scrollTop(editor.lineHeight * 6) - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [6, 0], metaKey: true) - expect(editor.scrollTop()).toBe editor.lineHeight * (6 - editor.vScrollMargin) - - [cursor1, cursor2] = editor.getCursorViews() - expect(cursor1.position()).toEqual(top: 3 * editor.lineHeight, left: 0) - expect(cursor1.getBufferPosition()).toEqual [3, 0] - expect(cursor2.position()).toEqual(top: 6 * editor.lineHeight, left: 0) - expect(cursor2.getBufferPosition()).toEqual [6, 0] - - describe "click and drag", -> - it "creates a selection from the initial click to mouse cursor's location ", -> - editor.attachToDom() - editor.css(position: 'absolute', top: 10, left: 10) - - # start - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 10]) - - # moving changes selection - $(document).trigger mousemoveEvent(editor: editor, point: [5, 27]) - - range = editor.getSelection().getScreenRange() - expect(range.start).toEqual({row: 4, column: 10}) - expect(range.end).toEqual({row: 5, column: 27}) - expect(editor.getCursorScreenPosition()).toEqual(row: 5, column: 27) - - # mouse up may occur outside of editor, but still need to halt selection - $(document).trigger 'mouseup' - - # moving after mouse up should not change selection - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [8, 8]) - - range = editor.getSelection().getScreenRange() - expect(range.start).toEqual({row: 4, column: 10}) - expect(range.end).toEqual({row: 5, column: 27}) - expect(editor.getCursorScreenPosition()).toEqual(row: 5, column: 27) - - it "selects and scrolls if the mouse is dragged outside of the editor itself", -> - editor.vScrollMargin = 0 - editor.attachToDom(heightInLines: 5) - editor.scrollToBottom() - - spyOn(window, 'setInterval').andCallFake -> - - # start - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [12, 0]) - originalScrollTop = editor.scrollTop() - - # moving changes selection - $(document).trigger mousemoveEvent(editor: editor, pageX: 0, pageY: -1) - expect(editor.scrollTop()).toBe originalScrollTop - editor.lineHeight - - # every mouse move selects more text - for x in [0..10] - $(document).trigger mousemoveEvent(editor: editor, pageX: 0, pageY: -1) - - expect(editor.scrollTop()).toBe 0 - - it "ignores non left-click and drags", -> - editor.attachToDom() - editor.css(position: 'absolute', top: 10, left: 10) - - event = mousedownEvent(editor: editor, point: [4, 10]) - event.originalEvent.which = 2 - editor.renderedLines.trigger(event) - $(document).trigger mousemoveEvent(editor: editor, point: [5, 27]) - $(document).trigger 'mouseup' - - range = editor.getSelection().getScreenRange() - expect(range.start).toEqual({row: 4, column: 10}) - expect(range.end).toEqual({row: 4, column: 10}) - - it "ignores ctrl-click and drags", -> - editor.attachToDom() - editor.css(position: 'absolute', top: 10, left: 10) - - event = mousedownEvent(editor: editor, point: [4, 10]) - event.ctrlKey = true - editor.renderedLines.trigger(event) - $(document).trigger mousemoveEvent(editor: editor, point: [5, 27]) - $(document).trigger 'mouseup' - - range = editor.getSelection().getScreenRange() - expect(range.start).toEqual({row: 4, column: 10}) - expect(range.end).toEqual({row: 4, column: 10}) - - describe "double-click and drag", -> - it "selects the word under the cursor, then continues to select by word in either direction as the mouse is dragged", -> - expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 1}) - editor.renderedLines.trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 2}) - expect(editor.getSelectedText()).toBe "quicksort" - - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [1, 8]) - expect(editor.getSelectedBufferRange()).toEqual [[0, 4], [1, 10]] - expect(editor.getCursorBufferPosition()).toEqual [1, 10] - - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [0, 1]) - expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]] - expect(editor.getCursorBufferPosition()).toEqual [0, 0] - - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]] - - # shift-clicking still selects by word, but does not preserve the initial range - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 25], originalEvent: {detail: 1}, shiftKey: true) - editor.renderedLines.trigger 'mouseup' - expect(editor.getSelectedBufferRange()).toEqual [[0, 13], [5, 27]] - - describe "triple-click and drag", -> - it "expands the initial selection linewise in either direction", -> - editor.attachToDom() - - # triple click - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 1}) - $(document).trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 2}) - $(document).trigger 'mouseup' - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 3}) - expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [5, 0]] - - # moving changes selection linewise - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [5, 27]) - expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [6, 0]] - expect(editor.getCursorBufferPosition()).toEqual [6, 0] - - # moving changes selection linewise - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [2, 27]) - expect(editor.getSelectedBufferRange()).toEqual [[2, 0], [5, 0]] - expect(editor.getCursorBufferPosition()).toEqual [2, 0] - - # mouse up may occur outside of editor, but still need to halt selection - $(document).trigger 'mouseup' - - describe "meta-click and drag", -> - it "adds an additional selection", -> - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 10]) - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [5, 27]) - editor.renderedLines.trigger 'mouseup' - - editor.renderedLines.trigger mousedownEvent(editor: editor, point: [6, 10], metaKey: true) - editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [8, 27], metaKey: true) - editor.renderedLines.trigger 'mouseup' - - selections = editor.getSelections() - expect(selections.length).toBe 2 - [selection1, selection2] = selections - expect(selection1.getScreenRange()).toEqual [[4, 10], [5, 27]] - expect(selection2.getScreenRange()).toEqual [[6, 10], [8, 27]] - - describe "when text input events are triggered on the hidden input element", -> - it "inserts the typed character at the cursor position, both in the buffer and the pre element", -> - editor.attachToDom() - editor.setCursorScreenPosition(row: 1, column: 6) - - expect(buffer.lineForRow(1).charAt(6)).not.toBe 'q' - - editor.hiddenInput.textInput 'q' - - expect(buffer.lineForRow(1).charAt(6)).toBe 'q' - expect(editor.getCursorScreenPosition()).toEqual(row: 1, column: 7) - expect(editor.renderedLines.find('.line:eq(1)')).toHaveText buffer.lineForRow(1) - - describe "selection rendering", -> - [charWidth, lineHeight, selection, selectionView] = [] - - beforeEach -> - editor.attachToDom() - editor.width(500) - { charWidth, lineHeight } = editor - selection = editor.getSelection() - selectionView = editor.getSelectionView() - - describe "when a selection is added", -> - it "adds a selection view for it with the proper regions", -> - editor.activeEditSession.addSelectionForBufferRange([[2, 7], [2, 25]]) - selectionViews = editor.getSelectionViews() - expect(selectionViews.length).toBe 2 - expect(selectionViews[1].regions.length).toBe 1 - region = selectionViews[1].regions[0] - expect(region.position().top).toBeCloseTo(2 * lineHeight) - expect(region.position().left).toBeCloseTo(7 * charWidth) - expect(region.height()).toBeCloseTo lineHeight - expect(region.width()).toBeCloseTo((25 - 7) * charWidth) - - describe "when a selection changes", -> - describe "when the selection is within a single line", -> - it "covers the selection's range with a single region", -> - selection.setBufferRange([[2, 7], [2, 25]]) - - expect(selectionView.regions.length).toBe 1 - region = selectionView.regions[0] - expect(region.position().top).toBeCloseTo(2 * lineHeight) - expect(region.position().left).toBeCloseTo(7 * charWidth) - expect(region.height()).toBeCloseTo lineHeight - expect(region.width()).toBeCloseTo((25 - 7) * charWidth) - - describe "when the selection spans 2 lines", -> - it "covers the selection's range with 2 regions", -> - selection.setBufferRange([[2,7],[3,25]]) - - expect(selectionView.regions.length).toBe 2 - - region1 = selectionView.regions[0] - expect(region1.position().top).toBeCloseTo(2 * lineHeight) - expect(region1.position().left).toBeCloseTo(7 * charWidth) - expect(region1.height()).toBeCloseTo lineHeight - - expect(region1.width()).toBeCloseTo(editor.renderedLines.outerWidth() - region1.position().left) - region2 = selectionView.regions[1] - expect(region2.position().top).toBeCloseTo(3 * lineHeight) - expect(region2.position().left).toBeCloseTo(0) - expect(region2.height()).toBeCloseTo lineHeight - expect(region2.width()).toBeCloseTo(25 * charWidth) - - describe "when the selection spans more than 2 lines", -> - it "covers the selection's range with 3 regions", -> - selection.setBufferRange([[2,7],[6,25]]) - - expect(selectionView.regions.length).toBe 3 - - region1 = selectionView.regions[0] - expect(region1.position().top).toBeCloseTo(2 * lineHeight) - expect(region1.position().left).toBeCloseTo(7 * charWidth) - expect(region1.height()).toBeCloseTo lineHeight - - expect(region1.width()).toBeCloseTo(editor.renderedLines.outerWidth() - region1.position().left) - region2 = selectionView.regions[1] - expect(region2.position().top).toBeCloseTo(3 * lineHeight) - expect(region2.position().left).toBeCloseTo(0) - expect(region2.height()).toBeCloseTo(3 * lineHeight) - expect(region2.width()).toBeCloseTo(editor.renderedLines.outerWidth()) - - # resizes with the editor - expect(editor.width()).toBeLessThan(800) - editor.width(800) - editor.resize() # call to trigger the resize event. - - region2 = selectionView.regions[1] - expect(region2.width()).toBe(editor.renderedLines.outerWidth()) - - region3 = selectionView.regions[2] - expect(region3.position().top).toBeCloseTo(6 * lineHeight) - expect(region3.position().left).toBeCloseTo(0) - expect(region3.height()).toBeCloseTo lineHeight - expect(region3.width()).toBeCloseTo(25 * charWidth) - - it "clears previously drawn regions before creating new ones", -> - selection.setBufferRange([[2,7],[4,25]]) - expect(selectionView.regions.length).toBe 3 - expect(selectionView.find('.region').length).toBe 3 - - selectionView.updateDisplay() - expect(selectionView.regions.length).toBe 3 - expect(selectionView.find('.region').length).toBe 3 - - describe "when a selection merges with another selection", -> - it "removes the merged selection view", -> - editSession = editor.activeEditSession - editSession.setCursorScreenPosition([4, 10]) - editSession.selectToScreenPosition([5, 27]) - editSession.addCursorAtScreenPosition([3, 10]) - editSession.selectToScreenPosition([6, 27]) - - expect(editor.getSelectionViews().length).toBe 1 - expect(editor.find('.region').length).toBe 3 - - describe "when a selection is added and removed before the display is updated", -> - it "does not attempt to render the selection", -> - # don't update display until we request it - jasmine.unspy(editor, 'requestDisplayUpdate') - spyOn(editor, 'requestDisplayUpdate') - - editSession = editor.activeEditSession - selection = editSession.addSelectionForBufferRange([[3, 0], [3, 4]]) - selection.destroy() - editor.updateDisplay() - expect(editor.getSelectionViews().length).toBe 1 - - describe "when the selection is created with the selectAll event", -> - it "does not scroll to the end of the buffer", -> - editor.height(150) - editor.selectAll() - expect(editor.scrollTop()).toBe 0 - - # regression: does not scroll the scroll view when the editor is refocused - editor.hiddenInput.blur() - editor.hiddenInput.focus() - expect(editor.scrollTop()).toBe 0 - expect(editor.scrollView.scrollTop()).toBe 0 - - # does autoscroll when the selection is cleared - editor.moveCursorDown() - expect(editor.scrollTop()).toBeGreaterThan(0) - - describe "selection autoscrolling and highlighting when setting selected buffer range", -> - beforeEach -> - setEditorHeightInLines(editor, 4) - - describe "if autoscroll is true", -> - it "centers the viewport on the selection if its vertical center is currently offscreen", -> - editor.setSelectedBufferRange([[2, 0], [4, 0]], autoscroll: true) - expect(editor.scrollTop()).toBe 0 - - editor.setSelectedBufferRange([[6, 0], [8, 0]], autoscroll: true) - expect(editor.scrollTop()).toBe 5 * editor.lineHeight - - it "highlights the selection if autoscroll is true", -> - editor.setSelectedBufferRange([[2, 0], [4, 0]], autoscroll: true) - expect(editor.getSelectionView()).toHaveClass 'highlighted' - advanceClock(1000) - expect(editor.getSelectionView()).not.toHaveClass 'highlighted' - - editor.setSelectedBufferRange([[3, 0], [5, 0]], autoscroll: true) - expect(editor.getSelectionView()).toHaveClass 'highlighted' - - advanceClock(500) - spyOn(editor.getSelectionView(), 'removeClass').andCallThrough() - editor.setSelectedBufferRange([[2, 0], [4, 0]], autoscroll: true) - expect(editor.getSelectionView().removeClass).toHaveBeenCalledWith('highlighted') - expect(editor.getSelectionView()).toHaveClass 'highlighted' - - advanceClock(500) - expect(editor.getSelectionView()).toHaveClass 'highlighted' - - describe "if autoscroll is false", -> - it "does not scroll to the selection or the cursor", -> - editor.scrollToBottom() - scrollTopBefore = editor.scrollTop() - editor.setSelectedBufferRange([[0, 0], [1, 0]], autoscroll: false) - expect(editor.scrollTop()).toBe scrollTopBefore - - describe "if autoscroll is not specified", -> - it "autoscrolls to the cursor as normal", -> - editor.scrollToBottom() - editor.setSelectedBufferRange([[0, 0], [1, 0]]) - expect(editor.scrollTop()).toBe 0 - - describe "cursor rendering", -> - describe "when the cursor moves", -> - charWidth = null - - beforeEach -> - editor.attachToDom() - editor.vScrollMargin = 3 - editor.hScrollMargin = 5 - {charWidth} = editor - - it "repositions the cursor's view on screen", -> - editor.setCursorScreenPosition(row: 2, column: 2) - expect(editor.getCursorView().position()).toEqual(top: 2 * editor.lineHeight, left: 2 * editor.charWidth) - - it "hides the cursor when the selection is non-empty, and shows it otherwise", -> - cursorView = editor.getCursorView() - expect(editor.getSelection().isEmpty()).toBeTruthy() - expect(cursorView).toBeVisible() - - editor.setSelectedBufferRange([[0, 0], [3, 0]]) - expect(editor.getSelection().isEmpty()).toBeFalsy() - expect(cursorView).toBeHidden() - - editor.setCursorBufferPosition([1, 3]) - expect(editor.getSelection().isEmpty()).toBeTruthy() - expect(cursorView).toBeVisible() - - it "moves the hiddenInput to the same position with cursor's view", -> - editor.setCursorScreenPosition(row: 2, column: 2) - expect(editor.getCursorView().offset()).toEqual(editor.hiddenInput.offset()) - - describe "when the editor is using a variable-width font", -> - beforeEach -> - editor.setFontFamily('sans-serif') - - describe "on #darwin or #linux", -> - it "correctly positions the cursor", -> - editor.setCursorBufferPosition([3, 30]) - expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 178} - editor.setCursorBufferPosition([3, Infinity]) - expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 353} - - describe "on #win32", -> - it "correctly positions the cursor", -> - editor.setCursorBufferPosition([3, 30]) - expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 175} - editor.setCursorBufferPosition([3, Infinity]) - expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 346} - - describe "autoscrolling", -> - it "only autoscrolls when the last cursor is moved", -> - editor.setCursorBufferPosition([11,0]) - editor.addCursorAtBufferPosition([6,50]) - [cursor1, cursor2] = editor.getCursors() - - spyOn(editor, 'scrollToPixelPosition') - cursor1.setScreenPosition([10, 10]) - expect(editor.scrollToPixelPosition).not.toHaveBeenCalled() - - cursor2.setScreenPosition([11, 11]) - expect(editor.scrollToPixelPosition).toHaveBeenCalled() - - it "does not autoscroll if the 'autoscroll' option is false", -> - editor.setCursorBufferPosition([11,0]) - spyOn(editor, 'scrollToPixelPosition') - editor.setCursorScreenPosition([10, 10], autoscroll: false) - expect(editor.scrollToPixelPosition).not.toHaveBeenCalled() - - it "autoscrolls to cursor if autoscroll is true, even if the position does not change", -> - spyOn(editor, 'scrollToPixelPosition') - editor.setCursorScreenPosition([4, 10], autoscroll: false) - editor.setCursorScreenPosition([4, 10]) - expect(editor.scrollToPixelPosition).toHaveBeenCalled() - editor.scrollToPixelPosition.reset() - - editor.setCursorBufferPosition([4, 10]) - expect(editor.scrollToPixelPosition).toHaveBeenCalled() - - it "does not autoscroll the cursor based on a buffer change, unless the buffer change was initiated by the cursor", -> - lastVisibleRow = editor.getLastVisibleScreenRow() - editor.addCursorAtBufferPosition([lastVisibleRow, 0]) - spyOn(editor, 'scrollToPixelPosition') - buffer.insert([lastVisibleRow, 0], "\n\n") - expect(editor.scrollToPixelPosition).not.toHaveBeenCalled() - editor.insertText('\n\n') - expect(editor.scrollToPixelPosition.callCount).toBe 1 - - it "autoscrolls on undo/redo", -> - spyOn(editor, 'scrollToPixelPosition') - editor.insertText('\n\n') - expect(editor.scrollToPixelPosition.callCount).toBe 1 - editor.undo() - expect(editor.scrollToPixelPosition.callCount).toBe 2 - editor.redo() - expect(editor.scrollToPixelPosition.callCount).toBe 3 - - describe "when the last cursor exceeds the upper or lower scroll margins", -> - describe "when the editor is taller than twice the vertical scroll margin", -> - it "sets the scrollTop so the cursor remains within the scroll margin", -> - setEditorHeightInLines(editor, 10) - - _.times 6, -> editor.moveCursorDown() - expect(editor.scrollTop()).toBe(0) - - editor.moveCursorDown() - expect(editor.scrollTop()).toBe(editor.lineHeight) - - editor.moveCursorDown() - expect(editor.scrollTop()).toBe(editor.lineHeight * 2) - - _.times 3, -> editor.moveCursorUp() - - editor.moveCursorUp() - expect(editor.scrollTop()).toBe(editor.lineHeight) - - editor.moveCursorUp() - expect(editor.scrollTop()).toBe(0) - - describe "when the editor is shorter than twice the vertical scroll margin", -> - it "sets the scrollTop based on a reduced scroll margin, which prevents a jerky tug-of-war between upper and lower scroll margins", -> - setEditorHeightInLines(editor, 5) - - _.times 3, -> editor.moveCursorDown() - - expect(editor.scrollTop()).toBe(editor.lineHeight) - - editor.moveCursorUp() - expect(editor.renderedLines.css('top')).toBe "0px" - - describe "when the last cursor exceeds the right or left scroll margins", -> - describe "when soft-wrap is disabled", -> - describe "when the editor is wider than twice the horizontal scroll margin", -> - it "sets the scrollView's scrollLeft so the cursor remains within the scroll margin", -> - setEditorWidthInChars(editor, 30) - - # moving right - editor.setCursorScreenPosition([2, 24]) - expect(editor.scrollLeft()).toBe 0 - - editor.setCursorScreenPosition([2, 25]) - expect(editor.scrollLeft()).toBe charWidth - - editor.setCursorScreenPosition([2, 28]) - expect(editor.scrollLeft()).toBe charWidth * 4 - - # moving left - editor.setCursorScreenPosition([2, 9]) - expect(editor.scrollLeft()).toBe charWidth * 4 - - editor.setCursorScreenPosition([2, 8]) - expect(editor.scrollLeft()).toBe charWidth * 3 - - editor.setCursorScreenPosition([2, 5]) - expect(editor.scrollLeft()).toBe 0 - - describe "when the editor is narrower than twice the horizontal scroll margin", -> - it "sets the scrollView's scrollLeft based on a reduced horizontal scroll margin, to prevent a jerky tug-of-war between right and left scroll margins", -> - editor.hScrollMargin = 6 - setEditorWidthInChars(editor, 7) - - editor.setCursorScreenPosition([2, 3]) - window.advanceClock() - expect(editor.scrollLeft()).toBe(0) - - editor.setCursorScreenPosition([2, 4]) - window.advanceClock() - expect(editor.scrollLeft()).toBe(charWidth) - - editor.setCursorScreenPosition([2, 3]) - window.advanceClock() - expect(editor.scrollLeft()).toBe(0) - - describe "when soft-wrap is enabled", -> - beforeEach -> - editSession.setSoftWrap(true) - - it "does not scroll the buffer horizontally", -> - editor.width(charWidth * 30) - - # moving right - editor.setCursorScreenPosition([2, 24]) - expect(editor.scrollLeft()).toBe 0 - - editor.setCursorScreenPosition([2, 25]) - expect(editor.scrollLeft()).toBe 0 - - editor.setCursorScreenPosition([2, 28]) - expect(editor.scrollLeft()).toBe 0 - - # moving left - editor.setCursorScreenPosition([2, 9]) - expect(editor.scrollLeft()).toBe 0 - - editor.setCursorScreenPosition([2, 8]) - expect(editor.scrollLeft()).toBe 0 - - editor.setCursorScreenPosition([2, 5]) - expect(editor.scrollLeft()).toBe 0 - - describe "when editor:toggle-soft-wrap is toggled", -> - describe "when the text exceeds the editor width and the scroll-view is horizontally scrolled", -> - it "wraps the text and renders properly", -> - editor.attachToDom(heightInLines: 30, widthInChars: 30) - editor.setWidthInChars(100) - editor.setText("Fashion axe umami jean shorts retro hashtag carles mumblecore. Photo booth skateboard Austin gentrify occupy ethical. Food truck gastropub keffiyeh, squid deep v pinterest literally sustainable salvia scenester messenger bag. Neutra messenger bag flexitarian four loko, shoreditch VHS pop-up tumblr seitan synth master cleanse. Marfa selvage ugh, raw denim authentic try-hard mcsweeney's trust fund fashion axe actually polaroid viral sriracha. Banh mi marfa plaid single-origin coffee. Pickled mumblecore lomo ugh bespoke.") - editor.scrollLeft(editor.charWidth * 30) - editor.trigger "editor:toggle-soft-wrap" - expect(editor.scrollLeft()).toBe 0 - expect(editor.activeEditSession.getSoftWrapColumn()).not.toBe 100 - - describe "text rendering", -> - describe "when all lines in the buffer are visible on screen", -> - beforeEach -> - editor.attachToDom() - expect(editor.trueHeight()).toBeCloseTo buffer.getLineCount() * editor.lineHeight - - it "creates a line element for each line in the buffer with the html-escaped text of the line", -> - expect(editor.renderedLines.find('.line').length).toEqual(buffer.getLineCount()) - expect(buffer.lineForRow(2)).toContain('<') - expect(editor.renderedLines.find('.line:eq(2)').html()).toContain '<' - - # renders empty lines with a non breaking space - expect(buffer.lineForRow(10)).toBe '' - expect(editor.renderedLines.find('.line:eq(10)').html()).toBe ' ' - - it "syntax highlights code based on the file type", -> - line0 = editor.renderedLines.find('.line:first') - span0 = line0.children('span:eq(0)') - expect(span0).toMatchSelector '.source.js' - expect(span0.children('span:eq(0)')).toMatchSelector '.storage.modifier.js' - expect(span0.children('span:eq(0)').text()).toBe 'var' - - span0_1 = span0.children('span:eq(1)') - expect(span0_1).toMatchSelector '.meta.function.js' - expect(span0_1.text()).toBe 'quicksort = function ()' - expect(span0_1.children('span:eq(0)')).toMatchSelector '.entity.name.function.js' - expect(span0_1.children('span:eq(0)').text()).toBe "quicksort" - expect(span0_1.children('span:eq(1)')).toMatchSelector '.keyword.operator.js' - expect(span0_1.children('span:eq(1)').text()).toBe "=" - expect(span0_1.children('span:eq(2)')).toMatchSelector '.storage.type.function.js' - expect(span0_1.children('span:eq(2)').text()).toBe "function" - expect(span0_1.children('span:eq(3)')).toMatchSelector '.punctuation.definition.parameters.begin.js' - expect(span0_1.children('span:eq(3)').text()).toBe "(" - expect(span0_1.children('span:eq(4)')).toMatchSelector '.punctuation.definition.parameters.end.js' - expect(span0_1.children('span:eq(4)').text()).toBe ")" - - expect(span0.children('span:eq(2)')).toMatchSelector '.meta.brace.curly.js' - expect(span0.children('span:eq(2)').text()).toBe "{" - - line12 = editor.renderedLines.find('.line:eq(11)').children('span:eq(0)') - expect(line12.children('span:eq(1)')).toMatchSelector '.keyword' - - it "wraps hard tabs in a span", -> - editor.setText('\t<- hard tab') - line0 = editor.renderedLines.find('.line:first') - span0_0 = line0.children('span:eq(0)').children('span:eq(0)') - expect(span0_0).toMatchSelector '.hard-tab' - expect(span0_0.text()).toBe ' ' - - it "wraps leading whitespace in a span", -> - line1 = editor.renderedLines.find('.line:eq(1)') - span0_0 = line1.children('span:eq(0)').children('span:eq(0)') - expect(span0_0).toMatchSelector '.leading-whitespace' - expect(span0_0.text()).toBe ' ' - - describe "when the line has trailing whitespace", -> - it "wraps trailing whitespace in a span", -> - editor.setText('trailing whitespace -> ') - line0 = editor.renderedLines.find('.line:first') - span0_last = line0.children('span:eq(0)').children('span:last') - expect(span0_last).toMatchSelector '.trailing-whitespace' - expect(span0_last.text()).toBe ' ' - - describe "when lines are updated in the buffer", -> - it "syntax highlights the updated lines", -> - expect(editor.renderedLines.find('.line:eq(0) > span:first > span:first')).toMatchSelector '.storage.modifier.js' - buffer.insert([0, 0], "q") - expect(editor.renderedLines.find('.line:eq(0) > span:first > span:first')).not.toMatchSelector '.storage.modifier.js' - - # verify that re-highlighting can occur below the changed line - buffer.insert([5,0], "/* */") - buffer.insert([1,0], "/*") - expect(editor.renderedLines.find('.line:eq(2) > span:first > span:first')).toMatchSelector '.comment' - - describe "when some lines at the end of the buffer are not visible on screen", -> - beforeEach -> - editor.attachToDom(heightInLines: 5.5) - - it "only renders the visible lines plus the overdrawn lines, setting the padding-bottom of the lines element to account for the missing lines", -> - expect(editor.renderedLines.find('.line').length).toBe 8 - expectedPaddingBottom = (buffer.getLineCount() - 8) * editor.lineHeight - expect(editor.renderedLines.css('padding-bottom')).toBe "#{expectedPaddingBottom}px" - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) - - it "renders additional lines when the editor is resized", -> - setEditorHeightInLines(editor, 10) - $(window).trigger 'resize' - - expect(editor.renderedLines.find('.line').length).toBe 12 - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(11) - - it "renders correctly when scrolling after text is added to the buffer", -> - editor.insertText("1\n") - _.times 4, -> editor.moveCursorDown() - expect(editor.renderedLines.find('.line:eq(2)').text()).toBe editor.lineForBufferRow(2) - expect(editor.renderedLines.find('.line:eq(7)').text()).toBe editor.lineForBufferRow(7) - - it "renders correctly when scrolling after text is removed from buffer", -> - editor.getBuffer().delete([[0,0],[1,0]]) - expect(editor.renderedLines.find('.line:eq(0)').text()).toBe editor.lineForBufferRow(0) - expect(editor.renderedLines.find('.line:eq(5)').text()).toBe editor.lineForBufferRow(5) - - editor.scrollTop(3 * editor.lineHeight) - expect(editor.renderedLines.find('.line:first').text()).toBe editor.lineForBufferRow(1) - expect(editor.renderedLines.find('.line:last').text()).toBe editor.lineForBufferRow(10) - - describe "when creating and destroying folds that are longer than the visible lines", -> - describe "when the cursor precedes the fold when it is destroyed", -> - it "renders lines and line numbers correctly", -> - scrollHeightBeforeFold = editor.scrollView.prop('scrollHeight') - fold = editor.createFold(1, 9) - fold.destroy() - expect(editor.scrollView.prop('scrollHeight')).toBe scrollHeightBeforeFold - - expect(editor.renderedLines.find('.line').length).toBe 8 - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) - - expect(editor.gutter.find('.line-number').length).toBe 8 - expect(editor.gutter.find('.line-number:last').intValue()).toBe 8 - - editor.scrollTop(4 * editor.lineHeight) - expect(editor.renderedLines.find('.line').length).toBe 10 - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(11) - - describe "when the cursor follows the fold when it is destroyed", -> - it "renders lines and line numbers correctly", -> - fold = editor.createFold(1, 9) - editor.setCursorBufferPosition([10, 0]) - fold.destroy() - - expect(editor.renderedLines.find('.line').length).toBe 8 - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(12) - - expect(editor.gutter.find('.line-number').length).toBe 8 - expect(editor.gutter.find('.line-number:last').text()).toBe '13' - - editor.scrollTop(4 * editor.lineHeight) - - expect(editor.renderedLines.find('.line').length).toBe 10 - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(11) - - describe "when scrolling vertically", -> - describe "when scrolling less than the editor's height", -> - it "draws new lines and removes old lines when the last visible line will exceed the last rendered line", -> - expect(editor.renderedLines.find('.line').length).toBe 8 - - editor.scrollTop(editor.lineHeight * 1.5) - expect(editor.renderedLines.find('.line').length).toBe 8 - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) - - editor.scrollTop(editor.lineHeight * 3.5) # first visible row will be 3, last will be 8 - expect(editor.renderedLines.find('.line').length).toBe 10 - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(1) - expect(editor.renderedLines.find('.line:last').html()).toBe ' ' # line 10 is blank - expect(editor.gutter.find('.line-number:first').intValue()).toBe 2 - expect(editor.gutter.find('.line-number:last').intValue()).toBe 11 - - # here we don't scroll far enough to trigger additional rendering - editor.scrollTop(editor.lineHeight * 5.5) # first visible row will be 5, last will be 10 - expect(editor.renderedLines.find('.line').length).toBe 10 - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(1) - expect(editor.renderedLines.find('.line:last').html()).toBe ' ' # line 10 is blank - expect(editor.gutter.find('.line-number:first').intValue()).toBe 2 - expect(editor.gutter.find('.line-number:last').intValue()).toBe 11 - - editor.scrollTop(editor.lineHeight * 7.5) # first visible row is 7, last will be 12 - expect(editor.renderedLines.find('.line').length).toBe 8 - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(5) - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(12) - - editor.scrollTop(editor.lineHeight * 3.5) # first visible row will be 3, last will be 8 - expect(editor.renderedLines.find('.line').length).toBe 10 - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(1) - expect(editor.renderedLines.find('.line:last').html()).toBe ' ' # line 10 is blank - - editor.scrollTop(0) - expect(editor.renderedLines.find('.line').length).toBe 8 - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) - - describe "when scrolling more than the editors height", -> - it "removes lines that are offscreen and not in range of the overdraw and builds lines that become visible", -> - editor.scrollTop(editor.layerHeight - editor.scrollView.height()) - expect(editor.renderedLines.find('.line').length).toBe 8 - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(5) - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(12) - - editor.verticalScrollbar.scrollBottom(0) - editor.verticalScrollbar.trigger 'scroll' - expect(editor.renderedLines.find('.line').length).toBe 8 - expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(0) - expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(7) - - it "adjusts the vertical padding of the lines element to account for non-rendered lines", -> - editor.scrollTop(editor.lineHeight * 3) - firstVisibleBufferRow = 3 - expectedPaddingTop = (firstVisibleBufferRow - editor.lineOverdraw) * editor.lineHeight - expect(editor.renderedLines.css('padding-top')).toBe "#{expectedPaddingTop}px" - - lastVisibleBufferRow = Math.ceil(3 + 5.5) # scroll top in lines + height in lines - lastOverdrawnRow = lastVisibleBufferRow + editor.lineOverdraw - expectedPaddingBottom = ((buffer.getLineCount() - lastOverdrawnRow) * editor.lineHeight) - expect(editor.renderedLines.css('padding-bottom')).toBe "#{expectedPaddingBottom}px" - - editor.scrollToBottom() - # scrolled to bottom, first visible row is 5 and first rendered row is 3 - firstVisibleBufferRow = Math.floor(buffer.getLineCount() - 5.5) - firstOverdrawnBufferRow = firstVisibleBufferRow - editor.lineOverdraw - expectedPaddingTop = firstOverdrawnBufferRow * editor.lineHeight - expect(editor.renderedLines.css('padding-top')).toBe "#{expectedPaddingTop}px" - expect(editor.renderedLines.css('padding-bottom')).toBe "0px" - - describe "when lines are added", -> - beforeEach -> - editor.attachToDom(heightInLines: 5) - - describe "when the change precedes the first rendered row", -> - it "inserts and removes rendered lines to account for upstream change", -> - editor.scrollToBottom() - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) - - buffer.change([[1,0], [3,0]], "1\n2\n3\n") - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) - - describe "when the change straddles the first rendered row", -> - it "doesn't render rows that were not previously rendered", -> - editor.scrollToBottom() - - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) - - buffer.change([[2,0], [7,0]], "2\n3\n4\n5\n6\n7\n8\n9\n") - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) - - describe "when the change straddles the last rendered row", -> - it "doesn't render rows that were not previously rendered", -> - buffer.change([[2,0], [7,0]], "2\n3\n4\n5\n6\n7\n8\n") - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6) - - describe "when the change the follows the last rendered row", -> - it "does not change the rendered lines", -> - buffer.change([[12,0], [12,0]], "12\n13\n14\n") - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6) - - it "increases the width of the rendered lines element to be either the width of the longest line or the width of the scrollView (whichever is longer)", -> - maxLineLength = editor.getMaxScreenLineLength() - setEditorWidthInChars(editor, maxLineLength) - widthBefore = editor.renderedLines.width() - expect(widthBefore).toBe editor.scrollView.width() + 20 - buffer.change([[12,0], [12,0]], [1..maxLineLength*2].join('')) - expect(editor.renderedLines.width()).toBeGreaterThan widthBefore - - describe "when lines are removed", -> - beforeEach -> - editor.attachToDom(heightInLines: 5) - - it "sets the rendered screen line's width to either the max line length or the scollView's width (whichever is greater)", -> - maxLineLength = editor.getMaxScreenLineLength() - setEditorWidthInChars(editor, maxLineLength) - buffer.change([[12,0], [12,0]], [1..maxLineLength*2].join('')) - expect(editor.renderedLines.width()).toBeGreaterThan editor.scrollView.width() - widthBefore = editor.renderedLines.width() - buffer.delete([[12, 0], [12, Infinity]]) - expect(editor.renderedLines.width()).toBe editor.scrollView.width() + 20 - - describe "when the change the precedes the first rendered row", -> - it "removes rendered lines to account for upstream change", -> - editor.scrollToBottom() - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) - - buffer.change([[1,0], [2,0]], "") - expect(editor.renderedLines.find(".line").length).toBe 6 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(11) - - describe "when the change straddles the first rendered row", -> - it "renders the correct rows", -> - editor.scrollToBottom() - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(12) - - buffer.change([[7,0], [11,0]], "1\n2\n") - expect(editor.renderedLines.find(".line").length).toBe 5 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(6) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(10) - - describe "when the change straddles the last rendered row", -> - it "renders the correct rows", -> - buffer.change([[2,0], [7,0]], "") - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6) - - describe "when the change the follows the last rendered row", -> - it "does not change the rendered lines", -> - buffer.change([[10,0], [12,0]], "") - expect(editor.renderedLines.find(".line").length).toBe 7 - expect(editor.renderedLines.find(".line:first").text()).toBe buffer.lineForRow(0) - expect(editor.renderedLines.find(".line:last").text()).toBe buffer.lineForRow(6) - - describe "when the last line is removed when the editor is scrolled to the bottom", -> - it "reduces the editor's scrollTop (due to the reduced total scroll height) and renders the correct screen lines", -> - editor.setCursorScreenPosition([Infinity, Infinity]) - editor.insertText('\n\n\n') - editor.scrollToBottom() - - expect(buffer.getLineCount()).toBe 16 - - initialScrollTop = editor.scrollTop() - expect(editor.firstRenderedScreenRow).toBe 9 - expect(editor.lastRenderedScreenRow).toBe 15 - - editor.backspace() - - expect(editor.scrollTop()).toBeLessThan initialScrollTop - expect(editor.firstRenderedScreenRow).toBe 9 - expect(editor.lastRenderedScreenRow).toBe 14 - - expect(editor.find('.line').length).toBe 6 - - editor.backspace() - expect(editor.firstRenderedScreenRow).toBe 9 - expect(editor.lastRenderedScreenRow).toBe 13 - - expect(editor.find('.line').length).toBe 5 - - editor.backspace() - expect(editor.firstRenderedScreenRow).toBe 6 - expect(editor.lastRenderedScreenRow).toBe 12 - - expect(editor.find('.line').length).toBe 7 - - describe "when folding leaves less then a screen worth of text (regression)", -> - it "renders lines properly", -> - editor.lineOverdraw = 1 - editor.attachToDom(heightInLines: 5) - editor.activeEditSession.foldBufferRow(4) - editor.activeEditSession.foldBufferRow(0) - - expect(editor.renderedLines.find('.line').length).toBe 1 - expect(editor.renderedLines.find('.line').text()).toBe buffer.lineForRow(0) - - describe "when folding leaves fewer screen lines than the first rendered screen line (regression)", -> - it "clears all screen lines and does not throw any exceptions", -> - editor.lineOverdraw = 1 - editor.attachToDom(heightInLines: 5) - editor.scrollToBottom() - editor.activeEditSession.foldBufferRow(0) - expect(editor.renderedLines.find('.line').length).toBe 1 - expect(editor.renderedLines.find('.line').text()).toBe buffer.lineForRow(0) - - describe "when autoscrolling at the end of the document", -> - it "renders lines properly", -> - editor.edit(project.openSync('two-hundred.txt')) - editor.attachToDom(heightInLines: 5.5) - - expect(editor.renderedLines.find('.line').length).toBe 8 - - editor.moveCursorToBottom() - - expect(editor.renderedLines.find('.line').length).toBe 8 - - describe "when line has a character that could push it to be too tall (regression)", -> - it "does renders the line at a consistent height", -> - editor.attachToDom() - buffer.insert([0, 0], "–") - expect(editor.find('.line:eq(0)').outerHeight()).toBe editor.find('.line:eq(1)').outerHeight() - - describe "when editor.showInvisibles config is set to true", -> - it "displays spaces, tabs, and newlines using visible non-empty values", -> - editor.setText " a line with tabs\tand spaces " - editor.attachToDom() - - expect(atom.config.get("editor.showInvisibles")).toBeFalsy() - expect(editor.renderedLines.find('.line').text()).toBe " a line with tabs and spaces " - - atom.config.set("editor.showInvisibles", true) - space = editor.invisibles?.space - expect(space).toBeTruthy() - tab = editor.invisibles?.tab - expect(tab).toBeTruthy() - eol = editor.invisibles?.eol - expect(eol).toBeTruthy() - expect(editor.renderedLines.find('.line').text()).toBe "#{space}a line with tabs#{tab} and spaces#{space}#{eol}" - - atom.config.set("editor.showInvisibles", false) - expect(editor.renderedLines.find('.line').text()).toBe " a line with tabs and spaces " - - it "displays newlines as their own token outside of the other tokens scope", -> - editor.setShowInvisibles(true) - editor.attachToDom() - editor.setText "var" - expect(editor.find('.line').html()).toBe 'var¬' - - it "allows invisible glyphs to be customized via the editor.invisibles config", -> - editor.setText(" \t ") - editor.attachToDom() - atom.config.set("editor.showInvisibles", true) - atom.config.set("editor.invisibles", eol: ";", space: "_", tab: "tab") - expect(editor.find(".line:first").text()).toBe "_tab _;" - - it "displays trailing carriage return using a visible non-empty value", -> - editor.setText "a line that ends with a carriage return\r\n" - editor.attachToDom() - - expect(atom.config.get("editor.showInvisibles")).toBeFalsy() - expect(editor.renderedLines.find('.line:first').text()).toBe "a line that ends with a carriage return" - - atom.config.set("editor.showInvisibles", true) - cr = editor.invisibles?.cr - expect(cr).toBeTruthy() - eol = editor.invisibles?.eol - expect(eol).toBeTruthy() - expect(editor.renderedLines.find('.line:first').text()).toBe "a line that ends with a carriage return#{cr}#{eol}" - - describe "when wrapping is on", -> - beforeEach -> - editSession.setSoftWrap(true) - - it "doesn't show the end of line invisible at the end of lines broken due to wrapping", -> - editor.setText "a line that wraps" - editor.attachToDom() - editor.setWidthInChars(6) - atom.config.set "editor.showInvisibles", true - space = editor.invisibles?.space - expect(space).toBeTruthy() - eol = editor.invisibles?.eol - expect(eol).toBeTruthy() - expect(editor.renderedLines.find('.line:first').text()).toBe "a line#{space}" - expect(editor.renderedLines.find('.line:last').text()).toBe "wraps#{eol}" - - it "displays trailing carriage return using a visible non-empty value", -> - editor.setText "a line that\r\n" - editor.attachToDom() - editor.setWidthInChars(6) - atom.config.set "editor.showInvisibles", true - space = editor.invisibles?.space - expect(space).toBeTruthy() - cr = editor.invisibles?.cr - expect(cr).toBeTruthy() - eol = editor.invisibles?.eol - expect(eol).toBeTruthy() - expect(editor.renderedLines.find('.line:first').text()).toBe "a line#{space}" - expect(editor.renderedLines.find('.line:eq(1)').text()).toBe "that#{cr}#{eol}" - expect(editor.renderedLines.find('.line:last').text()).toBe "#{eol}" - - describe "when editor.showIndentGuide is set to true", -> - it "adds an indent-guide class to each leading whitespace span", -> - editor.attachToDom() - - expect(atom.config.get("editor.showIndentGuide")).toBeFalsy() - atom.config.set("editor.showIndentGuide", true) - expect(editor.showIndentGuide).toBeTruthy() - - expect(editor.renderedLines.find('.line:eq(0) .indent-guide').length).toBe 0 - - expect(editor.renderedLines.find('.line:eq(1) .indent-guide').length).toBe 1 - expect(editor.renderedLines.find('.line:eq(1) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(2) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(2) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(3) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(3) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(4) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(4) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(5) .indent-guide').length).toBe 3 - expect(editor.renderedLines.find('.line:eq(5) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(6) .indent-guide').length).toBe 3 - expect(editor.renderedLines.find('.line:eq(6) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(7) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(7) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(8) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(8) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(9) .indent-guide').length).toBe 1 - expect(editor.renderedLines.find('.line:eq(9) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1 - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(11) .indent-guide').length).toBe 1 - expect(editor.renderedLines.find('.line:eq(11) .indent-guide').text()).toBe ' ' - - expect(editor.renderedLines.find('.line:eq(12) .indent-guide').length).toBe 0 - - describe "when the indentation level on a line before an empty line is changed", -> - it "updates the indent guide on the empty line", -> - editor.attachToDom() - atom.config.set("editor.showIndentGuide", true) - - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1 - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' - - editor.setCursorBufferPosition([9]) - editor.indentSelectedRows() - - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' - - describe "when the indentation level on a line after an empty line is changed", -> - it "updates the indent guide on the empty line", -> - editor.attachToDom() - atom.config.set("editor.showIndentGuide", true) - - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1 - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' - - editor.setCursorBufferPosition([11]) - editor.indentSelectedRows() - - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' - - describe "when a line contains only whitespace", -> - it "displays an indent guide on the line", -> - editor.attachToDom() - atom.config.set("editor.showIndentGuide", true) - - editor.setCursorBufferPosition([10]) - editor.indent() - editor.indent() - expect(editor.getCursorBufferPosition()).toEqual [10, 4] - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' - - it "uses the highest indent guide level from the next or previous non-empty line", -> - editor.attachToDom() - atom.config.set("editor.showIndentGuide", true) - - editor.setCursorBufferPosition([1, Infinity]) - editor.insertNewline() - expect(editor.getCursorBufferPosition()).toEqual [2, 0] - expect(editor.renderedLines.find('.line:eq(2) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(2) .indent-guide').text()).toBe ' ' - - describe "when the line has leading and trailing whitespace", -> - it "does not display the indent guide in the trailing whitespace", -> - editor.attachToDom() - atom.config.set("editor.showIndentGuide", true) - - editor.insertText("/*\n * \n*/") - expect(editor.renderedLines.find('.line:eq(1) .indent-guide').length).toBe 1 - expect(editor.renderedLines.find('.line:eq(1) .indent-guide')).toHaveClass('leading-whitespace') - - describe "when the line is empty and end of show invisibles are enabled", -> - it "renders the indent guides interleaved with the end of line invisibles", -> - editor.attachToDom() - atom.config.set("editor.showIndentGuide", true) - atom.config.set("editor.showInvisibles", true) - eol = editor.invisibles?.eol - - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1 - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} " - expect(editor.renderedLines.find('.line:eq(10) .invisible-character').text()).toBe eol - - editor.setCursorBufferPosition([9]) - editor.indent() - - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 - expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} " - expect(editor.renderedLines.find('.line:eq(10) .invisible-character').text()).toBe eol - - describe "when soft-wrap is enabled", -> - beforeEach -> - jasmine.unspy(window, 'setTimeout') - editSession.setSoftWrap(true) - editor.attachToDom() - setEditorHeightInLines(editor, 20) - setEditorWidthInChars(editor, 50) - expect(editor.activeEditSession.getSoftWrapColumn()).toBe 50 - - it "wraps lines that are too long to fit within the editor's width, adjusting cursor positioning accordingly", -> - expect(editor.renderedLines.find('.line').length).toBe 16 - expect(editor.renderedLines.find('.line:eq(3)').text()).toBe " var pivot = items.shift(), current, left = [], " - expect(editor.renderedLines.find('.line:eq(4)').text()).toBe "right = [];" - - editor.setCursorBufferPosition([3, 51], wrapAtSoftNewlines: true) - expect(editor.find('.cursor').offset()).toEqual(editor.renderedLines.find('.line:eq(4)').offset()) - - editor.setCursorBufferPosition([4, 0]) - expect(editor.find('.cursor').offset()).toEqual(editor.renderedLines.find('.line:eq(5)').offset()) - - editor.getSelection().setBufferRange([[6, 30], [6, 55]]) - [region1, region2] = editor.getSelectionView().regions - expect(region1.offset().top).toBeCloseTo(editor.renderedLines.find('.line:eq(7)').offset().top) - expect(region2.offset().top).toBeCloseTo(editor.renderedLines.find('.line:eq(8)').offset().top) - - it "handles changes to wrapped lines correctly", -> - buffer.insert([6, 28], '1234567') - expect(editor.renderedLines.find('.line:eq(7)').text()).toBe ' current < pivot ? left1234567.push(current) ' - expect(editor.renderedLines.find('.line:eq(8)').text()).toBe ': right.push(current);' - expect(editor.renderedLines.find('.line:eq(9)').text()).toBe ' }' - - it "changes the max line length and repositions the cursor when the window size changes", -> - editor.setCursorBufferPosition([3, 60]) - setEditorWidthInChars(editor, 40) - expect(editor.renderedLines.find('.line').length).toBe 19 - expect(editor.renderedLines.find('.line:eq(4)').text()).toBe "left = [], right = [];" - expect(editor.renderedLines.find('.line:eq(5)').text()).toBe " while(items.length > 0) {" - expect(editor.bufferPositionForScreenPosition(editor.getCursorScreenPosition())).toEqual [3, 60] - - it "does not wrap the lines of any newly assigned buffers", -> - otherEditSession = project.openSync() - otherEditSession.buffer.setText([1..100].join('')) - editor.edit(otherEditSession) - expect(editor.renderedLines.find('.line').length).toBe(1) - - it "unwraps lines when softwrap is disabled", -> - editor.toggleSoftWrap() - expect(editor.renderedLines.find('.line:eq(3)').text()).toBe ' var pivot = items.shift(), current, left = [], right = [];' - - it "allows the cursor to move down to the last line", -> - _.times editor.getLastScreenRow(), -> editor.moveCursorDown() - expect(editor.getCursorScreenPosition()).toEqual [editor.getLastScreenRow(), 0] - editor.moveCursorDown() - expect(editor.getCursorScreenPosition()).toEqual [editor.getLastScreenRow(), 2] - - it "allows the cursor to move up to a shorter soft wrapped line", -> - editor.setCursorScreenPosition([11, 15]) - editor.moveCursorUp() - expect(editor.getCursorScreenPosition()).toEqual [10, 10] - editor.moveCursorUp() - editor.moveCursorUp() - expect(editor.getCursorScreenPosition()).toEqual [8, 15] - - it "it allows the cursor to wrap when moving horizontally past the beginning / end of a wrapped line", -> - editor.setCursorScreenPosition([11, 0]) - editor.moveCursorLeft() - expect(editor.getCursorScreenPosition()).toEqual [10, 10] - - editor.moveCursorRight() - expect(editor.getCursorScreenPosition()).toEqual [11, 0] - - it "calls .setWidthInChars() when the editor is attached because now its dimensions are available to calculate it", -> - otherEditor = new TextEditorView(editSession: project.openSync('sample.js')) - spyOn(otherEditor, 'setWidthInChars') - - otherEditor.activeEditSession.setSoftWrap(true) - expect(otherEditor.setWidthInChars).not.toHaveBeenCalled() - - otherEditor.simulateDomAttachment() - expect(otherEditor.setWidthInChars).toHaveBeenCalled() - otherEditor.remove() - - describe "when the editor's width changes", -> - it "updates the width in characters on the edit session", -> - previousSoftWrapColumn = editSession.getSoftWrapColumn() - - spyOn(editor, 'setWidthInChars').andCallThrough() - editor.width(editor.width() / 2) - - waitsFor -> - editor.setWidthInChars.callCount > 0 - - runs -> - expect(editSession.getSoftWrapColumn()).toBeLessThan previousSoftWrapColumn - - describe "gutter rendering", -> - beforeEach -> - editor.attachToDom(heightInLines: 5.5) - - it "creates a line number element for each visible line with   padding to the left of the number", -> - expect(editor.gutter.find('.line-number').length).toBe 8 - expect(editor.find('.line-number:first').html()).toBe " 1" - expect(editor.gutter.find('.line-number:last').html()).toBe " 8" - - # here we don't scroll far enough to trigger additional rendering - editor.scrollTop(editor.lineHeight * 1.5) - expect(editor.renderedLines.find('.line').length).toBe 8 - expect(editor.gutter.find('.line-number:first').html()).toBe " 1" - expect(editor.gutter.find('.line-number:last').html()).toBe " 8" - - editor.scrollTop(editor.lineHeight * 3.5) - expect(editor.renderedLines.find('.line').length).toBe 10 - expect(editor.gutter.find('.line-number:first').html()).toBe " 2" - expect(editor.gutter.find('.line-number:last').html()).toBe "11" - - describe "when lines are inserted", -> - it "re-renders the correct line number range in the gutter", -> - editor.scrollTop(3 * editor.lineHeight) - expect(editor.gutter.find('.line-number:first').intValue()).toBe 2 - expect(editor.gutter.find('.line-number:last').intValue()).toBe 11 - - buffer.insert([6, 0], '\n') - - expect(editor.gutter.find('.line-number:first').intValue()).toBe 2 - expect(editor.gutter.find('.line-number:last').intValue()).toBe 11 - - it "re-renders the correct line number range when there are folds", -> - editor.activeEditSession.foldBufferRow(1) - expect(editor.gutter.find('.line-number-1')).toHaveClass 'fold' - - buffer.insert([0, 0], '\n') - - expect(editor.gutter.find('.line-number-2')).toHaveClass 'fold' - - describe "when wrapping is on", -> - it "renders a • instead of line number for wrapped portions of lines", -> - editSession.setSoftWrap(true) - editor.setWidthInChars(50) - expect(editor.gutter.find('.line-number').length).toEqual(8) - expect(editor.gutter.find('.line-number:eq(3)').intValue()).toBe 4 - expect(editor.gutter.find('.line-number:eq(4)').html()).toBe ' â€¢' - expect(editor.gutter.find('.line-number:eq(5)').intValue()).toBe 5 - - describe "when there are folds", -> - it "skips line numbers covered by the fold and updates them when the fold changes", -> - editor.createFold(3, 5) - expect(editor.gutter.find('.line-number:eq(3)').intValue()).toBe 4 - expect(editor.gutter.find('.line-number:eq(4)').intValue()).toBe 7 - - buffer.insert([4,0], "\n\n") - expect(editor.gutter.find('.line-number:eq(3)').intValue()).toBe 4 - expect(editor.gutter.find('.line-number:eq(4)').intValue()).toBe 9 - - buffer.delete([[3,0], [6,0]]) - expect(editor.gutter.find('.line-number:eq(3)').intValue()).toBe 4 - expect(editor.gutter.find('.line-number:eq(4)').intValue()).toBe 6 - - it "redraws gutter numbers when lines are unfolded", -> - setEditorHeightInLines(editor, 20) - fold = editor.createFold(2, 12) - expect(editor.gutter.find('.line-number').length).toBe 3 - - fold.destroy() - expect(editor.gutter.find('.line-number').length).toBe 13 - - it "styles folded line numbers", -> - editor.createFold(3, 5) - expect(editor.gutter.find('.line-number.fold').length).toBe 1 - expect(editor.gutter.find('.line-number.fold:eq(0)').intValue()).toBe 4 - - describe "when the scrollView is scrolled to the right", -> - it "adds a drop shadow to the gutter", -> - editor.attachToDom() - editor.width(100) - - expect(editor.gutter).not.toHaveClass('drop-shadow') - - editor.scrollLeft(10) - editor.scrollView.trigger('scroll') - - expect(editor.gutter).toHaveClass('drop-shadow') - - editor.scrollLeft(0) - editor.scrollView.trigger('scroll') - - expect(editor.gutter).not.toHaveClass('drop-shadow') - - describe "when the editor is scrolled vertically", -> - it "adjusts the padding-top to account for non-rendered line numbers", -> - editor.scrollTop(editor.lineHeight * 3.5) - expect(editor.gutter.lineNumbers.css('padding-top')).toBe "#{editor.lineHeight * 1}px" - expect(editor.gutter.lineNumbers.css('padding-bottom')).toBe "#{editor.lineHeight * 2}px" - expect(editor.renderedLines.find('.line').length).toBe 10 - expect(editor.gutter.find('.line-number:first').intValue()).toBe 2 - expect(editor.gutter.find('.line-number:last').intValue()).toBe 11 - - describe "when the switching from an edit session for a long buffer to an edit session for a short buffer", -> - it "updates the line numbers to reflect the shorter buffer", -> - emptyEditSession = project.openSync(null) - editor.edit(emptyEditSession) - expect(editor.gutter.lineNumbers.find('.line-number').length).toBe 1 - - editor.edit(editSession) - expect(editor.gutter.lineNumbers.find('.line-number').length).toBeGreaterThan 1 - - editor.edit(emptyEditSession) - expect(editor.gutter.lineNumbers.find('.line-number').length).toBe 1 - - describe "when the editor is mini", -> - it "hides the gutter", -> - miniEditor = new TextEditorView(mini: true) - miniEditor.attachToDom() - expect(miniEditor.gutter).toBeHidden() - - it "doesn't highlight the only line", -> - miniEditor = new TextEditorView(mini: true) - miniEditor.attachToDom() - expect(miniEditor.getCursorBufferPosition().row).toBe 0 - expect(miniEditor.find('.line.cursor-line').length).toBe 0 - - it "doesn't show the end of line invisible", -> - atom.config.set "editor.showInvisibles", true - miniEditor = new TextEditorView(mini: true) - miniEditor.attachToDom() - space = miniEditor.invisibles?.space - expect(space).toBeTruthy() - tab = miniEditor.invisibles?.tab - expect(tab).toBeTruthy() - miniEditor.setText(" a line with tabs\tand spaces ") - expect(miniEditor.renderedLines.find('.line').text()).toBe "#{space}a line with tabs#{tab} and spaces#{space}" - - it "doesn't show the indent guide", -> - atom.config.set "editor.showIndentGuide", true - miniEditor = new TextEditorView(mini: true) - miniEditor.attachToDom() - miniEditor.setText(" and indented line") - expect(miniEditor.renderedLines.find('.indent-guide').length).toBe 0 - - - it "lets you set the grammar", -> - miniEditor = new TextEditorView(mini: true) - miniEditor.setText("var something") - previousTokens = miniEditor.lineForScreenRow(0).tokens - miniEditor.setGrammar(atom.syntax.selectGrammar('something.js')) - expect(miniEditor.getGrammar().name).toBe "JavaScript" - expect(previousTokens).not.toEqual miniEditor.lineForScreenRow(0).tokens - - # doesn't allow regular editors to set grammars - expect(-> editor.setGrammar()).toThrow() - - describe "when the editor.showLineNumbers config is false", -> - it "doesn't render any line numbers", -> - expect(editor.gutter.lineNumbers).toBeVisible() - atom.config.set("editor.showLineNumbers", false) - expect(editor.gutter.lineNumbers).not.toBeVisible() - - describe "using gutter's api", -> - it "can get all the line number elements", -> - elements = editor.gutter.getLineNumberElements() - len = editor.gutter.lastScreenRow - editor.gutter.firstScreenRow + 1 - expect(elements).toHaveLength(len) - - it "can get a single line number element", -> - element = editor.gutter.getLineNumberElement(3) - expect(element).toBeTruthy() - - it "returns falsy when there is no line element", -> - expect(editor.gutter.getLineNumberElement(42)).toHaveLength 0 - - it "can add and remove classes to all the line numbers", -> - wasAdded = editor.gutter.addClassToAllLines('heyok') - expect(wasAdded).toBe true - - elements = editor.gutter.getLineNumberElementsForClass('heyok') - expect($(elements)).toHaveClass('heyok') - - editor.gutter.removeClassFromAllLines('heyok') - expect($(editor.gutter.getLineNumberElements())).not.toHaveClass('heyok') - - it "can add and remove classes from a single line number", -> - wasAdded = editor.gutter.addClassToLine(3, 'heyok') - expect(wasAdded).toBe true - - element = editor.gutter.getLineNumberElement(2) - expect($(element)).not.toHaveClass('heyok') - - it "can fetch line numbers by their class", -> - editor.gutter.addClassToLine(1, 'heyok') - editor.gutter.addClassToLine(3, 'heyok') - - elements = editor.gutter.getLineNumberElementsForClass('heyok') - expect(elements.length).toBe 2 - - expect($(elements[0])).toHaveClass 'line-number-1' - expect($(elements[0])).toHaveClass 'heyok' - - expect($(elements[1])).toHaveClass 'line-number-3' - expect($(elements[1])).toHaveClass 'heyok' - - describe "gutter line highlighting", -> - beforeEach -> - editor.attachToDom(heightInLines: 5.5) - - describe "when there is no wrapping", -> - it "highlights the line where the initial cursor position is", -> - expect(editor.getCursorBufferPosition().row).toBe 0 - expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 1 - expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').intValue()).toBe 1 - - it "updates the highlighted line when the cursor position changes", -> - editor.setCursorBufferPosition([1,0]) - expect(editor.getCursorBufferPosition().row).toBe 1 - expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 1 - expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').intValue()).toBe 2 - - describe "when there is wrapping", -> - beforeEach -> - editor.attachToDom(30) - editSession.setSoftWrap(true) - setEditorWidthInChars(editor, 20) - - it "highlights the line where the initial cursor position is", -> - expect(editor.getCursorBufferPosition().row).toBe 0 - expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 1 - expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').intValue()).toBe 1 - - it "updates the highlighted line when the cursor position changes", -> - editor.setCursorBufferPosition([1,0]) - expect(editor.getCursorBufferPosition().row).toBe 1 - expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 1 - expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').intValue()).toBe 2 - - describe "when the selection spans multiple lines", -> - beforeEach -> - editor.attachToDom(30) - - it "highlights the foreground of the gutter", -> - editor.getSelection().setBufferRange([[0,0],[2,2]]) - expect(editor.getSelection().isSingleScreenLine()).toBe false - expect(editor.find('.line-number.cursor-line').length).toBe 3 - - it "doesn't highlight the background of the gutter", -> - editor.getSelection().setBufferRange([[0,0],[2,0]]) - expect(editor.getSelection().isSingleScreenLine()).toBe false - expect(editor.find('.line-number.cursor-line.cursor-line-no-selection').length).toBe 0 - - it "doesn't highlight the last line if it ends at the beginning of a line", -> - editor.getSelection().setBufferRange([[0,0],[1,0]]) - expect(editor.getSelection().isSingleScreenLine()).toBe false - expect(editor.find('.line-number.cursor-line').length).toBe 1 - expect(editor.find('.line-number.cursor-line').intValue()).toBe 1 - - it "when a newline is deleted with backspace, the line number of the new cursor position is highlighted", -> - editor.setCursorScreenPosition([1,0]) - editor.backspace() - expect(editor.find('.line-number.cursor-line').length).toBe 1 - expect(editor.find('.line-number.cursor-line').intValue()).toBe 1 - - describe "line highlighting", -> - beforeEach -> - editor.attachToDom(30) - - describe "when there is no wrapping", -> - it "highlights the line where the initial cursor position is", -> - expect(editor.getCursorBufferPosition().row).toBe 0 - expect(editor.find('.line.cursor-line').length).toBe 1 - expect(editor.find('.line.cursor-line').text()).toBe buffer.lineForRow(0) - - it "updates the highlighted line when the cursor position changes", -> - editor.setCursorBufferPosition([1,0]) - expect(editor.getCursorBufferPosition().row).toBe 1 - expect(editor.find('.line.cursor-line').length).toBe 1 - expect(editor.find('.line.cursor-line').text()).toBe buffer.lineForRow(1) - - it "when a newline is deleted with backspace, the line of the new cursor position is highlighted", -> - editor.setCursorScreenPosition([1,0]) - editor.backspace() - expect(editor.find('.line.cursor-line').length).toBe 1 - - describe "when there is wrapping", -> - beforeEach -> - editSession.setSoftWrap(true) - setEditorWidthInChars(editor, 20) - - it "highlights the line where the initial cursor position is", -> - expect(editor.getCursorBufferPosition().row).toBe 0 - expect(editor.find('.line.cursor-line').length).toBe 1 - expect(editor.find('.line.cursor-line').text()).toBe 'var quicksort = ' - - it "updates the highlighted line when the cursor position changes", -> - editor.setCursorBufferPosition([1,0]) - expect(editor.getCursorBufferPosition().row).toBe 1 - expect(editor.find('.line.cursor-line').length).toBe 1 - expect(editor.find('.line.cursor-line').text()).toBe ' var sort = ' - - describe "when there is a non-empty selection", -> - it "does not highlight the line", -> - editor.setSelectedBufferRange([[1, 0], [1, 1]]) - expect(editor.find('.line.cursor-line').length).toBe 0 - - describe "folding", -> - beforeEach -> - editSession = project.openSync('two-hundred.txt') - buffer = editSession.buffer - editor.edit(editSession) - editor.attachToDom() - - describe "when a fold-selection event is triggered", -> - it "folds the lines covered by the selection into a single line with a fold class and marker", -> - editor.getSelection().setBufferRange([[4,29],[7,4]]) - editor.trigger 'editor:fold-selection' - - expect(editor.renderedLines.find('.line:eq(4)')).toHaveClass('fold') - expect(editor.renderedLines.find('.line:eq(4) > .fold-marker')).toExist() - expect(editor.renderedLines.find('.line:eq(5)').text()).toBe '8' - - expect(editor.getSelection().isEmpty()).toBeTruthy() - expect(editor.getCursorScreenPosition()).toEqual [5, 0] - - it "keeps the gutter line and the editor line the same heights (regression)", -> - editor.getSelection().setBufferRange([[4,29],[7,4]]) - editor.trigger 'editor:fold-selection' - - expect(editor.gutter.find('.line-number:eq(4)').height()).toBe editor.renderedLines.find('.line:eq(4)').height() - - describe "when a fold placeholder line is clicked", -> - it "removes the associated fold and places the cursor at its beginning", -> - editor.setCursorBufferPosition([3,0]) - editSession.createFold(3, 5) - - foldLine = editor.find('.line.fold') - expect(foldLine).toExist() - foldLine.mousedown() - - expect(editor.find('.fold')).not.toExist() - expect(editor.find('.fold-marker')).not.toExist() - expect(editor.renderedLines.find('.line:eq(4)').text()).toMatch /4-+/ - expect(editor.renderedLines.find('.line:eq(5)').text()).toMatch /5/ - - expect(editor.getCursorBufferPosition()).toEqual [3, 0] - - describe "when the unfold-current-row event is triggered when the cursor is on a fold placeholder line", -> - it "removes the associated fold and places the cursor at its beginning", -> - editor.setCursorBufferPosition([3,0]) - editor.trigger 'editor:fold-current-row' - - editor.setCursorBufferPosition([3,0]) - editor.trigger 'editor:unfold-current-row' - - expect(editor.find('.fold')).not.toExist() - expect(editor.renderedLines.find('.line:eq(4)').text()).toMatch /4-+/ - expect(editor.renderedLines.find('.line:eq(5)').text()).toMatch /5/ - - expect(editor.getCursorBufferPosition()).toEqual [3, 0] - - describe "when a selection starts/stops intersecting a fold", -> - it "adds/removes the 'fold-selected' class to the fold's line element and hides the cursor if it is on the fold line", -> - editor.createFold(2, 4) - - editor.setSelectedBufferRange([[1, 0], [2, 0]], preserveFolds: true, isReversed: true) - expect(editor.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected') - - editor.setSelectedBufferRange([[1, 0], [1, 1]], preserveFolds: true) - expect(editor.lineElementForScreenRow(2)).not.toMatchSelector('.fold.fold-selected') - - editor.setSelectedBufferRange([[1, 0], [5, 0]], preserveFolds: true) - expect(editor.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected') - - editor.setCursorScreenPosition([3,0]) - expect(editor.lineElementForScreenRow(2)).not.toMatchSelector('.fold.fold-selected') - - editor.setCursorScreenPosition([2,0]) - expect(editor.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected') - expect(editor.find('.cursor')).toBeHidden() - - editor.setCursorScreenPosition([3,0]) - expect(editor.find('.cursor')).toBeVisible() - - describe "when a selected fold is scrolled into view (and the fold line was not previously rendered)", -> - it "renders the fold's line element with the 'fold-selected' class", -> - setEditorHeightInLines(editor, 5) - editor.resetDisplay() - - editor.createFold(2, 4) - editor.setSelectedBufferRange([[1, 0], [5, 0]], preserveFolds: true) - expect(editor.renderedLines.find('.fold.fold-selected')).toExist() - - editor.scrollToBottom() - expect(editor.renderedLines.find('.fold.fold-selected')).not.toExist() - - editor.scrollTop(0) - expect(editor.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected') - - describe "paging up and down", -> - beforeEach -> - editor.attachToDom() - - it "moves to the last line when page down is repeated from the first line", -> - rows = editor.getLineCount() - 1 - expect(rows).toBeGreaterThan(0) - row = editor.getCursor().getScreenPosition().row - expect(row).toBe(0) - while row < rows - editor.pageDown() - newRow = editor.getCursor().getScreenPosition().row - expect(newRow).toBeGreaterThan(row) - if (newRow <= row) - break - row = newRow - expect(row).toBe(rows) - expect(editor.getLastVisibleScreenRow()).toBe(rows) - - it "moves to the first line when page up is repeated from the last line", -> - editor.moveCursorToBottom() - row = editor.getCursor().getScreenPosition().row - expect(row).toBeGreaterThan(0) - while row > 0 - editor.pageUp() - newRow = editor.getCursor().getScreenPosition().row - expect(newRow).toBeLessThan(row) - if (newRow >= row) - break - row = newRow - expect(row).toBe(0) - expect(editor.getFirstVisibleScreenRow()).toBe(0) - - it "resets to original position when down is followed by up", -> - expect(editor.getCursor().getScreenPosition().row).toBe(0) - editor.pageDown() - expect(editor.getCursor().getScreenPosition().row).toBeGreaterThan(0) - editor.pageUp() - expect(editor.getCursor().getScreenPosition().row).toBe(0) - expect(editor.getFirstVisibleScreenRow()).toBe(0) - - describe ".checkoutHead()", -> - [filePath, originalPathText] = [] - - beforeEach -> - filePath = project.resolve('git/working-dir/file.txt') - originalPathText = fs.readFileSync(filePath, 'utf8') - editor.edit(project.openSync(filePath)) - - afterEach -> - fs.writeFileSync(filePath, originalPathText) - - it "restores the contents of the editor to the HEAD revision", -> - editor.setText('') - editor.getBuffer().save() - - fileChangeHandler = jasmine.createSpy('fileChange') - editor.getBuffer().file.on 'contents-changed', fileChangeHandler - - editor.checkoutHead() - - waitsFor "file to trigger contents-changed event", -> - fileChangeHandler.callCount > 0 - - runs -> - expect(editor.getText()).toBe(originalPathText) - - describe ".pixelPositionForBufferPosition(position)", -> - describe "when the editor is detached", -> - it "returns top and left values of 0", -> - expect(editor.isOnDom()).toBeFalsy() - expect(editor.pixelPositionForBufferPosition([2,7])).toEqual top: 0, left: 0 - - describe "when the editor is invisible", -> - it "returns top and left values of 0", -> - editor.attachToDom() - editor.hide() - expect(editor.isVisible()).toBeFalsy() - expect(editor.pixelPositionForBufferPosition([2,7])).toEqual top: 0, left: 0 - - describe "when the editor is attached and visible", -> - beforeEach -> - editor.attachToDom() - - it "returns the top and left pixel positions", -> - expect(editor.pixelPositionForBufferPosition([2,7])).toEqual top: 40, left: 70 - - it "caches the left position", -> - editor.renderedLines.css('font-size', '16px') - expect(editor.pixelPositionForBufferPosition([2,8])).toEqual top: 40, left: 80 - - # make characters smaller - editor.renderedLines.css('font-size', '15px') - - expect(editor.pixelPositionForBufferPosition([2,8])).toEqual top: 40, left: 80 - - describe "when clicking in the gutter", -> - beforeEach -> - editor.attachToDom() - - describe "when single clicking", -> - it "moves the cursor to the start of the selected line", -> - expect(editor.getCursorScreenPosition()).toEqual [0,0] - event = $.Event("mousedown") - event.pageY = editor.gutter.find(".line-number:eq(1)").offset().top - event.originalEvent = {detail: 1} - editor.gutter.find(".line-number:eq(1)").trigger event - expect(editor.getCursorScreenPosition()).toEqual [1,0] - - describe "when shift-clicking", -> - it "selects to the start of the selected line", -> - expect(editor.getSelection().getScreenRange()).toEqual [[0,0], [0,0]] - event = $.Event("mousedown") - event.pageY = editor.gutter.find(".line-number:eq(1)").offset().top - event.originalEvent = {detail: 1} - event.shiftKey = true - editor.gutter.find(".line-number:eq(1)").trigger event - expect(editor.getSelection().getScreenRange()).toEqual [[0,0], [2,0]] - - describe "when mousing down and then moving across multiple lines before mousing up", -> - describe "when selecting from top to bottom", -> - it "selects the lines", -> - mousedownEvent = $.Event("mousedown") - mousedownEvent.pageY = editor.gutter.find(".line-number:eq(1)").offset().top - mousedownEvent.originalEvent = {detail: 1} - editor.gutter.find(".line-number:eq(1)").trigger mousedownEvent - - mousemoveEvent = $.Event("mousemove") - mousemoveEvent.pageY = editor.gutter.find(".line-number:eq(5)").offset().top - mousemoveEvent.originalEvent = {detail: 1} - editor.gutter.find(".line-number:eq(5)").trigger mousemoveEvent - - $(document).trigger 'mouseup' - - expect(editor.getSelection().getScreenRange()).toEqual [[1,0], [6,0]] - - describe "when selecting from bottom to top", -> - it "selects the lines", -> - mousedownEvent = $.Event("mousedown") - mousedownEvent.pageY = editor.gutter.find(".line-number:eq(5)").offset().top - mousedownEvent.originalEvent = {detail: 1} - editor.gutter.find(".line-number:eq(5)").trigger mousedownEvent - - mousemoveEvent = $.Event("mousemove") - mousemoveEvent.pageY = editor.gutter.find(".line-number:eq(1)").offset().top - mousemoveEvent.originalEvent = {detail: 1} - editor.gutter.find(".line-number:eq(1)").trigger mousemoveEvent - - $(document).trigger 'mouseup' - - expect(editor.getSelection().getScreenRange()).toEqual [[1,0], [6,0]] - - describe "when clicking below the last line", -> - beforeEach -> - editor.attachToDom() - - it "move the cursor to the end of the file", -> - expect(editor.getCursorScreenPosition()).toEqual [0,0] - event = mousedownEvent(editor: editor, point: [Infinity, 10]) - editor.underlayer.trigger event - expect(editor.getCursorScreenPosition()).toEqual [12,2] - - it "selects to the end of the files when shift is pressed", -> - expect(editor.getSelection().getScreenRange()).toEqual [[0,0], [0,0]] - event = mousedownEvent(editor: editor, point: [Infinity, 10], shiftKey: true) - editor.underlayer.trigger event - expect(editor.getSelection().getScreenRange()).toEqual [[0,0], [12,2]] - - describe ".reloadGrammar()", -> - [filePath] = [] - - beforeEach -> - tmpdir = fs.absolute(temp.dir) - filePath = path.join(tmpdir, "grammar-change.txt") - fs.writeFileSync(filePath, "var i;") - - afterEach -> - fs.removeSync(filePath) if fs.existsSync(filePath) - - it "updates all the rendered lines when the grammar changes", -> - editor.edit(project.openSync(filePath)) - expect(editor.getGrammar().name).toBe 'Plain Text' - atom.syntax.setGrammarOverrideForPath(filePath, 'source.js') - editor.reloadGrammar() - expect(editor.getGrammar().name).toBe 'JavaScript' - - tokenizedBuffer = editor.activeEditSession.displayBuffer.tokenizedBuffer - line0 = tokenizedBuffer.lineForScreenRow(0) - expect(line0.tokens.length).toBe 3 - expect(line0.tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.modifier.js']) - - it "doesn't update the rendered lines when the grammar doesn't change", -> - expect(editor.getGrammar().name).toBe 'JavaScript' - spyOn(editor, 'updateDisplay').andCallThrough() - editor.reloadGrammar() - expect(editor.reloadGrammar()).toBeFalsy() - expect(editor.updateDisplay).not.toHaveBeenCalled() - expect(editor.getGrammar().name).toBe 'JavaScript' - - it "emits an editor:grammar-changed event when updated", -> - editor.edit(project.openSync(filePath)) - - eventHandler = jasmine.createSpy('eventHandler') - editor.on('editor:grammar-changed', eventHandler) - editor.reloadGrammar() - - expect(eventHandler).not.toHaveBeenCalled() - - atom.syntax.setGrammarOverrideForPath(filePath, 'source.js') - editor.reloadGrammar() - expect(eventHandler).toHaveBeenCalled() - - describe ".replaceSelectedText()", -> - it "doesn't call the replace function when the selection is empty", -> - replaced = false - edited = false - replacer = (text) -> - replaced = true - 'new' - - editor.moveCursorToTop() - edited = editor.replaceSelectedText(replacer) - expect(replaced).toBe false - expect(edited).toBe false - - it "returns true when transformed text is non-empty", -> - replaced = false - edited = false - replacer = (text) -> - replaced = true - 'new' - - editor.moveCursorToTop() - editor.selectToEndOfLine() - edited = editor.replaceSelectedText(replacer) - expect(replaced).toBe true - expect(edited).toBe true - - it "returns false when transformed text is null", -> - replaced = false - edited = false - replacer = (text) -> - replaced = true - null - - editor.moveCursorToTop() - editor.selectToEndOfLine() - edited = editor.replaceSelectedText(replacer) - expect(replaced).toBe true - expect(edited).toBe false - - it "returns false when transformed text is undefined", -> - replaced = false - edited = false - replacer = (text) -> - replaced = true - undefined - - editor.moveCursorToTop() - editor.selectToEndOfLine() - edited = editor.replaceSelectedText(replacer) - expect(replaced).toBe true - expect(edited).toBe false - - describe "when editor:copy-path is triggered", -> - it "copies the absolute path to the editor's file to the pasteboard", -> - editor.trigger 'editor:copy-path' - expect(atom.pasteboard.read()[0]).toBe editor.getPath() - - describe "when editor:move-line-up is triggered", -> - describe "when there is no selection", -> - it "moves the line where the cursor is up", -> - editor.setCursorBufferPosition([1,0]) - editor.trigger 'editor:move-line-up' - expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {' - expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {' - - it "moves the cursor to the new row and the same column", -> - editor.setCursorBufferPosition([1,2]) - editor.trigger 'editor:move-line-up' - expect(editor.getCursorBufferPosition()).toEqual [0,2] - - describe "where there is a selection", -> - describe "when the selection falls inside the line", -> - it "maintains the selection", -> - editor.setSelectedBufferRange([[1, 2], [1, 5]]) - expect(editor.getSelectedText()).toBe 'var' - editor.trigger 'editor:move-line-up' - expect(editor.getSelectedBufferRange()).toEqual [[0, 2], [0, 5]] - expect(editor.getSelectedText()).toBe 'var' - - describe "where there are multiple lines selected", -> - it "moves the selected lines up", -> - editor.setSelectedBufferRange([[2, 0], [3, Infinity]]) - editor.trigger 'editor:move-line-up' - expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {' - expect(buffer.lineForRow(1)).toBe ' if (items.length <= 1) return items;' - expect(buffer.lineForRow(2)).toBe ' var pivot = items.shift(), current, left = [], right = [];' - expect(buffer.lineForRow(3)).toBe ' var sort = function(items) {' - - it "maintains the selection", -> - editor.setSelectedBufferRange([[2, 0], [3, 62]]) - editor.trigger 'editor:move-line-up' - expect(editor.getSelectedBufferRange()).toEqual [[1, 0], [2, 62]] - - describe "when the last line is selected", -> - it "moves the selected line up", -> - editor.setSelectedBufferRange([[12, 0], [12, Infinity]]) - editor.trigger 'editor:move-line-up' - expect(buffer.lineForRow(11)).toBe '};' - expect(buffer.lineForRow(12)).toBe ' return sort(Array.apply(this, arguments));' - - describe "when the last two lines are selected", -> - it "moves the selected lines up", -> - editor.setSelectedBufferRange([[11, 0], [12, Infinity]]) - editor.trigger 'editor:move-line-up' - expect(buffer.lineForRow(10)).toBe ' return sort(Array.apply(this, arguments));' - expect(buffer.lineForRow(11)).toBe '};' - expect(buffer.lineForRow(12)).toBe '' - - describe "when the cursor is on the first line", -> - it "does not move the line", -> - editor.setCursorBufferPosition([0,0]) - originalText = editor.getText() - editor.trigger 'editor:move-line-up' - expect(editor.getText()).toBe originalText - - describe "when the cursor is on the trailing newline", -> - it "does not move the line", -> - editor.moveCursorToBottom() - editor.insertNewline() - editor.moveCursorToBottom() - originalText = editor.getText() - editor.trigger 'editor:move-line-up' - expect(editor.getText()).toBe originalText - - describe "when the cursor is on a folded line", -> - it "moves all lines in the fold up and preserves the fold", -> - editor.setCursorBufferPosition([4, 0]) - editor.foldCurrentRow() - editor.trigger 'editor:move-line-up' - expect(buffer.lineForRow(3)).toBe ' while(items.length > 0) {' - expect(buffer.lineForRow(7)).toBe ' var pivot = items.shift(), current, left = [], right = [];' - expect(editor.getSelectedBufferRange()).toEqual [[3, 0], [3, 0]] - expect(editor.isFoldedAtScreenRow(3)).toBeTruthy() - - describe "when the selection contains a folded and unfolded line", -> - it "moves the selected lines up and preserves the fold", -> - editor.setCursorBufferPosition([4, 0]) - editor.foldCurrentRow() - editor.setCursorBufferPosition([3, 4]) - editor.selectDown() - expect(editor.isFoldedAtScreenRow(4)).toBeTruthy() - editor.trigger 'editor:move-line-up' - expect(buffer.lineForRow(2)).toBe ' var pivot = items.shift(), current, left = [], right = [];' - expect(buffer.lineForRow(3)).toBe ' while(items.length > 0) {' - expect(editor.getSelectedBufferRange()).toEqual [[2, 4], [3, 0]] - expect(editor.isFoldedAtScreenRow(3)).toBeTruthy() - - describe "when an entire line is selected including the newline", -> - it "moves the selected line up", -> - editor.setCursorBufferPosition([1]) - editor.selectToEndOfLine() - editor.selectRight() - editor.trigger 'editor:move-line-up' - expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {' - expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {' - - describe "when editor:move-line-down is triggered", -> - describe "when there is no selection", -> - it "moves the line where the cursor is down", -> - editor.setCursorBufferPosition([0, 0]) - editor.trigger 'editor:move-line-down' - expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {' - expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {' - - it "moves the cursor to the new row and the same column", -> - editor.setCursorBufferPosition([0, 2]) - editor.trigger 'editor:move-line-down' - expect(editor.getCursorBufferPosition()).toEqual [1, 2] - - describe "when the cursor is on the last line", -> - it "does not move the line", -> - editor.moveCursorToBottom() - editor.trigger 'editor:move-line-down' - expect(buffer.lineForRow(12)).toBe '};' - expect(editor.getSelectedBufferRange()).toEqual [[12, 2], [12, 2]] - - describe "when the cursor is on the second to last line", -> - it "moves the line down", -> - editor.setCursorBufferPosition([11, 0]) - editor.trigger 'editor:move-line-down' - expect(buffer.lineForRow(11)).toBe '};' - expect(buffer.lineForRow(12)).toBe ' return sort(Array.apply(this, arguments));' - expect(buffer.lineForRow(13)).toBeUndefined() - - describe "when the cursor is on the second to last line and the last line is empty", -> - it "does not move the line", -> - editor.moveCursorToBottom() - editor.insertNewline() - editor.setCursorBufferPosition([12, 2]) - editor.trigger 'editor:move-line-down' - expect(buffer.lineForRow(12)).toBe '};' - expect(buffer.lineForRow(13)).toBe '' - expect(editor.getSelectedBufferRange()).toEqual [[12, 2], [12, 2]] - - describe "where there is a selection", -> - describe "when the selection falls inside the line", -> - it "maintains the selection", -> - editor.setSelectedBufferRange([[1, 2], [1, 5]]) - expect(editor.getSelectedText()).toBe 'var' - editor.trigger 'editor:move-line-down' - expect(editor.getSelectedBufferRange()).toEqual [[2, 2], [2, 5]] - expect(editor.getSelectedText()).toBe 'var' - - describe "where there are multiple lines selected", -> - it "moves the selected lines down", -> - editor.setSelectedBufferRange([[2, 0], [3, Infinity]]) - editor.trigger 'editor:move-line-down' - expect(buffer.lineForRow(2)).toBe ' while(items.length > 0) {' - expect(buffer.lineForRow(3)).toBe ' if (items.length <= 1) return items;' - expect(buffer.lineForRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];' - expect(buffer.lineForRow(5)).toBe ' current = items.shift();' - - it "maintains the selection", -> - editor.setSelectedBufferRange([[2, 0], [3, 62]]) - editor.trigger 'editor:move-line-down' - expect(editor.getSelectedBufferRange()).toEqual [[3, 0], [4, 62]] - - describe "when the cursor is on a folded line", -> - it "moves all lines in the fold down and preserves the fold", -> - editor.setCursorBufferPosition([4, 0]) - editor.foldCurrentRow() - editor.trigger 'editor:move-line-down' - expect(buffer.lineForRow(4)).toBe ' return sort(left).concat(pivot).concat(sort(right));' - expect(buffer.lineForRow(5)).toBe ' while(items.length > 0) {' - expect(editor.getSelectedBufferRange()).toEqual [[5, 0], [5, 0]] - expect(editor.isFoldedAtScreenRow(5)).toBeTruthy() - - describe "when the selection contains a folded and unfolded line", -> - it "moves the selected lines down and preserves the fold", -> - editor.setCursorBufferPosition([4, 0]) - editor.foldCurrentRow() - editor.setCursorBufferPosition([3, 4]) - editor.selectDown() - expect(editor.isFoldedAtScreenRow(4)).toBeTruthy() - editor.trigger 'editor:move-line-down' - expect(buffer.lineForRow(3)).toBe ' return sort(left).concat(pivot).concat(sort(right));' - expect(buffer.lineForRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];' - expect(buffer.lineForRow(5)).toBe ' while(items.length > 0) {' - expect(editor.getSelectedBufferRange()).toEqual [[4, 4], [5, 0]] - expect(editor.isFoldedAtScreenRow(5)).toBeTruthy() - - describe "when an entire line is selected including the newline", -> - it "moves the selected line down", -> - editor.setCursorBufferPosition([1]) - editor.selectToEndOfLine() - editor.selectRight() - editor.trigger 'editor:move-line-down' - expect(buffer.lineForRow(1)).toBe ' if (items.length <= 1) return items;' - expect(buffer.lineForRow(2)).toBe ' var sort = function(items) {' - - describe "when editor:duplicate-line is triggered", -> - describe "where there is no selection", -> - describe "when the cursor isn't on a folded line", -> - it "duplicates the current line below and moves the cursor down one row", -> - editor.setCursorBufferPosition([0, 5]) - editor.trigger 'editor:duplicate-line' - expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {' - expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {' - expect(editor.getCursorBufferPosition()).toEqual [1, 5] - - describe "when the cursor is on a folded line", -> - it "duplicates the entire fold before and moves the cursor to the new fold", -> - editor.setCursorBufferPosition([4]) - editor.foldCurrentRow() - editor.trigger 'editor:duplicate-line' - expect(editor.getCursorScreenPosition()).toEqual [5] - expect(editor.isFoldedAtScreenRow(4)).toBeTruthy() - expect(editor.isFoldedAtScreenRow(5)).toBeTruthy() - expect(buffer.lineForRow(8)).toBe ' while(items.length > 0) {' - expect(buffer.lineForRow(9)).toBe ' current = items.shift();' - expect(buffer.lineForRow(10)).toBe ' current < pivot ? left.push(current) : right.push(current);' - expect(buffer.lineForRow(11)).toBe ' }' - - describe "when the cursor is on the last line and it doesn't have a trailing newline", -> - it "inserts a newline and the duplicated line", -> - editor.moveCursorToBottom() - editor.trigger 'editor:duplicate-line' - expect(buffer.lineForRow(12)).toBe '};' - expect(buffer.lineForRow(13)).toBe '};' - expect(buffer.lineForRow(14)).toBeUndefined() - expect(editor.getCursorBufferPosition()).toEqual [13, 2] - - describe "when the cursor in on the last line and it is only a newline", -> - it "duplicates the current line below and moves the cursor down one row", -> - editor.moveCursorToBottom() - editor.insertNewline() - editor.moveCursorToBottom() - editor.trigger 'editor:duplicate-line' - expect(buffer.lineForRow(13)).toBe '' - expect(buffer.lineForRow(14)).toBe '' - expect(buffer.lineForRow(15)).toBeUndefined() - expect(editor.getCursorBufferPosition()).toEqual [14, 0] - - describe "when the cursor is on the second to last line and the last line only a newline", -> - it "duplicates the current line below and moves the cursor down one row", -> - editor.moveCursorToBottom() - editor.insertNewline() - editor.setCursorBufferPosition([12]) - editor.trigger 'editor:duplicate-line' - expect(buffer.lineForRow(12)).toBe '};' - expect(buffer.lineForRow(13)).toBe '};' - expect(buffer.lineForRow(14)).toBe '' - expect(buffer.lineForRow(15)).toBeUndefined() - expect(editor.getCursorBufferPosition()).toEqual [13, 0] - - describe "editor:save-debug-snapshot", -> - it "saves the state of the rendered lines, the display buffer, and the buffer to a file of the user's choosing", -> - saveDialogCallback = null - spyOn(atom, 'showSaveDialog').andCallFake (callback) -> saveDialogCallback = callback - spyOn(fs, 'writeFileSync') - - editor.trigger 'editor:save-debug-snapshot' - - statePath = path.join(temp.dir, 'state') - expect(atom.showSaveDialog).toHaveBeenCalled() - saveDialogCallback(statePath) - expect(fs.writeFileSync).toHaveBeenCalled() - expect(fs.writeFileSync.argsForCall[0][0]).toBe statePath - expect(typeof fs.writeFileSync.argsForCall[0][1]).toBe 'string' - - describe "when the escape key is pressed on the editor", -> - it "clears multiple selections if there are any, and otherwise allows other bindings to be handled", -> - keymap.bindKeys 'name', '.editor', 'escape': 'test-event' - testEventHandler = jasmine.createSpy("testEventHandler") - - editor.on 'test-event', testEventHandler - editor.activeEditSession.addSelectionForBufferRange([[3, 0], [3, 0]]) - expect(editor.activeEditSession.getSelections().length).toBe 2 - - editor.trigger(keydownEvent('escape')) - expect(editor.activeEditSession.getSelections().length).toBe 1 - expect(testEventHandler).not.toHaveBeenCalled() - - editor.trigger(keydownEvent('escape')) - expect(testEventHandler).toHaveBeenCalled() - - describe "when the editor is attached but invisible", -> - describe "when the editor's text is changed", -> - it "redraws the editor when it is next shown", -> - window.rootView = new RootView - rootView.openSync('sample.js') - rootView.attachToDom() - editor = rootView.getActiveView() - - view = $$ -> @div id: 'view', tabindex: -1, 'View' - editor.getPane().showItem(view) - expect(editor.isVisible()).toBeFalsy() - - editor.setText('hidden changes') - editor.setCursorBufferPosition([0,4]) - - displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler") - editor.on 'editor:display-updated', displayUpdatedHandler - editor.getPane().showItem(editor.getModel()) - expect(editor.isVisible()).toBeTruthy() - - waitsFor -> - displayUpdatedHandler.callCount is 1 - - runs -> - expect(editor.renderedLines.find('.line').text()).toBe 'hidden changes' - - it "redraws the editor when it is next reattached", -> - editor.attachToDom() - editor.hide() - editor.setText('hidden changes') - editor.setCursorBufferPosition([0,4]) - editor.detach() - - displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler") - editor.on 'editor:display-updated', displayUpdatedHandler - editor.show() - editor.attachToDom() - - waitsFor -> - displayUpdatedHandler.callCount is 1 - - runs -> - expect(editor.renderedLines.find('.line').text()).toBe 'hidden changes' - - describe "editor:scroll-to-cursor", -> - it "scrolls to and centers the editor on the cursor's position", -> - editor.attachToDom(heightInLines: 3) - editor.setCursorBufferPosition([1, 2]) - editor.scrollToBottom() - expect(editor.getFirstVisibleScreenRow()).not.toBe 0 - expect(editor.getLastVisibleScreenRow()).not.toBe 2 - editor.trigger('editor:scroll-to-cursor') - expect(editor.getFirstVisibleScreenRow()).toBe 0 - expect(editor.getLastVisibleScreenRow()).toBe 2 - - describe "when the editor is removed", -> - it "fires a editor:will-be-removed event", -> - window.rootView = new RootView - rootView.openSync('sample.js') - rootView.attachToDom() - editor = rootView.getActiveView() - - willBeRemovedHandler = jasmine.createSpy('fileChange') - editor.on 'editor:will-be-removed', willBeRemovedHandler - editor.getPane().destroyActiveItem() - expect(willBeRemovedHandler).toHaveBeenCalled() - - describe "when setInvisibles is toggled (regression)", -> - it "renders inserted newlines properly", -> - editor.setShowInvisibles(true) - editor.setCursorBufferPosition([0, 0]) - editor.attachToDom(heightInLines: 20) - editor.setShowInvisibles(false) - editor.insertText("\n") - - for rowNumber in [1..5] - expect(editor.lineElementForScreenRow(rowNumber).text()).toBe buffer.lineForRow(rowNumber) - - describe "when the window is resized", -> - it "updates the active edit session with the current soft wrap column", -> - editor.attachToDom() - setEditorWidthInChars(editor, 50) - expect(editor.activeEditSession.getSoftWrapColumn()).toBe 50 - setEditorWidthInChars(editor, 100) - $(window).trigger 'resize' - expect(editor.activeEditSession.getSoftWrapColumn()).toBe 100 diff --git a/src/cursor.coffee b/src/cursor.coffee index dcf3d6429..83c42ffb4 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -5,7 +5,7 @@ _ = require 'underscore-plus' # Public: The `Cursor` class represents the little blinking line identifying # where text can be inserted. # -# Cursors belong to {TextEditor}s and have some metadata attached in the form +# Cursors belong to {Editor}s and have some metadata attached in the form # of a {StringMarker}. module.exports = class Cursor @@ -17,7 +17,7 @@ class Cursor visible: true needsAutoscroll: null - # Private: Instantiated by an {TextEditor} + # Private: Instantiated by an {Editor} constructor: ({@editSession, @marker}) -> @updateVisibility() @marker.on 'changed', (e) => @@ -62,7 +62,7 @@ class Cursor # An {Array} of two numbers: the screen row, and the screen column. # * options: # + autoscroll: - # A Boolean which, if `true`, scrolls the {TextEditor} to wherever the + # A Boolean which, if `true`, scrolls the {Editor} to wherever the # cursor moves to. setScreenPosition: (screenPosition, options={}) -> @changePosition options, => @@ -78,7 +78,7 @@ class Cursor # An {Array} of two numbers: the buffer row, and the buffer column. # * options: # + autoscroll: - # A Boolean which, if `true`, scrolls the {TextEditor} to wherever the + # A Boolean which, if `true`, scrolls the {Editor} to wherever the # cursor moves to. setBufferPosition: (bufferPosition, options={}) -> @changePosition options, => @@ -118,7 +118,7 @@ class Cursor segments.push("[#{_.escapeRegExp(nonWordCharacters)}]+") new RegExp(segments.join("|"), "g") - # Public: Identifies if this cursor is the last in the {TextEditor}. + # Public: Identifies if this cursor is the last in the {Editor}. # # "Last" is defined as the most recently added cursor. # diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 28aeba67d..bd466424f 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -1721,7 +1721,7 @@ class EditorView extends View # Copies the current file path to the native clipboard. copyPathToPasteboard: -> path = @getPath() - pasteboard.write(path) if path? + atom.pasteboard.write(path) if path? ### Internal ### diff --git a/src/text-editor.coffee b/src/editor.coffee similarity index 98% rename from src/text-editor.coffee rename to src/editor.coffee index 80cfa2be9..5ec620cf9 100644 --- a/src/text-editor.coffee +++ b/src/editor.coffee @@ -12,18 +12,18 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # Public: The core model of Atom. # -# An {TextEditor} represents a unique view of each document, with it's own +# An {Editor} represents a unique view of each document, with it's own # {Cursor}s and scroll position. # -# For instance if a user creates a split, Atom creates a second {TextEditor} -# but both {TextEditor}s interact with the same buffer underlying buffer. So +# For instance if a user creates a split, Atom creates a second {Editor} +# but both {Editor}s interact with the same buffer underlying buffer. So # if you type in either buffer it immediately appears in both but if you scroll # in one it doesn't scroll the other. # # Almost all extension will interact primiarily with this class as it provides # access to objects you'll most commonly interact with. To access it you'll # want to register a callback on {RootView} which will be fired once for every -# existing {TextEditor} as well as any future {TextEditor}s. +# existing {Editor} as well as any future {Editor}s. # # ## Example # ```coffeescript @@ -36,7 +36,7 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # FIXME: Describe how there are both local and remote cursors and selections and # why that is. module.exports = -class TextEditor +class Editor Emitter.includeInto(this) Subscriber.includeInto(this) @@ -47,7 +47,7 @@ class TextEditor @version: 5 @deserialize: (state) -> - new TextEditor(state) + new Editor(state) id: null languageMode: null @@ -131,7 +131,7 @@ class TextEditor # Private: getViewClass: -> - require './text-editor-view' + require './editor-view' # Private: destroy: -> @@ -152,12 +152,12 @@ class TextEditor # Private: getState: -> @state - # Private: Creates an {TextEditor} with the same initial state + # Private: Creates an {Editor} with the same initial state copy: -> tabLength = @getTabLength() displayBuffer = @displayBuffer.copy() softTabs = @getSoftTabs() - newEditSession = new TextEditor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true}) + newEditSession = new Editor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true}) newEditSession.setScrollTop(@getScrollTop()) newEditSession.setScrollLeft(@getScrollLeft()) for marker in @findMarkers(editSessionId: @id) @@ -190,7 +190,7 @@ class TextEditor else 'untitled' - # Public: Compares two `TextEditor`s to determine equality. + # Public: Compares two `Editor`s to determine equality. # # Equality is based on the condition that: # @@ -200,7 +200,7 @@ class TextEditor # # Returns a {Boolean}. isEqual: (other) -> - return false unless other instanceof TextEditor + return false unless other instanceof Editor @buffer == other.buffer and @getScrollTop() == other.getScrollTop() and @getScrollLeft() == other.getScrollLeft() and @@ -876,7 +876,7 @@ class TextEditor @emit 'cursor-added', cursor cursor - # Public: Removes and returns a cursor from the `TextEditor`. + # Public: Removes and returns a cursor from the `Editor`. removeCursor: (cursor) -> _.remove(@cursors, cursor) diff --git a/src/gutter.coffee b/src/gutter.coffee index 040c244ba..710200473 100644 --- a/src/gutter.coffee +++ b/src/gutter.coffee @@ -2,7 +2,7 @@ {Range} = require 'telepath' _ = require 'underscore-plus' -# Private: Represents the portion of the {TextEditorView} containing row numbers. +# Private: Represents the portion of the {EditorView} containing row numbers. # # The gutter also indicates if rows are folded. module.exports = @@ -52,9 +52,9 @@ class Gutter extends View ### Public ### - # Retrieves the containing {TextEditorView}. + # Retrieves the containing {EditorView}. # - # Returns an {TextEditorView}. + # Returns an {EditorView}. getEditorView: -> @parentView diff --git a/src/language-mode.coffee b/src/language-mode.coffee index 194e32099..32e7c6719 100644 --- a/src/language-mode.coffee +++ b/src/language-mode.coffee @@ -22,9 +22,9 @@ class LanguageMode ### Public ### - # Sets up a `LanguageMode` for the given {TextEditor}. + # Sets up a `LanguageMode` for the given {Editor}. # - # editSession - The {TextEditor} to associate with + # editSession - The {Editor} to associate with constructor: (@editSession) -> @buffer = @editSession.buffer diff --git a/src/pane.coffee b/src/pane.coffee index b91ed926e..a33c7388b 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -7,7 +7,7 @@ PaneColumn = require './pane-column' # Public: A container which can contains multiple items to be switched between. # -# Items can be almost anything however most commonly they're {TextEditorView}s. +# Items can be almost anything however most commonly they're {EditorView}s. # # Most packages won't need to use this class, unless you're interested in # building a package that deals with switching between panes or tiems. diff --git a/src/project.coffee b/src/project.coffee index df17e5bad..0071be769 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -7,7 +7,7 @@ Q = require 'q' telepath = require 'telepath' TextBuffer = require './text-buffer' -TextEditor = require './text-editor' +Editor = require './editor' {Emitter} = require 'emissary' Directory = require './directory' Task = require './task' @@ -133,14 +133,14 @@ class Project extends telepath.Model @rootDirectory?.contains(pathToCheck) ? false # Public: Given a path to a file, this constructs and associates a new - # {TextEditor}, showing the file. + # {Editor}, showing the file. # # * filePath: # The {String} path of the file to associate with # * editSessionOptions: - # Options that you can pass to the {TextEditor} constructor + # Options that you can pass to the {Editor} constructor # - # Returns a promise that resolves to an {TextEditor}. + # Returns a promise that resolves to an {Editor}. open: (filePath, options={}) -> filePath = @resolve(filePath) resource = null @@ -160,18 +160,18 @@ class Project extends telepath.Model @buildEditSessionForBuffer(@bufferForPathSync(filePath), options) - # Public: Retrieves all {TextEditor}s for all open files. + # Public: Retrieves all {Editor}s for all open files. # - # Returns an {Array} of {TextEditor}s. + # Returns an {Array} of {Editor}s. getEditSessions: -> new Array(@editSessions...) - # Public: Add the given {TextEditor}. + # Public: Add the given {Editor}. addEditSession: (editSession) -> @editSessions.push editSession @emit 'edit-session-created', editSession - # Public: Return and removes the given {TextEditor}. + # Public: Return and removes the given {Editor}. removeEditSession: (editSession) -> _.remove(@editSessions, editSession) @@ -332,7 +332,7 @@ class Project extends telepath.Model # Private: buildEditSessionForBuffer: (buffer, editSessionOptions) -> - editSession = new TextEditor(_.extend({buffer}, editSessionOptions)) + editSession = new Editor(_.extend({buffer}, editSessionOptions)) @addEditSession(editSession) editSession diff --git a/src/root-view.coffee b/src/root-view.coffee index b9556eaaa..73c232882 100644 --- a/src/root-view.coffee +++ b/src/root-view.coffee @@ -5,12 +5,12 @@ Q = require 'q' _ = require 'underscore-plus' fs = require 'fs-plus' telepath = require 'telepath' -TextEditorView = require './text-editor-view' +EditorView = require './editor-view' Pane = require './pane' PaneColumn = require './pane-column' PaneRow = require './pane-row' PaneContainer = require './pane-container' -TextEditor = require './text-editor' +Editor = require './editor' # Public: The container for the entire Atom application. # @@ -38,7 +38,7 @@ TextEditor = require './text-editor' # module.exports = class RootView extends View - registerDeserializers(this, Pane, PaneRow, PaneColumn, TextEditorView) + registerDeserializers(this, Pane, PaneRow, PaneColumn, EditorView) @version: 1 @@ -169,7 +169,7 @@ class RootView extends View # * options # + initialLine: The buffer line number to open to. # - # Returns a promise that resolves to the {TextEditor} for the file URI. + # Returns a promise that resolves to the {Editor} for the file URI. open: (filePath, options={}) -> changeFocus = options.changeFocus ? true filePath = project.resolve(filePath) @@ -249,7 +249,7 @@ class RootView extends View setTitle: (title) -> document.title = title - # Private: Returns an Array of all of the application's {TextEditorView}s. + # Private: Returns an Array of all of the application's {EditorView}s. getEditors: -> @panes.find('.pane > .item-views > .editor').map(-> $(this).view()).toArray() @@ -259,7 +259,7 @@ class RootView extends View getModifiedBuffers: -> modifiedBuffers = [] for pane in @getPanes() - for item in pane.getItems() when item instanceof TextEditor + for item in pane.getItems() when item instanceof Editor modifiedBuffers.push item.buffer if item.buffer.isModified() modifiedBuffers @@ -308,14 +308,14 @@ class RootView extends View indexOfPane: (pane) -> @panes.indexOfPane(pane) - # Private: Fires a callback on each open {TextEditorView}. + # Private: Fires a callback on each open {EditorView}. eachEditor: (callback) -> callback(editor) for editor in @getEditors() attachedCallback = (e, editor) -> callback(editor) @on('editor:attached', attachedCallback) off: => @off('editor:attached', attachedCallback) - # Public: Fires a callback on each open {TextEditor}. + # Public: Fires a callback on each open {Editor}. eachEditSession: (callback) -> project.eachEditSession(callback) diff --git a/src/select-list.coffee b/src/select-list.coffee index aafe2ca58..3c858758d 100644 --- a/src/select-list.coffee +++ b/src/select-list.coffee @@ -1,5 +1,5 @@ {$, View} = require './space-pen-extensions' -TextEditorView = require './text-editor-view' +EditorView = require './editor-view' fuzzyFilter = require('fuzzaldrin').filter # Public: Provides a widget for users to make a selection from a list of @@ -10,7 +10,7 @@ class SelectList extends View # Private: @content: -> @div class: @viewClass(), => - @subview 'miniEditor', new TextEditorView(mini: true) + @subview 'miniEditor', new EditorView(mini: true) @div class: 'error-message', outlet: 'error' @div class: 'loading', outlet: 'loadingArea', => @span class: 'loading-message', outlet: 'loading' diff --git a/src/selection.coffee b/src/selection.coffee index e42864209..6e3315c98 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -2,7 +2,7 @@ {Emitter} = require 'emissary' {pick} = require 'underscore-plus' -# Public: Represents a selection in the {TextEditor}. +# Public: Represents a selection in the {Editor}. module.exports = class Selection Emitter.includeInto(this) @@ -79,7 +79,7 @@ class Selection # + preserveFolds: # if `true`, the fold settings are preserved after the selection moves # + autoscroll: - # if `true`, the {TextEditor} scrolls to the new selection + # if `true`, the {Editor} scrolls to the new selection setBufferRange: (bufferRange, options={}) -> bufferRange = Range.fromObject(bufferRange) @needsAutoscroll = options.autoscroll @@ -361,7 +361,7 @@ class Selection # * options - A hash with one key, # + autoIndent: # If `true`, the indentation is performed appropriately. Otherwise, - # {TextEditor.getTabText} is used + # {Editor.getTabText} is used indent: ({ autoIndent }={})-> { row, column } = @cursor.getBufferPosition() diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index e91d059e8..e90c836fb 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -126,12 +126,12 @@ class TextBuffer extends telepath.Model # Identifies if the buffer belongs to multiple editors. # - # For example, if the {TextEditorView} was split. + # For example, if the {EditorView} was split. # # Returns a {Boolean}. hasMultipleEditors: -> @refcount > 1 - # Reloads a file in the {TextEditor}. + # Reloads a file in the {Editor}. # # Sets the buffer's content to the cached disk contents reload: -> diff --git a/src/text-editor-view.coffee b/src/text-editor-view.coffee deleted file mode 100644 index 1086bde85..000000000 --- a/src/text-editor-view.coffee +++ /dev/null @@ -1,1853 +0,0 @@ -{View, $, $$} = require './space-pen-extensions' -TextBuffer = require './text-buffer' -Gutter = require './gutter' -{Point, Range} = require 'telepath' -TextEditor = require './text-editor' -CursorView = require './cursor-view' -SelectionView = require './selection-view' -fs = require 'fs-plus' -_ = require 'underscore-plus' - -MeasureRange = document.createRange() -TextNodeFilter = { acceptNode: -> NodeFilter.FILTER_ACCEPT } -NoScope = ['no-scope'] -LongLineLength = 1000 - -# Private: Represents the entire visual pane in Atom. -# -# The TextEditorView manages the {TextEditor}, which manages the file buffers. -module.exports = -class TextEditorView extends View - @characterWidthCache: {} - @configDefaults: - fontSize: 20 - showInvisibles: false - showIndentGuide: false - showLineNumbers: true - autoIndent: true - normalizeIndentOnPaste: true - nonWordCharacters: "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`~?-" - preferredLineLength: 80 - tabLength: 2 - softWrap: false - softTabs: true - softWrapAtPreferredLineLength: false - - @nextEditorId: 1 - - ### Internal ### - - @content: (params) -> - attributes = { class: @classes(params), tabindex: -1 } - _.extend(attributes, params.attributes) if params.attributes - @div attributes, => - @subview 'gutter', new Gutter - @div class: 'scroll-view', outlet: 'scrollView', => - @div class: 'overlayer', outlet: 'overlayer' - @div class: 'lines', outlet: 'renderedLines' - @div class: 'underlayer', outlet: 'underlayer', => - @input class: 'hidden-input', outlet: 'hiddenInput' - @div class: 'vertical-scrollbar', outlet: 'verticalScrollbar', => - @div outlet: 'verticalScrollbarContent' - - @classes: ({mini} = {}) -> - classes = ['editor', 'editor-colors'] - classes.push 'mini' if mini - classes.join(' ') - - vScrollMargin: 2 - hScrollMargin: 10 - lineHeight: null - charWidth: null - charHeight: null - cursorViews: null - selectionViews: null - lineCache: null - isFocused: false - activeEditSession: null - attached: false - lineOverdraw: 10 - pendingChanges: null - newCursors: null - newSelections: null - redrawOnReattach: false - bottomPaddingInLines: 10 - - ### Public ### - - # The constructor for setting up an `TextEditorView` instance. - # - # editSessionOrOptions - Either an {TextEditor}, or an object with one property, `mini`. - # If `mini` is `true`, a "miniature" `TextEditor` is constructed. - # Typically, this is ideal for scenarios where you need an Atom editor, - # but without all the chrome, like scrollbars, gutter, _e.t.c._. - # - initialize: (editSessionOrOptions) -> - if editSessionOrOptions instanceof TextEditor - editSession = editSessionOrOptions - else - {editSession, @mini} = editSessionOrOptions ? {} - - @id = TextEditorView.nextEditorId++ - @lineCache = [] - @configure() - @bindKeys() - @handleEvents() - @handleInputEvents() - @cursorViews = [] - @selectionViews = [] - @pendingChanges = [] - @newCursors = [] - @newSelections = [] - - if editSession? - @edit(editSession) - else if @mini - @edit(new TextEditor - buffer: TextBuffer.createAsRoot() - softWrap: false - tabLength: 2 - softTabs: true - ) - else - throw new Error("Must supply an TextEditor or mini: true") - - # Internal: Sets up the core Atom commands. - # - # Some commands are excluded from mini-editors. - bindKeys: -> - editorBindings = - 'core:move-left': @moveCursorLeft - 'core:move-right': @moveCursorRight - 'core:select-left': @selectLeft - 'core:select-right': @selectRight - 'core:select-all': @selectAll - 'core:backspace': @backspace - 'core:delete': @delete - 'core:undo': @undo - 'core:redo': @redo - 'core:cut': @cutSelection - 'core:copy': @copySelection - 'core:paste': @paste - 'editor:move-to-previous-word': @moveCursorToPreviousWord - 'editor:select-word': @selectWord - 'editor:consolidate-selections': @consolidateSelections - 'editor:backspace-to-beginning-of-word': @backspaceToBeginningOfWord - 'editor:backspace-to-beginning-of-line': @backspaceToBeginningOfLine - 'editor:delete-to-end-of-word': @deleteToEndOfWord - 'editor:delete-line': @deleteLine - 'editor:cut-to-end-of-line': @cutToEndOfLine - 'editor:move-to-beginning-of-line': @moveCursorToBeginningOfLine - 'editor:move-to-end-of-line': @moveCursorToEndOfLine - 'editor:move-to-first-character-of-line': @moveCursorToFirstCharacterOfLine - 'editor:move-to-beginning-of-word': @moveCursorToBeginningOfWord - 'editor:move-to-end-of-word': @moveCursorToEndOfWord - 'editor:move-to-beginning-of-next-word': @moveCursorToBeginningOfNextWord - 'editor:move-to-previous-word-boundary': @moveCursorToPreviousWordBoundary - 'editor:move-to-next-word-boundary': @moveCursorToNextWordBoundary - 'editor:select-to-end-of-line': @selectToEndOfLine - 'editor:select-to-beginning-of-line': @selectToBeginningOfLine - 'editor:select-to-end-of-word': @selectToEndOfWord - 'editor:select-to-beginning-of-word': @selectToBeginningOfWord - 'editor:select-to-beginning-of-next-word': @selectToBeginningOfNextWord - 'editor:select-to-next-word-boundary': @selectToNextWordBoundary - 'editor:select-to-previous-word-boundary': @selectToPreviousWordBoundary - 'editor:select-to-first-character-of-line': @selectToFirstCharacterOfLine - 'editor:select-line': @selectLine - 'editor:transpose': @transpose - 'editor:upper-case': @upperCase - 'editor:lower-case': @lowerCase - - unless @mini - _.extend editorBindings, - 'core:move-up': @moveCursorUp - 'core:move-down': @moveCursorDown - 'core:move-to-top': @moveCursorToTop - 'core:move-to-bottom': @moveCursorToBottom - 'core:page-down': @pageDown - 'core:page-up': @pageUp - 'core:select-up': @selectUp - 'core:select-down': @selectDown - 'core:select-to-top': @selectToTop - 'core:select-to-bottom': @selectToBottom - 'editor:indent': @indent - 'editor:auto-indent': @autoIndent - 'editor:indent-selected-rows': @indentSelectedRows - 'editor:outdent-selected-rows': @outdentSelectedRows - 'editor:newline': @insertNewline - 'editor:newline-below': @insertNewlineBelow - 'editor:newline-above': @insertNewlineAbove - 'editor:add-selection-below': @addSelectionBelow - 'editor:add-selection-above': @addSelectionAbove - 'editor:toggle-soft-tabs': @toggleSoftTabs - 'editor:toggle-soft-wrap': @toggleSoftWrap - 'editor:fold-all': @foldAll - 'editor:unfold-all': @unfoldAll - 'editor:fold-current-row': @foldCurrentRow - 'editor:unfold-current-row': @unfoldCurrentRow - 'editor:fold-selection': @foldSelection - 'editor:fold-at-indent-level-1': => @foldAllAtIndentLevel(0) - 'editor:fold-at-indent-level-2': => @foldAllAtIndentLevel(1) - 'editor:fold-at-indent-level-3': => @foldAllAtIndentLevel(2) - 'editor:fold-at-indent-level-4': => @foldAllAtIndentLevel(3) - 'editor:fold-at-indent-level-5': => @foldAllAtIndentLevel(4) - 'editor:fold-at-indent-level-6': => @foldAllAtIndentLevel(5) - 'editor:fold-at-indent-level-7': => @foldAllAtIndentLevel(6) - 'editor:fold-at-indent-level-8': => @foldAllAtIndentLevel(7) - 'editor:fold-at-indent-level-9': => @foldAllAtIndentLevel(8) - 'editor:toggle-line-comments': @toggleLineCommentsInSelection - 'editor:log-cursor-scope': @logCursorScope - 'editor:checkout-head-revision': @checkoutHead - 'editor:copy-path': @copyPathToPasteboard - 'editor:move-line-up': @moveLineUp - 'editor:move-line-down': @moveLineDown - 'editor:duplicate-line': @duplicateLine - 'editor:join-line': @joinLine - 'editor:toggle-indent-guide': => atom.config.toggle('editor.showIndentGuide') - 'editor:save-debug-snapshot': @saveDebugSnapshot - 'editor:toggle-line-numbers': => atom.config.toggle('editor.showLineNumbers') - 'editor:scroll-to-cursor': @scrollToCursorPosition - - documentation = {} - for name, method of editorBindings - do (name, method) => - @command name, (e) => method.call(this, e); false - - # {Delegates to: TextEditor.getCursor} - getCursor: -> @activeEditSession.getCursor() - - # {Delegates to: TextEditor.getCursors} - getCursors: -> @activeEditSession.getCursors() - - # {Delegates to: TextEditor.addCursorAtScreenPosition} - addCursorAtScreenPosition: (screenPosition) -> @activeEditSession.addCursorAtScreenPosition(screenPosition) - - # {Delegates to: TextEditor.addCursorAtBufferPosition} - addCursorAtBufferPosition: (bufferPosition) -> @activeEditSession.addCursorAtBufferPosition(bufferPosition) - - # {Delegates to: TextEditor.moveCursorUp} - moveCursorUp: -> @activeEditSession.moveCursorUp() - - # {Delegates to: TextEditor.moveCursorDown} - moveCursorDown: -> @activeEditSession.moveCursorDown() - - # {Delegates to: TextEditor.moveCursorLeft} - moveCursorLeft: -> @activeEditSession.moveCursorLeft() - - # {Delegates to: TextEditor.moveCursorRight} - moveCursorRight: -> @activeEditSession.moveCursorRight() - - # {Delegates to: TextEditor.moveCursorToBeginningOfWord} - moveCursorToBeginningOfWord: -> @activeEditSession.moveCursorToBeginningOfWord() - - # {Delegates to: TextEditor.moveCursorToEndOfWord} - moveCursorToEndOfWord: -> @activeEditSession.moveCursorToEndOfWord() - - # {Delegates to: TextEditor.moveCursorToBeginningOfNextWord} - moveCursorToBeginningOfNextWord: -> @activeEditSession.moveCursorToBeginningOfNextWord() - - # {Delegates to: TextEditor.moveCursorToTop} - moveCursorToTop: -> @activeEditSession.moveCursorToTop() - - # {Delegates to: TextEditor.moveCursorToBottom} - moveCursorToBottom: -> @activeEditSession.moveCursorToBottom() - - # {Delegates to: TextEditor.moveCursorToBeginningOfLine} - moveCursorToBeginningOfLine: -> @activeEditSession.moveCursorToBeginningOfLine() - - # {Delegates to: TextEditor.moveCursorToFirstCharacterOfLine} - moveCursorToFirstCharacterOfLine: -> @activeEditSession.moveCursorToFirstCharacterOfLine() - - # {Delegates to: TextEditor.moveCursorToPreviousWordBoundary} - moveCursorToPreviousWordBoundary: -> @activeEditSession.moveCursorToPreviousWordBoundary() - - # {Delegates to: TextEditor.moveCursorToNextWordBoundary} - moveCursorToNextWordBoundary: -> @activeEditSession.moveCursorToNextWordBoundary() - - # {Delegates to: TextEditor.moveCursorToEndOfLine} - moveCursorToEndOfLine: -> @activeEditSession.moveCursorToEndOfLine() - - # {Delegates to: TextEditor.moveLineUp} - moveLineUp: -> @activeEditSession.moveLineUp() - - # {Delegates to: TextEditor.moveLineDown} - moveLineDown: -> @activeEditSession.moveLineDown() - - # {Delegates to: TextEditor.setCursorScreenPosition} - setCursorScreenPosition: (position, options) -> @activeEditSession.setCursorScreenPosition(position, options) - - # {Delegates to: TextEditor.duplicateLine} - duplicateLine: -> @activeEditSession.duplicateLine() - - # {Delegates to: TextEditor.joinLine} - joinLine: -> @activeEditSession.joinLine() - - # {Delegates to: TextEditor.getCursorScreenPosition} - getCursorScreenPosition: -> @activeEditSession.getCursorScreenPosition() - - # {Delegates to: TextEditor.getCursorScreenRow} - getCursorScreenRow: -> @activeEditSession.getCursorScreenRow() - - # {Delegates to: TextEditor.setCursorBufferPosition} - setCursorBufferPosition: (position, options) -> @activeEditSession.setCursorBufferPosition(position, options) - - # {Delegates to: TextEditor.getCursorBufferPosition} - getCursorBufferPosition: -> @activeEditSession.getCursorBufferPosition() - - # {Delegates to: TextEditor.getCurrentParagraphBufferRange} - getCurrentParagraphBufferRange: -> @activeEditSession.getCurrentParagraphBufferRange() - - # {Delegates to: TextEditor.getWordUnderCursor} - getWordUnderCursor: (options) -> @activeEditSession.getWordUnderCursor(options) - - # {Delegates to: TextEditor.getSelection} - getSelection: (index) -> @activeEditSession.getSelection(index) - - # {Delegates to: TextEditor.getSelections} - getSelections: -> @activeEditSession.getSelections() - - # {Delegates to: TextEditor.getSelectionsOrderedByBufferPosition} - getSelectionsOrderedByBufferPosition: -> @activeEditSession.getSelectionsOrderedByBufferPosition() - - # {Delegates to: TextEditor.getLastSelectionInBuffer} - getLastSelectionInBuffer: -> @activeEditSession.getLastSelectionInBuffer() - - # {Delegates to: TextEditor.getSelectedText} - getSelectedText: -> @activeEditSession.getSelectedText() - - # {Delegates to: TextEditor.getSelectedBufferRanges} - getSelectedBufferRanges: -> @activeEditSession.getSelectedBufferRanges() - - # {Delegates to: TextEditor.getSelectedBufferRange} - getSelectedBufferRange: -> @activeEditSession.getSelectedBufferRange() - - # {Delegates to: TextEditor.setSelectedBufferRange} - setSelectedBufferRange: (bufferRange, options) -> @activeEditSession.setSelectedBufferRange(bufferRange, options) - - # {Delegates to: TextEditor.setSelectedBufferRanges} - setSelectedBufferRanges: (bufferRanges, options) -> @activeEditSession.setSelectedBufferRanges(bufferRanges, options) - - # {Delegates to: TextEditor.addSelectionForBufferRange} - addSelectionForBufferRange: (bufferRange, options) -> @activeEditSession.addSelectionForBufferRange(bufferRange, options) - - # {Delegates to: TextEditor.selectRight} - selectRight: -> @activeEditSession.selectRight() - - # {Delegates to: TextEditor.selectLeft} - selectLeft: -> @activeEditSession.selectLeft() - - # {Delegates to: TextEditor.selectUp} - selectUp: -> @activeEditSession.selectUp() - - # {Delegates to: TextEditor.selectDown} - selectDown: -> @activeEditSession.selectDown() - - # {Delegates to: TextEditor.selectToTop} - selectToTop: -> @activeEditSession.selectToTop() - - # {Delegates to: TextEditor.selectToBottom} - selectToBottom: -> @activeEditSession.selectToBottom() - - # {Delegates to: TextEditor.selectAll} - selectAll: -> @activeEditSession.selectAll() - - # {Delegates to: TextEditor.selectToBeginningOfLine} - selectToBeginningOfLine: -> @activeEditSession.selectToBeginningOfLine() - - # {Delegates to: TextEditor.selectToFirstCharacterOfLine} - selectToFirstCharacterOfLine: -> @activeEditSession.selectToFirstCharacterOfLine() - - # {Delegates to: TextEditor.selectToEndOfLine} - selectToEndOfLine: -> @activeEditSession.selectToEndOfLine() - - # {Delegates to: TextEditor.selectToPreviousWordBoundary} - selectToPreviousWordBoundary: -> @activeEditSession.selectToPreviousWordBoundary() - - # {Delegates to: TextEditor.selectToNextWordBoundary} - selectToNextWordBoundary: -> @activeEditSession.selectToNextWordBoundary() - - # {Delegates to: TextEditor.addSelectionBelow} - addSelectionBelow: -> @activeEditSession.addSelectionBelow() - - # {Delegates to: TextEditor.addSelectionAbove} - addSelectionAbove: -> @activeEditSession.addSelectionAbove() - - # {Delegates to: TextEditor.selectToBeginningOfWord} - selectToBeginningOfWord: -> @activeEditSession.selectToBeginningOfWord() - - # {Delegates to: TextEditor.selectToEndOfWord} - selectToEndOfWord: -> @activeEditSession.selectToEndOfWord() - - # {Delegates to: TextEditor.selectToBeginningOfNextWord} - selectToBeginningOfNextWord: -> @activeEditSession.selectToBeginningOfNextWord() - - # {Delegates to: TextEditor.selectWord} - selectWord: -> @activeEditSession.selectWord() - - # {Delegates to: TextEditor.selectLine} - selectLine: -> @activeEditSession.selectLine() - - # {Delegates to: TextEditor.selectToScreenPosition} - selectToScreenPosition: (position) -> @activeEditSession.selectToScreenPosition(position) - - # {Delegates to: TextEditor.transpose} - transpose: -> @activeEditSession.transpose() - - # {Delegates to: TextEditor.upperCase} - upperCase: -> @activeEditSession.upperCase() - - # {Delegates to: TextEditor.lowerCase} - lowerCase: -> @activeEditSession.lowerCase() - - # {Delegates to: TextEditor.clearSelections} - clearSelections: -> @activeEditSession.clearSelections() - - # {Delegates to: TextEditor.backspace} - backspace: -> @activeEditSession.backspace() - - # {Delegates to: TextEditor.backspaceToBeginningOfWord} - backspaceToBeginningOfWord: -> @activeEditSession.backspaceToBeginningOfWord() - - # {Delegates to: TextEditor.backspaceToBeginningOfLine} - backspaceToBeginningOfLine: -> @activeEditSession.backspaceToBeginningOfLine() - - # {Delegates to: TextEditor.delete} - delete: -> @activeEditSession.delete() - - # {Delegates to: TextEditor.deleteToEndOfWord} - deleteToEndOfWord: -> @activeEditSession.deleteToEndOfWord() - - # {Delegates to: TextEditor.deleteLine} - deleteLine: -> @activeEditSession.deleteLine() - - # {Delegates to: TextEditor.cutToEndOfLine} - cutToEndOfLine: -> @activeEditSession.cutToEndOfLine() - - # {Delegates to: TextEditor.insertText} - insertText: (text, options) -> @activeEditSession.insertText(text, options) - - # {Delegates to: TextEditor.insertNewline} - insertNewline: -> @activeEditSession.insertNewline() - - # {Delegates to: TextEditor.insertNewlineBelow} - insertNewlineBelow: -> @activeEditSession.insertNewlineBelow() - - # {Delegates to: TextEditor.insertNewlineAbove} - insertNewlineAbove: -> @activeEditSession.insertNewlineAbove() - - # {Delegates to: TextEditor.indent} - indent: (options) -> @activeEditSession.indent(options) - - # {Delegates to: TextEditor.autoIndentSelectedRows} - autoIndent: (options) -> @activeEditSession.autoIndentSelectedRows() - - # {Delegates to: TextEditor.indentSelectedRows} - indentSelectedRows: -> @activeEditSession.indentSelectedRows() - - # {Delegates to: TextEditor.outdentSelectedRows} - outdentSelectedRows: -> @activeEditSession.outdentSelectedRows() - - # {Delegates to: TextEditor.cutSelectedText} - cutSelection: -> @activeEditSession.cutSelectedText() - - # {Delegates to: TextEditor.copySelectedText} - copySelection: -> @activeEditSession.copySelectedText() - - # {Delegates to: TextEditor.pasteText} - paste: (options) -> @activeEditSession.pasteText(options) - - # {Delegates to: TextEditor.undo} - undo: -> @activeEditSession.undo() - - # {Delegates to: TextEditor.redo} - redo: -> @activeEditSession.redo() - - # {Delegates to: TextEditor.createFold} - createFold: (startRow, endRow) -> @activeEditSession.createFold(startRow, endRow) - - # {Delegates to: TextEditor.foldCurrentRow} - foldCurrentRow: -> @activeEditSession.foldCurrentRow() - - # {Delegates to: TextEditor.unfoldCurrentRow} - unfoldCurrentRow: -> @activeEditSession.unfoldCurrentRow() - - # {Delegates to: TextEditor.foldAll} - foldAll: -> @activeEditSession.foldAll() - - # {Delegates to: TextEditor.unfoldAll} - unfoldAll: -> @activeEditSession.unfoldAll() - - # {Delegates to: TextEditor.foldSelection} - foldSelection: -> @activeEditSession.foldSelection() - - # {Delegates to: TextEditor.destroyFoldsContainingBufferRow} - destroyFoldsContainingBufferRow: (bufferRow) -> @activeEditSession.destroyFoldsContainingBufferRow(bufferRow) - - # {Delegates to: TextEditor.isFoldedAtScreenRow} - isFoldedAtScreenRow: (screenRow) -> @activeEditSession.isFoldedAtScreenRow(screenRow) - - # {Delegates to: TextEditor.isFoldedAtBufferRow} - isFoldedAtBufferRow: (bufferRow) -> @activeEditSession.isFoldedAtBufferRow(bufferRow) - - # {Delegates to: TextEditor.isFoldedAtCursorRow} - isFoldedAtCursorRow: -> @activeEditSession.isFoldedAtCursorRow() - - foldAllAtIndentLevel: (indentLevel) -> @activeEditSession.foldAllAtIndentLevel(indentLevel) - - # {Delegates to: TextEditor.lineForScreenRow} - lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow) - - # {Delegates to: TextEditor.linesForScreenRows} - linesForScreenRows: (start, end) -> @activeEditSession.linesForScreenRows(start, end) - - # {Delegates to: TextEditor.getScreenLineCount} - getScreenLineCount: -> @activeEditSession.getScreenLineCount() - - # Private: - setHeightInLines: (heightInLines)-> - heightInLines ?= @calculateHeightInLines() - @heightInLines = heightInLines if heightInLines - - # {Delegates to: TextEditor.setEditorWidthInChars} - setWidthInChars: (widthInChars) -> - widthInChars ?= @calculateWidthInChars() - @activeEditSession.setEditorWidthInChars(widthInChars) if widthInChars - - # {Delegates to: TextEditor.getMaxScreenLineLength} - getMaxScreenLineLength: -> @activeEditSession.getMaxScreenLineLength() - - # {Delegates to: TextEditor.getLastScreenRow} - getLastScreenRow: -> @activeEditSession.getLastScreenRow() - - # {Delegates to: TextEditor.clipScreenPosition} - clipScreenPosition: (screenPosition, options={}) -> @activeEditSession.clipScreenPosition(screenPosition, options) - - # {Delegates to: TextEditor.screenPositionForBufferPosition} - screenPositionForBufferPosition: (position, options) -> @activeEditSession.screenPositionForBufferPosition(position, options) - - # {Delegates to: TextEditor.bufferPositionForScreenPosition} - bufferPositionForScreenPosition: (position, options) -> @activeEditSession.bufferPositionForScreenPosition(position, options) - - # {Delegates to: TextEditor.screenRangeForBufferRange} - screenRangeForBufferRange: (range) -> @activeEditSession.screenRangeForBufferRange(range) - - # {Delegates to: TextEditor.bufferRangeForScreenRange} - bufferRangeForScreenRange: (range) -> @activeEditSession.bufferRangeForScreenRange(range) - - # {Delegates to: TextEditor.bufferRowsForScreenRows} - bufferRowsForScreenRows: (startRow, endRow) -> @activeEditSession.bufferRowsForScreenRows(startRow, endRow) - - # Public: Emulates the "page down" key, where the last row of a buffer scrolls to become the first. - pageDown: -> - newScrollTop = @scrollTop() + @scrollView[0].clientHeight - @activeEditSession.moveCursorDown(@getPageRows()) - @scrollTop(newScrollTop, adjustVerticalScrollbar: true) - - # Public: Emulates the "page up" key, where the frst row of a buffer scrolls to become the last. - pageUp: -> - newScrollTop = @scrollTop() - @scrollView[0].clientHeight - @activeEditSession.moveCursorUp(@getPageRows()) - @scrollTop(newScrollTop, adjustVerticalScrollbar: true) - - # Gets the number of actual page rows existing in an editor. - # - # Returns a {Number}. - getPageRows: -> - Math.max(1, Math.ceil(@scrollView[0].clientHeight / @lineHeight)) - - # Set whether invisible characters are shown. - # - # showInvisibles - A {Boolean} which, if `true`, show invisible characters - setShowInvisibles: (showInvisibles) -> - return if showInvisibles == @showInvisibles - @showInvisibles = showInvisibles - @resetDisplay() - - # Defines which characters are invisible. - # - # invisibles - A hash defining the invisible characters: The defaults are: - # eol: `\u00ac` - # space: `\u00b7` - # tab: `\u00bb` - # cr: `\u00a4` - setInvisibles: (@invisibles={}) -> - _.defaults @invisibles, - eol: '\u00ac' - space: '\u00b7' - tab: '\u00bb' - cr: '\u00a4' - @resetDisplay() - - # Sets whether you want to show the indentation guides. - # - # showIndentGuide - A {Boolean} you can set to `true` if you want to see the indentation guides. - setShowIndentGuide: (showIndentGuide) -> - return if showIndentGuide == @showIndentGuide - @showIndentGuide = showIndentGuide - @resetDisplay() - - # Checkout the HEAD revision of this editor's file. - checkoutHead: -> - if path = @getPath() - atom.project.getRepo()?.checkoutHead(path) - - # {Delegates to: TextEditor.setText} - setText: (text) -> @activeEditSession.setText(text) - - # {Delegates to: TextEditor.getText} - getText: -> @activeEditSession.getText() - - # {Delegates to: TextEditor.getPath} - getPath: -> @activeEditSession?.getPath() - - # {Delegates to: TextBuffer.getLineCount} - getLineCount: -> @getBuffer().getLineCount() - - # {Delegates to: TextBuffer.getLastRow} - getLastBufferRow: -> @getBuffer().getLastRow() - - # {Delegates to: TextBuffer.getTextInRange} - getTextInRange: (range) -> @getBuffer().getTextInRange(range) - - # {Delegates to: TextBuffer.getEofPosition} - getEofPosition: -> @getBuffer().getEofPosition() - - # {Delegates to: TextBuffer.lineForRow} - lineForBufferRow: (row) -> @getBuffer().lineForRow(row) - - # {Delegates to: TextBuffer.lineLengthForRow} - lineLengthForBufferRow: (row) -> @getBuffer().lineLengthForRow(row) - - # {Delegates to: TextBuffer.rangeForRow} - rangeForBufferRow: (row) -> @getBuffer().rangeForRow(row) - - # {Delegates to: TextBuffer.scanInRange} - scanInBufferRange: (args...) -> @getBuffer().scanInRange(args...) - - # {Delegates to: TextBuffer.backwardsScanInRange} - backwardsScanInBufferRange: (args...) -> @getBuffer().backwardsScanInRange(args...) - - ### Internal ### - - configure: -> - @observeConfig 'editor.showLineNumbers', (showLineNumbers) => @gutter.setShowLineNumbers(showLineNumbers) - @observeConfig 'editor.showInvisibles', (showInvisibles) => @setShowInvisibles(showInvisibles) - @observeConfig 'editor.showIndentGuide', (showIndentGuide) => @setShowIndentGuide(showIndentGuide) - @observeConfig 'editor.invisibles', (invisibles) => @setInvisibles(invisibles) - @observeConfig 'editor.fontSize', (fontSize) => @setFontSize(fontSize) - @observeConfig 'editor.fontFamily', (fontFamily) => @setFontFamily(fontFamily) - - handleEvents: -> - @on 'focus', => - @hiddenInput.focus() - false - - @hiddenInput.on 'focus', => - @bringHiddenInputIntoView() - @isFocused = true - @addClass 'is-focused' - - @hiddenInput.on 'focusout', => - @bringHiddenInputIntoView() - @isFocused = false - @removeClass 'is-focused' - - @underlayer.on 'mousedown', (e) => - @renderedLines.trigger(e) - false if @isFocused - - @overlayer.on 'mousedown', (e) => - @overlayer.hide() - clickedElement = document.elementFromPoint(e.pageX, e.pageY) - @overlayer.show() - e.target = clickedElement - $(clickedElement).trigger(e) - false if @isFocused - - @renderedLines.on 'mousedown', '.fold.line', (e) => - id = $(e.currentTarget).attr('fold-id') - marker = @activeEditSession.displayBuffer.getMarker(id) - @activeEditSession.setCursorBufferPosition(marker.getBufferRange().start) - @activeEditSession.destroyFoldWithId(id) - false - - @renderedLines.on 'mousedown', (e) => - clickCount = e.originalEvent.detail - - screenPosition = @screenPositionFromMouseEvent(e) - if clickCount == 1 - if e.metaKey - @addCursorAtScreenPosition(screenPosition) - else if e.shiftKey - @selectToScreenPosition(screenPosition) - else - @setCursorScreenPosition(screenPosition) - else if clickCount == 2 - @activeEditSession.selectWord() unless e.shiftKey - else if clickCount == 3 - @activeEditSession.selectLine() unless e.shiftKey - - @selectOnMousemoveUntilMouseup() unless e.ctrlKey or e.originalEvent.which > 1 - - unless @mini - @scrollView.on 'mousewheel', (e) => - if delta = e.originalEvent.wheelDeltaY - @scrollTop(@scrollTop() - delta) - false - - @verticalScrollbar.on 'scroll', => - @scrollTop(@verticalScrollbar.scrollTop(), adjustVerticalScrollbar: false) - - @scrollView.on 'scroll', => - if @scrollLeft() == 0 - @gutter.removeClass('drop-shadow') - else - @gutter.addClass('drop-shadow') - - # Listen for overflow events to detect when the editor's width changes - # to update the soft wrap column. - updateWidthInChars = _.debounce((=> @setWidthInChars()), 100) - @scrollView.on 'overflowchanged', => - updateWidthInChars() if @[0].classList.contains('soft-wrap') - - handleInputEvents: -> - @on 'cursor:moved', => - return unless @isFocused - cursorView = @getCursorView() - - if cursorView.isVisible() - # This is an order of magnitude faster than checking .offset(). - style = cursorView[0].style - @hiddenInput[0].style.top = style.top - @hiddenInput[0].style.left = style.left - - selectedText = null - @hiddenInput.on 'compositionstart', => - selectedText = @getSelectedText() - @hiddenInput.css('width', '100%') - @hiddenInput.on 'compositionupdate', (e) => - @insertText(e.originalEvent.data, {select: true, undo: 'skip'}) - @hiddenInput.on 'compositionend', => - @insertText(selectedText, {select: true, undo: 'skip'}) - @hiddenInput.css('width', '1px') - - lastInput = '' - @on "textInput", (e) => - # Work around of the accented character suggestion feature in OS X. - selectedLength = @hiddenInput[0].selectionEnd - @hiddenInput[0].selectionStart - if selectedLength is 1 and lastInput is @hiddenInput.val() - @selectLeft() - - lastInput = e.originalEvent.data - @insertText(lastInput) - @hiddenInput.val(lastInput) - false - - bringHiddenInputIntoView: -> - @hiddenInput.css(top: @scrollTop(), left: @scrollLeft()) - - selectOnMousemoveUntilMouseup: -> - lastMoveEvent = null - moveHandler = (event = lastMoveEvent) => - if event - @selectToScreenPosition(@screenPositionFromMouseEvent(event)) - lastMoveEvent = event - - $(document).on "mousemove.editor-#{@id}", moveHandler - interval = setInterval(moveHandler, 20) - - $(document).one "mouseup.editor-#{@id}", => - clearInterval(interval) - $(document).off 'mousemove', moveHandler - @activeEditSession.mergeIntersectingSelections(isReversed: @activeEditSession.getLastSelection().isReversed()) - @activeEditSession.finalizeSelections() - @syncCursorAnimations() - - afterAttach: (onDom) -> - return unless onDom - @redraw() if @redrawOnReattach - return if @attached - @attached = true - @calculateDimensions() - @setWidthInChars() - @subscribe $(window), "resize.editor-#{@id}", => - @setHeightInLines() - @setWidthInChars() - @updateLayerDimensions() - @requestDisplayUpdate() - @focus() if @isFocused - - if pane = @getPane() - @active = @is(pane.activeView) - @subscribe pane, 'pane:active-item-changed', (event, item) => - wasActive = @active - @active = @is(pane.activeView) - @redraw() if @active and not wasActive - - @resetDisplay() - - @trigger 'editor:attached', [this] - - edit: (editSession) -> - return if editSession is @activeEditSession - - if @activeEditSession - @saveScrollPositionForActiveEditSession() - @activeEditSession.off(".editor") - - @activeEditSession = editSession - - return unless @activeEditSession? - - @activeEditSession.setVisible(true) - - @activeEditSession.on "contents-conflicted.editor", => - @showBufferConflictAlert(@activeEditSession) - - @activeEditSession.on "path-changed.editor", => - @reloadGrammar() - @trigger 'editor:path-changed' - - @activeEditSession.on "grammar-changed.editor", => - @trigger 'editor:grammar-changed' - - @activeEditSession.on 'selection-added.editor', (selection) => - @newCursors.push(selection.cursor) - @newSelections.push(selection) - @requestDisplayUpdate() - - @activeEditSession.on 'screen-lines-changed.editor', (e) => - @handleScreenLinesChange(e) - - @activeEditSession.on 'scroll-top-changed.editor', (scrollTop) => - @scrollTop(scrollTop) - - @activeEditSession.on 'scroll-left-changed.editor', (scrollLeft) => - @scrollLeft(scrollLeft) - - @activeEditSession.on 'soft-wrap-changed.editor', (softWrap) => - @setSoftWrap(softWrap) - - @trigger 'editor:path-changed' - @resetDisplay() - - if @attached and @activeEditSession.buffer.isInConflict() - _.defer => @showBufferConflictAlert(@activeEditSession) # Display after editSession has a chance to display - - getModel: -> - @activeEditSession - - setModel: (editSession) -> - @edit(editSession) - - showBufferConflictAlert: (editSession) -> - atom.confirm( - editSession.getPath(), - "Has changed on disk. Do you want to reload it?", - "Reload", (=> editSession.buffer.reload()), - "Cancel" - ) - - scrollTop: (scrollTop, options={}) -> - return @cachedScrollTop or 0 unless scrollTop? - maxScrollTop = @verticalScrollbar.prop('scrollHeight') - @verticalScrollbar.height() - scrollTop = Math.floor(Math.max(0, Math.min(maxScrollTop, scrollTop))) - return if scrollTop == @cachedScrollTop - @cachedScrollTop = scrollTop - - @updateDisplay() if @attached - - @renderedLines.css('top', -scrollTop) - @underlayer.css('top', -scrollTop) - @overlayer.css('top', -scrollTop) - @gutter.lineNumbers.css('top', -scrollTop) - - if options?.adjustVerticalScrollbar ? true - @verticalScrollbar.scrollTop(scrollTop) - @activeEditSession.setScrollTop(@scrollTop()) - - scrollBottom: (scrollBottom) -> - if scrollBottom? - @scrollTop(scrollBottom - @scrollView.height()) - else - @scrollTop() + @scrollView.height() - - scrollLeft: (scrollLeft) -> - if scrollLeft? - @scrollView.scrollLeft(scrollLeft) - @activeEditSession.setScrollLeft(@scrollLeft()) - else - @scrollView.scrollLeft() - - scrollRight: (scrollRight) -> - if scrollRight? - @scrollView.scrollRight(scrollRight) - @activeEditSession.setScrollLeft(@scrollLeft()) - else - @scrollView.scrollRight() - - ### Public ### - - # Retrieves the {TextEditor}'s buffer. - # - # Returns the current {TextBuffer}. - getBuffer: -> @activeEditSession.buffer - - # Scrolls the editor to the bottom. - scrollToBottom: -> - @scrollBottom(@getScreenLineCount() * @lineHeight) - - # Scrolls the editor to the position of the most recently added cursor. - # - # The editor is also centered. - scrollToCursorPosition: -> - @scrollToBufferPosition(@getCursorBufferPosition(), center: true) - - # Scrolls the editor to the given buffer position. - # - # bufferPosition - An object that represents a buffer position. It can be either - # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # options - A hash matching the options available to {.scrollToPixelPosition} - scrollToBufferPosition: (bufferPosition, options) -> - @scrollToPixelPosition(@pixelPositionForBufferPosition(bufferPosition), options) - - # Scrolls the editor to the given screen position. - # - # screenPosition - An object that represents a buffer position. It can be either - # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # options - A hash matching the options available to {.scrollToPixelPosition} - scrollToScreenPosition: (screenPosition, options) -> - @scrollToPixelPosition(@pixelPositionForScreenPosition(screenPosition), options) - - # Scrolls the editor to the given pixel position. - # - # pixelPosition - An object that represents a pixel position. It can be either - # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # options - A hash with the following keys: - # center: if `true`, the position is scrolled such that it's in the center of the editor - scrollToPixelPosition: (pixelPosition, options) -> - return unless @attached - @scrollVertically(pixelPosition, options) - @scrollHorizontally(pixelPosition) - - # Highlight all the folds within the given buffer range. - # - # "Highlighting" essentially just adds the `fold-selected` class to the line's - # DOM element. - # - # bufferRange - The {Range} to check. - highlightFoldsContainingBufferRange: (bufferRange) -> - screenLines = @linesForScreenRows(@firstRenderedScreenRow, @lastRenderedScreenRow) - for screenLine, i in screenLines - if fold = screenLine.fold - screenRow = @firstRenderedScreenRow + i - element = @lineElementForScreenRow(screenRow) - - if bufferRange.intersectsWith(fold.getBufferRange()) - element.addClass('fold-selected') - else - element.removeClass('fold-selected') - - saveScrollPositionForActiveEditSession: -> - if @attached - @activeEditSession.setScrollTop(@scrollTop()) - @activeEditSession.setScrollLeft(@scrollLeft()) - - # Toggle soft tabs on the edit session. - toggleSoftTabs: -> - @activeEditSession.setSoftTabs(not @activeEditSession.getSoftTabs()) - - # Toggle soft wrap on the edit session. - toggleSoftWrap: -> - @setWidthInChars() - @activeEditSession.setSoftWrap(not @activeEditSession.getSoftWrap()) - - calculateWidthInChars: -> - Math.floor(@scrollView.width() / @charWidth) - - calculateHeightInLines: -> - Math.ceil($(window).height() / @lineHeight) - - # Enables/disables soft wrap on the editor. - # - # softWrap - A {Boolean} which, if `true`, enables soft wrap - setSoftWrap: (softWrap) -> - if softWrap - @addClass 'soft-wrap' - @scrollLeft(0) - else - @removeClass 'soft-wrap' - - # Sets the font size for the editor. - # - # fontSize - A {Number} indicating the font size in pixels. - setFontSize: (fontSize) -> - @css('font-size', "#{fontSize}px}") - - @clearCharacterWidthCache() - - if @isOnDom() - @redraw() - else - @redrawOnReattach = @attached - - # Retrieves the font size for the editor. - # - # Returns a {Number} indicating the font size in pixels. - getFontSize: -> - parseInt(@css("font-size")) - - # Sets the font family for the editor. - # - # fontFamily - A {String} identifying the CSS `font-family`, - setFontFamily: (fontFamily='') -> - @css('font-family', fontFamily) - - @clearCharacterWidthCache() - - @redraw() - - # Gets the font family for the editor. - # - # Returns a {String} identifying the CSS `font-family`, - getFontFamily: -> @css("font-family") - - # Redraw the editor - redraw: -> - return unless @hasParent() - return unless @attached - @redrawOnReattach = false - @calculateDimensions() - @updatePaddingOfRenderedLines() - @updateLayerDimensions() - @requestDisplayUpdate() - - splitLeft: -> - pane = @getPane() - pane?.splitLeft(pane?.copyActiveItem()).activeView - - splitRight: -> - pane = @getPane() - pane?.splitRight(pane?.copyActiveItem()).activeView - - splitUp: -> - pane = @getPane() - pane?.splitUp(pane?.copyActiveItem()).activeView - - splitDown: -> - pane = @getPane() - pane?.splitDown(pane?.copyActiveItem()).activeView - - # Retrieve's the `TextEditorView`'s pane. - # - # Returns a {Pane}. - getPane: -> - @parent('.item-views').parent('.pane').view() - - remove: (selector, keepData) -> - return super if keepData or @removed - super - rootView?.focus() - - beforeRemove: -> - @trigger 'editor:will-be-removed' - @removed = true - @activeEditSession?.destroy() - $(window).off(".editor-#{@id}") - $(document).off(".editor-#{@id}") - - getCursorView: (index) -> - index ?= @cursorViews.length - 1 - @cursorViews[index] - - getCursorViews: -> - new Array(@cursorViews...) - - addCursorView: (cursor, options) -> - cursorView = new CursorView(cursor, this, options) - @cursorViews.push(cursorView) - @overlayer.append(cursorView) - cursorView - - removeCursorView: (cursorView) -> - _.remove(@cursorViews, cursorView) - - getSelectionView: (index) -> - index ?= @selectionViews.length - 1 - @selectionViews[index] - - getSelectionViews: -> - new Array(@selectionViews...) - - addSelectionView: (selection) -> - selectionView = new SelectionView({editor: this, selection}) - @selectionViews.push(selectionView) - @underlayer.append(selectionView) - selectionView - - removeSelectionView: (selectionView) -> - _.remove(@selectionViews, selectionView) - - removeAllCursorAndSelectionViews: -> - cursorView.remove() for cursorView in @getCursorViews() - selectionView.remove() for selectionView in @getSelectionViews() - - appendToLinesView: (view) -> - @overlayer.append(view) - - ### Internal ### - - # Scrolls the editor vertically to a given position. - scrollVertically: (pixelPosition, {center}={}) -> - scrollViewHeight = @scrollView.height() - scrollTop = @scrollTop() - scrollBottom = scrollTop + scrollViewHeight - - if center - unless scrollTop < pixelPosition.top < scrollBottom - @scrollTop(pixelPosition.top - (scrollViewHeight / 2)) - else - linesInView = @scrollView.height() / @lineHeight - maxScrollMargin = Math.floor((linesInView - 1) / 2) - scrollMargin = Math.min(@vScrollMargin, maxScrollMargin) - margin = scrollMargin * @lineHeight - desiredTop = pixelPosition.top - margin - desiredBottom = pixelPosition.top + @lineHeight + margin - if desiredBottom > scrollBottom - @scrollTop(desiredBottom - scrollViewHeight) - else if desiredTop < scrollTop - @scrollTop(desiredTop) - - # Scrolls the editor horizontally to a given position. - scrollHorizontally: (pixelPosition) -> - return if @activeEditSession.getSoftWrap() - - charsInView = @scrollView.width() / @charWidth - maxScrollMargin = Math.floor((charsInView - 1) / 2) - scrollMargin = Math.min(@hScrollMargin, maxScrollMargin) - margin = scrollMargin * @charWidth - desiredRight = pixelPosition.left + @charWidth + margin - desiredLeft = pixelPosition.left - margin - - if desiredRight > @scrollRight() - @scrollRight(desiredRight) - else if desiredLeft < @scrollLeft() - @scrollLeft(desiredLeft) - @saveScrollPositionForActiveEditSession() - - calculateDimensions: -> - fragment = $('') - @renderedLines.append(fragment) - - lineRect = fragment[0].getBoundingClientRect() - charRect = fragment.find('span')[0].getBoundingClientRect() - @lineHeight = lineRect.height - @charWidth = charRect.width - @charHeight = charRect.height - fragment.remove() - @setHeightInLines() - - updateLayerDimensions: -> - height = @lineHeight * @getScreenLineCount() - unless @layerHeight == height - @layerHeight = height - @underlayer.height(@layerHeight) - @renderedLines.height(@layerHeight) - @overlayer.height(@layerHeight) - @verticalScrollbarContent.height(@layerHeight) - @scrollBottom(height) if @scrollBottom() > height - - minWidth = Math.max(@charWidth * @getMaxScreenLineLength() + 20, @scrollView.width()) - unless @layerMinWidth == minWidth - @renderedLines.css('min-width', minWidth) - @underlayer.css('min-width', minWidth) - @overlayer.css('min-width', minWidth) - @layerMinWidth = minWidth - @trigger 'editor:min-width-changed' - - # Override for speed. The base function checks computedStyle, unnecessary here. - isHidden: -> - style = this[0].style - if style.display == 'none' or not @isOnDom() - true - else - false - - clearRenderedLines: -> - @renderedLines.empty() - @firstRenderedScreenRow = null - @lastRenderedScreenRow = null - - resetDisplay: -> - return unless @attached - - @clearRenderedLines() - @removeAllCursorAndSelectionViews() - editSessionScrollTop = @activeEditSession.getScrollTop() ? 0 - editSessionScrollLeft = @activeEditSession.getScrollLeft() ? 0 - @updateLayerDimensions() - @scrollTop(editSessionScrollTop) - @scrollLeft(editSessionScrollLeft) - @setSoftWrap(@activeEditSession.getSoftWrap()) - @newCursors = @activeEditSession.getAllCursors() - @newSelections = @activeEditSession.getAllSelections() - @updateDisplay(suppressAutoScroll: true) - - requestDisplayUpdate: -> - return if @pendingDisplayUpdate - return unless @isVisible() - @pendingDisplayUpdate = true - setImmediate => - @updateDisplay() - @pendingDisplayUpdate = false - - updateDisplay: (options={}) -> - return unless @attached and @activeEditSession - return if @activeEditSession.destroyed - unless @isOnDom() and @isVisible() - @redrawOnReattach = true - return - - @updateRenderedLines() - @highlightCursorLine() - @updateCursorViews() - @updateSelectionViews() - @autoscroll(options) - @trigger 'editor:display-updated' - - updateCursorViews: -> - if @newCursors.length > 0 - @addCursorView(cursor) for cursor in @newCursors when not cursor.destroyed - @syncCursorAnimations() - @newCursors = [] - - for cursorView in @getCursorViews() - if cursorView.needsRemoval - cursorView.remove() - else if @shouldUpdateCursor(cursorView) - cursorView.updateDisplay() - - shouldUpdateCursor: (cursorView) -> - return false unless cursorView.needsUpdate - - pos = cursorView.getScreenPosition() - pos.row >= @firstRenderedScreenRow and pos.row <= @lastRenderedScreenRow - - updateSelectionViews: -> - if @newSelections.length > 0 - @addSelectionView(selection) for selection in @newSelections when not selection.destroyed - @newSelections = [] - - for selectionView in @getSelectionViews() - if selectionView.needsRemoval - selectionView.remove() - else if @shouldUpdateSelection(selectionView) - selectionView.updateDisplay() - - shouldUpdateSelection: (selectionView) -> - screenRange = selectionView.getScreenRange() - startRow = screenRange.start.row - endRow = screenRange.end.row - (startRow >= @firstRenderedScreenRow and startRow <= @lastRenderedScreenRow) or # startRow in range - (endRow >= @firstRenderedScreenRow and endRow <= @lastRenderedScreenRow) or # endRow in range - (startRow <= @firstRenderedScreenRow and endRow >= @lastRenderedScreenRow) # selection surrounds the rendered items - - syncCursorAnimations: -> - for cursorView in @getCursorViews() - do (cursorView) -> cursorView.resetBlinking() - - autoscroll: (options={}) -> - for cursorView in @getCursorViews() - if !options.suppressAutoScroll and cursorView.needsAutoscroll() - @scrollToPixelPosition(cursorView.getPixelPosition()) - cursorView.clearAutoscroll() - - for selectionView in @getSelectionViews() - if !options.suppressAutoScroll and selectionView.needsAutoscroll() - @scrollToPixelPosition(selectionView.getCenterPixelPosition(), center: true) - selectionView.highlight() - selectionView.clearAutoscroll() - - updateRenderedLines: -> - firstVisibleScreenRow = @getFirstVisibleScreenRow() - lastScreenRowToRender = firstVisibleScreenRow + @heightInLines - 1 - lastScreenRow = @getLastScreenRow() - - if @firstRenderedScreenRow? and firstVisibleScreenRow >= @firstRenderedScreenRow and lastScreenRowToRender <= @lastRenderedScreenRow - renderFrom = Math.min(lastScreenRow, @firstRenderedScreenRow) - renderTo = Math.min(lastScreenRow, @lastRenderedScreenRow) - else - renderFrom = Math.min(lastScreenRow, Math.max(0, firstVisibleScreenRow - @lineOverdraw)) - renderTo = Math.min(lastScreenRow, lastScreenRowToRender + @lineOverdraw) - - if @pendingChanges.length == 0 and @firstRenderedScreenRow and @firstRenderedScreenRow <= renderFrom and renderTo <= @lastRenderedScreenRow - return - - changes = @pendingChanges - intactRanges = @computeIntactRanges(renderFrom, renderTo) - - @gutter.updateLineNumbers(changes, renderFrom, renderTo) - - @clearDirtyRanges(intactRanges) - @fillDirtyRanges(intactRanges, renderFrom, renderTo) - @firstRenderedScreenRow = renderFrom - @lastRenderedScreenRow = renderTo - @updateLayerDimensions() - @updatePaddingOfRenderedLines() - - computeSurroundingEmptyLineChanges: (change) -> - emptyLineChanges = [] - - if change.bufferDelta? - afterStart = change.end + change.bufferDelta + 1 - if @lineForBufferRow(afterStart) is '' - afterEnd = afterStart - afterEnd++ while @lineForBufferRow(afterEnd + 1) is '' - emptyLineChanges.push({start: afterStart, end: afterEnd, screenDelta: 0}) - - beforeEnd = change.start - 1 - if @lineForBufferRow(beforeEnd) is '' - beforeStart = beforeEnd - beforeStart-- while @lineForBufferRow(beforeStart - 1) is '' - emptyLineChanges.push({start: beforeStart, end: beforeEnd, screenDelta: 0}) - - emptyLineChanges - - computeIntactRanges: (renderFrom, renderTo) -> - return [] if !@firstRenderedScreenRow? and !@lastRenderedScreenRow? - - intactRanges = [{start: @firstRenderedScreenRow, end: @lastRenderedScreenRow, domStart: 0}] - - if not @mini and @showIndentGuide - emptyLineChanges = [] - for change in @pendingChanges - emptyLineChanges.push(@computeSurroundingEmptyLineChanges(change)...) - @pendingChanges.push(emptyLineChanges...) - - for change in @pendingChanges - newIntactRanges = [] - for range in intactRanges - if change.end < range.start and change.screenDelta != 0 - newIntactRanges.push( - start: range.start + change.screenDelta - end: range.end + change.screenDelta - domStart: range.domStart - ) - else if change.end < range.start or change.start > range.end - newIntactRanges.push(range) - else - if change.start > range.start - newIntactRanges.push( - start: range.start - end: change.start - 1 - domStart: range.domStart) - if change.end < range.end - newIntactRanges.push( - start: change.end + change.screenDelta + 1 - end: range.end + change.screenDelta - domStart: range.domStart + change.end + 1 - range.start - ) - intactRanges = newIntactRanges - - @truncateIntactRanges(intactRanges, renderFrom, renderTo) - - @pendingChanges = [] - - intactRanges - - truncateIntactRanges: (intactRanges, renderFrom, renderTo) -> - i = 0 - while i < intactRanges.length - range = intactRanges[i] - if range.start < renderFrom - range.domStart += renderFrom - range.start - range.start = renderFrom - if range.end > renderTo - range.end = renderTo - if range.start >= range.end - intactRanges.splice(i--, 1) - i++ - intactRanges.sort (a, b) -> a.domStart - b.domStart - - clearDirtyRanges: (intactRanges) -> - if intactRanges.length == 0 - @renderedLines[0].innerHTML = '' - else if currentLine = @renderedLines[0].firstChild - domPosition = 0 - for intactRange in intactRanges - while intactRange.domStart > domPosition - currentLine = @clearLine(currentLine) - domPosition++ - for i in [intactRange.start..intactRange.end] - currentLine = currentLine.nextSibling - domPosition++ - while currentLine - currentLine = @clearLine(currentLine) - - clearLine: (lineElement) -> - next = lineElement.nextSibling - @renderedLines[0].removeChild(lineElement) - next - - fillDirtyRanges: (intactRanges, renderFrom, renderTo) -> - i = 0 - nextIntact = intactRanges[i] - currentLine = @renderedLines[0].firstChild - - row = renderFrom - while row <= renderTo - if row == nextIntact?.end + 1 - nextIntact = intactRanges[++i] - - if !nextIntact or row < nextIntact.start - if nextIntact - dirtyRangeEnd = nextIntact.start - 1 - else - dirtyRangeEnd = renderTo - - for lineElement in @buildLineElementsForScreenRows(row, dirtyRangeEnd) - @renderedLines[0].insertBefore(lineElement, currentLine) - row++ - else - currentLine = currentLine.nextSibling - row++ - - updatePaddingOfRenderedLines: -> - paddingTop = @firstRenderedScreenRow * @lineHeight - @renderedLines.css('padding-top', paddingTop) - @gutter.lineNumbers.css('padding-top', paddingTop) - - paddingBottom = (@getLastScreenRow() - @lastRenderedScreenRow) * @lineHeight - @renderedLines.css('padding-bottom', paddingBottom) - @gutter.lineNumbers.css('padding-bottom', paddingBottom) - - ### Public ### - - # Retrieves the number of the row that is visible and currently at the top of the editor. - # - # Returns a {Number}. - getFirstVisibleScreenRow: -> - screenRow = Math.floor(@scrollTop() / @lineHeight) - screenRow = 0 if isNaN(screenRow) - screenRow - - # Retrieves the number of the row that is visible and currently at the bottom of the editor. - # - # Returns a {Number}. - getLastVisibleScreenRow: -> - calculatedRow = Math.ceil((@scrollTop() + @scrollView.height()) / @lineHeight) - 1 - screenRow = Math.max(0, Math.min(@getScreenLineCount() - 1, calculatedRow)) - screenRow = 0 if isNaN(screenRow) - screenRow - - # Given a row number, identifies if it is currently visible. - # - # row - A row {Number} to check - # - # Returns a {Boolean}. - isScreenRowVisible: (row) -> - @getFirstVisibleScreenRow() <= row <= @getLastVisibleScreenRow() - - ### Internal ### - - handleScreenLinesChange: (change) -> - @pendingChanges.push(change) - @requestDisplayUpdate() - - buildLineElementForScreenRow: (screenRow) -> - @buildLineElementsForScreenRows(screenRow, screenRow)[0] - - buildLineElementsForScreenRows: (startRow, endRow) -> - div = document.createElement('div') - div.innerHTML = @htmlForScreenRows(startRow, endRow) - new Array(div.children...) - - htmlForScreenRows: (startRow, endRow) -> - htmlLines = '' - screenRow = startRow - for line in @activeEditSession.linesForScreenRows(startRow, endRow) - htmlLines += @htmlForScreenLine(line, screenRow++) - htmlLines - - htmlForScreenLine: (screenLine, screenRow) -> - { tokens, text, lineEnding, fold, isSoftWrapped } = screenLine - if fold - attributes = { class: 'fold line', 'fold-id': fold.id } - else - attributes = { class: 'line' } - - invisibles = @invisibles if @showInvisibles - eolInvisibles = @getEndOfLineInvisibles(screenLine) - htmlEolInvisibles = @buildHtmlEndOfLineInvisibles(screenLine) - - indentation = TextEditorView.buildIndentation(screenRow, @activeEditSession) - - TextEditorView.buildLineHtml({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, @showIndentGuide, indentation, @activeEditSession, @mini}) - - @buildIndentation: (screenRow, activeEditSession) -> - bufferRow = activeEditSession.bufferPositionForScreenPosition([screenRow]).row - bufferLine = activeEditSession.lineForBufferRow(bufferRow) - if bufferLine is '' - indentation = 0 - nextRow = screenRow + 1 - while nextRow < activeEditSession.getBuffer().getLineCount() - bufferRow = activeEditSession.bufferPositionForScreenPosition([nextRow]).row - bufferLine = activeEditSession.lineForBufferRow(bufferRow) - if bufferLine isnt '' - indentation = Math.ceil(activeEditSession.indentLevelForLine(bufferLine)) - break - nextRow++ - - previousRow = screenRow - 1 - while previousRow >= 0 - bufferRow = activeEditSession.bufferPositionForScreenPosition([previousRow]).row - bufferLine = activeEditSession.lineForBufferRow(bufferRow) - if bufferLine isnt '' - indentation = Math.max(indentation, Math.ceil(activeEditSession.indentLevelForLine(bufferLine))) - break - previousRow-- - - indentation - else - Math.ceil(activeEditSession.indentLevelForLine(bufferLine)) - - buildHtmlEndOfLineInvisibles: (screenLine) -> - invisibles = [] - for invisible in @getEndOfLineInvisibles(screenLine) - invisibles.push("#{invisible}") - invisibles.join('') - - getEndOfLineInvisibles: (screenLine) -> - return [] unless @showInvisibles and @invisibles - return [] if @mini or screenLine.isSoftWrapped() - - invisibles = [] - invisibles.push(@invisibles.cr) if @invisibles.cr and screenLine.lineEnding is '\r\n' - invisibles.push(@invisibles.eol) if @invisibles.eol - invisibles - - lineElementForScreenRow: (screenRow) -> - @renderedLines.children(":eq(#{screenRow - @firstRenderedScreenRow})") - - toggleLineCommentsInSelection: -> - @activeEditSession.toggleLineCommentsInSelection() - - ### Public ### - - # Converts a buffer position to a pixel position. - # - # position - An object that represents a buffer position. It can be either - # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # - # Returns an object with two values: `top` and `left`, representing the pixel positions. - pixelPositionForBufferPosition: (position) -> - @pixelPositionForScreenPosition(@screenPositionForBufferPosition(position)) - - # Converts a screen position to a pixel position. - # - # position - An object that represents a screen position. It can be either - # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} - # - # Returns an object with two values: `top` and `left`, representing the pixel positions. - pixelPositionForScreenPosition: (position) -> - return { top: 0, left: 0 } unless @isOnDom() and @isVisible() - {row, column} = Point.fromObject(position) - actualRow = Math.floor(row) - - lineElement = existingLineElement = @lineElementForScreenRow(actualRow)[0] - unless existingLineElement - lineElement = @buildLineElementForScreenRow(actualRow) - @renderedLines.append(lineElement) - left = @positionLeftForLineAndColumn(lineElement, actualRow, column) - unless existingLineElement - @renderedLines[0].removeChild(lineElement) - { top: row * @lineHeight, left } - - positionLeftForLineAndColumn: (lineElement, screenRow, column) -> - return 0 if column == 0 - - bufferRow = @bufferRowsForScreenRows(screenRow, screenRow)[0] ? screenRow - tokenizedLine = @activeEditSession.displayBuffer.tokenizedBuffer.tokenizedLines[bufferRow] - - left = 0 - index = 0 - for token in tokenizedLine.tokens - for char in token.value - return left if index >= column - - val = @getCharacterWidthCache(token.scopes, char) - if val? - left += val - else - return @measureToColumn(lineElement, tokenizedLine, column) - - index++ - left - - scopesForColumn: (tokenizedLine, column) -> - index = 0 - for token in tokenizedLine.tokens - for char in token.value - return token.scopes if index == column - index++ - null - - measureToColumn: (lineElement, tokenizedLine, column) -> - left = oldLeft = index = 0 - iterator = document.createNodeIterator(lineElement, NodeFilter.SHOW_TEXT, TextNodeFilter) - - returnLeft = null - - offsetLeft = @scrollView.offset().left - paddingLeft = parseInt(@scrollView.css('padding-left')) - - while textNode = iterator.nextNode() - content = textNode.textContent - - for char, i in content - # Don't continue caching long lines :racehorse: - break if index > LongLineLength and column < index - - # Dont return right away, finish caching the whole line - returnLeft = left if index == column - oldLeft = left - - scopes = @scopesForColumn(tokenizedLine, index) - cachedCharWidth = @getCharacterWidthCache(scopes, char) - - if cachedCharWidth? - left = oldLeft + cachedCharWidth - else - # i + 1 to measure to the end of the current character - MeasureRange.setEnd(textNode, i + 1) - MeasureRange.collapse() - rects = MeasureRange.getClientRects() - return 0 if rects.length == 0 - left = rects[0].left - Math.floor(offsetLeft) + Math.floor(@scrollLeft()) - paddingLeft - - if scopes? - cachedCharWidth = left - oldLeft - @setCharacterWidthCache(scopes, char, cachedCharWidth) - - # Assume all the characters are the same width when dealing with long - # lines :racehorse: - return column * cachedCharWidth if index > LongLineLength - - index++ - - returnLeft ? left - - getCharacterWidthCache: (scopes, char) -> - scopes ?= NoScope - obj = TextEditorView.characterWidthCache - for scope in scopes - obj = obj[scope] - return null unless obj? - obj[char] - - setCharacterWidthCache: (scopes, char, val) -> - scopes ?= NoScope - obj = TextEditorView.characterWidthCache - for scope in scopes - obj[scope] ?= {} - obj = obj[scope] - obj[char] = val - - clearCharacterWidthCache: -> - TextEditorView.characterWidthCache = {} - - pixelOffsetForScreenPosition: (position) -> - {top, left} = @pixelPositionForScreenPosition(position) - offset = @renderedLines.offset() - {top: top + offset.top, left: left + offset.left} - - screenPositionFromMouseEvent: (e) -> - { pageX, pageY } = e - offset = @scrollView.offset() - - editorRelativeTop = pageY - offset.top + @scrollTop() - row = Math.floor(editorRelativeTop / @lineHeight) - column = 0 - - if pageX > offset.left and lineElement = @lineElementForScreenRow(row)[0] - range = document.createRange() - iterator = document.createNodeIterator(lineElement, NodeFilter.SHOW_TEXT, acceptNode: -> NodeFilter.FILTER_ACCEPT) - while node = iterator.nextNode() - range.selectNodeContents(node) - column += node.textContent.length - {left, right} = range.getClientRects()[0] - break if left <= pageX <= right - - if node - for characterPosition in [node.textContent.length...0] - range.setStart(node, characterPosition - 1) - range.setEnd(node, characterPosition) - {left, right, width} = range.getClientRects()[0] - break if left <= pageX - width / 2 <= right - column-- - - range.detach() - - new Point(row, column) - - # Highlights the current line the cursor is on. - highlightCursorLine: -> - return if @mini - - @highlightedLine?.removeClass('cursor-line') - if @getSelection().isEmpty() - @highlightedLine = @lineElementForScreenRow(@getCursorScreenRow()) - @highlightedLine.addClass('cursor-line') - else - @highlightedLine = null - - # {Delegates to: TextEditor.getGrammar} - getGrammar: -> - @activeEditSession.getGrammar() - - # {Delegates to: TextEditor.setGrammar} - setGrammar: (grammar) -> - throw new Error("Only mini-editors can explicity set their grammar") unless @mini - @activeEditSession.setGrammar(grammar) - - # {Delegates to: TextEditor.reloadGrammar} - reloadGrammar: -> - @activeEditSession.reloadGrammar() - - # {Delegates to: TextEditor.scopesForBufferPosition} - scopesForBufferPosition: (bufferPosition) -> - @activeEditSession.scopesForBufferPosition(bufferPosition) - - # Copies the current file path to the native clipboard. - copyPathToPasteboard: -> - path = @getPath() - atom.pasteboard.write(path) if path? - - ### Internal ### - - @buildLineHtml: ({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, showIndentGuide, indentation, activeEditSession, mini}) -> - scopeStack = [] - line = [] - - attributePairs = '' - attributePairs += " #{attributeName}=\"#{value}\"" for attributeName, value of attributes - line.push("
") - - if text == '' - html = TextEditorView.buildEmptyLineHtml(showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini) - line.push(html) if html - else - firstNonWhitespacePosition = text.search(/\S/) - firstTrailingWhitespacePosition = text.search(/\s*$/) - lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0 - position = 0 - for token in tokens - @updateScopeStack(line, scopeStack, token.scopes) - hasLeadingWhitespace = position < firstNonWhitespacePosition - hasTrailingWhitespace = position + token.value.length > firstTrailingWhitespacePosition - hasIndentGuide = not mini and showIndentGuide and (hasLeadingWhitespace or lineIsWhitespaceOnly) - line.push(token.getValueAsHtml({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide})) - position += token.value.length - - @popScope(line, scopeStack) while scopeStack.length > 0 - line.push(htmlEolInvisibles) unless text == '' - line.push("") if fold - - line.push('
') - line.join('') - - @updateScopeStack: (line, scopeStack, desiredScopes) -> - excessScopes = scopeStack.length - desiredScopes.length - if excessScopes > 0 - @popScope(line, scopeStack) while excessScopes-- - - # pop until common prefix - for i in [scopeStack.length..0] - break if _.isEqual(scopeStack[0...i], desiredScopes[0...i]) - @popScope(line, scopeStack) - - # push on top of common prefix until scopeStack == desiredScopes - for j in [i...desiredScopes.length] - @pushScope(line, scopeStack, desiredScopes[j]) - - null - - @pushScope: (line, scopeStack, scope) -> - scopeStack.push(scope) - line.push("") - - @popScope: (line, scopeStack) -> - scopeStack.pop() - line.push("") - - @buildEmptyLineHtml: (showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini) -> - indentCharIndex = 0 - if not mini and showIndentGuide - if indentation > 0 - tabLength = activeEditSession.getTabLength() - indentGuideHtml = '' - for level in [0...indentation] - indentLevelHtml = "" - for characterPosition in [0...tabLength] - if invisible = eolInvisibles[indentCharIndex++] - indentLevelHtml += "#{invisible}" - else - indentLevelHtml += ' ' - indentLevelHtml += "" - indentGuideHtml += indentLevelHtml - - while indentCharIndex < eolInvisibles.length - indentGuideHtml += "#{eolInvisibles[indentCharIndex++]}" - - return indentGuideHtml - - if htmlEolInvisibles.length > 0 - htmlEolInvisibles - else - ' ' - - replaceSelectedText: (replaceFn) -> - selection = @getSelection() - return false if selection.isEmpty() - - text = replaceFn(@getTextInRange(selection.getBufferRange())) - return false if text is null or text is undefined - - @insertText(text, select: true) - true - - consolidateSelections: (e) -> e.abortKeyBinding() unless @activeEditSession.consolidateSelections() - - logCursorScope: -> - console.log @activeEditSession.getCursorScopes() - - transact: (fn) -> @activeEditSession.transact(fn) - beginTransaction: -> @activeEditSession.beginTransaction() - commitTransaction: -> @activeEditSession.commitTransaction() - abortTransaction: -> @activeEditSession.abortTransaction() - - saveDebugSnapshot: -> - atom.showSaveDialog (path) => - fs.writeFileSync(path, @getDebugSnapshot()) if path - - getDebugSnapshot: -> - [ - "Debug Snapshot: #{@getPath()}" - @getRenderedLinesDebugSnapshot() - @activeEditSession.getDebugSnapshot() - @getBuffer().getDebugSnapshot() - ].join('\n\n') - - getRenderedLinesDebugSnapshot: -> - lines = ['Rendered Lines:'] - firstRenderedScreenRow = @firstRenderedScreenRow - @renderedLines.find('.line').each (n) -> - lines.push "#{firstRenderedScreenRow + n}: #{$(this).text()}" - lines.join('\n') - - logScreenLines: (start, end) -> - @activeEditSession.logScreenLines(start, end) - - logRenderedLines: -> - @renderedLines.find('.line').each (n) -> - console.log n, $(this).text() diff --git a/src/window.coffee b/src/window.coffee index 3d34342c7..f4f580bdc 100644 --- a/src/window.coffee +++ b/src/window.coffee @@ -49,7 +49,7 @@ window.startEditorWindow = -> atom.restoreDimensions() atom.config.load() atom.config.setDefaults('core', require('./root-view').configDefaults) - atom.config.setDefaults('editor', require('./text-editor-view').configDefaults) + atom.config.setDefaults('editor', require('./editor-view').configDefaults) atom.keymap.loadBundledKeymaps() atom.themes.loadBaseStylesheets() atom.packages.loadPackages() diff --git a/test.coffee b/test.coffee new file mode 100644 index 000000000..3ab511bc5 --- /dev/null +++ b/test.coffee @@ -0,0 +1,7 @@ +a = -> + if false + 1 + else + 3 + +console.log a() From 31a9bb83cf729da175b1310e5c37b6536b7e1b56 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 15:22:47 -0800 Subject: [PATCH 10/15] Replace editSession variables with editor --- spec/editor-spec.coffee | 2240 ++++++++++++++-------------- spec/editor-view-spec.coffee | 62 +- spec/git-spec.coffee | 30 +- spec/language-mode-spec.coffee | 94 +- spec/pane-container-spec.coffee | 8 +- spec/pane-spec.coffee | 202 +-- spec/project-spec.coffee | 158 +- spec/root-view-spec.coffee | 118 +- spec/selection-spec.coffee | 6 +- spec/text-mate-grammar-spec.coffee | 18 +- spec/window-spec.coffee | 12 +- src/cursor.coffee | 56 +- src/editor-view.coffee | 40 +- src/editor.coffee | 14 +- src/language-mode.coffee | 88 +- src/project.coffee | 30 +- src/root-view.coffee | 14 +- src/selection.coffee | 92 +- 18 files changed, 1641 insertions(+), 1641 deletions(-) diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 8f7400dc4..07a9eff91 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -1,94 +1,94 @@ clipboard = require 'clipboard' describe "Editor", -> - [buffer, editSession, lineLengths] = [] + [buffer, editor, lineLengths] = [] convertToHardTabs = (buffer) -> buffer.setText(buffer.getText().replace(/[ ]{2}/g, "\t")) describe "with an initial line option", -> beforeEach -> - editSession = project.openSync('sample.js', initialLine: 2) - buffer = editSession.buffer + editor = project.openSync('sample.js', initialLine: 2) + buffer = editor.buffer it "opens the file and positions the cursor on line 2", -> - expect(editSession.getCursor().getBufferPosition().row).toEqual 2 + expect(editor.getCursor().getBufferPosition().row).toEqual 2 describe "with default options", -> beforeEach -> atom.activatePackage('language-javascript', sync: true) - editSession = project.openSync('sample.js', autoIndent: false) - buffer = editSession.buffer + editor = project.openSync('sample.js', autoIndent: false) + buffer = editor.buffer lineLengths = buffer.getLines().map (line) -> line.length describe "@deserialize(state)", -> it "restores selections and folds based on markers in the buffer", -> - editSession.setSelectedBufferRange([[1, 2], [3, 4]]) - editSession.addSelectionForBufferRange([[5, 6], [7, 5]], isReversed: true) - editSession.foldBufferRow(4) - expect(editSession.isFoldedAtBufferRow(4)).toBeTruthy() + editor.setSelectedBufferRange([[1, 2], [3, 4]]) + editor.addSelectionForBufferRange([[5, 6], [7, 5]], isReversed: true) + editor.foldBufferRow(4) + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() - editSession2 = deserialize(editSession.serialize()) + editor2 = deserialize(editor.serialize()) - expect(editSession2.id).toBe editSession.id - expect(editSession2.getBuffer().getPath()).toBe editSession.getBuffer().getPath() - expect(editSession2.getSelectedBufferRanges()).toEqual [[[1, 2], [3, 4]], [[5, 6], [7, 5]]] - expect(editSession2.getSelection(1).isReversed()).toBeTruthy() - expect(editSession2.isFoldedAtBufferRow(4)).toBeTruthy() + 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() describe ".copy()", -> it "returns a different edit session with the same initial state", -> - editSession.setSelectedBufferRange([[1, 2], [3, 4]]) - editSession.addSelectionForBufferRange([[5, 6], [7, 8]], isReversed: true) - editSession.foldBufferRow(4) - expect(editSession.isFoldedAtBufferRow(4)).toBeTruthy() + editor.setSelectedBufferRange([[1, 2], [3, 4]]) + editor.addSelectionForBufferRange([[5, 6], [7, 8]], isReversed: true) + editor.foldBufferRow(4) + expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() - editSession2 = editSession.copy() - expect(editSession2.id).not.toBe editSession.id - expect(editSession2.getSelectedBufferRanges()).toEqual editSession.getSelectedBufferRanges() - expect(editSession2.getSelection(1).isReversed()).toBeTruthy() - expect(editSession2.isFoldedAtBufferRow(4)).toBeTruthy() + editor2 = editor.copy() + expect(editor2.id).not.toBe editor.id + expect(editor2.getSelectedBufferRanges()).toEqual editor.getSelectedBufferRanges() + expect(editor2.getSelection(1).isReversed()).toBeTruthy() + expect(editor2.isFoldedAtBufferRow(4)).toBeTruthy() - # editSession2 can now diverge from its origin edit session - editSession2.getSelection().setBufferRange([[2, 1], [4, 3]]) - expect(editSession2.getSelectedBufferRanges()).not.toEqual editSession.getSelectedBufferRanges() - editSession2.unfoldBufferRow(4) - expect(editSession2.isFoldedAtBufferRow(4)).not.toBe editSession.isFoldedAtBufferRow(4) + # editor2 can now diverge from its origin edit session + editor2.getSelection().setBufferRange([[2, 1], [4, 3]]) + expect(editor2.getSelectedBufferRanges()).not.toEqual editor.getSelectedBufferRanges() + editor2.unfoldBufferRow(4) + expect(editor2.isFoldedAtBufferRow(4)).not.toBe editor.isFoldedAtBufferRow(4) describe "config defaults", -> it "uses the `editor.tabLength`, `editor.softWrap`, and `editor.softTabs` config values", -> atom.config.set('editor.tabLength', 4) atom.config.set('editor.softWrap', true) atom.config.set('editor.softTabs', false) - editSession1 = project.openSync('a') - expect(editSession1.getTabLength()).toBe 4 - expect(editSession1.getSoftWrap()).toBe true - expect(editSession1.getSoftTabs()).toBe false + editor1 = project.openSync('a') + expect(editor1.getTabLength()).toBe 4 + expect(editor1.getSoftWrap()).toBe true + expect(editor1.getSoftTabs()).toBe false atom.config.set('editor.tabLength', 100) atom.config.set('editor.softWrap', false) atom.config.set('editor.softTabs', true) - editSession2 = project.openSync('b') - expect(editSession2.getTabLength()).toBe 100 - expect(editSession2.getSoftWrap()).toBe false - expect(editSession2.getSoftTabs()).toBe true + editor2 = project.openSync('b') + expect(editor2.getTabLength()).toBe 100 + expect(editor2.getSoftWrap()).toBe false + expect(editor2.getSoftTabs()).toBe true describe "title", -> describe ".getTitle()", -> it "uses the basename of the buffer's path as its title, or 'untitled' if the path is undefined", -> - expect(editSession.getTitle()).toBe 'sample.js' + expect(editor.getTitle()).toBe 'sample.js' buffer.setPath(undefined) - expect(editSession.getTitle()).toBe 'untitled' + expect(editor.getTitle()).toBe 'untitled' describe ".getLongTitle()", -> it "appends the name of the containing directory to the basename of the file", -> - expect(editSession.getLongTitle()).toBe 'sample.js - fixtures' + expect(editor.getLongTitle()).toBe 'sample.js - fixtures' buffer.setPath(undefined) - expect(editSession.getLongTitle()).toBe 'untitled' + expect(editor.getLongTitle()).toBe 'untitled' it "emits 'title-changed' events when the underlying buffer path", -> titleChangedHandler = jasmine.createSpy("titleChangedHandler") - editSession.on 'title-changed', titleChangedHandler + editor.on 'title-changed', titleChangedHandler buffer.setPath('/foo/bar/baz.txt') buffer.setPath(undefined) @@ -97,105 +97,105 @@ describe "Editor", -> describe "cursor", -> describe ".getCursor()", -> it "returns the most recently created cursor", -> - editSession.addCursorAtScreenPosition([1, 0]) - lastCursor = editSession.addCursorAtScreenPosition([2, 0]) - expect(editSession.getCursor()).toBe lastCursor + editor.addCursorAtScreenPosition([1, 0]) + lastCursor = editor.addCursorAtScreenPosition([2, 0]) + expect(editor.getCursor()).toBe lastCursor describe ".setCursorScreenPosition(screenPosition)", -> it "clears a goal column established by vertical movement", -> # set a goal column by moving down - editSession.setCursorScreenPosition(row: 3, column: lineLengths[3]) - editSession.moveCursorDown() - expect(editSession.getCursorScreenPosition().column).not.toBe 6 + editor.setCursorScreenPosition(row: 3, column: lineLengths[3]) + editor.moveCursorDown() + expect(editor.getCursorScreenPosition().column).not.toBe 6 # clear the goal column by explicitly setting the cursor position - editSession.setCursorScreenPosition([4,6]) - expect(editSession.getCursorScreenPosition().column).toBe 6 + editor.setCursorScreenPosition([4,6]) + expect(editor.getCursorScreenPosition().column).toBe 6 - editSession.moveCursorDown() - expect(editSession.getCursorScreenPosition().column).toBe 6 + editor.moveCursorDown() + expect(editor.getCursorScreenPosition().column).toBe 6 it "merges multiple cursors", -> - editSession.setCursorScreenPosition([0, 0]) - editSession.addCursorAtScreenPosition([0, 1]) - [cursor1, cursor2] = editSession.getCursors() - editSession.setCursorScreenPosition([4, 7]) - expect(editSession.getCursors().length).toBe 1 - expect(editSession.getCursors()).toEqual [cursor1] - expect(editSession.getCursorScreenPosition()).toEqual [4, 7] + editor.setCursorScreenPosition([0, 0]) + editor.addCursorAtScreenPosition([0, 1]) + [cursor1, cursor2] = editor.getCursors() + editor.setCursorScreenPosition([4, 7]) + expect(editor.getCursors().length).toBe 1 + expect(editor.getCursors()).toEqual [cursor1] + expect(editor.getCursorScreenPosition()).toEqual [4, 7] describe "when soft-wrap is enabled and code is folded", -> beforeEach -> - editSession.setSoftWrap(true) - editSession.setEditorWidthInChars(50) - editSession.createFold(2, 3) + editor.setSoftWrap(true) + editor.setEditorWidthInChars(50) + editor.createFold(2, 3) it "positions the cursor at the buffer position that corresponds to the given screen position", -> - editSession.setCursorScreenPosition([9, 0]) - expect(editSession.getCursorBufferPosition()).toEqual [8, 11] + editor.setCursorScreenPosition([9, 0]) + expect(editor.getCursorBufferPosition()).toEqual [8, 11] describe ".moveCursorUp()", -> it "moves the cursor up", -> - editSession.setCursorScreenPosition([2, 2]) - editSession.moveCursorUp() - expect(editSession.getCursorScreenPosition()).toEqual [1, 2] + editor.setCursorScreenPosition([2, 2]) + editor.moveCursorUp() + expect(editor.getCursorScreenPosition()).toEqual [1, 2] it "retains the goal column across lines of differing length", -> expect(lineLengths[6]).toBeGreaterThan(32) - editSession.setCursorScreenPosition(row: 6, column: 32) + editor.setCursorScreenPosition(row: 6, column: 32) - editSession.moveCursorUp() - expect(editSession.getCursorScreenPosition().column).toBe lineLengths[5] + editor.moveCursorUp() + expect(editor.getCursorScreenPosition().column).toBe lineLengths[5] - editSession.moveCursorUp() - expect(editSession.getCursorScreenPosition().column).toBe lineLengths[4] + editor.moveCursorUp() + expect(editor.getCursorScreenPosition().column).toBe lineLengths[4] - editSession.moveCursorUp() - expect(editSession.getCursorScreenPosition().column).toBe 32 + editor.moveCursorUp() + expect(editor.getCursorScreenPosition().column).toBe 32 describe "when the cursor is on the first line", -> it "moves the cursor to the beginning of the line, but retains the goal column", -> - editSession.setCursorScreenPosition([0, 4]) - editSession.moveCursorUp() - expect(editSession.getCursorScreenPosition()).toEqual([0, 0]) + editor.setCursorScreenPosition([0, 4]) + editor.moveCursorUp() + expect(editor.getCursorScreenPosition()).toEqual([0, 0]) - editSession.moveCursorDown() - expect(editSession.getCursorScreenPosition()).toEqual([1, 4]) + editor.moveCursorDown() + expect(editor.getCursorScreenPosition()).toEqual([1, 4]) describe "when there is a selection", -> beforeEach -> - editSession.setSelectedBufferRange([[4, 9],[5, 10]]) + editor.setSelectedBufferRange([[4, 9],[5, 10]]) it "moves above the selection", -> - cursor = editSession.getCursor() - editSession.moveCursorUp() + cursor = editor.getCursor() + editor.moveCursorUp() expect(cursor.getBufferPosition()).toEqual [3, 9] it "merges cursors when they overlap", -> - editSession.addCursorAtScreenPosition([1, 0]) - [cursor1, cursor2] = editSession.getCursors() + editor.addCursorAtScreenPosition([1, 0]) + [cursor1, cursor2] = editor.getCursors() - editSession.moveCursorUp() - expect(editSession.getCursors()).toEqual [cursor1] + editor.moveCursorUp() + expect(editor.getCursors()).toEqual [cursor1] expect(cursor1.getBufferPosition()).toEqual [0,0] describe ".moveCursorDown()", -> it "moves the cursor down", -> - editSession.setCursorScreenPosition([2, 2]) - editSession.moveCursorDown() - expect(editSession.getCursorScreenPosition()).toEqual [3, 2] + editor.setCursorScreenPosition([2, 2]) + editor.moveCursorDown() + expect(editor.getCursorScreenPosition()).toEqual [3, 2] it "retains the goal column across lines of differing length", -> - editSession.setCursorScreenPosition(row: 3, column: lineLengths[3]) + editor.setCursorScreenPosition(row: 3, column: lineLengths[3]) - editSession.moveCursorDown() - expect(editSession.getCursorScreenPosition().column).toBe lineLengths[4] + editor.moveCursorDown() + expect(editor.getCursorScreenPosition().column).toBe lineLengths[4] - editSession.moveCursorDown() - expect(editSession.getCursorScreenPosition().column).toBe lineLengths[5] + editor.moveCursorDown() + expect(editor.getCursorScreenPosition().column).toBe lineLengths[5] - editSession.moveCursorDown() - expect(editSession.getCursorScreenPosition().column).toBe lineLengths[3] + editor.moveCursorDown() + expect(editor.getCursorScreenPosition().column).toBe lineLengths[3] describe "when the cursor is on the last line", -> it "moves the cursor to the end of line, but retains the goal column when moving back up", -> @@ -203,100 +203,100 @@ describe "Editor", -> lastLine = buffer.lineForRow(lastLineIndex) expect(lastLine.length).toBeGreaterThan(0) - editSession.setCursorScreenPosition(row: lastLineIndex, column: editSession.getTabLength()) - editSession.moveCursorDown() - expect(editSession.getCursorScreenPosition()).toEqual(row: lastLineIndex, column: lastLine.length) + editor.setCursorScreenPosition(row: lastLineIndex, column: editor.getTabLength()) + editor.moveCursorDown() + expect(editor.getCursorScreenPosition()).toEqual(row: lastLineIndex, column: lastLine.length) - editSession.moveCursorUp() - expect(editSession.getCursorScreenPosition().column).toBe editSession.getTabLength() + editor.moveCursorUp() + expect(editor.getCursorScreenPosition().column).toBe editor.getTabLength() it "retains a goal column of 0 when moving back up", -> lastLineIndex = buffer.getLines().length - 1 lastLine = buffer.lineForRow(lastLineIndex) expect(lastLine.length).toBeGreaterThan(0) - editSession.setCursorScreenPosition(row: lastLineIndex, column: 0) - editSession.moveCursorDown() - editSession.moveCursorUp() - expect(editSession.getCursorScreenPosition().column).toBe 0 + editor.setCursorScreenPosition(row: lastLineIndex, column: 0) + editor.moveCursorDown() + editor.moveCursorUp() + expect(editor.getCursorScreenPosition().column).toBe 0 describe "when there is a selection", -> beforeEach -> - editSession.setSelectedBufferRange([[4, 9],[5, 10]]) + editor.setSelectedBufferRange([[4, 9],[5, 10]]) it "moves below the selection", -> - cursor = editSession.getCursor() - editSession.moveCursorDown() + cursor = editor.getCursor() + editor.moveCursorDown() expect(cursor.getBufferPosition()).toEqual [6, 10] it "merges cursors when they overlap", -> - editSession.setCursorScreenPosition([12, 2]) - editSession.addCursorAtScreenPosition([11, 2]) - [cursor1, cursor2] = editSession.getCursors() + editor.setCursorScreenPosition([12, 2]) + editor.addCursorAtScreenPosition([11, 2]) + [cursor1, cursor2] = editor.getCursors() - editSession.moveCursorDown() - expect(editSession.getCursors()).toEqual [cursor1] + editor.moveCursorDown() + expect(editor.getCursors()).toEqual [cursor1] expect(cursor1.getBufferPosition()).toEqual [12,2] describe ".moveCursorLeft()", -> it "moves the cursor by one column to the left", -> - editSession.setCursorScreenPosition([1, 8]) - editSession.moveCursorLeft() - expect(editSession.getCursorScreenPosition()).toEqual [1, 7] + editor.setCursorScreenPosition([1, 8]) + editor.moveCursorLeft() + expect(editor.getCursorScreenPosition()).toEqual [1, 7] describe "when the cursor is in the first column", -> describe "when there is a previous line", -> it "wraps to the end of the previous line", -> - editSession.setCursorScreenPosition(row: 1, column: 0) - editSession.moveCursorLeft() - expect(editSession.getCursorScreenPosition()).toEqual(row: 0, column: buffer.lineForRow(0).length) + editor.setCursorScreenPosition(row: 1, column: 0) + editor.moveCursorLeft() + expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: buffer.lineForRow(0).length) describe "when the cursor is on the first line", -> it "remains in the same position (0,0)", -> - editSession.setCursorScreenPosition(row: 0, column: 0) - editSession.moveCursorLeft() - expect(editSession.getCursorScreenPosition()).toEqual(row: 0, column: 0) + editor.setCursorScreenPosition(row: 0, column: 0) + editor.moveCursorLeft() + expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0) describe "when softTabs is enabled and the cursor is preceded by leading whitespace", -> it "skips tabLength worth of whitespace at a time", -> - editSession.setCursorBufferPosition([5, 6]) + editor.setCursorBufferPosition([5, 6]) - editSession.moveCursorLeft() - expect(editSession.getCursorBufferPosition()).toEqual [5, 4] + editor.moveCursorLeft() + expect(editor.getCursorBufferPosition()).toEqual [5, 4] describe "when there is a selection", -> beforeEach -> - editSession.setSelectedBufferRange([[5, 22],[5, 27]]) + editor.setSelectedBufferRange([[5, 22],[5, 27]]) it "moves to the left of the selection", -> - cursor = editSession.getCursor() - editSession.moveCursorLeft() + cursor = editor.getCursor() + editor.moveCursorLeft() expect(cursor.getBufferPosition()).toEqual [5, 22] - editSession.moveCursorLeft() + editor.moveCursorLeft() expect(cursor.getBufferPosition()).toEqual [5, 21] it "merges cursors when they overlap", -> - editSession.setCursorScreenPosition([0, 0]) - editSession.addCursorAtScreenPosition([0, 1]) + editor.setCursorScreenPosition([0, 0]) + editor.addCursorAtScreenPosition([0, 1]) - [cursor1, cursor2] = editSession.getCursors() - editSession.moveCursorLeft() - expect(editSession.getCursors()).toEqual [cursor1] + [cursor1, cursor2] = editor.getCursors() + editor.moveCursorLeft() + expect(editor.getCursors()).toEqual [cursor1] expect(cursor1.getBufferPosition()).toEqual [0,0] describe ".moveCursorRight()", -> it "moves the cursor by one column to the right", -> - editSession.setCursorScreenPosition([3, 3]) - editSession.moveCursorRight() - expect(editSession.getCursorScreenPosition()).toEqual [3, 4] + editor.setCursorScreenPosition([3, 3]) + editor.moveCursorRight() + expect(editor.getCursorScreenPosition()).toEqual [3, 4] describe "when the cursor is on the last column of a line", -> describe "when there is a subsequent line", -> it "wraps to the beginning of the next line", -> - editSession.setCursorScreenPosition([0, buffer.lineForRow(0).length]) - editSession.moveCursorRight() - expect(editSession.getCursorScreenPosition()).toEqual [1, 0] + editor.setCursorScreenPosition([0, buffer.lineForRow(0).length]) + editor.moveCursorRight() + expect(editor.getCursorScreenPosition()).toEqual [1, 0] describe "when the cursor is on the last line", -> it "remains in the same position", -> @@ -305,155 +305,155 @@ describe "Editor", -> expect(lastLine.length).toBeGreaterThan(0) lastPosition = { row: lastLineIndex, column: lastLine.length } - editSession.setCursorScreenPosition(lastPosition) - editSession.moveCursorRight() + editor.setCursorScreenPosition(lastPosition) + editor.moveCursorRight() - expect(editSession.getCursorScreenPosition()).toEqual(lastPosition) + expect(editor.getCursorScreenPosition()).toEqual(lastPosition) describe "when there is a selection", -> beforeEach -> - editSession.setSelectedBufferRange([[5, 22],[5, 27]]) + editor.setSelectedBufferRange([[5, 22],[5, 27]]) it "moves to the left of the selection", -> - cursor = editSession.getCursor() - editSession.moveCursorRight() + cursor = editor.getCursor() + editor.moveCursorRight() expect(cursor.getBufferPosition()).toEqual [5, 27] - editSession.moveCursorRight() + editor.moveCursorRight() expect(cursor.getBufferPosition()).toEqual [5, 28] it "merges cursors when they overlap", -> - editSession.setCursorScreenPosition([12, 2]) - editSession.addCursorAtScreenPosition([12, 1]) - [cursor1, cursor2] = editSession.getCursors() + editor.setCursorScreenPosition([12, 2]) + editor.addCursorAtScreenPosition([12, 1]) + [cursor1, cursor2] = editor.getCursors() - editSession.moveCursorRight() - expect(editSession.getCursors()).toEqual [cursor1] + editor.moveCursorRight() + expect(editor.getCursors()).toEqual [cursor1] expect(cursor1.getBufferPosition()).toEqual [12,2] describe ".moveCursorToTop()", -> it "moves the cursor to the top of the buffer", -> - editSession.setCursorScreenPosition [11,1] - editSession.addCursorAtScreenPosition [12,0] - editSession.moveCursorToTop() - expect(editSession.getCursors().length).toBe 1 - expect(editSession.getCursorBufferPosition()).toEqual [0,0] + editor.setCursorScreenPosition [11,1] + editor.addCursorAtScreenPosition [12,0] + editor.moveCursorToTop() + expect(editor.getCursors().length).toBe 1 + expect(editor.getCursorBufferPosition()).toEqual [0,0] describe ".moveCursorToBottom()", -> it "moves the cusor to the bottom of the buffer", -> - editSession.setCursorScreenPosition [0,0] - editSession.addCursorAtScreenPosition [1,0] - editSession.moveCursorToBottom() - expect(editSession.getCursors().length).toBe 1 - expect(editSession.getCursorBufferPosition()).toEqual [12,2] + editor.setCursorScreenPosition [0,0] + editor.addCursorAtScreenPosition [1,0] + editor.moveCursorToBottom() + expect(editor.getCursors().length).toBe 1 + expect(editor.getCursorBufferPosition()).toEqual [12,2] describe ".moveCursorToBeginningOfLine()", -> describe "when soft wrap is on", -> it "moves cursor to the beginning of the screen line", -> - editSession.setSoftWrap(true) - editSession.setEditorWidthInChars(10) - editSession.setCursorScreenPosition([1, 2]) - editSession.moveCursorToBeginningOfLine() - cursor = editSession.getCursor() + editor.setSoftWrap(true) + editor.setEditorWidthInChars(10) + editor.setCursorScreenPosition([1, 2]) + editor.moveCursorToBeginningOfLine() + cursor = editor.getCursor() expect(cursor.getScreenPosition()).toEqual [1, 0] describe "when soft wrap is off", -> it "moves cursor to the beginning of then line", -> - editSession.setCursorScreenPosition [0,5] - editSession.addCursorAtScreenPosition [1,7] - editSession.moveCursorToBeginningOfLine() - expect(editSession.getCursors().length).toBe 2 - [cursor1, cursor2] = editSession.getCursors() + editor.setCursorScreenPosition [0,5] + editor.addCursorAtScreenPosition [1,7] + editor.moveCursorToBeginningOfLine() + expect(editor.getCursors().length).toBe 2 + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,0] expect(cursor2.getBufferPosition()).toEqual [1,0] describe ".moveCursorToEndOfLine()", -> describe "when soft wrap is on", -> it "moves cursor to the beginning of the screen line", -> - editSession.setSoftWrap(true) - editSession.setEditorWidthInChars(10) - editSession.setCursorScreenPosition([1, 2]) - editSession.moveCursorToEndOfLine() - cursor = editSession.getCursor() + editor.setSoftWrap(true) + editor.setEditorWidthInChars(10) + editor.setCursorScreenPosition([1, 2]) + editor.moveCursorToEndOfLine() + cursor = editor.getCursor() expect(cursor.getScreenPosition()).toEqual [1, 9] describe "when soft wrap is off", -> it "moves cursor to the end of line", -> - editSession.setCursorScreenPosition [0,0] - editSession.addCursorAtScreenPosition [1,0] - editSession.moveCursorToEndOfLine() - expect(editSession.getCursors().length).toBe 2 - [cursor1, cursor2] = editSession.getCursors() + editor.setCursorScreenPosition [0,0] + editor.addCursorAtScreenPosition [1,0] + editor.moveCursorToEndOfLine() + expect(editor.getCursors().length).toBe 2 + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,29] expect(cursor2.getBufferPosition()).toEqual [1,30] describe ".moveCursorToFirstCharacterOfLine()", -> describe "when soft wrap is on", -> it "moves to the first character of the current screen line or the beginning of the screen line if it's already on the first character", -> - editSession.setSoftWrap(true) - editSession.setEditorWidthInChars(10) - editSession.setCursorScreenPosition [2,5] - editSession.addCursorAtScreenPosition [8,7] + editor.setSoftWrap(true) + editor.setEditorWidthInChars(10) + editor.setCursorScreenPosition [2,5] + editor.addCursorAtScreenPosition [8,7] - editSession.moveCursorToFirstCharacterOfLine() - [cursor1, cursor2] = editSession.getCursors() + editor.moveCursorToFirstCharacterOfLine() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getScreenPosition()).toEqual [2,0] expect(cursor2.getScreenPosition()).toEqual [8,4] - editSession.moveCursorToFirstCharacterOfLine() + editor.moveCursorToFirstCharacterOfLine() expect(cursor1.getScreenPosition()).toEqual [2,0] expect(cursor2.getScreenPosition()).toEqual [8,0] describe "when soft wrap is off", -> it "moves to the first character of the current line or the beginning of the line if it's already on the first character", -> - editSession.setCursorScreenPosition [0,5] - editSession.addCursorAtScreenPosition [1,7] + editor.setCursorScreenPosition [0,5] + editor.addCursorAtScreenPosition [1,7] - editSession.moveCursorToFirstCharacterOfLine() - [cursor1, cursor2] = editSession.getCursors() + editor.moveCursorToFirstCharacterOfLine() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,0] expect(cursor2.getBufferPosition()).toEqual [1,2] - editSession.moveCursorToFirstCharacterOfLine() + editor.moveCursorToFirstCharacterOfLine() expect(cursor1.getBufferPosition()).toEqual [0,0] expect(cursor2.getBufferPosition()).toEqual [1,0] describe ".moveCursorToBeginningOfWord()", -> it "moves the cursor to the beginning of the word", -> - editSession.setCursorBufferPosition [0, 8] - editSession.addCursorAtBufferPosition [1, 12] - editSession.addCursorAtBufferPosition [3, 0] - [cursor1, cursor2, cursor3] = editSession.getCursors() + editor.setCursorBufferPosition [0, 8] + editor.addCursorAtBufferPosition [1, 12] + editor.addCursorAtBufferPosition [3, 0] + [cursor1, cursor2, cursor3] = editor.getCursors() - editSession.moveCursorToBeginningOfWord() + editor.moveCursorToBeginningOfWord() expect(cursor1.getBufferPosition()).toEqual [0, 4] expect(cursor2.getBufferPosition()).toEqual [1, 11] expect(cursor3.getBufferPosition()).toEqual [2, 39] it "does not fail at position [0, 0]", -> - editSession.setCursorBufferPosition([0, 0]) - editSession.moveCursorToBeginningOfWord() + editor.setCursorBufferPosition([0, 0]) + editor.moveCursorToBeginningOfWord() it "treats lines with only whitespace as a word", -> - editSession.setCursorBufferPosition([11, 0]) - editSession.moveCursorToBeginningOfWord() - expect(editSession.getCursorBufferPosition()).toEqual [10, 0] + editor.setCursorBufferPosition([11, 0]) + editor.moveCursorToBeginningOfWord() + expect(editor.getCursorBufferPosition()).toEqual [10, 0] it "works when the current line is blank", -> - editSession.setCursorBufferPosition([10, 0]) - editSession.moveCursorToBeginningOfWord() - expect(editSession.getCursorBufferPosition()).toEqual [9, 2] + editor.setCursorBufferPosition([10, 0]) + editor.moveCursorToBeginningOfWord() + expect(editor.getCursorBufferPosition()).toEqual [9, 2] describe ".moveCursorToPreviousWordBoundary()", -> it "moves the cursor to the previous word boundary", -> - editSession.setCursorBufferPosition [0, 8] - editSession.addCursorAtBufferPosition [2, 0] - editSession.addCursorAtBufferPosition [2, 4] - editSession.addCursorAtBufferPosition [3, 14] - [cursor1, cursor2, cursor3, cursor4] = editSession.getCursors() + editor.setCursorBufferPosition [0, 8] + editor.addCursorAtBufferPosition [2, 0] + editor.addCursorAtBufferPosition [2, 4] + editor.addCursorAtBufferPosition [3, 14] + [cursor1, cursor2, cursor3, cursor4] = editor.getCursors() - editSession.moveCursorToPreviousWordBoundary() + editor.moveCursorToPreviousWordBoundary() expect(cursor1.getBufferPosition()).toEqual [0, 4] expect(cursor2.getBufferPosition()).toEqual [1, 30] @@ -462,13 +462,13 @@ describe "Editor", -> describe ".moveCursorToNextWordBoundary()", -> it "moves the cursor to the previous word boundary", -> - editSession.setCursorBufferPosition [0, 8] - editSession.addCursorAtBufferPosition [2, 40] - editSession.addCursorAtBufferPosition [3, 0] - editSession.addCursorAtBufferPosition [3, 30] - [cursor1, cursor2, cursor3, cursor4] = editSession.getCursors() + editor.setCursorBufferPosition [0, 8] + editor.addCursorAtBufferPosition [2, 40] + editor.addCursorAtBufferPosition [3, 0] + editor.addCursorAtBufferPosition [3, 30] + [cursor1, cursor2, cursor3, cursor4] = editor.getCursors() - editSession.moveCursorToNextWordBoundary() + editor.moveCursorToNextWordBoundary() expect(cursor1.getBufferPosition()).toEqual [0, 13] expect(cursor2.getBufferPosition()).toEqual [3, 0] @@ -477,69 +477,69 @@ describe "Editor", -> describe ".moveCursorToEndOfWord()", -> it "moves the cursor to the end of the word", -> - editSession.setCursorBufferPosition [0, 6] - editSession.addCursorAtBufferPosition [1, 10] - editSession.addCursorAtBufferPosition [2, 40] - [cursor1, cursor2, cursor3] = editSession.getCursors() + editor.setCursorBufferPosition [0, 6] + editor.addCursorAtBufferPosition [1, 10] + editor.addCursorAtBufferPosition [2, 40] + [cursor1, cursor2, cursor3] = editor.getCursors() - editSession.moveCursorToEndOfWord() + editor.moveCursorToEndOfWord() expect(cursor1.getBufferPosition()).toEqual [0, 13] expect(cursor2.getBufferPosition()).toEqual [1, 12] expect(cursor3.getBufferPosition()).toEqual [3, 7] it "does not blow up when there is no next word", -> - editSession.setCursorBufferPosition [Infinity, Infinity] - endPosition = editSession.getCursorBufferPosition() - editSession.moveCursorToEndOfWord() - expect(editSession.getCursorBufferPosition()).toEqual endPosition + editor.setCursorBufferPosition [Infinity, Infinity] + endPosition = editor.getCursorBufferPosition() + editor.moveCursorToEndOfWord() + expect(editor.getCursorBufferPosition()).toEqual endPosition it "treats lines with only whitespace as a word", -> - editSession.setCursorBufferPosition([9, 4]) - editSession.moveCursorToEndOfWord() - expect(editSession.getCursorBufferPosition()).toEqual [10, 0] + editor.setCursorBufferPosition([9, 4]) + editor.moveCursorToEndOfWord() + expect(editor.getCursorBufferPosition()).toEqual [10, 0] it "works when the current line is blank", -> - editSession.setCursorBufferPosition([10, 0]) - editSession.moveCursorToEndOfWord() - expect(editSession.getCursorBufferPosition()).toEqual [11, 8] + editor.setCursorBufferPosition([10, 0]) + editor.moveCursorToEndOfWord() + expect(editor.getCursorBufferPosition()).toEqual [11, 8] describe ".moveCursorToBeginningOfNextWord()", -> it "moves the cursor before the first character of the next word", -> - editSession.setCursorBufferPosition [0,6] - editSession.addCursorAtBufferPosition [1,11] - editSession.addCursorAtBufferPosition [2,0] - [cursor1, cursor2, cursor3] = editSession.getCursors() + editor.setCursorBufferPosition [0,6] + editor.addCursorAtBufferPosition [1,11] + editor.addCursorAtBufferPosition [2,0] + [cursor1, cursor2, cursor3] = editor.getCursors() - editSession.moveCursorToBeginningOfNextWord() + editor.moveCursorToBeginningOfNextWord() expect(cursor1.getBufferPosition()).toEqual [0, 14] expect(cursor2.getBufferPosition()).toEqual [1, 13] expect(cursor3.getBufferPosition()).toEqual [2, 4] # When the cursor is on whitespace - editSession.setText("ab cde- ") - editSession.setCursorBufferPosition [0,2] - cursor = editSession.getCursor() - editSession.moveCursorToBeginningOfNextWord() + editor.setText("ab cde- ") + editor.setCursorBufferPosition [0,2] + cursor = editor.getCursor() + editor.moveCursorToBeginningOfNextWord() expect(cursor.getBufferPosition()).toEqual [0, 3] it "does not blow up when there is no next word", -> - editSession.setCursorBufferPosition [Infinity, Infinity] - endPosition = editSession.getCursorBufferPosition() - editSession.moveCursorToBeginningOfNextWord() - expect(editSession.getCursorBufferPosition()).toEqual endPosition + editor.setCursorBufferPosition [Infinity, Infinity] + endPosition = editor.getCursorBufferPosition() + editor.moveCursorToBeginningOfNextWord() + expect(editor.getCursorBufferPosition()).toEqual endPosition it "treats lines with only whitespace as a word", -> - editSession.setCursorBufferPosition([9, 4]) - editSession.moveCursorToBeginningOfNextWord() - expect(editSession.getCursorBufferPosition()).toEqual [10, 0] + editor.setCursorBufferPosition([9, 4]) + editor.moveCursorToBeginningOfNextWord() + expect(editor.getCursorBufferPosition()).toEqual [10, 0] it "works when the current line is blank", -> - editSession.setCursorBufferPosition([10, 0]) - editSession.moveCursorToBeginningOfNextWord() - expect(editSession.getCursorBufferPosition()).toEqual [11, 9] + editor.setCursorBufferPosition([10, 0]) + editor.moveCursorToBeginningOfNextWord() + expect(editor.getCursorBufferPosition()).toEqual [11, 9] describe ".getCurrentParagraphBufferRange()", -> it "returns the buffer range of the current paragraph, delimited by blank lines or the beginning / end of the file", -> @@ -558,27 +558,27 @@ describe "Editor", -> """ # in a paragraph - editSession.setCursorBufferPosition([1, 7]) - expect(editSession.getCurrentParagraphBufferRange()).toEqual [[0, 0], [2, 8]] + editor.setCursorBufferPosition([1, 7]) + expect(editor.getCurrentParagraphBufferRange()).toEqual [[0, 0], [2, 8]] - editSession.setCursorBufferPosition([7, 1]) - expect(editSession.getCurrentParagraphBufferRange()).toEqual [[5, 0], [7, 3]] + editor.setCursorBufferPosition([7, 1]) + expect(editor.getCurrentParagraphBufferRange()).toEqual [[5, 0], [7, 3]] - editSession.setCursorBufferPosition([9, 10]) - expect(editSession.getCurrentParagraphBufferRange()).toEqual [[9, 0], [10, 32]] + editor.setCursorBufferPosition([9, 10]) + expect(editor.getCurrentParagraphBufferRange()).toEqual [[9, 0], [10, 32]] # between paragraphs - editSession.setCursorBufferPosition([3, 1]) - expect(editSession.getCurrentParagraphBufferRange()).toBeUndefined() + editor.setCursorBufferPosition([3, 1]) + expect(editor.getCurrentParagraphBufferRange()).toBeUndefined() describe "cursor-moved events", -> cursorMovedHandler = null beforeEach -> - editSession.foldBufferRow(4) - editSession.setSelectedBufferRange([[8, 1], [9, 0]]) + editor.foldBufferRow(4) + editor.setSelectedBufferRange([[8, 1], [9, 0]]) cursorMovedHandler = jasmine.createSpy("cursorMovedHandler") - editSession.on 'cursor-moved', cursorMovedHandler + editor.on 'cursor-moved', cursorMovedHandler describe "when the position of the cursor changes", -> it "emits a cursor-moved event", -> @@ -599,111 +599,111 @@ describe "Editor", -> describe "addCursorAtScreenPosition(screenPosition)", -> describe "when a cursor already exists at the position", -> it "returns the existing cursor", -> - cursor1 = editSession.addCursorAtScreenPosition([0,2]) - cursor2 = editSession.addCursorAtScreenPosition([0,2]) + cursor1 = editor.addCursorAtScreenPosition([0,2]) + cursor2 = editor.addCursorAtScreenPosition([0,2]) expect(cursor2.marker).toBe cursor1.marker describe "addCursorAtBufferPosition(bufferPosition)", -> describe "when a cursor already exists at the position", -> it "returns the existing cursor", -> - cursor1 = editSession.addCursorAtBufferPosition([1,4]) - cursor2 = editSession.addCursorAtBufferPosition([1,4]) + cursor1 = editor.addCursorAtBufferPosition([1,4]) + cursor2 = editor.addCursorAtBufferPosition([1,4]) expect(cursor2.marker).toBe cursor1.marker describe "selection", -> selection = null beforeEach -> - selection = editSession.getSelection() + selection = editor.getSelection() describe ".selectUp/Down/Left/Right()", -> it "expands each selection to its cursor's new location", -> - editSession.setSelectedBufferRanges([[[0,9], [0,13]], [[3,16], [3,21]]]) - [selection1, selection2] = editSession.getSelections() + editor.setSelectedBufferRanges([[[0,9], [0,13]], [[3,16], [3,21]]]) + [selection1, selection2] = editor.getSelections() - editSession.selectRight() + editor.selectRight() expect(selection1.getBufferRange()).toEqual [[0,9], [0,14]] expect(selection2.getBufferRange()).toEqual [[3,16], [3,22]] - editSession.selectLeft() - editSession.selectLeft() + editor.selectLeft() + editor.selectLeft() expect(selection1.getBufferRange()).toEqual [[0,9], [0,12]] expect(selection2.getBufferRange()).toEqual [[3,16], [3,20]] - editSession.selectDown() + editor.selectDown() expect(selection1.getBufferRange()).toEqual [[0,9], [1,12]] expect(selection2.getBufferRange()).toEqual [[3,16], [4,20]] - editSession.selectUp() + editor.selectUp() expect(selection1.getBufferRange()).toEqual [[0,9], [0,12]] expect(selection2.getBufferRange()).toEqual [[3,16], [3,20]] it "merges selections when they intersect when moving down", -> - editSession.setSelectedBufferRanges([[[0,9], [0,13]], [[1,10], [1,20]], [[2,15], [3,25]]]) - [selection1, selection2, selection3] = editSession.getSelections() + editor.setSelectedBufferRanges([[[0,9], [0,13]], [[1,10], [1,20]], [[2,15], [3,25]]]) + [selection1, selection2, selection3] = editor.getSelections() - editSession.selectDown() - expect(editSession.getSelections()).toEqual [selection1] + editor.selectDown() + expect(editor.getSelections()).toEqual [selection1] expect(selection1.getScreenRange()).toEqual([[0, 9], [4, 25]]) expect(selection1.isReversed()).toBeFalsy() it "merges selections when they intersect when moving up", -> - editSession.setSelectedBufferRanges([[[0,9], [0,13]], [[1,10], [1,20]]], isReversed: true) - [selection1, selection2] = editSession.getSelections() + editor.setSelectedBufferRanges([[[0,9], [0,13]], [[1,10], [1,20]]], isReversed: true) + [selection1, selection2] = editor.getSelections() - editSession.selectUp() + editor.selectUp() - expect(editSession.getSelections().length).toBe 1 - expect(editSession.getSelections()).toEqual [selection1] + expect(editor.getSelections().length).toBe 1 + expect(editor.getSelections()).toEqual [selection1] expect(selection1.getScreenRange()).toEqual([[0, 0], [1, 20]]) expect(selection1.isReversed()).toBeTruthy() it "merges selections when they intersect when moving left", -> - editSession.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]], isReversed: true) - [selection1, selection2] = editSession.getSelections() + editor.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]], isReversed: true) + [selection1, selection2] = editor.getSelections() - editSession.selectLeft() - expect(editSession.getSelections()).toEqual [selection1] + editor.selectLeft() + expect(editor.getSelections()).toEqual [selection1] expect(selection1.getScreenRange()).toEqual([[0, 8], [1, 20]]) expect(selection1.isReversed()).toBeTruthy() it "merges selections when they intersect when moving right", -> - editSession.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]]) - [selection1, selection2] = editSession.getSelections() + editor.setSelectedBufferRanges([[[0,9], [0,13]], [[0,14], [1,20]]]) + [selection1, selection2] = editor.getSelections() - editSession.selectRight() - expect(editSession.getSelections()).toEqual [selection1] + editor.selectRight() + expect(editor.getSelections()).toEqual [selection1] expect(selection1.getScreenRange()).toEqual([[0, 9], [1, 21]]) expect(selection1.isReversed()).toBeFalsy() describe ".selectToScreenPosition(screenPosition)", -> it "expands the last selection to the given position", -> - editSession.setSelectedBufferRange([[3, 0], [4, 5]]) - editSession.addCursorAtScreenPosition([5, 6]) - editSession.selectToScreenPosition([6, 2]) + editor.setSelectedBufferRange([[3, 0], [4, 5]]) + editor.addCursorAtScreenPosition([5, 6]) + editor.selectToScreenPosition([6, 2]) - selections = editSession.getSelections() + selections = editor.getSelections() expect(selections.length).toBe 2 [selection1, selection2] = selections expect(selection1.getScreenRange()).toEqual [[3, 0], [4, 5]] expect(selection2.getScreenRange()).toEqual [[5, 6], [6, 2]] it "merges selections if they intersect, maintaining the directionality of the last selection", -> - editSession.setCursorScreenPosition([4, 10]) - editSession.selectToScreenPosition([5, 27]) - editSession.addCursorAtScreenPosition([3, 10]) - editSession.selectToScreenPosition([6, 27]) + editor.setCursorScreenPosition([4, 10]) + editor.selectToScreenPosition([5, 27]) + editor.addCursorAtScreenPosition([3, 10]) + editor.selectToScreenPosition([6, 27]) - selections = editSession.getSelections() + selections = editor.getSelections() expect(selections.length).toBe 1 [selection1] = selections expect(selection1.getScreenRange()).toEqual [[3, 10], [6, 27]] expect(selection1.isReversed()).toBeFalsy() - editSession.addCursorAtScreenPosition([7, 4]) - editSession.selectToScreenPosition([4, 11]) + editor.addCursorAtScreenPosition([7, 4]) + editor.selectToScreenPosition([4, 11]) - selections = editSession.getSelections() + selections = editor.getSelections() expect(selections.length).toBe 1 [selection1] = selections expect(selection1.getScreenRange()).toEqual [[3, 10], [7, 4]] @@ -711,43 +711,43 @@ describe "Editor", -> describe ".selectToTop()", -> it "selects text from cusor position to the top of the buffer", -> - editSession.setCursorScreenPosition [11,2] - editSession.addCursorAtScreenPosition [10,0] - editSession.selectToTop() - expect(editSession.getCursors().length).toBe 1 - expect(editSession.getCursorBufferPosition()).toEqual [0,0] - expect(editSession.getSelection().getBufferRange()).toEqual [[0,0], [11,2]] - expect(editSession.getSelection().isReversed()).toBeTruthy() + editor.setCursorScreenPosition [11,2] + editor.addCursorAtScreenPosition [10,0] + editor.selectToTop() + expect(editor.getCursors().length).toBe 1 + expect(editor.getCursorBufferPosition()).toEqual [0,0] + expect(editor.getSelection().getBufferRange()).toEqual [[0,0], [11,2]] + expect(editor.getSelection().isReversed()).toBeTruthy() describe ".selectToBottom()", -> it "selects text from cusor position to the bottom of the buffer", -> - editSession.setCursorScreenPosition [10,0] - editSession.addCursorAtScreenPosition [9,3] - editSession.selectToBottom() - expect(editSession.getCursors().length).toBe 1 - expect(editSession.getCursorBufferPosition()).toEqual [12,2] - expect(editSession.getSelection().getBufferRange()).toEqual [[9,3], [12,2]] - expect(editSession.getSelection().isReversed()).toBeFalsy() + editor.setCursorScreenPosition [10,0] + editor.addCursorAtScreenPosition [9,3] + editor.selectToBottom() + expect(editor.getCursors().length).toBe 1 + expect(editor.getCursorBufferPosition()).toEqual [12,2] + expect(editor.getSelection().getBufferRange()).toEqual [[9,3], [12,2]] + expect(editor.getSelection().isReversed()).toBeFalsy() describe ".selectAll()", -> it "selects the entire buffer", -> - editSession.selectAll() - expect(editSession.getSelection().getBufferRange()).toEqual buffer.getRange() + editor.selectAll() + expect(editor.getSelection().getBufferRange()).toEqual buffer.getRange() describe ".selectToBeginningOfLine()", -> it "selects text from cusor position to beginning of line", -> - editSession.setCursorScreenPosition [12,2] - editSession.addCursorAtScreenPosition [11,3] + editor.setCursorScreenPosition [12,2] + editor.addCursorAtScreenPosition [11,3] - editSession.selectToBeginningOfLine() + editor.selectToBeginningOfLine() - expect(editSession.getCursors().length).toBe 2 - [cursor1, cursor2] = editSession.getCursors() + expect(editor.getCursors().length).toBe 2 + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [12,0] expect(cursor2.getBufferPosition()).toEqual [11,0] - expect(editSession.getSelections().length).toBe 2 - [selection1, selection2] = editSession.getSelections() + expect(editor.getSelections().length).toBe 2 + [selection1, selection2] = editor.getSelections() expect(selection1.getBufferRange()).toEqual [[12,0], [12,2]] expect(selection1.isReversed()).toBeTruthy() expect(selection2.getBufferRange()).toEqual [[11,0], [11,3]] @@ -755,18 +755,18 @@ describe "Editor", -> describe ".selectToEndOfLine()", -> it "selects text from cusor position to end of line", -> - editSession.setCursorScreenPosition [12,0] - editSession.addCursorAtScreenPosition [11,3] + editor.setCursorScreenPosition [12,0] + editor.addCursorAtScreenPosition [11,3] - editSession.selectToEndOfLine() + editor.selectToEndOfLine() - expect(editSession.getCursors().length).toBe 2 - [cursor1, cursor2] = editSession.getCursors() + expect(editor.getCursors().length).toBe 2 + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [12,2] expect(cursor2.getBufferPosition()).toEqual [11,44] - expect(editSession.getSelections().length).toBe 2 - [selection1, selection2] = editSession.getSelections() + expect(editor.getSelections().length).toBe 2 + [selection1, selection2] = editor.getSelections() expect(selection1.getBufferRange()).toEqual [[12,0], [12,2]] expect(selection1.isReversed()).toBeFalsy() expect(selection2.getBufferRange()).toEqual [[11,3], [11,44]] @@ -774,29 +774,29 @@ describe "Editor", -> describe ".selectLine()", -> it "selects the entire line (including newlines) at given row", -> - editSession.setCursorScreenPosition([1, 2]) - editSession.selectLine() - expect(editSession.getSelectedBufferRange()).toEqual [[1,0], [2,0]] - expect(editSession.getSelectedText()).toBe " var sort = function(items) {\n" + editor.setCursorScreenPosition([1, 2]) + editor.selectLine() + expect(editor.getSelectedBufferRange()).toEqual [[1,0], [2,0]] + expect(editor.getSelectedText()).toBe " var sort = function(items) {\n" - editSession.setCursorScreenPosition([12, 2]) - editSession.selectLine() - expect(editSession.getSelectedBufferRange()).toEqual [[12,0], [12,2]] + editor.setCursorScreenPosition([12, 2]) + editor.selectLine() + expect(editor.getSelectedBufferRange()).toEqual [[12,0], [12,2]] describe ".selectToBeginningOfWord()", -> it "selects text from cusor position to beginning of word", -> - editSession.setCursorScreenPosition [0,13] - editSession.addCursorAtScreenPosition [3,49] + editor.setCursorScreenPosition [0,13] + editor.addCursorAtScreenPosition [3,49] - editSession.selectToBeginningOfWord() + editor.selectToBeginningOfWord() - expect(editSession.getCursors().length).toBe 2 - [cursor1, cursor2] = editSession.getCursors() + expect(editor.getCursors().length).toBe 2 + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,4] expect(cursor2.getBufferPosition()).toEqual [3,47] - expect(editSession.getSelections().length).toBe 2 - [selection1, selection2] = editSession.getSelections() + expect(editor.getSelections().length).toBe 2 + [selection1, selection2] = editor.getSelections() expect(selection1.getBufferRange()).toEqual [[0,4], [0,13]] expect(selection1.isReversed()).toBeTruthy() expect(selection2.getBufferRange()).toEqual [[3,47], [3,49]] @@ -804,18 +804,18 @@ describe "Editor", -> describe ".selectToEndOfWord()", -> it "selects text from cusor position to end of word", -> - editSession.setCursorScreenPosition [0,4] - editSession.addCursorAtScreenPosition [3,48] + editor.setCursorScreenPosition [0,4] + editor.addCursorAtScreenPosition [3,48] - editSession.selectToEndOfWord() + editor.selectToEndOfWord() - expect(editSession.getCursors().length).toBe 2 - [cursor1, cursor2] = editSession.getCursors() + expect(editor.getCursors().length).toBe 2 + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,13] expect(cursor2.getBufferPosition()).toEqual [3,50] - expect(editSession.getSelections().length).toBe 2 - [selection1, selection2] = editSession.getSelections() + expect(editor.getSelections().length).toBe 2 + [selection1, selection2] = editor.getSelections() expect(selection1.getBufferRange()).toEqual [[0,4], [0,13]] expect(selection1.isReversed()).toBeFalsy() expect(selection2.getBufferRange()).toEqual [[3,48], [3,50]] @@ -823,18 +823,18 @@ describe "Editor", -> describe ".selectToBeginningOfNextWord()", -> it "selects text from cusor position to beginning of next word", -> - editSession.setCursorScreenPosition [0,4] - editSession.addCursorAtScreenPosition [3,48] + editor.setCursorScreenPosition [0,4] + editor.addCursorAtScreenPosition [3,48] - editSession.selectToBeginningOfNextWord() + editor.selectToBeginningOfNextWord() - expect(editSession.getCursors().length).toBe 2 - [cursor1, cursor2] = editSession.getCursors() + expect(editor.getCursors().length).toBe 2 + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,14] expect(cursor2.getBufferPosition()).toEqual [3,51] - expect(editSession.getSelections().length).toBe 2 - [selection1, selection2] = editSession.getSelections() + expect(editor.getSelections().length).toBe 2 + [selection1, selection2] = editor.getSelections() expect(selection1.getBufferRange()).toEqual [[0,4], [0,14]] expect(selection1.isReversed()).toBeFalsy() expect(selection2.getBufferRange()).toEqual [[3,48], [3,51]] @@ -842,15 +842,15 @@ describe "Editor", -> describe ".selectToPreviousWordBoundary()", -> it "select to the previous word boundary", -> - editSession.setCursorBufferPosition [0, 8] - editSession.addCursorAtBufferPosition [2, 0] - editSession.addCursorAtBufferPosition [3, 4] - editSession.addCursorAtBufferPosition [3, 14] + editor.setCursorBufferPosition [0, 8] + editor.addCursorAtBufferPosition [2, 0] + editor.addCursorAtBufferPosition [3, 4] + editor.addCursorAtBufferPosition [3, 14] - editSession.selectToPreviousWordBoundary() + editor.selectToPreviousWordBoundary() - expect(editSession.getSelections().length).toBe 4 - [selection1, selection2, selection3, selection4] = editSession.getSelections() + expect(editor.getSelections().length).toBe 4 + [selection1, selection2, selection3, selection4] = editor.getSelections() expect(selection1.getBufferRange()).toEqual [[0,8], [0,4]] expect(selection1.isReversed()).toBeTruthy() expect(selection2.getBufferRange()).toEqual [[2,0], [1,30]] @@ -862,15 +862,15 @@ describe "Editor", -> describe ".selectToNextWordBoundary()", -> it "select to the next word boundary", -> - editSession.setCursorBufferPosition [0, 8] - editSession.addCursorAtBufferPosition [2, 40] - editSession.addCursorAtBufferPosition [4, 0] - editSession.addCursorAtBufferPosition [3, 30] + editor.setCursorBufferPosition [0, 8] + editor.addCursorAtBufferPosition [2, 40] + editor.addCursorAtBufferPosition [4, 0] + editor.addCursorAtBufferPosition [3, 30] - editSession.selectToNextWordBoundary() + editor.selectToNextWordBoundary() - expect(editSession.getSelections().length).toBe 4 - [selection1, selection2, selection3, selection4] = editSession.getSelections() + expect(editor.getSelections().length).toBe 4 + [selection1, selection2, selection3, selection4] = editor.getSelections() expect(selection1.getBufferRange()).toEqual [[0,8], [0,13]] expect(selection1.isReversed()).toBeFalsy() expect(selection2.getBufferRange()).toEqual [[2,40], [3,0]] @@ -883,58 +883,58 @@ describe "Editor", -> describe ".selectWord()", -> describe "when the cursor is inside a word", -> it "selects the entire word", -> - editSession.setCursorScreenPosition([0, 8]) - editSession.selectWord() - expect(editSession.getSelectedText()).toBe 'quicksort' + editor.setCursorScreenPosition([0, 8]) + editor.selectWord() + expect(editor.getSelectedText()).toBe 'quicksort' describe "when the cursor is between two words", -> it "selects the word the cursor is on", -> - editSession.setCursorScreenPosition([0, 4]) - editSession.selectWord() - expect(editSession.getSelectedText()).toBe 'quicksort' + editor.setCursorScreenPosition([0, 4]) + editor.selectWord() + expect(editor.getSelectedText()).toBe 'quicksort' - editSession.setCursorScreenPosition([0, 3]) - editSession.selectWord() - expect(editSession.getSelectedText()).toBe 'var' + editor.setCursorScreenPosition([0, 3]) + editor.selectWord() + expect(editor.getSelectedText()).toBe 'var' describe "when the cursor is inside a region of whitespace", -> it "selects the whitespace region", -> - editSession.setCursorScreenPosition([5, 2]) - editSession.selectWord() - expect(editSession.getSelectedBufferRange()).toEqual [[5, 0], [5, 6]] + editor.setCursorScreenPosition([5, 2]) + editor.selectWord() + expect(editor.getSelectedBufferRange()).toEqual [[5, 0], [5, 6]] - editSession.setCursorScreenPosition([5, 0]) - editSession.selectWord() - expect(editSession.getSelectedBufferRange()).toEqual [[5, 0], [5, 6]] + editor.setCursorScreenPosition([5, 0]) + editor.selectWord() + expect(editor.getSelectedBufferRange()).toEqual [[5, 0], [5, 6]] describe "when the cursor is at the end of the text", -> it "select the previous word", -> - editSession.buffer.append 'word' - editSession.moveCursorToBottom() - editSession.selectWord() - expect(editSession.getSelectedBufferRange()).toEqual [[12, 2], [12, 6]] + editor.buffer.append 'word' + editor.moveCursorToBottom() + editor.selectWord() + expect(editor.getSelectedBufferRange()).toEqual [[12, 2], [12, 6]] describe ".selectToFirstCharacterOfLine()", -> it "moves to the first character of the current line or the beginning of the line if it's already on the first character", -> - editSession.setCursorScreenPosition [0,5] - editSession.addCursorAtScreenPosition [1,7] + editor.setCursorScreenPosition [0,5] + editor.addCursorAtScreenPosition [1,7] - editSession.selectToFirstCharacterOfLine() + editor.selectToFirstCharacterOfLine() - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,0] expect(cursor2.getBufferPosition()).toEqual [1,2] - expect(editSession.getSelections().length).toBe 2 - [selection1, selection2] = editSession.getSelections() + expect(editor.getSelections().length).toBe 2 + [selection1, selection2] = editor.getSelections() expect(selection1.getBufferRange()).toEqual [[0,0], [0,5]] expect(selection1.isReversed()).toBeTruthy() expect(selection2.getBufferRange()).toEqual [[1,2], [1,7]] expect(selection2.isReversed()).toBeTruthy() - editSession.selectToFirstCharacterOfLine() - [selection1, selection2] = editSession.getSelections() + editor.selectToFirstCharacterOfLine() + [selection1, selection2] = editor.getSelections() expect(selection1.getBufferRange()).toEqual [[0,0], [0,5]] expect(selection1.isReversed()).toBeTruthy() expect(selection2.getBufferRange()).toEqual [[1,0], [1,7]] @@ -942,90 +942,90 @@ describe "Editor", -> describe ".setSelectedBufferRanges(ranges)", -> it "clears existing selections and creates selections for each of the given ranges", -> - editSession.setSelectedBufferRanges([[[2, 2], [3, 3]], [[4, 4], [5, 5]]]) - expect(editSession.getSelectedBufferRanges()).toEqual [[[2, 2], [3, 3]], [[4, 4], [5, 5]]] + editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[4, 4], [5, 5]]]) + expect(editor.getSelectedBufferRanges()).toEqual [[[2, 2], [3, 3]], [[4, 4], [5, 5]]] - editSession.setSelectedBufferRanges([[[5, 5], [6, 6]]]) - expect(editSession.getSelectedBufferRanges()).toEqual [[[5, 5], [6, 6]]] + editor.setSelectedBufferRanges([[[5, 5], [6, 6]]]) + expect(editor.getSelectedBufferRanges()).toEqual [[[5, 5], [6, 6]]] it "merges intersecting selections", -> - editSession.setSelectedBufferRanges([[[2, 2], [3, 3]], [[3, 0], [5, 5]]]) - expect(editSession.getSelectedBufferRanges()).toEqual [[[2, 2], [5, 5]]] + editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[3, 0], [5, 5]]]) + expect(editor.getSelectedBufferRanges()).toEqual [[[2, 2], [5, 5]]] it "recyles existing selection instances", -> - selection = editSession.getSelection() - editSession.setSelectedBufferRanges([[[2, 2], [3, 3]], [[4, 4], [5, 5]]]) + selection = editor.getSelection() + editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[4, 4], [5, 5]]]) - [selection1, selection2] = editSession.getSelections() + [selection1, selection2] = editor.getSelections() expect(selection1).toBe selection expect(selection1.getBufferRange()).toEqual [[2, 2], [3, 3]] describe "when the preserveFolds option is false (the default)", -> it "removes folds that contain the selections", -> - editSession.setSelectedBufferRange([[0,0], [0,0]]) - editSession.createFold(1, 4) - editSession.createFold(2, 3) - editSession.createFold(6, 8) - editSession.createFold(10, 11) + editor.setSelectedBufferRange([[0,0], [0,0]]) + editor.createFold(1, 4) + editor.createFold(2, 3) + editor.createFold(6, 8) + editor.createFold(10, 11) - editSession.setSelectedBufferRanges([[[2, 2], [3, 3]], [[6, 6], [7, 7]]]) - expect(editSession.lineForScreenRow(1).fold).toBeUndefined() - expect(editSession.lineForScreenRow(2).fold).toBeUndefined() - expect(editSession.lineForScreenRow(6).fold).toBeUndefined() - expect(editSession.lineForScreenRow(10).fold).toBeDefined() + editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[6, 6], [7, 7]]]) + expect(editor.lineForScreenRow(1).fold).toBeUndefined() + expect(editor.lineForScreenRow(2).fold).toBeUndefined() + expect(editor.lineForScreenRow(6).fold).toBeUndefined() + expect(editor.lineForScreenRow(10).fold).toBeDefined() describe "when the preserve folds option is true", -> it "does not remove folds that contain the selections", -> - editSession.setSelectedBufferRange([[0,0], [0,0]]) - editSession.createFold(1, 4) - editSession.createFold(6, 8) - editSession.setSelectedBufferRanges([[[2, 2], [3, 3]], [[6, 0], [6, 1]]], preserveFolds: true) - expect(editSession.isFoldedAtBufferRow(1)).toBeTruthy() - expect(editSession.isFoldedAtBufferRow(6)).toBeTruthy() + editor.setSelectedBufferRange([[0,0], [0,0]]) + editor.createFold(1, 4) + editor.createFold(6, 8) + editor.setSelectedBufferRanges([[[2, 2], [3, 3]], [[6, 0], [6, 1]]], preserveFolds: true) + expect(editor.isFoldedAtBufferRow(1)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(6)).toBeTruthy() describe ".selectMarker(marker)", -> describe "if the marker is valid", -> it "selects the marker's range and returns the selected range", -> - marker = editSession.markBufferRange([[0, 1], [3, 3]]) - expect(editSession.selectMarker(marker)).toEqual [[0, 1], [3, 3]] - expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [3, 3]] + marker = editor.markBufferRange([[0, 1], [3, 3]]) + expect(editor.selectMarker(marker)).toEqual [[0, 1], [3, 3]] + expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [3, 3]] describe "if the marker is invalid", -> it "does not change the selection and returns a falsy value", -> - marker = editSession.markBufferRange([[0, 1], [3, 3]]) + marker = editor.markBufferRange([[0, 1], [3, 3]]) marker.destroy() - expect(editSession.selectMarker(marker)).toBeFalsy() - expect(editSession.getSelectedBufferRange()).toEqual [[0, 0], [0, 0]] + expect(editor.selectMarker(marker)).toBeFalsy() + expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 0]] describe ".addSelectionBelow()", -> describe "when the selection is non-empty", -> it "selects the same region of the line below current selections if possible", -> - editSession.setSelectedBufferRange([[3, 16], [3, 21]]) - editSession.addSelectionForBufferRange([[3, 25], [3, 34]]) - editSession.addSelectionBelow() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setSelectedBufferRange([[3, 16], [3, 21]]) + editor.addSelectionForBufferRange([[3, 25], [3, 34]]) + editor.addSelectionBelow() + expect(editor.getSelectedBufferRanges()).toEqual [ [[3, 16], [3, 21]] [[3, 25], [3, 34]] [[4, 16], [4, 21]] [[4, 25], [4, 29]] ] - for cursor in editSession.getCursors() + for cursor in editor.getCursors() expect(cursor.isVisible()).toBeFalsy() it "skips lines that are too short to create a non-empty selection", -> - editSession.setSelectedBufferRange([[3, 31], [3, 38]]) - editSession.addSelectionBelow() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setSelectedBufferRange([[3, 31], [3, 38]]) + editor.addSelectionBelow() + expect(editor.getSelectedBufferRanges()).toEqual [ [[3, 31], [3, 38]] [[6, 31], [6, 38]] ] it "honors the original selection's range (goal range) when adding across shorter lines", -> - editSession.setSelectedBufferRange([[3, 22], [3, 38]]) - editSession.addSelectionBelow() - editSession.addSelectionBelow() - editSession.addSelectionBelow() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setSelectedBufferRange([[3, 22], [3, 38]]) + editor.addSelectionBelow() + editor.addSelectionBelow() + editor.addSelectionBelow() + expect(editor.getSelectedBufferRanges()).toEqual [ [[3, 22], [3, 38]] [[4, 22], [4, 29]] [[5, 22], [5, 30]] @@ -1033,19 +1033,19 @@ describe "Editor", -> ] it "clears selection goal ranges when the selection changes", -> - editSession.setSelectedBufferRange([[3, 22], [3, 38]]) - editSession.addSelectionBelow() - editSession.selectLeft() - editSession.addSelectionBelow() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setSelectedBufferRange([[3, 22], [3, 38]]) + editor.addSelectionBelow() + editor.selectLeft() + editor.addSelectionBelow() + expect(editor.getSelectedBufferRanges()).toEqual [ [[3, 22], [3, 37]] [[4, 22], [4, 29]] [[5, 22], [5, 28]] ] # goal range from previous add selection is honored next time - editSession.addSelectionBelow() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.addSelectionBelow() + expect(editor.getSelectedBufferRanges()).toEqual [ [[3, 22], [3, 37]] [[4, 22], [4, 29]] [[5, 22], [5, 30]] # select to end of line 5 because line 4's goal range was reset by line 3 previously @@ -1054,11 +1054,11 @@ describe "Editor", -> describe "when the selection is empty", -> it "does not skip lines that are shorter than the current column", -> - editSession.setCursorBufferPosition([3, 36]) - editSession.addSelectionBelow() - editSession.addSelectionBelow() - editSession.addSelectionBelow() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setCursorBufferPosition([3, 36]) + editor.addSelectionBelow() + editor.addSelectionBelow() + editor.addSelectionBelow() + expect(editor.getSelectedBufferRanges()).toEqual [ [[3, 36], [3, 36]] [[4, 29], [4, 29]] [[5, 30], [5, 30]] @@ -1066,17 +1066,17 @@ describe "Editor", -> ] it "skips empty lines when the column is non-zero", -> - editSession.setCursorBufferPosition([9, 4]) - editSession.addSelectionBelow() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setCursorBufferPosition([9, 4]) + editor.addSelectionBelow() + expect(editor.getSelectedBufferRanges()).toEqual [ [[9, 4], [9, 4]] [[11, 4], [11, 4]] ] it "does not skip empty lines when the column is zero", -> - editSession.setCursorBufferPosition([9, 0]) - editSession.addSelectionBelow() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setCursorBufferPosition([9, 0]) + editor.addSelectionBelow() + expect(editor.getSelectedBufferRanges()).toEqual [ [[9, 0], [9, 0]] [[10, 0], [10, 0]] ] @@ -1084,32 +1084,32 @@ describe "Editor", -> describe ".addSelectionAbove()", -> describe "when the selection is non-empty", -> it "selects the same region of the line above current selections if possible", -> - editSession.setSelectedBufferRange([[3, 16], [3, 21]]) - editSession.addSelectionForBufferRange([[3, 37], [3, 44]]) - editSession.addSelectionAbove() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setSelectedBufferRange([[3, 16], [3, 21]]) + editor.addSelectionForBufferRange([[3, 37], [3, 44]]) + editor.addSelectionAbove() + expect(editor.getSelectedBufferRanges()).toEqual [ [[2, 16], [2, 21]] [[2, 37], [2, 40]] [[3, 16], [3, 21]] [[3, 37], [3, 44]] ] - for cursor in editSession.getCursors() + for cursor in editor.getCursors() expect(cursor.isVisible()).toBeFalsy() it "skips lines that are too short to create a non-empty selection", -> - editSession.setSelectedBufferRange([[6, 31], [6, 38]]) - editSession.addSelectionAbove() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setSelectedBufferRange([[6, 31], [6, 38]]) + editor.addSelectionAbove() + expect(editor.getSelectedBufferRanges()).toEqual [ [[3, 31], [3, 38]] [[6, 31], [6, 38]] ] it "honors the original selection's range (goal range) when adding across shorter lines", -> - editSession.setSelectedBufferRange([[6, 22], [6, 38]]) - editSession.addSelectionAbove() - editSession.addSelectionAbove() - editSession.addSelectionAbove() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setSelectedBufferRange([[6, 22], [6, 38]]) + editor.addSelectionAbove() + editor.addSelectionAbove() + editor.addSelectionAbove() + expect(editor.getSelectedBufferRanges()).toEqual [ [[3, 22], [3, 38]] [[4, 22], [4, 29]] [[5, 22], [5, 30]] @@ -1118,11 +1118,11 @@ describe "Editor", -> describe "when the selection is empty", -> it "does not skip lines that are shorter than the current column", -> - editSession.setCursorBufferPosition([6, 36]) - editSession.addSelectionAbove() - editSession.addSelectionAbove() - editSession.addSelectionAbove() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setCursorBufferPosition([6, 36]) + editor.addSelectionAbove() + editor.addSelectionAbove() + editor.addSelectionAbove() + expect(editor.getSelectedBufferRanges()).toEqual [ [[3, 36], [3, 36]] [[4, 29], [4, 29]] [[5, 30], [5, 30]] @@ -1130,91 +1130,91 @@ describe "Editor", -> ] it "skips empty lines when the column is non-zero", -> - editSession.setCursorBufferPosition([11, 4]) - editSession.addSelectionAbove() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setCursorBufferPosition([11, 4]) + editor.addSelectionAbove() + expect(editor.getSelectedBufferRanges()).toEqual [ [[9, 4], [9, 4]] [[11, 4], [11, 4]] ] it "does not skip empty lines when the column is zero", -> - editSession.setCursorBufferPosition([10, 0]) - editSession.addSelectionAbove() - expect(editSession.getSelectedBufferRanges()).toEqual [ + editor.setCursorBufferPosition([10, 0]) + editor.addSelectionAbove() + expect(editor.getSelectedBufferRanges()).toEqual [ [[9, 0], [9, 0]] [[10, 0], [10, 0]] ] describe ".consolidateSelections()", -> it "destroys all selections but the most recent, returning true if any selections were destroyed", -> - editSession.setSelectedBufferRange([[3, 16], [3, 21]]) - selection1 = editSession.getSelection() - selection2 = editSession.addSelectionForBufferRange([[3, 25], [3, 34]]) - selection3 = editSession.addSelectionForBufferRange([[8, 4], [8, 10]]) + editor.setSelectedBufferRange([[3, 16], [3, 21]]) + selection1 = editor.getSelection() + selection2 = editor.addSelectionForBufferRange([[3, 25], [3, 34]]) + selection3 = editor.addSelectionForBufferRange([[8, 4], [8, 10]]) - expect(editSession.getSelections()).toEqual [selection1, selection2, selection3] - expect(editSession.consolidateSelections()).toBeTruthy() - expect(editSession.getSelections()).toEqual [selection3] + expect(editor.getSelections()).toEqual [selection1, selection2, selection3] + expect(editor.consolidateSelections()).toBeTruthy() + expect(editor.getSelections()).toEqual [selection3] expect(selection3.isEmpty()).toBeFalsy() - expect(editSession.consolidateSelections()).toBeFalsy() - expect(editSession.getSelections()).toEqual [selection3] + expect(editor.consolidateSelections()).toBeFalsy() + expect(editor.getSelections()).toEqual [selection3] describe "when the cursor is moved while there is a selection", -> makeSelection = -> selection.setBufferRange [[1, 2], [1, 5]] it "clears the selection", -> makeSelection() - editSession.moveCursorDown() + editor.moveCursorDown() expect(selection.isEmpty()).toBeTruthy() makeSelection() - editSession.moveCursorUp() + editor.moveCursorUp() expect(selection.isEmpty()).toBeTruthy() makeSelection() - editSession.moveCursorLeft() + editor.moveCursorLeft() expect(selection.isEmpty()).toBeTruthy() makeSelection() - editSession.moveCursorRight() + editor.moveCursorRight() expect(selection.isEmpty()).toBeTruthy() makeSelection() - editSession.setCursorScreenPosition([3, 3]) + editor.setCursorScreenPosition([3, 3]) expect(selection.isEmpty()).toBeTruthy() it "does not share selections between different edit sessions for the same buffer", -> - editSession2 = project.openSync('sample.js') - editSession.setSelectedBufferRanges([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) - editSession2.setSelectedBufferRanges([[[8, 7], [6, 5]], [[4, 3], [2, 1]]]) - expect(editSession2.getSelectedBufferRanges()).not.toEqual editSession.getSelectedBufferRanges() + editor2 = project.openSync('sample.js') + editor.setSelectedBufferRanges([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) + editor2.setSelectedBufferRanges([[[8, 7], [6, 5]], [[4, 3], [2, 1]]]) + expect(editor2.getSelectedBufferRanges()).not.toEqual editor.getSelectedBufferRanges() describe "buffer manipulation", -> describe ".insertText(text)", -> describe "when there are multiple empty selections", -> describe "when the cursors are on the same line", -> it "inserts the given text at the location of each cursor and moves the cursors to the end of each cursor's inserted text", -> - editSession.setCursorScreenPosition([1, 2]) - editSession.addCursorAtScreenPosition([1, 5]) + editor.setCursorScreenPosition([1, 2]) + editor.addCursorAtScreenPosition([1, 5]) - editSession.insertText('xxx') + editor.insertText('xxx') expect(buffer.lineForRow(1)).toBe ' xxxvarxxx sort = function(items) {' - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [1, 5] expect(cursor2.getBufferPosition()).toEqual [1, 11] describe "when the cursors are on different lines", -> it "inserts the given text at the location of each cursor and moves the cursors to the end of each cursor's inserted text", -> - editSession.setCursorScreenPosition([1, 2]) - editSession.addCursorAtScreenPosition([2, 4]) + editor.setCursorScreenPosition([1, 2]) + editor.addCursorAtScreenPosition([2, 4]) - editSession.insertText('xxx') + editor.insertText('xxx') expect(buffer.lineForRow(1)).toBe ' xxxvar sort = function(items) {' expect(buffer.lineForRow(2)).toBe ' xxxif (items.length <= 1) return items;' - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [1, 5] expect(cursor2.getBufferPosition()).toEqual [2, 7] @@ -1222,28 +1222,28 @@ describe "Editor", -> describe "when there are multiple non-empty selections", -> describe "when the selections are on the same line", -> it "replaces each selection range with the inserted characters", -> - editSession.setSelectedBufferRanges([[[0,4], [0,13]], [[0,22], [0,24]]]) - editSession.insertText("x") + editor.setSelectedBufferRanges([[[0,4], [0,13]], [[0,22], [0,24]]]) + editor.insertText("x") - [cursor1, cursor2] = editSession.getCursors() - [selection1, selection2] = editSession.getSelections() + [cursor1, cursor2] = editor.getCursors() + [selection1, selection2] = editor.getSelections() expect(cursor1.getScreenPosition()).toEqual [0, 5] expect(cursor2.getScreenPosition()).toEqual [0, 15] expect(selection1.isEmpty()).toBeTruthy() expect(selection2.isEmpty()).toBeTruthy() - expect(editSession.lineForBufferRow(0)).toBe "var x = functix () {" + expect(editor.lineForBufferRow(0)).toBe "var x = functix () {" describe "when the selections are on different lines", -> it "replaces each selection with the given text, clears the selections, and places the cursor at the end of each selection's inserted text", -> - editSession.setSelectedBufferRanges([[[1, 0], [1, 2]], [[2, 0], [2, 4]]]) + editor.setSelectedBufferRanges([[[1, 0], [1, 2]], [[2, 0], [2, 4]]]) - editSession.insertText('xxx') + editor.insertText('xxx') expect(buffer.lineForRow(1)).toBe 'xxxvar sort = function(items) {' expect(buffer.lineForRow(2)).toBe 'xxxif (items.length <= 1) return items;' - [selection1, selection2] = editSession.getSelections() + [selection1, selection2] = editor.getSelections() expect(selection1.isEmpty()).toBeTruthy() expect(selection1.cursor.getBufferPosition()).toEqual [1, 3] @@ -1252,138 +1252,138 @@ describe "Editor", -> describe "when there is a selection that ends on a folded line", -> it "destroys the selection", -> - editSession.createFold(2,4) - editSession.setSelectedBufferRange([[1,0], [2,0]]) - editSession.insertText('holy cow') - expect(editSession.lineForScreenRow(2).fold).toBeUndefined() + editor.createFold(2,4) + editor.setSelectedBufferRange([[1,0], [2,0]]) + editor.insertText('holy cow') + expect(editor.lineForScreenRow(2).fold).toBeUndefined() describe ".insertNewline()", -> describe "when there is a single cursor", -> describe "when the cursor is at the beginning of a line", -> it "inserts an empty line before it", -> - editSession.setCursorScreenPosition(row: 1, column: 0) + editor.setCursorScreenPosition(row: 1, column: 0) - editSession.insertNewline() + editor.insertNewline() expect(buffer.lineForRow(1)).toBe '' - expect(editSession.getCursorScreenPosition()).toEqual(row: 2, column: 0) + expect(editor.getCursorScreenPosition()).toEqual(row: 2, column: 0) describe "when the cursor is in the middle of a line", -> it "splits the current line to form a new line", -> - editSession.setCursorScreenPosition(row: 1, column: 6) + editor.setCursorScreenPosition(row: 1, column: 6) originalLine = buffer.lineForRow(1) lineBelowOriginalLine = buffer.lineForRow(2) - editSession.insertNewline() + editor.insertNewline() expect(buffer.lineForRow(1)).toBe originalLine[0...6] expect(buffer.lineForRow(2)).toBe originalLine[6..] expect(buffer.lineForRow(3)).toBe lineBelowOriginalLine - expect(editSession.getCursorScreenPosition()).toEqual(row: 2, column: 0) + expect(editor.getCursorScreenPosition()).toEqual(row: 2, column: 0) describe "when the cursor is on the end of a line", -> it "inserts an empty line after it", -> - editSession.setCursorScreenPosition(row: 1, column: buffer.lineForRow(1).length) + editor.setCursorScreenPosition(row: 1, column: buffer.lineForRow(1).length) - editSession.insertNewline() + editor.insertNewline() expect(buffer.lineForRow(2)).toBe '' - expect(editSession.getCursorScreenPosition()).toEqual(row: 2, column: 0) + expect(editor.getCursorScreenPosition()).toEqual(row: 2, column: 0) describe "when there are multiple cursors", -> describe "when the cursors are on the same line", -> it "breaks the line at the cursor locations", -> - editSession.setCursorScreenPosition([3, 13]) - editSession.addCursorAtScreenPosition([3, 38]) + editor.setCursorScreenPosition([3, 13]) + editor.addCursorAtScreenPosition([3, 38]) - editSession.insertNewline() + editor.insertNewline() - expect(editSession.lineForBufferRow(3)).toBe " var pivot" - expect(editSession.lineForBufferRow(4)).toBe " = items.shift(), current" - expect(editSession.lineForBufferRow(5)).toBe ", left = [], right = [];" - expect(editSession.lineForBufferRow(6)).toBe " while(items.length > 0) {" + expect(editor.lineForBufferRow(3)).toBe " var pivot" + expect(editor.lineForBufferRow(4)).toBe " = items.shift(), current" + expect(editor.lineForBufferRow(5)).toBe ", left = [], right = [];" + expect(editor.lineForBufferRow(6)).toBe " while(items.length > 0) {" - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [4, 0] expect(cursor2.getBufferPosition()).toEqual [5, 0] describe "when the cursors are on different lines", -> it "inserts newlines at each cursor location", -> - editSession.setCursorScreenPosition([3, 0]) - editSession.addCursorAtScreenPosition([6, 0]) + editor.setCursorScreenPosition([3, 0]) + editor.addCursorAtScreenPosition([6, 0]) - editSession.insertText("\n") - expect(editSession.lineForBufferRow(3)).toBe "" - expect(editSession.lineForBufferRow(4)).toBe " var pivot = items.shift(), current, left = [], right = [];" - expect(editSession.lineForBufferRow(5)).toBe " while(items.length > 0) {" - expect(editSession.lineForBufferRow(6)).toBe " current = items.shift();" - expect(editSession.lineForBufferRow(7)).toBe "" - expect(editSession.lineForBufferRow(8)).toBe " current < pivot ? left.push(current) : right.push(current);" - expect(editSession.lineForBufferRow(9)).toBe " }" + editor.insertText("\n") + expect(editor.lineForBufferRow(3)).toBe "" + expect(editor.lineForBufferRow(4)).toBe " var pivot = items.shift(), current, left = [], right = [];" + expect(editor.lineForBufferRow(5)).toBe " while(items.length > 0) {" + expect(editor.lineForBufferRow(6)).toBe " current = items.shift();" + expect(editor.lineForBufferRow(7)).toBe "" + expect(editor.lineForBufferRow(8)).toBe " current < pivot ? left.push(current) : right.push(current);" + expect(editor.lineForBufferRow(9)).toBe " }" - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [4,0] expect(cursor2.getBufferPosition()).toEqual [8,0] describe ".insertNewlineBelow()", -> describe "when the operation is undone", -> it "places the cursor back at the previous location", -> - editSession.setCursorBufferPosition([0,2]) - editSession.insertNewlineBelow() - expect(editSession.getCursorBufferPosition()).toEqual [1,0] - editSession.undo() - expect(editSession.getCursorBufferPosition()).toEqual [0,2] + editor.setCursorBufferPosition([0,2]) + editor.insertNewlineBelow() + expect(editor.getCursorBufferPosition()).toEqual [1,0] + editor.undo() + expect(editor.getCursorBufferPosition()).toEqual [0,2] it "inserts a newline below the cursor's current line, autoindents it, and moves the cursor to the end of the line", -> atom.config.set("editor.autoIndent", true) - editSession.insertNewlineBelow() + editor.insertNewlineBelow() expect(buffer.lineForRow(0)).toBe "var quicksort = function () {" expect(buffer.lineForRow(1)).toBe " " - expect(editSession.getCursorBufferPosition()).toEqual [1, 2] + expect(editor.getCursorBufferPosition()).toEqual [1, 2] describe ".insertNewlineAbove()", -> describe "when the cursor is on first line", -> it "inserts a newline on the first line and moves the cursor to the first line", -> - editSession.setCursorBufferPosition([0]) - editSession.insertNewlineAbove() - expect(editSession.getCursorBufferPosition()).toEqual [0,0] - expect(editSession.lineForBufferRow(0)).toBe '' - expect(editSession.lineForBufferRow(1)).toBe 'var quicksort = function () {' - expect(editSession.buffer.getLineCount()).toBe 14 + editor.setCursorBufferPosition([0]) + editor.insertNewlineAbove() + expect(editor.getCursorBufferPosition()).toEqual [0,0] + expect(editor.lineForBufferRow(0)).toBe '' + expect(editor.lineForBufferRow(1)).toBe 'var quicksort = function () {' + expect(editor.buffer.getLineCount()).toBe 14 describe "when the cursor is not on the first line", -> it "inserts a newline above the current line and moves the cursor to the inserted line", -> - editSession.setCursorBufferPosition([3,4]) - editSession.insertNewlineAbove() - expect(editSession.getCursorBufferPosition()).toEqual [3,0] - expect(editSession.lineForBufferRow(3)).toBe '' - expect(editSession.lineForBufferRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];' - expect(editSession.buffer.getLineCount()).toBe 14 + editor.setCursorBufferPosition([3,4]) + editor.insertNewlineAbove() + expect(editor.getCursorBufferPosition()).toEqual [3,0] + expect(editor.lineForBufferRow(3)).toBe '' + expect(editor.lineForBufferRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];' + expect(editor.buffer.getLineCount()).toBe 14 - editSession.undo() - expect(editSession.getCursorBufferPosition()).toEqual [3,4] + editor.undo() + expect(editor.getCursorBufferPosition()).toEqual [3,4] describe ".backspace()", -> describe "when there is a single cursor", -> changeScreenRangeHandler = null beforeEach -> - selection = editSession.getLastSelection() + selection = editor.getLastSelection() changeScreenRangeHandler = jasmine.createSpy('changeScreenRangeHandler') selection.on 'screen-range-changed', changeScreenRangeHandler describe "when the cursor is on the middle of the line", -> it "removes the character before the cursor", -> - editSession.setCursorScreenPosition(row: 1, column: 7) + editor.setCursorScreenPosition(row: 1, column: 7) expect(buffer.lineForRow(1)).toBe " var sort = function(items) {" - editSession.backspace() + editor.backspace() line = buffer.lineForRow(1) expect(line).toBe " var ort = function(items) {" - expect(editSession.getCursorScreenPosition()).toEqual {row: 1, column: 6} + expect(editor.getCursorScreenPosition()).toEqual {row: 1, column: 6} expect(changeScreenRangeHandler).toHaveBeenCalled() - expect(editSession.getCursor().isVisible()).toBeTruthy() + expect(editor.getCursor().isVisible()).toBeTruthy() describe "when the cursor is at the beginning of a line", -> it "joins it with the line above", -> @@ -1391,145 +1391,145 @@ describe "Editor", -> expect(originalLine0).toBe "var quicksort = function () {" expect(buffer.lineForRow(1)).toBe " var sort = function(items) {" - editSession.setCursorScreenPosition(row: 1, column: 0) - editSession.backspace() + editor.setCursorScreenPosition(row: 1, column: 0) + editor.backspace() line0 = buffer.lineForRow(0) line1 = buffer.lineForRow(1) expect(line0).toBe "var quicksort = function () { var sort = function(items) {" expect(line1).toBe " if (items.length <= 1) return items;" - expect(editSession.getCursorScreenPosition()).toEqual [0, originalLine0.length] + expect(editor.getCursorScreenPosition()).toEqual [0, originalLine0.length] expect(changeScreenRangeHandler).toHaveBeenCalled() describe "when the cursor is at the first column of the first line", -> it "does nothing, but doesn't raise an error", -> - editSession.setCursorScreenPosition(row: 0, column: 0) - editSession.backspace() + editor.setCursorScreenPosition(row: 0, column: 0) + editor.backspace() describe "when the cursor is on the first column of a line below a fold", -> it "deletes the folded lines", -> - editSession.setCursorScreenPosition([4,0]) - editSession.foldCurrentRow() - editSession.setCursorScreenPosition([5,0]) - editSession.backspace() + editor.setCursorScreenPosition([4,0]) + editor.foldCurrentRow() + editor.setCursorScreenPosition([5,0]) + editor.backspace() expect(buffer.lineForRow(4)).toBe " return sort(left).concat(pivot).concat(sort(right));" expect(buffer.lineForRow(4).fold).toBeUndefined() describe "when the cursor is in the middle of a line below a fold", -> it "backspaces as normal", -> - editSession.setCursorScreenPosition([4,0]) - editSession.foldCurrentRow() - editSession.setCursorScreenPosition([5,5]) - editSession.backspace() + editor.setCursorScreenPosition([4,0]) + editor.foldCurrentRow() + editor.setCursorScreenPosition([5,5]) + editor.backspace() expect(buffer.lineForRow(7)).toBe " }" expect(buffer.lineForRow(8)).toBe " eturn sort(left).concat(pivot).concat(sort(right));" describe "when the cursor is on a folded screen line", -> it "deletes all of the folded lines along with the fold", -> - editSession.setCursorBufferPosition([3, 0]) - editSession.foldCurrentRow() - editSession.backspace() + editor.setCursorBufferPosition([3, 0]) + editor.foldCurrentRow() + editor.backspace() expect(buffer.lineForRow(1)).toBe "" expect(buffer.lineForRow(2)).toBe " return sort(Array.apply(this, arguments));" - expect(editSession.getCursorScreenPosition()).toEqual [1, 0] + expect(editor.getCursorScreenPosition()).toEqual [1, 0] describe "when there are multiple cursors", -> describe "when cursors are on the same line", -> it "removes the characters preceding each cursor", -> - editSession.setCursorScreenPosition([3, 13]) - editSession.addCursorAtScreenPosition([3, 38]) + editor.setCursorScreenPosition([3, 13]) + editor.addCursorAtScreenPosition([3, 38]) - editSession.backspace() + editor.backspace() - expect(editSession.lineForBufferRow(3)).toBe " var pivo = items.shift(), curren, left = [], right = [];" + expect(editor.lineForBufferRow(3)).toBe " var pivo = items.shift(), curren, left = [], right = [];" - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [3, 12] expect(cursor2.getBufferPosition()).toEqual [3, 36] - [selection1, selection2] = editSession.getSelections() + [selection1, selection2] = editor.getSelections() expect(selection1.isEmpty()).toBeTruthy() expect(selection2.isEmpty()).toBeTruthy() describe "when cursors are on different lines", -> describe "when the cursors are in the middle of their lines", -> it "removes the characters preceding each cursor", -> - editSession.setCursorScreenPosition([3, 13]) - editSession.addCursorAtScreenPosition([4, 10]) + editor.setCursorScreenPosition([3, 13]) + editor.addCursorAtScreenPosition([4, 10]) - editSession.backspace() + editor.backspace() - expect(editSession.lineForBufferRow(3)).toBe " var pivo = items.shift(), current, left = [], right = [];" - expect(editSession.lineForBufferRow(4)).toBe " whileitems.length > 0) {" + expect(editor.lineForBufferRow(3)).toBe " var pivo = items.shift(), current, left = [], right = [];" + expect(editor.lineForBufferRow(4)).toBe " whileitems.length > 0) {" - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [3, 12] expect(cursor2.getBufferPosition()).toEqual [4, 9] - [selection1, selection2] = editSession.getSelections() + [selection1, selection2] = editor.getSelections() expect(selection1.isEmpty()).toBeTruthy() expect(selection2.isEmpty()).toBeTruthy() describe "when the cursors are on the first column of their lines", -> it "removes the newlines preceding each cursor", -> - editSession.setCursorScreenPosition([3, 0]) - editSession.addCursorAtScreenPosition([6, 0]) + editor.setCursorScreenPosition([3, 0]) + editor.addCursorAtScreenPosition([6, 0]) - editSession.backspace() - expect(editSession.lineForBufferRow(2)).toBe " if (items.length <= 1) return items; var pivot = items.shift(), current, left = [], right = [];" - expect(editSession.lineForBufferRow(3)).toBe " while(items.length > 0) {" - expect(editSession.lineForBufferRow(4)).toBe " current = items.shift(); current < pivot ? left.push(current) : right.push(current);" - expect(editSession.lineForBufferRow(5)).toBe " }" + editor.backspace() + expect(editor.lineForBufferRow(2)).toBe " if (items.length <= 1) return items; var pivot = items.shift(), current, left = [], right = [];" + expect(editor.lineForBufferRow(3)).toBe " while(items.length > 0) {" + expect(editor.lineForBufferRow(4)).toBe " current = items.shift(); current < pivot ? left.push(current) : right.push(current);" + expect(editor.lineForBufferRow(5)).toBe " }" - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [2,40] expect(cursor2.getBufferPosition()).toEqual [4,30] describe "when there is a single selection", -> it "deletes the selection, but not the character before it", -> - editSession.setSelectedBufferRange([[0,5], [0,9]]) - editSession.backspace() - expect(editSession.buffer.lineForRow(0)).toBe 'var qsort = function () {' + editor.setSelectedBufferRange([[0,5], [0,9]]) + editor.backspace() + expect(editor.buffer.lineForRow(0)).toBe 'var qsort = function () {' describe "when the selection ends on a folded line", -> it "preserves the fold", -> - editSession.setSelectedBufferRange([[3,0], [4,0]]) - editSession.foldBufferRow(4) - editSession.backspace() + editor.setSelectedBufferRange([[3,0], [4,0]]) + editor.foldBufferRow(4) + editor.backspace() expect(buffer.lineForRow(3)).toBe " while(items.length > 0) {" - expect(editSession.lineForScreenRow(3).fold).toBeDefined() + expect(editor.lineForScreenRow(3).fold).toBeDefined() describe "when there are multiple selections", -> it "removes all selected text", -> - editSession.setSelectedBufferRanges([[[0,4], [0,13]], [[0,16], [0,24]]]) - editSession.backspace() - expect(editSession.lineForBufferRow(0)).toBe 'var = () {' + editor.setSelectedBufferRanges([[[0,4], [0,13]], [[0,16], [0,24]]]) + editor.backspace() + expect(editor.lineForBufferRow(0)).toBe 'var = () {' describe ".backspaceToBeginningOfWord()", -> describe "when no text is selected", -> it "deletes all text between the cursor and the beginning of the word", -> - editSession.setCursorBufferPosition([1, 24]) - editSession.addCursorAtBufferPosition([3, 5]) - [cursor1, cursor2] = editSession.getCursors() + editor.setCursorBufferPosition([1, 24]) + editor.addCursorAtBufferPosition([3, 5]) + [cursor1, cursor2] = editor.getCursors() - editSession.backspaceToBeginningOfWord() + editor.backspaceToBeginningOfWord() expect(buffer.lineForRow(1)).toBe ' var sort = function(ems) {' expect(buffer.lineForRow(3)).toBe ' ar pivot = items.shift(), current, left = [], right = [];' expect(cursor1.getBufferPosition()).toEqual [1, 22] expect(cursor2.getBufferPosition()).toEqual [3, 4] - editSession.backspaceToBeginningOfWord() + editor.backspaceToBeginningOfWord() expect(buffer.lineForRow(1)).toBe ' var sort = functionems) {' expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return itemsar pivot = items.shift(), current, left = [], right = [];' expect(cursor1.getBufferPosition()).toEqual [1, 21] expect(cursor2.getBufferPosition()).toEqual [2, 39] - editSession.backspaceToBeginningOfWord() + editor.backspaceToBeginningOfWord() expect(buffer.lineForRow(1)).toBe ' var sort = ems) {' expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return ar pivot = items.shift(), current, left = [], right = [];' expect(cursor1.getBufferPosition()).toEqual [1, 13] @@ -1537,19 +1537,19 @@ describe "Editor", -> describe "when text is selected", -> it "deletes only selected text", -> - editSession.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]]) - editSession.backspaceToBeginningOfWord() + editor.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]]) + editor.backspaceToBeginningOfWord() expect(buffer.lineForRow(1)).toBe ' var sort = function(it) {' expect(buffer.lineForRow(2)).toBe 'if (items.length <= 1) return items;' describe ".backspaceToBeginningOfLine()", -> describe "when no text is selected", -> it "deletes all text between the cursor and the beginning of the line", -> - editSession.setCursorBufferPosition([1, 24]) - editSession.addCursorAtBufferPosition([2, 5]) - [cursor1, cursor2] = editSession.getCursors() + editor.setCursorBufferPosition([1, 24]) + editor.addCursorAtBufferPosition([2, 5]) + [cursor1, cursor2] = editor.getCursors() - editSession.backspaceToBeginningOfLine() + editor.backspaceToBeginningOfLine() expect(buffer.lineForRow(1)).toBe 'ems) {' expect(buffer.lineForRow(2)).toBe 'f (items.length <= 1) return items;' expect(cursor1.getBufferPosition()).toEqual [1, 0] @@ -1557,14 +1557,14 @@ describe "Editor", -> describe "when at the beginning of the line", -> it "deletes the newline", -> - editSession.setCursorBufferPosition([2]) - editSession.backspaceToBeginningOfLine() + editor.setCursorBufferPosition([2]) + editor.backspaceToBeginningOfLine() expect(buffer.lineForRow(1)).toBe ' var sort = function(items) { if (items.length <= 1) return items;' describe "when text is selected", -> it "still deletes all text to begginning of the line", -> - editSession.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]]) - editSession.backspaceToBeginningOfLine() + editor.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]]) + editor.backspaceToBeginningOfLine() expect(buffer.lineForRow(1)).toBe 'ems) {' expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return items;' @@ -1572,137 +1572,137 @@ describe "Editor", -> describe "when there is a single cursor", -> describe "when the cursor is on the middle of a line", -> it "deletes the character following the cursor", -> - editSession.setCursorScreenPosition([1, 6]) - editSession.delete() + editor.setCursorScreenPosition([1, 6]) + editor.delete() expect(buffer.lineForRow(1)).toBe ' var ort = function(items) {' describe "when the cursor is on the end of a line", -> it "joins the line with the following line", -> - editSession.setCursorScreenPosition([1, buffer.lineForRow(1).length]) - editSession.delete() + editor.setCursorScreenPosition([1, buffer.lineForRow(1).length]) + editor.delete() expect(buffer.lineForRow(1)).toBe ' var sort = function(items) { if (items.length <= 1) return items;' describe "when the cursor is on the last column of the last line", -> it "does nothing, but doesn't raise an error", -> - editSession.setCursorScreenPosition([12, buffer.lineForRow(12).length]) - editSession.delete() + editor.setCursorScreenPosition([12, buffer.lineForRow(12).length]) + editor.delete() expect(buffer.lineForRow(12)).toBe '};' describe "when the cursor is on the end of a line above a fold", -> it "only deletes the lines inside the fold", -> - editSession.foldBufferRow(4) - editSession.setCursorScreenPosition([3, Infinity]) - cursorPositionBefore = editSession.getCursorScreenPosition() + editor.foldBufferRow(4) + editor.setCursorScreenPosition([3, Infinity]) + cursorPositionBefore = editor.getCursorScreenPosition() - editSession.delete() + editor.delete() expect(buffer.lineForRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];" expect(buffer.lineForRow(4)).toBe " return sort(left).concat(pivot).concat(sort(right));" - expect(editSession.getCursorScreenPosition()).toEqual cursorPositionBefore + expect(editor.getCursorScreenPosition()).toEqual cursorPositionBefore describe "when the cursor is in the middle a line above a fold", -> it "deletes as normal", -> - editSession.foldBufferRow(4) - editSession.setCursorScreenPosition([3, 4]) - cursorPositionBefore = editSession.getCursorScreenPosition() + editor.foldBufferRow(4) + editor.setCursorScreenPosition([3, 4]) + cursorPositionBefore = editor.getCursorScreenPosition() - editSession.delete() + editor.delete() expect(buffer.lineForRow(3)).toBe " ar pivot = items.shift(), current, left = [], right = [];" - expect(editSession.lineForScreenRow(4).fold).toBeDefined() - expect(editSession.getCursorScreenPosition()).toEqual [3, 4] + expect(editor.lineForScreenRow(4).fold).toBeDefined() + expect(editor.getCursorScreenPosition()).toEqual [3, 4] describe "when the cursor is on a folded line", -> it "removes the lines contained by the fold", -> - editSession.setSelectedBufferRange([[2, 0], [2, 0]]) - editSession.createFold(2,4) - editSession.createFold(2,6) + editor.setSelectedBufferRange([[2, 0], [2, 0]]) + editor.createFold(2,4) + editor.createFold(2,6) oldLine7 = buffer.lineForRow(7) oldLine8 = buffer.lineForRow(8) - editSession.delete() - expect(editSession.lineForScreenRow(2).text).toBe oldLine7 - expect(editSession.lineForScreenRow(3).text).toBe oldLine8 + editor.delete() + expect(editor.lineForScreenRow(2).text).toBe oldLine7 + expect(editor.lineForScreenRow(3).text).toBe oldLine8 describe "when there are multiple cursors", -> describe "when cursors are on the same line", -> it "removes the characters following each cursor", -> - editSession.setCursorScreenPosition([3, 13]) - editSession.addCursorAtScreenPosition([3, 38]) + editor.setCursorScreenPosition([3, 13]) + editor.addCursorAtScreenPosition([3, 38]) - editSession.delete() + editor.delete() - expect(editSession.lineForBufferRow(3)).toBe " var pivot= items.shift(), current left = [], right = [];" + expect(editor.lineForBufferRow(3)).toBe " var pivot= items.shift(), current left = [], right = [];" - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [3, 13] expect(cursor2.getBufferPosition()).toEqual [3, 37] - [selection1, selection2] = editSession.getSelections() + [selection1, selection2] = editor.getSelections() expect(selection1.isEmpty()).toBeTruthy() expect(selection2.isEmpty()).toBeTruthy() describe "when cursors are on different lines", -> describe "when the cursors are in the middle of the lines", -> it "removes the characters following each cursor", -> - editSession.setCursorScreenPosition([3, 13]) - editSession.addCursorAtScreenPosition([4, 10]) + editor.setCursorScreenPosition([3, 13]) + editor.addCursorAtScreenPosition([4, 10]) - editSession.delete() + editor.delete() - expect(editSession.lineForBufferRow(3)).toBe " var pivot= items.shift(), current, left = [], right = [];" - expect(editSession.lineForBufferRow(4)).toBe " while(tems.length > 0) {" + expect(editor.lineForBufferRow(3)).toBe " var pivot= items.shift(), current, left = [], right = [];" + expect(editor.lineForBufferRow(4)).toBe " while(tems.length > 0) {" - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [3, 13] expect(cursor2.getBufferPosition()).toEqual [4, 10] - [selection1, selection2] = editSession.getSelections() + [selection1, selection2] = editor.getSelections() expect(selection1.isEmpty()).toBeTruthy() expect(selection2.isEmpty()).toBeTruthy() describe "when the cursors are at the end of their lines", -> it "removes the newlines following each cursor", -> - editSession.setCursorScreenPosition([0, 29]) - editSession.addCursorAtScreenPosition([1, 30]) + editor.setCursorScreenPosition([0, 29]) + editor.addCursorAtScreenPosition([1, 30]) - editSession.delete() + editor.delete() - expect(editSession.lineForBufferRow(0)).toBe "var quicksort = function () { var sort = function(items) { if (items.length <= 1) return items;" + expect(editor.lineForBufferRow(0)).toBe "var quicksort = function () { var sort = function(items) { if (items.length <= 1) return items;" - [cursor1, cursor2] = editSession.getCursors() + [cursor1, cursor2] = editor.getCursors() expect(cursor1.getBufferPosition()).toEqual [0,29] expect(cursor2.getBufferPosition()).toEqual [0,59] describe "when there is a single selection", -> it "deletes the selection, but not the character following it", -> - editSession.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]]) - editSession.delete() + editor.setSelectedBufferRanges([[[1, 24], [1, 27]], [[2, 0], [2, 4]]]) + editor.delete() expect(buffer.lineForRow(1)).toBe ' var sort = function(it) {' expect(buffer.lineForRow(2)).toBe 'if (items.length <= 1) return items;' - expect(editSession.getSelection().isEmpty()).toBeTruthy() + expect(editor.getSelection().isEmpty()).toBeTruthy() describe "when there are multiple selections", -> describe "when selections are on the same line", -> it "removes all selected text", -> - editSession.setSelectedBufferRanges([[[0,4], [0,13]], [[0,16], [0,24]]]) - editSession.delete() - expect(editSession.lineForBufferRow(0)).toBe 'var = () {' + editor.setSelectedBufferRanges([[[0,4], [0,13]], [[0,16], [0,24]]]) + editor.delete() + expect(editor.lineForBufferRow(0)).toBe 'var = () {' describe ".deleteToEndOfWord()", -> describe "when no text is selected", -> it "deletes to the end of the word", -> - editSession.setCursorBufferPosition([1, 24]) - editSession.addCursorAtBufferPosition([2, 5]) - [cursor1, cursor2] = editSession.getCursors() + editor.setCursorBufferPosition([1, 24]) + editor.addCursorAtBufferPosition([2, 5]) + [cursor1, cursor2] = editor.getCursors() - editSession.deleteToEndOfWord() + editor.deleteToEndOfWord() expect(buffer.lineForRow(1)).toBe ' var sort = function(it) {' expect(buffer.lineForRow(2)).toBe ' i (items.length <= 1) return items;' expect(cursor1.getBufferPosition()).toEqual [1, 24] expect(cursor2.getBufferPosition()).toEqual [2, 5] - editSession.deleteToEndOfWord() + editor.deleteToEndOfWord() expect(buffer.lineForRow(1)).toBe ' var sort = function(it {' expect(buffer.lineForRow(2)).toBe ' iitems.length <= 1) return items;' expect(cursor1.getBufferPosition()).toEqual [1, 24] @@ -1710,8 +1710,8 @@ describe "Editor", -> describe "when text is selected", -> it "deletes only selected text", -> - editSession.setSelectedBufferRange([[1, 24], [1, 27]]) - editSession.deleteToEndOfWord() + editor.setSelectedBufferRange([[1, 24], [1, 27]]) + editor.deleteToEndOfWord() expect(buffer.lineForRow(1)).toBe ' var sort = function(it) {' describe ".indent()", -> @@ -1719,16 +1719,16 @@ describe "Editor", -> describe "when autoIndent is disabled", -> describe "if 'softTabs' is true (the default)", -> it "inserts 'tabLength' spaces into the buffer", -> - tabRegex = new RegExp("^[ ]{#{editSession.getTabLength()}}") + tabRegex = new RegExp("^[ ]{#{editor.getTabLength()}}") expect(buffer.lineForRow(0)).not.toMatch(tabRegex) - editSession.indent() + editor.indent() expect(buffer.lineForRow(0)).toMatch(tabRegex) describe "if 'softTabs' is false", -> it "insert a \t into the buffer", -> - editSession.setSoftTabs(false) + editor.setSoftTabs(false) expect(buffer.lineForRow(0)).not.toMatch(/^\t/) - editSession.indent() + editor.indent() expect(buffer.lineForRow(0)).toMatch(/^\t/) describe "when autoIndent is enabled", -> @@ -1736,71 +1736,71 @@ describe "Editor", -> describe "when 'softTabs' is true (the default)", -> it "moves the cursor to the end of the leading whitespace and inserts enough whitespace to bring the line to the suggested level of indentaion", -> buffer.insert([5, 0], " \n") - editSession.setCursorBufferPosition [5, 0] - editSession.indent(autoIndent: true) + editor.setCursorBufferPosition [5, 0] + editor.indent(autoIndent: true) expect(buffer.lineForRow(5)).toMatch /^\s+$/ expect(buffer.lineForRow(5).length).toBe 6 - expect(editSession.getCursorBufferPosition()).toEqual [5, 6] + expect(editor.getCursorBufferPosition()).toEqual [5, 6] describe "when 'softTabs' is false", -> it "moves the cursor to the end of the leading whitespace and inserts enough tabs to bring the line to the suggested level of indentaion", -> convertToHardTabs(buffer) - editSession.setSoftTabs(false) + editor.setSoftTabs(false) buffer.insert([5, 0], "\t\n") - editSession.setCursorBufferPosition [5, 0] - editSession.indent(autoIndent: true) + editor.setCursorBufferPosition [5, 0] + editor.indent(autoIndent: true) expect(buffer.lineForRow(5)).toMatch /^\t\t\t$/ - expect(editSession.getCursorBufferPosition()).toEqual [5, 3] + expect(editor.getCursorBufferPosition()).toEqual [5, 3] describe "when the line's indent level is greater than the suggested level of indentation", -> describe "when 'softTabs' is true (the default)", -> it "moves the cursor to the end of the leading whitespace and inserts 'tabLength' spaces into the buffer", -> buffer.insert([7, 0], " \n") - editSession.setCursorBufferPosition [7, 2] - editSession.indent(autoIndent: true) + editor.setCursorBufferPosition [7, 2] + editor.indent(autoIndent: true) expect(buffer.lineForRow(7)).toMatch /^\s+$/ expect(buffer.lineForRow(7).length).toBe 8 - expect(editSession.getCursorBufferPosition()).toEqual [7, 8] + expect(editor.getCursorBufferPosition()).toEqual [7, 8] describe "when 'softTabs' is false", -> it "moves the cursor to the end of the leading whitespace and inserts \t into the buffer", -> convertToHardTabs(buffer) - editSession.setSoftTabs(false) + editor.setSoftTabs(false) buffer.insert([7, 0], "\t\t\t\n") - editSession.setCursorBufferPosition [7, 1] - editSession.indent(autoIndent: true) + editor.setCursorBufferPosition [7, 1] + editor.indent(autoIndent: true) expect(buffer.lineForRow(7)).toMatch /^\t\t\t\t$/ - expect(editSession.getCursorBufferPosition()).toEqual [7, 4] + expect(editor.getCursorBufferPosition()).toEqual [7, 4] describe "when the selection is not empty", -> it "indents the selected lines", -> - editSession.setSelectedBufferRange([[0, 0], [10, 0]]) - selection = editSession.getSelection() + editor.setSelectedBufferRange([[0, 0], [10, 0]]) + selection = editor.getSelection() spyOn(selection, "indentSelectedRows") - editSession.indent() + editor.indent() expect(selection.indentSelectedRows).toHaveBeenCalled() - describe "if editSession.softTabs is false", -> + describe "if editor.softTabs is false", -> it "inserts a tab character into the buffer", -> - editSession.setSoftTabs(false) + editor.setSoftTabs(false) expect(buffer.lineForRow(0)).not.toMatch(/^\t/) - editSession.indent() + editor.indent() expect(buffer.lineForRow(0)).toMatch(/^\t/) - expect(editSession.getCursorBufferPosition()).toEqual [0, 1] - expect(editSession.getCursorScreenPosition()).toEqual [0, editSession.getTabLength()] + expect(editor.getCursorBufferPosition()).toEqual [0, 1] + expect(editor.getCursorScreenPosition()).toEqual [0, editor.getTabLength()] - editSession.indent() + editor.indent() expect(buffer.lineForRow(0)).toMatch(/^\t\t/) - expect(editSession.getCursorBufferPosition()).toEqual [0, 2] - expect(editSession.getCursorScreenPosition()).toEqual [0, editSession.getTabLength() * 2] + expect(editor.getCursorBufferPosition()).toEqual [0, 2] + expect(editor.getCursorScreenPosition()).toEqual [0, editor.getTabLength() * 2] describe "pasteboard operations", -> beforeEach -> - editSession.setSelectedBufferRanges([[[0, 4], [0, 13]], [[1, 6], [1, 10]]]) + editor.setSelectedBufferRanges([[[0, 4], [0, 13]], [[1, 6], [1, 10]]]) describe ".cutSelectedText()", -> it "removes the selected text from the buffer and places it on the pasteboard", -> - editSession.cutSelectedText() + editor.cutSelectedText() expect(buffer.lineForRow(0)).toBe "var = function () {" expect(buffer.lineForRow(1)).toBe " var = function(items) {" @@ -1809,27 +1809,27 @@ describe "Editor", -> describe ".cutToEndOfLine()", -> describe "when soft wrap is on", -> it "cuts up to the end of the line", -> - editSession.setSoftWrap(true) - editSession.setEditorWidthInChars(10) - editSession.setCursorScreenPosition([2, 2]) - editSession.cutToEndOfLine() - expect(editSession.lineForScreenRow(2).text).toBe '= () {' + editor.setSoftWrap(true) + editor.setEditorWidthInChars(10) + editor.setCursorScreenPosition([2, 2]) + editor.cutToEndOfLine() + expect(editor.lineForScreenRow(2).text).toBe '= () {' describe "when soft wrap is off", -> describe "when nothing is selected", -> it "cuts up to the end of the line", -> - editSession.setCursorBufferPosition([2, 20]) - editSession.addCursorAtBufferPosition([3, 20]) - editSession.cutToEndOfLine() + editor.setCursorBufferPosition([2, 20]) + editor.addCursorAtBufferPosition([3, 20]) + editor.cutToEndOfLine() expect(buffer.lineForRow(2)).toBe ' if (items.length' expect(buffer.lineForRow(3)).toBe ' var pivot = item' expect(atom.pasteboard.read()[0]).toBe ' <= 1) return items;\ns.shift(), current, left = [], right = [];' describe "when text is selected", -> it "only cuts the selected text, not to the end of the line", -> - editSession.setSelectedBufferRanges([[[2,20], [2, 30]], [[3, 20], [3, 20]]]) + editor.setSelectedBufferRanges([[[2,20], [2, 30]], [[3, 20], [3, 20]]]) - editSession.cutToEndOfLine() + editor.cutToEndOfLine() expect(buffer.lineForRow(2)).toBe ' if (items.lengthurn items;' expect(buffer.lineForRow(3)).toBe ' var pivot = item' @@ -1837,7 +1837,7 @@ describe "Editor", -> describe ".copySelectedText()", -> it "copies selected text onto the clipboard", -> - editSession.copySelectedText() + editor.copySelectedText() expect(buffer.lineForRow(0)).toBe "var quicksort = function () {" expect(buffer.lineForRow(1)).toBe " var sort = function(items) {" expect(clipboard.readText()).toBe 'quicksort\nsort' @@ -1845,324 +1845,324 @@ describe "Editor", -> describe ".pasteText()", -> it "pastes text into the buffer", -> atom.pasteboard.write('first') - editSession.pasteText() - expect(editSession.buffer.lineForRow(0)).toBe "var first = function () {" + editor.pasteText() + expect(editor.buffer.lineForRow(0)).toBe "var first = function () {" expect(buffer.lineForRow(1)).toBe " var first = function(items) {" describe ".indentSelectedRows()", -> describe "when nothing is selected", -> describe "when softTabs is enabled", -> it "indents line and retains selection", -> - editSession.setSelectedBufferRange([[0,3], [0,3]]) - editSession.indentSelectedRows() + editor.setSelectedBufferRange([[0,3], [0,3]]) + editor.indentSelectedRows() expect(buffer.lineForRow(0)).toBe " var quicksort = function () {" - expect(editSession.getSelectedBufferRange()).toEqual [[0, 3 + editSession.getTabLength()], [0, 3 + editSession.getTabLength()]] + expect(editor.getSelectedBufferRange()).toEqual [[0, 3 + editor.getTabLength()], [0, 3 + editor.getTabLength()]] describe "when softTabs is disabled", -> it "indents line and retains selection", -> convertToHardTabs(buffer) - editSession.setSoftTabs(false) - editSession.setSelectedBufferRange([[0,3], [0,3]]) - editSession.indentSelectedRows() + editor.setSoftTabs(false) + editor.setSelectedBufferRange([[0,3], [0,3]]) + editor.indentSelectedRows() expect(buffer.lineForRow(0)).toBe "\tvar quicksort = function () {" - expect(editSession.getSelectedBufferRange()).toEqual [[0, 3 + 1], [0, 3 + 1]] + expect(editor.getSelectedBufferRange()).toEqual [[0, 3 + 1], [0, 3 + 1]] describe "when one line is selected", -> describe "when softTabs is enabled", -> it "indents line and retains selection", -> - editSession.setSelectedBufferRange([[0,4], [0,14]]) - editSession.indentSelectedRows() - expect(buffer.lineForRow(0)).toBe "#{editSession.getTabText()}var quicksort = function () {" - expect(editSession.getSelectedBufferRange()).toEqual [[0, 4 + editSession.getTabLength()], [0, 14 + editSession.getTabLength()]] + editor.setSelectedBufferRange([[0,4], [0,14]]) + editor.indentSelectedRows() + expect(buffer.lineForRow(0)).toBe "#{editor.getTabText()}var quicksort = function () {" + expect(editor.getSelectedBufferRange()).toEqual [[0, 4 + editor.getTabLength()], [0, 14 + editor.getTabLength()]] describe "when softTabs is disabled", -> it "indents line and retains selection", -> convertToHardTabs(buffer) - editSession.setSoftTabs(false) - editSession.setSelectedBufferRange([[0,4], [0,14]]) - editSession.indentSelectedRows() + editor.setSoftTabs(false) + editor.setSelectedBufferRange([[0,4], [0,14]]) + editor.indentSelectedRows() expect(buffer.lineForRow(0)).toBe "\tvar quicksort = function () {" - expect(editSession.getSelectedBufferRange()).toEqual [[0, 4 + 1], [0, 14 + 1]] + expect(editor.getSelectedBufferRange()).toEqual [[0, 4 + 1], [0, 14 + 1]] describe "when multiple lines are selected", -> describe "when softTabs is enabled", -> it "indents selected lines (that are not empty) and retains selection", -> - editSession.setSelectedBufferRange([[9,1], [11,15]]) - editSession.indentSelectedRows() + editor.setSelectedBufferRange([[9,1], [11,15]]) + editor.indentSelectedRows() expect(buffer.lineForRow(9)).toBe " };" expect(buffer.lineForRow(10)).toBe "" expect(buffer.lineForRow(11)).toBe " return sort(Array.apply(this, arguments));" - expect(editSession.getSelectedBufferRange()).toEqual [[9, 1 + editSession.getTabLength()], [11, 15 + editSession.getTabLength()]] + expect(editor.getSelectedBufferRange()).toEqual [[9, 1 + editor.getTabLength()], [11, 15 + editor.getTabLength()]] it "does not indent the last row if the selection ends at column 0", -> - editSession.setSelectedBufferRange([[9,1], [11,0]]) - editSession.indentSelectedRows() + editor.setSelectedBufferRange([[9,1], [11,0]]) + editor.indentSelectedRows() expect(buffer.lineForRow(9)).toBe " };" expect(buffer.lineForRow(10)).toBe "" expect(buffer.lineForRow(11)).toBe " return sort(Array.apply(this, arguments));" - expect(editSession.getSelectedBufferRange()).toEqual [[9, 1 + editSession.getTabLength()], [11, 0]] + expect(editor.getSelectedBufferRange()).toEqual [[9, 1 + editor.getTabLength()], [11, 0]] describe "when softTabs is disabled", -> it "indents selected lines (that are not empty) and retains selection", -> convertToHardTabs(buffer) - editSession.setSoftTabs(false) - editSession.setSelectedBufferRange([[9,1], [11,15]]) - editSession.indentSelectedRows() + editor.setSoftTabs(false) + editor.setSelectedBufferRange([[9,1], [11,15]]) + editor.indentSelectedRows() expect(buffer.lineForRow(9)).toBe "\t\t};" expect(buffer.lineForRow(10)).toBe "" expect(buffer.lineForRow(11)).toBe "\t\treturn sort(Array.apply(this, arguments));" - expect(editSession.getSelectedBufferRange()).toEqual [[9, 1 + 1], [11, 15 + 1]] + expect(editor.getSelectedBufferRange()).toEqual [[9, 1 + 1], [11, 15 + 1]] describe ".outdentSelectedRows()", -> describe "when nothing is selected", -> it "outdents line and retains selection", -> - editSession.setSelectedBufferRange([[1,3], [1,3]]) - editSession.outdentSelectedRows() + editor.setSelectedBufferRange([[1,3], [1,3]]) + editor.outdentSelectedRows() expect(buffer.lineForRow(1)).toBe "var sort = function(items) {" - expect(editSession.getSelectedBufferRange()).toEqual [[1, 3 - editSession.getTabLength()], [1, 3 - editSession.getTabLength()]] + expect(editor.getSelectedBufferRange()).toEqual [[1, 3 - editor.getTabLength()], [1, 3 - editor.getTabLength()]] it "outdents when indent is less than a tab length", -> - editSession.insertText(' ') - editSession.outdentSelectedRows() + editor.insertText(' ') + editor.outdentSelectedRows() expect(buffer.lineForRow(0)).toBe "var quicksort = function () {" it "outdents a single hard tab when indent is multiple hard tabs and and the session is using soft tabs", -> - editSession.insertText('\t\t') - editSession.outdentSelectedRows() + editor.insertText('\t\t') + editor.outdentSelectedRows() expect(buffer.lineForRow(0)).toBe "\tvar quicksort = function () {" - editSession.outdentSelectedRows() + editor.outdentSelectedRows() expect(buffer.lineForRow(0)).toBe "var quicksort = function () {" it "outdents when a mix of hard tabs and soft tabs are used", -> - editSession.insertText('\t ') - editSession.outdentSelectedRows() + editor.insertText('\t ') + editor.outdentSelectedRows() expect(buffer.lineForRow(0)).toBe " var quicksort = function () {" - editSession.outdentSelectedRows() + editor.outdentSelectedRows() expect(buffer.lineForRow(0)).toBe " var quicksort = function () {" - editSession.outdentSelectedRows() + editor.outdentSelectedRows() expect(buffer.lineForRow(0)).toBe "var quicksort = function () {" describe "when one line is selected", -> - it "outdents line and retains editSession", -> - editSession.setSelectedBufferRange([[1,4], [1,14]]) - editSession.outdentSelectedRows() + it "outdents line and retains editor", -> + editor.setSelectedBufferRange([[1,4], [1,14]]) + editor.outdentSelectedRows() expect(buffer.lineForRow(1)).toBe "var sort = function(items) {" - expect(editSession.getSelectedBufferRange()).toEqual [[1, 4 - editSession.getTabLength()], [1, 14 - editSession.getTabLength()]] + expect(editor.getSelectedBufferRange()).toEqual [[1, 4 - editor.getTabLength()], [1, 14 - editor.getTabLength()]] describe "when multiple lines are selected", -> - it "outdents selected lines and retains editSession", -> - editSession.setSelectedBufferRange([[0,1], [3,15]]) - editSession.outdentSelectedRows() + it "outdents selected lines and retains editor", -> + editor.setSelectedBufferRange([[0,1], [3,15]]) + editor.outdentSelectedRows() expect(buffer.lineForRow(0)).toBe "var quicksort = function () {" expect(buffer.lineForRow(1)).toBe "var sort = function(items) {" expect(buffer.lineForRow(2)).toBe " if (items.length <= 1) return items;" expect(buffer.lineForRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];" - expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [3, 15 - editSession.getTabLength()]] + expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [3, 15 - editor.getTabLength()]] it "does not outdent the last line of the selection if it ends at column 0", -> - editSession.setSelectedBufferRange([[0,1], [3,0]]) - editSession.outdentSelectedRows() + editor.setSelectedBufferRange([[0,1], [3,0]]) + editor.outdentSelectedRows() expect(buffer.lineForRow(0)).toBe "var quicksort = function () {" expect(buffer.lineForRow(1)).toBe "var sort = function(items) {" expect(buffer.lineForRow(2)).toBe " if (items.length <= 1) return items;" expect(buffer.lineForRow(3)).toBe " var pivot = items.shift(), current, left = [], right = [];" - expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [3, 0]] + expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [3, 0]] describe ".toggleLineCommentsInSelection()", -> it "toggles comments on the selected lines", -> - editSession.setSelectedBufferRange([[4, 5], [7, 5]]) - editSession.toggleLineCommentsInSelection() + editor.setSelectedBufferRange([[4, 5], [7, 5]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(4)).toBe " // while(items.length > 0) {" expect(buffer.lineForRow(5)).toBe " // current = items.shift();" expect(buffer.lineForRow(6)).toBe " // current < pivot ? left.push(current) : right.push(current);" expect(buffer.lineForRow(7)).toBe " // }" - expect(editSession.getSelectedBufferRange()).toEqual [[4, 8], [7, 8]] + expect(editor.getSelectedBufferRange()).toEqual [[4, 8], [7, 8]] - editSession.toggleLineCommentsInSelection() + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {" expect(buffer.lineForRow(5)).toBe " current = items.shift();" expect(buffer.lineForRow(6)).toBe " current < pivot ? left.push(current) : right.push(current);" expect(buffer.lineForRow(7)).toBe " }" it "does not comment the last line of a non-empty selection if it ends at column 0", -> - editSession.setSelectedBufferRange([[4, 5], [7, 0]]) - editSession.toggleLineCommentsInSelection() + editor.setSelectedBufferRange([[4, 5], [7, 0]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(4)).toBe " // while(items.length > 0) {" expect(buffer.lineForRow(5)).toBe " // current = items.shift();" expect(buffer.lineForRow(6)).toBe " // current < pivot ? left.push(current) : right.push(current);" expect(buffer.lineForRow(7)).toBe " }" it "uncomments lines if all lines match the comment regex", -> - editSession.setSelectedBufferRange([[0, 0], [0, 1]]) - editSession.toggleLineCommentsInSelection() + editor.setSelectedBufferRange([[0, 0], [0, 1]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(0)).toBe "// var quicksort = function () {" - editSession.setSelectedBufferRange([[0, 0], [2, Infinity]]) - editSession.toggleLineCommentsInSelection() + editor.setSelectedBufferRange([[0, 0], [2, Infinity]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(0)).toBe "// // var quicksort = function () {" expect(buffer.lineForRow(1)).toBe "// var sort = function(items) {" expect(buffer.lineForRow(2)).toBe "// if (items.length <= 1) return items;" - editSession.setSelectedBufferRange([[0, 0], [2, Infinity]]) - editSession.toggleLineCommentsInSelection() + editor.setSelectedBufferRange([[0, 0], [2, Infinity]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(0)).toBe "// var quicksort = function () {" expect(buffer.lineForRow(1)).toBe " var sort = function(items) {" expect(buffer.lineForRow(2)).toBe " if (items.length <= 1) return items;" - editSession.setSelectedBufferRange([[0, 0], [0, Infinity]]) - editSession.toggleLineCommentsInSelection() + editor.setSelectedBufferRange([[0, 0], [0, Infinity]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(0)).toBe "var quicksort = function () {" it "uncomments commented lines separated by an empty line", -> - editSession.setSelectedBufferRange([[0, 0], [1, Infinity]]) - editSession.toggleLineCommentsInSelection() + editor.setSelectedBufferRange([[0, 0], [1, Infinity]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(0)).toBe "// var quicksort = function () {" expect(buffer.lineForRow(1)).toBe "// var sort = function(items) {" buffer.insert([0, Infinity], '\n') - editSession.setSelectedBufferRange([[0, 0], [2, Infinity]]) - editSession.toggleLineCommentsInSelection() + editor.setSelectedBufferRange([[0, 0], [2, Infinity]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(0)).toBe "var quicksort = function () {" expect(buffer.lineForRow(1)).toBe "" expect(buffer.lineForRow(2)).toBe " var sort = function(items) {" it "preserves selection emptiness", -> - editSession.setCursorBufferPosition([4, 0]) - editSession.toggleLineCommentsInSelection() - expect(editSession.getSelection().isEmpty()).toBeTruthy() + editor.setCursorBufferPosition([4, 0]) + editor.toggleLineCommentsInSelection() + expect(editor.getSelection().isEmpty()).toBeTruthy() it "does not explode if the current language mode has no comment regex", -> - editSession.destroy() - editSession = project.openSync(null, autoIndent: false) - editSession.setSelectedBufferRange([[4, 5], [4, 5]]) - editSession.toggleLineCommentsInSelection() + editor.destroy() + editor = project.openSync(null, autoIndent: false) + editor.setSelectedBufferRange([[4, 5], [4, 5]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {" it "uncomments when the line lacks the trailing whitespace in the comment regex", -> - editSession.setCursorBufferPosition([10, 0]) - editSession.toggleLineCommentsInSelection() + editor.setCursorBufferPosition([10, 0]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(10)).toBe "// " - expect(editSession.getSelectedBufferRange()).toEqual [[10, 3], [10, 3]] - editSession.backspace() + expect(editor.getSelectedBufferRange()).toEqual [[10, 3], [10, 3]] + editor.backspace() expect(buffer.lineForRow(10)).toBe "//" - editSession.toggleLineCommentsInSelection() + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(10)).toBe "" - expect(editSession.getSelectedBufferRange()).toEqual [[10, 0], [10, 0]] + expect(editor.getSelectedBufferRange()).toEqual [[10, 0], [10, 0]] it "uncomments when the line has leading whitespace", -> - editSession.setCursorBufferPosition([10, 0]) - editSession.toggleLineCommentsInSelection() + editor.setCursorBufferPosition([10, 0]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(10)).toBe "// " - editSession.moveCursorToBeginningOfLine() - editSession.insertText(" ") - editSession.setSelectedBufferRange([[10, 0], [10, 0]]) - editSession.toggleLineCommentsInSelection() + editor.moveCursorToBeginningOfLine() + editor.insertText(" ") + editor.setSelectedBufferRange([[10, 0], [10, 0]]) + editor.toggleLineCommentsInSelection() expect(buffer.lineForRow(10)).toBe " " describe ".undo() and .redo()", -> it "undoes/redoes the last change", -> - editSession.insertText("foo") - editSession.undo() + editor.insertText("foo") + editor.undo() expect(buffer.lineForRow(0)).not.toContain "foo" - editSession.redo() + editor.redo() expect(buffer.lineForRow(0)).toContain "foo" it "batches the undo / redo of changes caused by multiple cursors", -> - editSession.setCursorScreenPosition([0, 0]) - editSession.addCursorAtScreenPosition([1, 0]) + editor.setCursorScreenPosition([0, 0]) + editor.addCursorAtScreenPosition([1, 0]) - editSession.insertText("foo") - editSession.backspace() + editor.insertText("foo") + editor.backspace() expect(buffer.lineForRow(0)).toContain "fovar" expect(buffer.lineForRow(1)).toContain "fo " - editSession.undo() + editor.undo() expect(buffer.lineForRow(0)).toContain "foo" expect(buffer.lineForRow(1)).toContain "foo" - editSession.redo() + editor.redo() expect(buffer.lineForRow(0)).not.toContain "foo" expect(buffer.lineForRow(0)).toContain "fovar" it "restores the selected ranges after undo and redo", -> - editSession.setSelectedBufferRanges([[[1, 6], [1, 10]], [[1, 22], [1, 27]]]) - editSession.delete() - editSession.delete() + editor.setSelectedBufferRanges([[[1, 6], [1, 10]], [[1, 22], [1, 27]]]) + editor.delete() + editor.delete() - selections = editSession.getSelections() + selections = editor.getSelections() expect(buffer.lineForRow(1)).toBe ' var = function( {' - expect(editSession.getSelectedBufferRanges()).toEqual [[[1, 6], [1, 6]], [[1, 17], [1, 17]]] + expect(editor.getSelectedBufferRanges()).toEqual [[[1, 6], [1, 6]], [[1, 17], [1, 17]]] - editSession.undo() - expect(editSession.getSelectedBufferRanges()).toEqual [[[1, 6], [1, 6]], [[1, 18], [1, 18]]] + editor.undo() + expect(editor.getSelectedBufferRanges()).toEqual [[[1, 6], [1, 6]], [[1, 18], [1, 18]]] - editSession.undo() - expect(editSession.getSelectedBufferRanges()).toEqual [[[1, 6], [1, 10]], [[1, 22], [1, 27]]] + editor.undo() + expect(editor.getSelectedBufferRanges()).toEqual [[[1, 6], [1, 10]], [[1, 22], [1, 27]]] - editSession.redo() - expect(editSession.getSelectedBufferRanges()).toEqual [[[1, 6], [1, 6]], [[1, 18], [1, 18]]] + editor.redo() + expect(editor.getSelectedBufferRanges()).toEqual [[[1, 6], [1, 6]], [[1, 18], [1, 18]]] xit "restores folds after undo and redo", -> - editSession.foldBufferRow(1) - editSession.setSelectedBufferRange([[1, 0], [10, Infinity]], preserveFolds: true) - expect(editSession.isFoldedAtBufferRow(1)).toBeTruthy() + editor.foldBufferRow(1) + editor.setSelectedBufferRange([[1, 0], [10, Infinity]], preserveFolds: true) + expect(editor.isFoldedAtBufferRow(1)).toBeTruthy() - editSession.insertText """ + editor.insertText """ \ // testing function foo() { return 1 + 2; } """ - expect(editSession.isFoldedAtBufferRow(1)).toBeFalsy() - editSession.foldBufferRow(2) + expect(editor.isFoldedAtBufferRow(1)).toBeFalsy() + editor.foldBufferRow(2) - editSession.undo() - expect(editSession.isFoldedAtBufferRow(1)).toBeTruthy() - expect(editSession.isFoldedAtBufferRow(9)).toBeTruthy() - expect(editSession.isFoldedAtBufferRow(10)).toBeFalsy() + editor.undo() + expect(editor.isFoldedAtBufferRow(1)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(9)).toBeTruthy() + expect(editor.isFoldedAtBufferRow(10)).toBeFalsy() - editSession.redo() - expect(editSession.isFoldedAtBufferRow(1)).toBeFalsy() - expect(editSession.isFoldedAtBufferRow(2)).toBeTruthy() + editor.redo() + expect(editor.isFoldedAtBufferRow(1)).toBeFalsy() + expect(editor.isFoldedAtBufferRow(2)).toBeTruthy() describe "begin/commitTransaction()", -> it "restores the selection when the transaction is undone/redone", -> buffer.setText('1234') - editSession.setSelectedBufferRange([[0, 1], [0, 3]]) - editSession.beginTransaction() + editor.setSelectedBufferRange([[0, 1], [0, 3]]) + editor.beginTransaction() - editSession.delete() - editSession.moveCursorToEndOfLine() - editSession.insertText('5') + editor.delete() + editor.moveCursorToEndOfLine() + editor.insertText('5') expect(buffer.getText()).toBe '145' - editSession.commitTransaction() + editor.commitTransaction() - editSession.undo() + editor.undo() expect(buffer.getText()).toBe '1234' - expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [0, 3]] + expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [0, 3]] - editSession.redo() + editor.redo() expect(buffer.getText()).toBe '145' - expect(editSession.getSelectedBufferRange()).toEqual [[0, 3], [0, 3]] + expect(editor.getSelectedBufferRange()).toEqual [[0, 3], [0, 3]] describe "when the buffer is changed (via its direct api, rather than via than edit session)", -> it "moves the cursor so it is in the same relative position of the buffer", -> - expect(editSession.getCursorScreenPosition()).toEqual [0, 0] - editSession.addCursorAtScreenPosition([0, 5]) - editSession.addCursorAtScreenPosition([1, 0]) - [cursor1, cursor2, cursor3] = editSession.getCursors() + expect(editor.getCursorScreenPosition()).toEqual [0, 0] + editor.addCursorAtScreenPosition([0, 5]) + editor.addCursorAtScreenPosition([1, 0]) + [cursor1, cursor2, cursor3] = editor.getCursors() buffer.insert([0, 1], 'abc') @@ -2171,40 +2171,40 @@ describe "Editor", -> expect(cursor3.getScreenPosition()).toEqual [1, 0] it "does not destroy cursors or selections when a change encompasses them", -> - cursor = editSession.getCursor() + cursor = editor.getCursor() cursor.setBufferPosition [3, 3] - editSession.buffer.delete([[3, 1], [3, 5]]) + editor.buffer.delete([[3, 1], [3, 5]]) expect(cursor.getBufferPosition()).toEqual [3, 1] - expect(editSession.getCursors().indexOf(cursor)).not.toBe -1 + expect(editor.getCursors().indexOf(cursor)).not.toBe -1 - selection = editSession.getLastSelection() + selection = editor.getLastSelection() selection.setBufferRange [[3, 5], [3, 10]] - editSession.buffer.delete [[3, 3], [3, 8]] + editor.buffer.delete [[3, 3], [3, 8]] expect(selection.getBufferRange()).toEqual [[3, 3], [3, 5]] - expect(editSession.getSelections().indexOf(selection)).not.toBe -1 + expect(editor.getSelections().indexOf(selection)).not.toBe -1 it "merges cursors when the change causes them to overlap", -> - editSession.setCursorScreenPosition([0, 0]) - editSession.addCursorAtScreenPosition([0, 2]) - editSession.addCursorAtScreenPosition([1, 2]) + editor.setCursorScreenPosition([0, 0]) + editor.addCursorAtScreenPosition([0, 2]) + editor.addCursorAtScreenPosition([1, 2]) - [cursor1, cursor2, cursor3] = editSession.getCursors() - expect(editSession.getCursors().length).toBe 3 + [cursor1, cursor2, cursor3] = editor.getCursors() + expect(editor.getCursors().length).toBe 3 buffer.delete([[0, 0], [0, 2]]) - expect(editSession.getCursors().length).toBe 2 - expect(editSession.getCursors()).toEqual [cursor1, cursor3] + expect(editor.getCursors().length).toBe 2 + expect(editor.getCursors()).toEqual [cursor1, cursor3] expect(cursor1.getBufferPosition()).toEqual [0,0] expect(cursor3.getBufferPosition()).toEqual [1,2] describe ".deleteLine()", -> it "deletes the first line when the cursor is there", -> - editSession.getCursor().moveToTop() + editor.getCursor().moveToTop() line1 = buffer.lineForRow(1) count = buffer.getLineCount() expect(buffer.lineForRow(0)).not.toBe(line1) - editSession.deleteLine() + editor.deleteLine() expect(buffer.lineForRow(0)).toBe(line1) expect(buffer.getLineCount()).toBe(count - 1) @@ -2212,45 +2212,45 @@ describe "Editor", -> count = buffer.getLineCount() secondToLastLine = buffer.lineForRow(count - 2) expect(buffer.lineForRow(count - 1)).not.toBe(secondToLastLine) - editSession.getCursor().moveToBottom() - editSession.deleteLine() + editor.getCursor().moveToBottom() + editor.deleteLine() newCount = buffer.getLineCount() expect(buffer.lineForRow(newCount - 1)).toBe(secondToLastLine) expect(newCount).toBe(count - 1) it "deletes whole lines when partial lines are selected", -> - editSession.setSelectedBufferRange([[0, 2], [1, 2]]) + editor.setSelectedBufferRange([[0, 2], [1, 2]]) line2 = buffer.lineForRow(2) count = buffer.getLineCount() expect(buffer.lineForRow(0)).not.toBe(line2) expect(buffer.lineForRow(1)).not.toBe(line2) - editSession.deleteLine() + editor.deleteLine() expect(buffer.lineForRow(0)).toBe(line2) expect(buffer.getLineCount()).toBe(count - 2) it "only deletes first line if only newline is selected on second line", -> - editSession.setSelectedBufferRange([[0, 2], [1, 0]]) + editor.setSelectedBufferRange([[0, 2], [1, 0]]) line1 = buffer.lineForRow(1) count = buffer.getLineCount() expect(buffer.lineForRow(0)).not.toBe(line1) - editSession.deleteLine() + editor.deleteLine() expect(buffer.lineForRow(0)).toBe(line1) expect(buffer.getLineCount()).toBe(count - 1) it "deletes the entire region when invoke on a folded region", -> - editSession.foldBufferRow(1) - editSession.getCursor().moveToTop() - editSession.getCursor().moveDown() + editor.foldBufferRow(1) + editor.getCursor().moveToTop() + editor.getCursor().moveDown() expect(buffer.getLineCount()).toBe(13) - editSession.deleteLine() + editor.deleteLine() expect(buffer.getLineCount()).toBe(4) it "deletes the entire file from the bottom up", -> count = buffer.getLineCount() expect(count).toBeGreaterThan(0) for line in [0...count] - editSession.getCursor().moveToBottom() - editSession.deleteLine() + editor.getCursor().moveToBottom() + editor.deleteLine() expect(buffer.getLineCount()).toBe(1) expect(buffer.getText()).toBe('') @@ -2258,170 +2258,170 @@ describe "Editor", -> count = buffer.getLineCount() expect(count).toBeGreaterThan(0) for line in [0...count] - editSession.getCursor().moveToTop() - editSession.deleteLine() + editor.getCursor().moveToTop() + editor.deleteLine() expect(buffer.getLineCount()).toBe(1) expect(buffer.getText()).toBe('') describe "when soft wrap is enabled", -> it "deletes the entire line that the cursor is on", -> - editSession.setSoftWrap(true) - editSession.setEditorWidthInChars(10) - editSession.setCursorBufferPosition([6]) + editor.setSoftWrap(true) + editor.setEditorWidthInChars(10) + editor.setCursorBufferPosition([6]) line7 = buffer.lineForRow(7) count = buffer.getLineCount() expect(buffer.lineForRow(6)).not.toBe(line7) - editSession.deleteLine() + editor.deleteLine() expect(buffer.lineForRow(6)).toBe(line7) expect(buffer.getLineCount()).toBe(count - 1) describe "when the line being deleted preceeds a fold, and the command is undone", -> it "restores the line and preserves the fold", -> - editSession.setCursorBufferPosition([4]) - editSession.foldCurrentRow() - expect(editSession.isFoldedAtScreenRow(4)).toBeTruthy() - editSession.setCursorBufferPosition([3]) - editSession.deleteLine() - expect(editSession.isFoldedAtScreenRow(3)).toBeTruthy() + editor.setCursorBufferPosition([4]) + editor.foldCurrentRow() + expect(editor.isFoldedAtScreenRow(4)).toBeTruthy() + editor.setCursorBufferPosition([3]) + editor.deleteLine() + expect(editor.isFoldedAtScreenRow(3)).toBeTruthy() expect(buffer.lineForRow(3)).toBe ' while(items.length > 0) {' - editSession.undo() - expect(editSession.isFoldedAtScreenRow(4)).toBeTruthy() + editor.undo() + expect(editor.isFoldedAtScreenRow(4)).toBeTruthy() expect(buffer.lineForRow(3)).toBe ' var pivot = items.shift(), current, left = [], right = [];' describe ".replaceSelectedText(options, fn)", -> describe "when no text is selected", -> it "inserts the text returned from the function at the cursor position", -> - editSession.replaceSelectedText {}, -> '123' + editor.replaceSelectedText {}, -> '123' expect(buffer.lineForRow(0)).toBe '123var quicksort = function () {' - editSession.replaceSelectedText {selectWordIfEmpty: true}, -> 'var' - editSession.setCursorBufferPosition([0]) + editor.replaceSelectedText {selectWordIfEmpty: true}, -> 'var' + editor.setCursorBufferPosition([0]) expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {' - editSession.setCursorBufferPosition([10]) - editSession.replaceSelectedText null, -> '' + editor.setCursorBufferPosition([10]) + editor.replaceSelectedText null, -> '' expect(buffer.lineForRow(10)).toBe '' describe "when text is selected", -> it "replaces the selected text with the text returned from the function", -> - editSession.setSelectedBufferRange([[0, 1], [0, 3]]) - editSession.replaceSelectedText {}, -> 'ia' + editor.setSelectedBufferRange([[0, 1], [0, 3]]) + editor.replaceSelectedText {}, -> 'ia' expect(buffer.lineForRow(0)).toBe 'via quicksort = function () {' describe ".transpose()", -> it "swaps two characters", -> - editSession.buffer.setText("abc") - editSession.setCursorScreenPosition([0, 1]) - editSession.transpose() - expect(editSession.lineForBufferRow(0)).toBe 'bac' + editor.buffer.setText("abc") + editor.setCursorScreenPosition([0, 1]) + editor.transpose() + expect(editor.lineForBufferRow(0)).toBe 'bac' it "reverses a selection", -> - editSession.buffer.setText("xabcz") - editSession.setSelectedBufferRange([[0, 1], [0, 4]]) - editSession.transpose() - expect(editSession.lineForBufferRow(0)).toBe 'xcbaz' + editor.buffer.setText("xabcz") + editor.setSelectedBufferRange([[0, 1], [0, 4]]) + editor.transpose() + expect(editor.lineForBufferRow(0)).toBe 'xcbaz' describe ".upperCase()", -> describe "when there is no selection", -> it "upper cases the current word", -> - editSession.buffer.setText("aBc") - editSession.setCursorScreenPosition([0, 1]) - editSession.upperCase() - expect(editSession.lineForBufferRow(0)).toBe 'ABC' - expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [0, 1]] + editor.buffer.setText("aBc") + editor.setCursorScreenPosition([0, 1]) + editor.upperCase() + expect(editor.lineForBufferRow(0)).toBe 'ABC' + expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [0, 1]] describe "when there is a selection", -> it "upper cases the current selection", -> - editSession.buffer.setText("abc") - editSession.setSelectedBufferRange([[0,0], [0,2]]) - editSession.upperCase() - expect(editSession.lineForBufferRow(0)).toBe 'ABc' - expect(editSession.getSelectedBufferRange()).toEqual [[0, 0], [0, 2]] + editor.buffer.setText("abc") + editor.setSelectedBufferRange([[0,0], [0,2]]) + editor.upperCase() + expect(editor.lineForBufferRow(0)).toBe 'ABc' + expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 2]] describe ".lowerCase()", -> describe "when there is no selection", -> it "lower cases the current word", -> - editSession.buffer.setText("aBC") - editSession.setCursorScreenPosition([0, 1]) - editSession.lowerCase() - expect(editSession.lineForBufferRow(0)).toBe 'abc' - expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [0, 1]] + editor.buffer.setText("aBC") + editor.setCursorScreenPosition([0, 1]) + editor.lowerCase() + expect(editor.lineForBufferRow(0)).toBe 'abc' + expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [0, 1]] describe "when there is a selection", -> it "lower cases the current selection", -> - editSession.buffer.setText("ABC") - editSession.setSelectedBufferRange([[0,0], [0,2]]) - editSession.lowerCase() - expect(editSession.lineForBufferRow(0)).toBe 'abC' - expect(editSession.getSelectedBufferRange()).toEqual [[0, 0], [0, 2]] + editor.buffer.setText("ABC") + editor.setSelectedBufferRange([[0,0], [0,2]]) + editor.lowerCase() + expect(editor.lineForBufferRow(0)).toBe 'abC' + expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 2]] describe "soft-tabs detection", -> it "assigns soft / hard tabs based on the contents of the buffer, or uses the default if unknown", -> - editSession = project.openSync('sample.js', softTabs: false) - expect(editSession.getSoftTabs()).toBeTruthy() + editor = project.openSync('sample.js', softTabs: false) + expect(editor.getSoftTabs()).toBeTruthy() - editSession = project.openSync('sample-with-tabs.coffee', softTabs: true) - expect(editSession.getSoftTabs()).toBeFalsy() + editor = project.openSync('sample-with-tabs.coffee', softTabs: true) + expect(editor.getSoftTabs()).toBeFalsy() - editSession = project.openSync(null, softTabs: false) - expect(editSession.getSoftTabs()).toBeFalsy() + editor = project.openSync(null, softTabs: false) + expect(editor.getSoftTabs()).toBeFalsy() describe ".indentLevelForLine(line)", -> it "returns the indent level when the line has only leading whitespace", -> - expect(editSession.indentLevelForLine(" hello")).toBe(2) - expect(editSession.indentLevelForLine(" hello")).toBe(1.5) + expect(editor.indentLevelForLine(" hello")).toBe(2) + expect(editor.indentLevelForLine(" hello")).toBe(1.5) it "returns the indent level when the line has only leading tabs", -> - expect(editSession.indentLevelForLine("\t\thello")).toBe(2) + expect(editor.indentLevelForLine("\t\thello")).toBe(2) it "returns the indent level when the line has mixed leading whitespace and tabs", -> - expect(editSession.indentLevelForLine("\t hello")).toBe(2) - expect(editSession.indentLevelForLine(" \thello")).toBe(2) - expect(editSession.indentLevelForLine(" \t hello")).toBe(2.5) - expect(editSession.indentLevelForLine(" \t \thello")).toBe(3.5) + expect(editor.indentLevelForLine("\t hello")).toBe(2) + expect(editor.indentLevelForLine(" \thello")).toBe(2) + expect(editor.indentLevelForLine(" \t hello")).toBe(2.5) + expect(editor.indentLevelForLine(" \t \thello")).toBe(3.5) describe "when the buffer is reloaded", -> it "preserves the current cursor position", -> - editSession.setCursorScreenPosition([0, 1]) - editSession.buffer.reload() - expect(editSession.getCursorScreenPosition()).toEqual [0,1] + editor.setCursorScreenPosition([0, 1]) + editor.buffer.reload() + expect(editor.getCursorScreenPosition()).toEqual [0,1] describe "when a better-matched grammar is added to syntax", -> it "switches to the better-matched grammar and re-tokenizes the buffer", -> - editSession.destroy() + editor.destroy() jsGrammar = atom.syntax.selectGrammar('a.js') atom.syntax.removeGrammar(jsGrammar) - editSession = project.openSync('sample.js', autoIndent: false) - expect(editSession.getGrammar()).toBe atom.syntax.nullGrammar - expect(editSession.lineForScreenRow(0).tokens.length).toBe 1 + editor = project.openSync('sample.js', autoIndent: false) + expect(editor.getGrammar()).toBe atom.syntax.nullGrammar + expect(editor.lineForScreenRow(0).tokens.length).toBe 1 atom.syntax.addGrammar(jsGrammar) - expect(editSession.getGrammar()).toBe jsGrammar - expect(editSession.lineForScreenRow(0).tokens.length).toBeGreaterThan 1 + expect(editor.getGrammar()).toBe jsGrammar + expect(editor.lineForScreenRow(0).tokens.length).toBeGreaterThan 1 describe "auto-indent", -> copyText = (text, {startColumn}={}) -> startColumn ?= 0 - editSession.setCursorBufferPosition([0, 0]) - editSession.insertText(text) + editor.setCursorBufferPosition([0, 0]) + editor.insertText(text) numberOfNewlines = text.match(/\n/g)?.length endColumn = text.match(/[^\n]*$/)[0]?.length - editSession.getSelection().setBufferRange([[0,startColumn], [numberOfNewlines,endColumn]]) - editSession.cutSelectedText() + editor.getSelection().setBufferRange([[0,startColumn], [numberOfNewlines,endColumn]]) + editor.cutSelectedText() describe "editor.autoIndent", -> describe "when editor.autoIndent is false (default)", -> describe "when `indent` is triggered", -> it "does not auto-indent the line", -> - editSession.setCursorBufferPosition([1, 30]) - editSession.insertText("\n ") - expect(editSession.lineForBufferRow(2)).toBe " " + editor.setCursorBufferPosition([1, 30]) + editor.insertText("\n ") + expect(editor.lineForBufferRow(2)).toBe " " atom.config.set("editor.autoIndent", false) - editSession.indent() - expect(editSession.lineForBufferRow(2)).toBe " " + editor.indent() + expect(editor.lineForBufferRow(2)).toBe " " describe "when editor.autoIndent is true", -> beforeEach -> @@ -2429,82 +2429,82 @@ describe "Editor", -> describe "when `indent` is triggered", -> it "auto-indents the line", -> - editSession.setCursorBufferPosition([1, 30]) - editSession.insertText("\n ") - expect(editSession.lineForBufferRow(2)).toBe " " + editor.setCursorBufferPosition([1, 30]) + editor.insertText("\n ") + expect(editor.lineForBufferRow(2)).toBe " " atom.config.set("editor.autoIndent", true) - editSession.indent() - expect(editSession.lineForBufferRow(2)).toBe " " + editor.indent() + expect(editor.lineForBufferRow(2)).toBe " " describe "when a newline is added", -> describe "when the line preceding the newline adds a new level of indentation", -> it "indents the newline to one additional level of indentation beyond the preceding line", -> - editSession.setCursorBufferPosition([1, Infinity]) - editSession.insertText('\n') - expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1) + 1 + editor.setCursorBufferPosition([1, Infinity]) + editor.insertText('\n') + expect(editor.indentationForBufferRow(2)).toBe editor.indentationForBufferRow(1) + 1 describe "when the line preceding the newline does't add a level of indentation", -> it "indents the new line to the same level a as the preceding line", -> - editSession.setCursorBufferPosition([5, 13]) - editSession.insertText('\n') - expect(editSession.indentationForBufferRow(6)).toBe editSession.indentationForBufferRow(5) + editor.setCursorBufferPosition([5, 13]) + editor.insertText('\n') + expect(editor.indentationForBufferRow(6)).toBe editor.indentationForBufferRow(5) describe "when the line preceding the newline is a comment", -> it "maintains the indent of the commented line", -> - editSession.setCursorBufferPosition([0, 0]) - editSession.insertText(' //') - editSession.setCursorBufferPosition([0, Infinity]) - editSession.insertText('\n') - expect(editSession.indentationForBufferRow(1)).toBe 2 + editor.setCursorBufferPosition([0, 0]) + editor.insertText(' //') + editor.setCursorBufferPosition([0, Infinity]) + editor.insertText('\n') + expect(editor.indentationForBufferRow(1)).toBe 2 it "does not indent the line preceding the newline", -> - editSession.setCursorBufferPosition([2, 0]) - editSession.insertText(' var this-line-should-be-indented-more\n') - expect(editSession.indentationForBufferRow(1)).toBe 1 + editor.setCursorBufferPosition([2, 0]) + editor.insertText(' var this-line-should-be-indented-more\n') + expect(editor.indentationForBufferRow(1)).toBe 1 atom.config.set("editor.autoIndent", true) - editSession.setCursorBufferPosition([2, Infinity]) - editSession.insertText('\n') - expect(editSession.indentationForBufferRow(1)).toBe 1 - expect(editSession.indentationForBufferRow(2)).toBe 1 + editor.setCursorBufferPosition([2, Infinity]) + editor.insertText('\n') + expect(editor.indentationForBufferRow(1)).toBe 1 + expect(editor.indentationForBufferRow(2)).toBe 1 describe "when inserted text matches a decrease indent pattern", -> describe "when the preceding line matches an increase indent pattern", -> it "decreases the indentation to match that of the preceding line", -> - editSession.setCursorBufferPosition([1, Infinity]) - editSession.insertText('\n') - expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1) + 1 - editSession.insertText('}') - expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1) + editor.setCursorBufferPosition([1, Infinity]) + editor.insertText('\n') + expect(editor.indentationForBufferRow(2)).toBe editor.indentationForBufferRow(1) + 1 + editor.insertText('}') + expect(editor.indentationForBufferRow(2)).toBe editor.indentationForBufferRow(1) describe "when the preceding line doesn't match an increase indent pattern", -> it "decreases the indentation to be one level below that of the preceding line", -> - editSession.setCursorBufferPosition([3, Infinity]) - editSession.insertText('\n ') - expect(editSession.indentationForBufferRow(4)).toBe editSession.indentationForBufferRow(3) - editSession.insertText('}') - expect(editSession.indentationForBufferRow(4)).toBe editSession.indentationForBufferRow(3) - 1 + editor.setCursorBufferPosition([3, Infinity]) + editor.insertText('\n ') + expect(editor.indentationForBufferRow(4)).toBe editor.indentationForBufferRow(3) + editor.insertText('}') + expect(editor.indentationForBufferRow(4)).toBe editor.indentationForBufferRow(3) - 1 it "doesn't break when decreasing the indentation on a row that has no indentation", -> - editSession.setCursorBufferPosition([12, Infinity]) - editSession.insertText("\n}; # too many closing brackets!") - expect(editSession.lineForBufferRow(13)).toBe "}; # too many closing brackets!" + editor.setCursorBufferPosition([12, Infinity]) + editor.insertText("\n}; # too many closing brackets!") + expect(editor.lineForBufferRow(13)).toBe "}; # too many closing brackets!" describe "when inserted text does not match a decrease indent pattern", -> it "does not the indentation", -> - editSession.setCursorBufferPosition([12, 0]) - editSession.insertText(' ') - expect(editSession.lineForBufferRow(12)).toBe ' };' - editSession.insertText('\t\t') - expect(editSession.lineForBufferRow(12)).toBe ' \t\t};' + editor.setCursorBufferPosition([12, 0]) + editor.insertText(' ') + expect(editor.lineForBufferRow(12)).toBe ' };' + editor.insertText('\t\t') + expect(editor.lineForBufferRow(12)).toBe ' \t\t};' describe "when the current line does not match a decrease indent pattern", -> it "leaves the line unchanged", -> - editSession.setCursorBufferPosition([2, 4]) - expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1) + 1 - editSession.insertText('foo') - expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1) + 1 + editor.setCursorBufferPosition([2, 4]) + expect(editor.indentationForBufferRow(2)).toBe editor.indentationForBufferRow(1) + 1 + editor.insertText('foo') + expect(editor.indentationForBufferRow(2)).toBe editor.indentationForBufferRow(1) + 1 describe "editor.normalizeIndentOnPaste", -> beforeEach -> @@ -2513,149 +2513,149 @@ describe "Editor", -> it "does not normalize the indentation level of the text when editor.normalizeIndentOnPaste is false", -> copyText(" function() {\nvar cool = 1;\n }\n") atom.config.set('editor.normalizeIndentOnPaste', false) - editSession.setCursorBufferPosition([5, 2]) - editSession.pasteText() - expect(editSession.lineForBufferRow(5)).toBe " function() {" - expect(editSession.lineForBufferRow(6)).toBe "var cool = 1;" - expect(editSession.lineForBufferRow(7)).toBe " }" + editor.setCursorBufferPosition([5, 2]) + editor.pasteText() + expect(editor.lineForBufferRow(5)).toBe " function() {" + expect(editor.lineForBufferRow(6)).toBe "var cool = 1;" + expect(editor.lineForBufferRow(7)).toBe " }" describe "when the inserted text contains no newlines", -> it "does not adjust the indentation level of the text", -> - editSession.setCursorBufferPosition([5, 2]) - editSession.insertText("foo", indentBasis: 5) - expect(editSession.lineForBufferRow(5)).toBe " foo current = items.shift();" + editor.setCursorBufferPosition([5, 2]) + editor.insertText("foo", indentBasis: 5) + expect(editor.lineForBufferRow(5)).toBe " foo current = items.shift();" it "does not adjust the whitespace if there are preceding characters", -> copyText(" foo") - editSession.setCursorBufferPosition([5, 30]) - editSession.pasteText() + editor.setCursorBufferPosition([5, 30]) + editor.pasteText() - expect(editSession.lineForBufferRow(5)).toBe " current = items.shift(); foo" + expect(editor.lineForBufferRow(5)).toBe " current = items.shift(); foo" describe "when the inserted text contains newlines", -> describe "when the cursor is preceded only by whitespace characters", -> it "normalizes indented lines to the cursor's current indentation level", -> copyText(" while (true) {\n foo();\n }\n", {startColumn: 2}) - editSession.setCursorBufferPosition([3, 4]) - editSession.pasteText() + editor.setCursorBufferPosition([3, 4]) + editor.pasteText() - expect(editSession.lineForBufferRow(3)).toBe " while (true) {" - expect(editSession.lineForBufferRow(4)).toBe " foo();" - expect(editSession.lineForBufferRow(5)).toBe " }" - expect(editSession.lineForBufferRow(6)).toBe "var pivot = items.shift(), current, left = [], right = [];" + expect(editor.lineForBufferRow(3)).toBe " while (true) {" + expect(editor.lineForBufferRow(4)).toBe " foo();" + expect(editor.lineForBufferRow(5)).toBe " }" + expect(editor.lineForBufferRow(6)).toBe "var pivot = items.shift(), current, left = [], right = [];" describe "when the cursor is preceded by non-whitespace characters", -> it "normalizes the indentation level of all lines based on the level of the existing first line", -> copyText(" while (true) {\n foo();\n }\n", {startColumn: 0}) - editSession.setCursorBufferPosition([1, Infinity]) - editSession.pasteText() + editor.setCursorBufferPosition([1, Infinity]) + editor.pasteText() - expect(editSession.lineForBufferRow(1)).toBe " var sort = function(items) {while (true) {" - expect(editSession.lineForBufferRow(2)).toBe " foo();" - expect(editSession.lineForBufferRow(3)).toBe " }" - expect(editSession.lineForBufferRow(4)).toBe "" + expect(editor.lineForBufferRow(1)).toBe " var sort = function(items) {while (true) {" + expect(editor.lineForBufferRow(2)).toBe " foo();" + expect(editor.lineForBufferRow(3)).toBe " }" + expect(editor.lineForBufferRow(4)).toBe "" it "autoIndentSelectedRows auto-indents the selection", -> - editSession.setCursorBufferPosition([2, 0]) - editSession.insertText("function() {\ninside=true\n}\n i=1\n") - editSession.getSelection().setBufferRange([[2,0], [6,0]]) - editSession.autoIndentSelectedRows() + editor.setCursorBufferPosition([2, 0]) + editor.insertText("function() {\ninside=true\n}\n i=1\n") + editor.getSelection().setBufferRange([[2,0], [6,0]]) + editor.autoIndentSelectedRows() - expect(editSession.lineForBufferRow(2)).toBe " function() {" - expect(editSession.lineForBufferRow(3)).toBe " inside=true" - expect(editSession.lineForBufferRow(4)).toBe " }" - expect(editSession.lineForBufferRow(5)).toBe " i=1" + expect(editor.lineForBufferRow(2)).toBe " function() {" + expect(editor.lineForBufferRow(3)).toBe " inside=true" + expect(editor.lineForBufferRow(4)).toBe " }" + expect(editor.lineForBufferRow(5)).toBe " i=1" describe ".destroy()", -> it "destroys all markers associated with the edit session", -> expect(buffer.getMarkerCount()).toBeGreaterThan 0 - editSession.destroy() + editor.destroy() expect(buffer.getMarkerCount()).toBe 0 describe ".joinLine()", -> describe "when no text is selected", -> describe "when the line below isn't empty", -> it "joins the line below with the current line separated by a space and moves the cursor to the start of line that was moved up", -> - editSession.joinLine() - expect(editSession.lineForBufferRow(0)).toBe 'var quicksort = function () { var sort = function(items) {' - expect(editSession.getCursorBufferPosition()).toEqual [0, 30] + editor.joinLine() + expect(editor.lineForBufferRow(0)).toBe 'var quicksort = function () { var sort = function(items) {' + expect(editor.getCursorBufferPosition()).toEqual [0, 30] describe "when the line below is empty", -> it "deletes the line below and moves the cursor to the end of the line", -> - editSession.setCursorBufferPosition([9]) - editSession.joinLine() - expect(editSession.lineForBufferRow(9)).toBe ' };' - expect(editSession.lineForBufferRow(10)).toBe ' return sort(Array.apply(this, arguments));' - expect(editSession.getCursorBufferPosition()).toEqual [9, 4] + editor.setCursorBufferPosition([9]) + editor.joinLine() + expect(editor.lineForBufferRow(9)).toBe ' };' + expect(editor.lineForBufferRow(10)).toBe ' return sort(Array.apply(this, arguments));' + expect(editor.getCursorBufferPosition()).toEqual [9, 4] describe "when the cursor is on the last row", -> it "does nothing", -> - editSession.setCursorBufferPosition([Infinity, Infinity]) - editSession.joinLine() - expect(editSession.lineForBufferRow(12)).toBe '};' + editor.setCursorBufferPosition([Infinity, Infinity]) + editor.joinLine() + expect(editor.lineForBufferRow(12)).toBe '};' describe "when text is selected", -> describe "when the selection does not span multiple lines", -> it "joins the line below with the current line separated by a space and retains the selected text", -> - editSession.setSelectedBufferRange([[0, 1], [0, 3]]) - editSession.joinLine() - expect(editSession.lineForBufferRow(0)).toBe 'var quicksort = function () { var sort = function(items) {' - expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [0, 3]] + editor.setSelectedBufferRange([[0, 1], [0, 3]]) + editor.joinLine() + expect(editor.lineForBufferRow(0)).toBe 'var quicksort = function () { var sort = function(items) {' + expect(editor.getSelectedBufferRange()).toEqual [[0, 1], [0, 3]] describe "when the selection spans multiple lines", -> it "joins all selected lines separated by a space and retains the selected text", -> - editSession.setSelectedBufferRange([[9, 3], [12, 1]]) - editSession.joinLine() - expect(editSession.lineForBufferRow(9)).toBe ' }; return sort(Array.apply(this, arguments)); };' - expect(editSession.getSelectedBufferRange()).toEqual [[9, 3], [9, 49]] + editor.setSelectedBufferRange([[9, 3], [12, 1]]) + editor.joinLine() + expect(editor.lineForBufferRow(9)).toBe ' }; return sort(Array.apply(this, arguments)); };' + expect(editor.getSelectedBufferRange()).toEqual [[9, 3], [9, 49]] describe ".shouldPromptToSave()", -> it "returns false when an edit session's buffer is in use by more than one session", -> - expect(editSession.shouldPromptToSave()).toBeFalsy() + expect(editor.shouldPromptToSave()).toBeFalsy() buffer.setText('changed') - expect(editSession.shouldPromptToSave()).toBeTruthy() - editSession2 = project.openSync('sample.js', autoIndent: false) - expect(editSession.shouldPromptToSave()).toBeFalsy() - editSession2.destroy() - expect(editSession.shouldPromptToSave()).toBeTruthy() + expect(editor.shouldPromptToSave()).toBeTruthy() + editor2 = project.openSync('sample.js', autoIndent: false) + expect(editor.shouldPromptToSave()).toBeFalsy() + editor2.destroy() + expect(editor.shouldPromptToSave()).toBeTruthy() describe "when the edit session contains surrogate pair characters", -> it "correctly backspaces over them", -> - editSession.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97') - editSession.moveCursorToBottom() - editSession.backspace() - expect(editSession.getText()).toBe '\uD835\uDF97\uD835\uDF97' - editSession.backspace() - expect(editSession.getText()).toBe '\uD835\uDF97' - editSession.backspace() - expect(editSession.getText()).toBe '' + editor.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97') + editor.moveCursorToBottom() + editor.backspace() + expect(editor.getText()).toBe '\uD835\uDF97\uD835\uDF97' + editor.backspace() + expect(editor.getText()).toBe '\uD835\uDF97' + editor.backspace() + expect(editor.getText()).toBe '' it "correctly deletes over them", -> - editSession.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97') - editSession.moveCursorToTop() - editSession.delete() - expect(editSession.getText()).toBe '\uD835\uDF97\uD835\uDF97' - editSession.delete() - expect(editSession.getText()).toBe '\uD835\uDF97' - editSession.delete() - expect(editSession.getText()).toBe '' + editor.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97') + editor.moveCursorToTop() + editor.delete() + expect(editor.getText()).toBe '\uD835\uDF97\uD835\uDF97' + editor.delete() + expect(editor.getText()).toBe '\uD835\uDF97' + editor.delete() + expect(editor.getText()).toBe '' it "correctly moves over them", -> - editSession.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97\n') - editSession.moveCursorToTop() - editSession.moveCursorRight() - expect(editSession.getCursorBufferPosition()).toEqual [0, 2] - editSession.moveCursorRight() - expect(editSession.getCursorBufferPosition()).toEqual [0, 4] - editSession.moveCursorRight() - expect(editSession.getCursorBufferPosition()).toEqual [0, 6] - editSession.moveCursorRight() - expect(editSession.getCursorBufferPosition()).toEqual [1, 0] - editSession.moveCursorLeft() - expect(editSession.getCursorBufferPosition()).toEqual [0, 6] - editSession.moveCursorLeft() - expect(editSession.getCursorBufferPosition()).toEqual [0, 4] - editSession.moveCursorLeft() - expect(editSession.getCursorBufferPosition()).toEqual [0, 2] - editSession.moveCursorLeft() - expect(editSession.getCursorBufferPosition()).toEqual [0, 0] + editor.setText('\uD835\uDF97\uD835\uDF97\uD835\uDF97\n') + editor.moveCursorToTop() + editor.moveCursorRight() + expect(editor.getCursorBufferPosition()).toEqual [0, 2] + editor.moveCursorRight() + expect(editor.getCursorBufferPosition()).toEqual [0, 4] + editor.moveCursorRight() + expect(editor.getCursorBufferPosition()).toEqual [0, 6] + editor.moveCursorRight() + expect(editor.getCursorBufferPosition()).toEqual [1, 0] + editor.moveCursorLeft() + expect(editor.getCursorBufferPosition()).toEqual [0, 6] + editor.moveCursorLeft() + expect(editor.getCursorBufferPosition()).toEqual [0, 4] + editor.moveCursorLeft() + expect(editor.getCursorBufferPosition()).toEqual [0, 2] + editor.moveCursorLeft() + expect(editor.getCursorBufferPosition()).toEqual [0, 0] diff --git a/spec/editor-view-spec.coffee b/spec/editor-view-spec.coffee index 86672b996..7b1dc5493 100644 --- a/spec/editor-view-spec.coffee +++ b/spec/editor-view-spec.coffee @@ -7,14 +7,14 @@ path = require 'path' temp = require 'temp' describe "EditorView", -> - [buffer, editorView, editSession, cachedLineHeight, cachedCharWidth] = [] + [buffer, editorView, editor, cachedLineHeight, cachedCharWidth] = [] beforeEach -> atom.activatePackage('language-text', sync: true) atom.activatePackage('language-javascript', sync: true) - editSession = project.openSync('sample.js') - buffer = editSession.buffer - editorView = new EditorView(editSession) + editor = project.openSync('sample.js') + buffer = editor.buffer + editorView = new EditorView(editor) editorView.lineOverdraw = 2 editorView.isFocused = true editorView.enableKeymap() @@ -37,7 +37,7 @@ describe "EditorView", -> cachedCharWidth calcDimensions = -> - editorForMeasurement = new EditorView(editSession: project.openSync('sample.js')) + editorForMeasurement = new EditorView(editor: project.openSync('sample.js')) editorForMeasurement.attachToDom() cachedLineHeight = editorForMeasurement.lineHeight cachedCharWidth = editorForMeasurement.charWidth @@ -103,12 +103,12 @@ describe "EditorView", -> it "triggers an alert", -> filePath = path.join(temp.dir, 'atom-changed-file.txt') fs.writeFileSync(filePath, "") - editSession = project.openSync(filePath) - editorView.edit(editSession) + editor = project.openSync(filePath) + editorView.edit(editor) editorView.insertText("now the buffer is modified") fileChangeHandler = jasmine.createSpy('fileChange') - editSession.buffer.file.on 'contents-changed', fileChangeHandler + editor.buffer.file.on 'contents-changed', fileChangeHandler spyOn(atom, "confirm") @@ -125,7 +125,7 @@ describe "EditorView", -> editorView.remove() expect(editorView.activeEditSession.destroyed).toBeTruthy() - describe ".edit(editSession)", -> + describe ".edit(editor)", -> [newEditSession, newBuffer] = [] beforeEach -> @@ -154,7 +154,7 @@ describe "EditorView", -> editorView.insertText("hello") expect(editorView.lineElementForScreenRow(40).text()).toBe "hello3" - editorView.edit(editSession) + editorView.edit(editor) { firstRenderedScreenRow, lastRenderedScreenRow } = editorView expect(editorView.lineElementForScreenRow(firstRenderedScreenRow).text()).toBe buffer.lineForRow(firstRenderedScreenRow) expect(editorView.lineElementForScreenRow(lastRenderedScreenRow).text()).toBe buffer.lineForRow(editorView.lastRenderedScreenRow) @@ -821,11 +821,11 @@ describe "EditorView", -> describe "when a selection merges with another selection", -> it "removes the merged selection view", -> - editSession = editorView.activeEditSession - editSession.setCursorScreenPosition([4, 10]) - editSession.selectToScreenPosition([5, 27]) - editSession.addCursorAtScreenPosition([3, 10]) - editSession.selectToScreenPosition([6, 27]) + editor = editorView.activeEditSession + editor.setCursorScreenPosition([4, 10]) + editor.selectToScreenPosition([5, 27]) + editor.addCursorAtScreenPosition([3, 10]) + editor.selectToScreenPosition([6, 27]) expect(editorView.getSelectionViews().length).toBe 1 expect(editorView.find('.region').length).toBe 3 @@ -836,8 +836,8 @@ describe "EditorView", -> jasmine.unspy(editorView, 'requestDisplayUpdate') spyOn(editorView, 'requestDisplayUpdate') - editSession = editorView.activeEditSession - selection = editSession.addSelectionForBufferRange([[3, 0], [3, 4]]) + editor = editorView.activeEditSession + selection = editor.addSelectionForBufferRange([[3, 0], [3, 4]]) selection.destroy() editorView.updateDisplay() expect(editorView.getSelectionViews().length).toBe 1 @@ -1075,7 +1075,7 @@ describe "EditorView", -> describe "when soft-wrap is enabled", -> beforeEach -> - editSession.setSoftWrap(true) + editor.setSoftWrap(true) it "does not scroll the buffer horizontally", -> editorView.width(charWidth * 30) @@ -1545,7 +1545,7 @@ describe "EditorView", -> describe "when wrapping is on", -> beforeEach -> - editSession.setSoftWrap(true) + editor.setSoftWrap(true) it "doesn't show the end of line invisible at the end of lines broken due to wrapping", -> editorView.setText "a line that wraps" @@ -1699,7 +1699,7 @@ describe "EditorView", -> describe "when soft-wrap is enabled", -> beforeEach -> jasmine.unspy(window, 'setTimeout') - editSession.setSoftWrap(true) + editor.setSoftWrap(true) editorView.attachToDom() setEditorHeightInLines(editorView, 20) setEditorWidthInChars(editorView, 50) @@ -1768,7 +1768,7 @@ describe "EditorView", -> expect(editorView.getCursorScreenPosition()).toEqual [11, 0] it "calls .setWidthInChars() when the editor view is attached because now its dimensions are available to calculate it", -> - otherEditor = new EditorView(editSession: project.openSync('sample.js')) + otherEditor = new EditorView(editor: project.openSync('sample.js')) spyOn(otherEditor, 'setWidthInChars') otherEditor.activeEditSession.setSoftWrap(true) @@ -1780,7 +1780,7 @@ describe "EditorView", -> describe "when the editor view's width changes", -> it "updates the width in characters on the edit session", -> - previousSoftWrapColumn = editSession.getSoftWrapColumn() + previousSoftWrapColumn = editor.getSoftWrapColumn() spyOn(editorView, 'setWidthInChars').andCallThrough() editorView.width(editorView.width() / 2) @@ -1789,7 +1789,7 @@ describe "EditorView", -> editorView.setWidthInChars.callCount > 0 runs -> - expect(editSession.getSoftWrapColumn()).toBeLessThan previousSoftWrapColumn + expect(editor.getSoftWrapColumn()).toBeLessThan previousSoftWrapColumn describe "gutter rendering", -> beforeEach -> @@ -1832,7 +1832,7 @@ describe "EditorView", -> describe "when wrapping is on", -> it "renders a • instead of line number for wrapped portions of lines", -> - editSession.setSoftWrap(true) + editor.setSoftWrap(true) editorView.setWidthInChars(50) expect(editorView.gutter.find('.line-number').length).toEqual(8) expect(editorView.gutter.find('.line-number:eq(3)').intValue()).toBe 4 @@ -1898,7 +1898,7 @@ describe "EditorView", -> editorView.edit(emptyEditSession) expect(editorView.gutter.lineNumbers.find('.line-number').length).toBe 1 - editorView.edit(editSession) + editorView.edit(editor) expect(editorView.gutter.lineNumbers.find('.line-number').length).toBeGreaterThan 1 editorView.edit(emptyEditSession) @@ -2014,7 +2014,7 @@ describe "EditorView", -> describe "when there is wrapping", -> beforeEach -> editorView.attachToDom(30) - editSession.setSoftWrap(true) + editor.setSoftWrap(true) setEditorWidthInChars(editorView, 20) it "highlights the line where the initial cursor position is", -> @@ -2077,7 +2077,7 @@ describe "EditorView", -> describe "when there is wrapping", -> beforeEach -> - editSession.setSoftWrap(true) + editor.setSoftWrap(true) setEditorWidthInChars(editorView, 20) it "highlights the line where the initial cursor position is", -> @@ -2098,9 +2098,9 @@ describe "EditorView", -> describe "folding", -> beforeEach -> - editSession = project.openSync('two-hundred.txt') - buffer = editSession.buffer - editorView.edit(editSession) + editor = project.openSync('two-hundred.txt') + buffer = editor.buffer + editorView.edit(editor) editorView.attachToDom() describe "when a fold-selection event is triggered", -> @@ -2124,7 +2124,7 @@ describe "EditorView", -> describe "when a fold placeholder line is clicked", -> it "removes the associated fold and places the cursor at its beginning", -> editorView.setCursorBufferPosition([3,0]) - editSession.createFold(3, 5) + editor.createFold(3, 5) foldLine = editorView.find('.line.fold') expect(foldLine).toExist() diff --git a/spec/git-spec.coffee b/spec/git-spec.coffee index a1bd31db4..b28f1094e 100644 --- a/spec/git-spec.coffee +++ b/spec/git-spec.coffee @@ -208,44 +208,44 @@ describe "Git", -> expect(repo.isStatusModified(statuses[modifiedPath])).toBeTruthy() describe "buffer events", -> - [originalContent, editSession] = [] + [originalContent, editor] = [] beforeEach -> - editSession = project.openSync('sample.js') - originalContent = editSession.getText() + editor = project.openSync('sample.js') + originalContent = editor.getText() afterEach -> - fs.writeFileSync(editSession.getPath(), originalContent) + fs.writeFileSync(editor.getPath(), originalContent) it "emits a status-changed event when a buffer is saved", -> - editSession.insertNewline() + editor.insertNewline() statusHandler = jasmine.createSpy('statusHandler') project.getRepo().on 'status-changed', statusHandler - editSession.save() + editor.save() expect(statusHandler.callCount).toBe 1 - expect(statusHandler).toHaveBeenCalledWith editSession.getPath(), 256 + expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256 it "emits a status-changed event when a buffer is reloaded", -> - fs.writeFileSync(editSession.getPath(), 'changed') + fs.writeFileSync(editor.getPath(), 'changed') statusHandler = jasmine.createSpy('statusHandler') project.getRepo().on 'status-changed', statusHandler - editSession.getBuffer().reload() + editor.getBuffer().reload() expect(statusHandler.callCount).toBe 1 - expect(statusHandler).toHaveBeenCalledWith editSession.getPath(), 256 - editSession.getBuffer().reload() + expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256 + editor.getBuffer().reload() expect(statusHandler.callCount).toBe 1 it "emits a status-changed event when a buffer's path changes", -> - fs.writeFileSync(editSession.getPath(), 'changed') + fs.writeFileSync(editor.getPath(), 'changed') statusHandler = jasmine.createSpy('statusHandler') project.getRepo().on 'status-changed', statusHandler - editSession.getBuffer().emit 'path-changed' + editor.getBuffer().emit 'path-changed' expect(statusHandler.callCount).toBe 1 - expect(statusHandler).toHaveBeenCalledWith editSession.getPath(), 256 - editSession.getBuffer().emit 'path-changed' + expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256 + editor.getBuffer().emit 'path-changed' expect(statusHandler.callCount).toBe 1 describe "when a project is deserialized", -> diff --git a/spec/language-mode-spec.coffee b/spec/language-mode-spec.coffee index b27a15c68..3d1db09d0 100644 --- a/spec/language-mode-spec.coffee +++ b/spec/language-mode-spec.coffee @@ -1,14 +1,14 @@ describe "LanguageMode", -> - [editSession, buffer, languageMode] = [] + [editor, buffer, languageMode] = [] afterEach -> - editSession.destroy() + editor.destroy() describe "javascript", -> beforeEach -> atom.activatePackage('language-javascript', sync: true) - editSession = project.openSync('sample.js', autoIndent: false) - {buffer, languageMode} = editSession + editor = project.openSync('sample.js', autoIndent: false) + {buffer, languageMode} = editor describe ".minIndentLevelForRowRange(startRow, endRow)", -> it "returns the minimum indent level for the given row range", -> @@ -110,8 +110,8 @@ describe "LanguageMode", -> describe "coffeescript", -> beforeEach -> atom.activatePackage('language-coffee-script', sync: true) - editSession = project.openSync('coffee.coffee', autoIndent: false) - {buffer, languageMode} = editSession + editor = project.openSync('coffee.coffee', autoIndent: false) + {buffer, languageMode} = editor describe ".toggleLineCommentsForBufferRows(start, end)", -> it "comments/uncomments lines in the given range", -> @@ -157,8 +157,8 @@ describe "LanguageMode", -> describe "css", -> beforeEach -> atom.activatePackage('language-css', sync: true) - editSession = project.openSync('css.css', autoIndent: false) - {buffer, languageMode} = editSession + editor = project.openSync('css.css', autoIndent: false) + {buffer, languageMode} = editor describe ".toggleLineCommentsForBufferRows(start, end)", -> it "comments/uncomments lines in the given range", -> @@ -199,8 +199,8 @@ describe "LanguageMode", -> beforeEach -> atom.activatePackage('language-less', sync: true) atom.activatePackage('language-css', sync: true) - editSession = project.openSync('sample.less', autoIndent: false) - {buffer, languageMode} = editSession + editor = project.openSync('sample.less', autoIndent: false) + {buffer, languageMode} = editor describe "when commenting lines", -> it "only uses the `commentEnd` pattern if it comes from the same grammar as the `commentStart`", -> @@ -210,67 +210,67 @@ describe "LanguageMode", -> describe "folding", -> beforeEach -> atom.activatePackage('language-javascript', sync: true) - editSession = project.openSync('sample.js', autoIndent: false) - {buffer, languageMode} = editSession + editor = project.openSync('sample.js', autoIndent: false) + {buffer, languageMode} = editor it "maintains cursor buffer position when a folding/unfolding", -> - editSession.setCursorBufferPosition([5,5]) + editor.setCursorBufferPosition([5,5]) languageMode.foldAll() - expect(editSession.getCursorBufferPosition()).toEqual([5,5]) + expect(editor.getCursorBufferPosition()).toEqual([5,5]) describe ".unfoldAll()", -> it "unfolds every folded line", -> - initialScreenLineCount = editSession.getScreenLineCount() + initialScreenLineCount = editor.getScreenLineCount() languageMode.foldBufferRow(0) languageMode.foldBufferRow(1) - expect(editSession.getScreenLineCount()).toBeLessThan initialScreenLineCount + expect(editor.getScreenLineCount()).toBeLessThan initialScreenLineCount languageMode.unfoldAll() - expect(editSession.getScreenLineCount()).toBe initialScreenLineCount + expect(editor.getScreenLineCount()).toBe initialScreenLineCount describe ".foldAll()", -> it "folds every foldable line", -> languageMode.foldAll() - fold1 = editSession.lineForScreenRow(0).fold + fold1 = editor.lineForScreenRow(0).fold expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 12] fold1.destroy() - fold2 = editSession.lineForScreenRow(1).fold + fold2 = editor.lineForScreenRow(1).fold expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [1, 9] fold2.destroy() - fold3 = editSession.lineForScreenRow(4).fold + fold3 = editor.lineForScreenRow(4).fold expect([fold3.getStartRow(), fold3.getEndRow()]).toEqual [4, 7] describe ".foldBufferRow(bufferRow)", -> describe "when bufferRow can be folded", -> it "creates a fold based on the syntactic region starting at the given row", -> languageMode.foldBufferRow(1) - fold = editSession.lineForScreenRow(1).fold + fold = editor.lineForScreenRow(1).fold expect(fold.getStartRow()).toBe 1 expect(fold.getEndRow()).toBe 9 describe "when bufferRow can't be folded", -> it "searches upward for the first row that begins a syntatic region containing the given buffer row (and folds it)", -> languageMode.foldBufferRow(8) - fold = editSession.lineForScreenRow(1).fold + fold = editor.lineForScreenRow(1).fold expect(fold.getStartRow()).toBe 1 expect(fold.getEndRow()).toBe 9 describe "when the bufferRow is already folded", -> it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", -> languageMode.foldBufferRow(2) - expect(editSession.lineForScreenRow(1).fold).toBeDefined() - expect(editSession.lineForScreenRow(0).fold).not.toBeDefined() + expect(editor.lineForScreenRow(1).fold).toBeDefined() + expect(editor.lineForScreenRow(0).fold).not.toBeDefined() languageMode.foldBufferRow(1) - expect(editSession.lineForScreenRow(0).fold).toBeDefined() + expect(editor.lineForScreenRow(0).fold).toBeDefined() describe "when the bufferRow is in a multi-line comment", -> it "searches upward and downward for surrounding comment lines and folds them as a single fold", -> buffer.insert([1,0], " //this is a comment\n // and\n //more docs\n\n//second comment") languageMode.foldBufferRow(1) - fold = editSession.lineForScreenRow(1).fold + fold = editor.lineForScreenRow(1).fold expect(fold.getStartRow()).toBe 1 expect(fold.getEndRow()).toBe 3 @@ -278,7 +278,7 @@ describe "LanguageMode", -> it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", -> buffer.insert([1,0], " //this is a single line comment\n") languageMode.foldBufferRow(1) - fold = editSession.lineForScreenRow(0).fold + fold = editor.lineForScreenRow(0).fold expect(fold.getStartRow()).toBe 0 expect(fold.getEndRow()).toBe 13 @@ -286,77 +286,77 @@ describe "LanguageMode", -> describe "when bufferRow can be unfolded", -> it "destroys a fold based on the syntactic region starting at the given row", -> languageMode.foldBufferRow(1) - expect(editSession.lineForScreenRow(1).fold).toBeDefined() + expect(editor.lineForScreenRow(1).fold).toBeDefined() languageMode.unfoldBufferRow(1) - expect(editSession.lineForScreenRow(1).fold).toBeUndefined() + expect(editor.lineForScreenRow(1).fold).toBeUndefined() describe "when bufferRow can't be unfolded", -> it "does not throw an error", -> - expect(editSession.lineForScreenRow(1).fold).toBeUndefined() + expect(editor.lineForScreenRow(1).fold).toBeUndefined() languageMode.unfoldBufferRow(1) - expect(editSession.lineForScreenRow(1).fold).toBeUndefined() + expect(editor.lineForScreenRow(1).fold).toBeUndefined() describe "folding with comments", -> beforeEach -> atom.activatePackage('language-javascript', sync: true) - editSession = project.openSync('sample-with-comments.js', autoIndent: false) - {buffer, languageMode} = editSession + editor = project.openSync('sample-with-comments.js', autoIndent: false) + {buffer, languageMode} = editor describe ".unfoldAll()", -> it "unfolds every folded line", -> - initialScreenLineCount = editSession.getScreenLineCount() + initialScreenLineCount = editor.getScreenLineCount() languageMode.foldBufferRow(0) languageMode.foldBufferRow(5) - expect(editSession.getScreenLineCount()).toBeLessThan initialScreenLineCount + expect(editor.getScreenLineCount()).toBeLessThan initialScreenLineCount languageMode.unfoldAll() - expect(editSession.getScreenLineCount()).toBe initialScreenLineCount + expect(editor.getScreenLineCount()).toBe initialScreenLineCount describe ".foldAll()", -> it "folds every foldable line", -> languageMode.foldAll() - fold1 = editSession.lineForScreenRow(0).fold + fold1 = editor.lineForScreenRow(0).fold expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 19] fold1.destroy() - fold2 = editSession.lineForScreenRow(1).fold + fold2 = editor.lineForScreenRow(1).fold expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [1, 4] - fold3 = editSession.lineForScreenRow(2).fold.destroy() + fold3 = editor.lineForScreenRow(2).fold.destroy() - fold4 = editSession.lineForScreenRow(3).fold + fold4 = editor.lineForScreenRow(3).fold expect([fold4.getStartRow(), fold4.getEndRow()]).toEqual [6, 8] describe ".foldAllAtIndentLevel()", -> it "folds every foldable range at a given indentLevel", -> languageMode.foldAllAtIndentLevel(2) - fold1 = editSession.lineForScreenRow(6).fold + fold1 = editor.lineForScreenRow(6).fold expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [6, 8] fold1.destroy() - fold2 = editSession.lineForScreenRow(11).fold + fold2 = editor.lineForScreenRow(11).fold expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [11, 14] fold2.destroy() it "does not fold anything but the indentLevel", -> languageMode.foldAllAtIndentLevel(0) - fold1 = editSession.lineForScreenRow(0).fold + fold1 = editor.lineForScreenRow(0).fold expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 19] fold1.destroy() - fold2 = editSession.lineForScreenRow(5).fold + fold2 = editor.lineForScreenRow(5).fold expect(fold2).toBeFalsy() describe "css", -> beforeEach -> atom.activatePackage('language-source', sync: true) atom.activatePackage('language-css', sync: true) - editSession = project.openSync('css.css', autoIndent: true) + editor = project.openSync('css.css', autoIndent: true) describe "suggestedIndentForBufferRow", -> it "does not return negative values (regression)", -> - editSession.setText('.test {\npadding: 0;\n}') - expect(editSession.suggestedIndentForBufferRow(2)).toBe 0 + editor.setText('.test {\npadding: 0;\n}') + expect(editor.suggestedIndentForBufferRow(2)).toBe 0 diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index d4ae4e057..d1f14541e 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -111,11 +111,11 @@ describe "PaneContainer", -> describe "when the last-closed pane item is an edit session", -> it "reopens the edit session (regression)", -> - editSession = project.openSync('sample.js') - pane3.showItem(editSession) - pane3.destroyItem(editSession) + editor = project.openSync('sample.js') + pane3.showItem(editor) + pane3.destroyItem(editor) expect(container.reopenItem()).toBeTruthy() - expect(pane3.activeItem.getPath()).toBe editSession.getPath() + expect(pane3.activeItem.getPath()).toBe editor.getPath() expect(container.reopenItem()).toBeFalsy() describe "when there is no active pane", -> diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 5f50b7251..29d40105d 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -5,7 +5,7 @@ path = require 'path' temp = require 'temp' describe "Pane", -> - [container, view1, view2, editSession1, editSession2, pane] = [] + [container, view1, view2, editor1, editor2, pane] = [] class TestView extends View @deserialize: ({id, text}) -> new TestView({id, text}) @@ -20,9 +20,9 @@ describe "Pane", -> container = new PaneContainer view1 = new TestView(id: 'view-1', text: 'View 1') view2 = new TestView(id: 'view-2', text: 'View 2') - editSession1 = project.openSync('sample.js') - editSession2 = project.openSync('sample.txt') - pane = new Pane(view1, editSession1, view2, editSession2) + editor1 = project.openSync('sample.js') + editor2 = project.openSync('sample.txt') + pane = new Pane(view1, editor1, view2, editor2) container.setRoot(pane) afterEach -> @@ -52,9 +52,9 @@ describe "Pane", -> expect(itemChangedHandler.argsForCall[0][1]).toBe view2 itemChangedHandler.reset() - pane.showItem(editSession1) + pane.showItem(editor1) expect(itemChangedHandler).toHaveBeenCalled() - expect(itemChangedHandler.argsForCall[0][1]).toBe editSession1 + expect(itemChangedHandler.argsForCall[0][1]).toBe editor1 itemChangedHandler.reset() describe "if the pane's active view is focused before calling showItem", -> @@ -70,12 +70,12 @@ describe "Pane", -> view3 = null beforeEach -> view3 = new TestView(id: 'view-3', text: "View 3") - pane.showItem(editSession1) + pane.showItem(editor1) expect(pane.getActiveItemIndex()).toBe 1 it "adds it to the items list after the active item", -> pane.showItem(view3) - expect(pane.getItems()).toEqual [view1, editSession1, view3, view2, editSession2] + expect(pane.getItems()).toEqual [view1, editor1, view3, view2, editor2] expect(pane.activeItem).toBe view3 expect(pane.getActiveItemIndex()).toBe 2 @@ -89,19 +89,19 @@ describe "Pane", -> describe "when showing a model item", -> describe "when no view has yet been appended for that item", -> it "appends and shows a view to display the item based on its `.getViewClass` method", -> - pane.showItem(editSession1) + pane.showItem(editor1) editorView = pane.activeView expect(editorView.css('display')).not.toBe 'none' - expect(editorView.activeEditSession).toBe editSession1 + expect(editorView.activeEditSession).toBe editor1 describe "when a valid view has already been appended for another item", -> it "multiple views are created for multiple items", -> - pane.showItem(editSession1) - pane.showItem(editSession2) + pane.showItem(editor1) + pane.showItem(editor2) expect(pane.itemViews.find('.editor').length).toBe 2 editorView = pane.activeView expect(editorView.css('display')).not.toBe 'none' - expect(editorView.activeEditSession).toBe editSession2 + expect(editorView.activeEditSession).toBe editor2 it "creates a new view with the item", -> initialViewCount = pane.itemViews.find('.test-view').length @@ -141,77 +141,77 @@ describe "Pane", -> describe ".destroyItem(item)", -> describe "if the item is not modified", -> it "removes the item and tries to call destroy on it", -> - pane.destroyItem(editSession2) - expect(pane.getItems().indexOf(editSession2)).toBe -1 - expect(editSession2.destroyed).toBeTruthy() + pane.destroyItem(editor2) + expect(pane.getItems().indexOf(editor2)).toBe -1 + expect(editor2.destroyed).toBeTruthy() describe "if the item is modified", -> beforeEach -> - spyOn(editSession2, 'save') - spyOn(editSession2, 'saveAs') + spyOn(editor2, 'save') + spyOn(editor2, 'saveAs') - editSession2.insertText('a') - expect(editSession2.isModified()).toBeTruthy() + editor2.insertText('a') + expect(editor2.isModified()).toBeTruthy() describe "if the [Save] option is selected", -> describe "when the item has a uri", -> it "saves the item before removing and destroying it", -> spyOn(atom, 'confirmSync').andReturn(0) - pane.destroyItem(editSession2) + pane.destroyItem(editor2) - expect(editSession2.save).toHaveBeenCalled() - expect(pane.getItems().indexOf(editSession2)).toBe -1 - expect(editSession2.destroyed).toBeTruthy() + expect(editor2.save).toHaveBeenCalled() + expect(pane.getItems().indexOf(editor2)).toBe -1 + expect(editor2.destroyed).toBeTruthy() describe "when the item has no uri", -> it "presents a save-as dialog, then saves the item with the given uri before removing and destroying it", -> - editSession2.buffer.setPath(undefined) + editor2.buffer.setPath(undefined) spyOn(atom, 'showSaveDialogSync').andReturn("/selected/path") spyOn(atom, 'confirmSync').andReturn(0) - pane.destroyItem(editSession2) + pane.destroyItem(editor2) expect(atom.showSaveDialogSync).toHaveBeenCalled() - expect(editSession2.saveAs).toHaveBeenCalledWith("/selected/path") - expect(pane.getItems().indexOf(editSession2)).toBe -1 - expect(editSession2.destroyed).toBeTruthy() + expect(editor2.saveAs).toHaveBeenCalledWith("/selected/path") + expect(pane.getItems().indexOf(editor2)).toBe -1 + expect(editor2.destroyed).toBeTruthy() describe "if the [Don't Save] option is selected", -> it "removes and destroys the item without saving it", -> spyOn(atom, 'confirmSync').andReturn(2) - pane.destroyItem(editSession2) + pane.destroyItem(editor2) - expect(editSession2.save).not.toHaveBeenCalled() - expect(pane.getItems().indexOf(editSession2)).toBe -1 - expect(editSession2.destroyed).toBeTruthy() + expect(editor2.save).not.toHaveBeenCalled() + expect(pane.getItems().indexOf(editor2)).toBe -1 + expect(editor2.destroyed).toBeTruthy() describe "if the [Cancel] option is selected", -> it "does not save, remove, or destroy the item", -> spyOn(atom, 'confirmSync').andReturn(1) - pane.destroyItem(editSession2) + pane.destroyItem(editor2) - expect(editSession2.save).not.toHaveBeenCalled() - expect(pane.getItems().indexOf(editSession2)).not.toBe -1 - expect(editSession2.destroyed).toBeFalsy() + expect(editor2.save).not.toHaveBeenCalled() + expect(pane.getItems().indexOf(editor2)).not.toBe -1 + expect(editor2.destroyed).toBeFalsy() describe ".removeItem(item)", -> it "removes the item from the items list and shows the next item if it was showing", -> pane.removeItem(view1) - expect(pane.getItems()).toEqual [editSession1, view2, editSession2] - expect(pane.activeItem).toBe editSession1 + expect(pane.getItems()).toEqual [editor1, view2, editor2] + expect(pane.activeItem).toBe editor1 - pane.showItem(editSession2) - pane.removeItem(editSession2) - expect(pane.getItems()).toEqual [editSession1, view2] - expect(pane.activeItem).toBe editSession1 + pane.showItem(editor2) + pane.removeItem(editor2) + expect(pane.getItems()).toEqual [editor1, view2] + expect(pane.activeItem).toBe editor1 it "triggers 'pane:item-removed' with the item and its former index", -> itemRemovedHandler = jasmine.createSpy("itemRemovedHandler") pane.on 'pane:item-removed', itemRemovedHandler - pane.removeItem(editSession1) + pane.removeItem(editor1) expect(itemRemovedHandler).toHaveBeenCalled() - expect(itemRemovedHandler.argsForCall[0][1..2]).toEqual [editSession1, 1] + expect(itemRemovedHandler.argsForCall[0][1..2]).toEqual [editor1, 1] describe "when removing the last item", -> it "removes the pane", -> @@ -236,11 +236,11 @@ describe "Pane", -> describe "when the item is a model", -> it "removes the associated view only when all items that require it have been removed", -> - pane.showItem(editSession1) - pane.showItem(editSession2) - pane.removeItem(editSession2) + pane.showItem(editor1) + pane.showItem(editor2) + pane.removeItem(editor2) expect(pane.itemViews.find('.editor')).toExist() - pane.removeItem(editSession1) + pane.removeItem(editor1) expect(pane.itemViews.find('.editor')).not.toExist() describe ".moveItem(item, index)", -> @@ -249,21 +249,21 @@ describe "Pane", -> pane.on 'pane:item-moved', itemMovedHandler pane.moveItem(view1, 2) - expect(pane.getItems()).toEqual [editSession1, view2, view1, editSession2] + expect(pane.getItems()).toEqual [editor1, view2, view1, editor2] expect(itemMovedHandler).toHaveBeenCalled() expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [view1, 2] itemMovedHandler.reset() - pane.moveItem(editSession1, 3) - expect(pane.getItems()).toEqual [view2, view1, editSession2, editSession1] + pane.moveItem(editor1, 3) + expect(pane.getItems()).toEqual [view2, view1, editor2, editor1] expect(itemMovedHandler).toHaveBeenCalled() - expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editSession1, 3] + expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editor1, 3] itemMovedHandler.reset() - pane.moveItem(editSession1, 1) - expect(pane.getItems()).toEqual [view2, editSession1, view1, editSession2] + pane.moveItem(editor1, 1) + expect(pane.getItems()).toEqual [view2, editor1, view1, editor2] expect(itemMovedHandler).toHaveBeenCalled() - expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editSession1, 1] + expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editor1, 1] itemMovedHandler.reset() describe ".moveItemToPane(item, pane, index)", -> @@ -275,21 +275,21 @@ describe "Pane", -> it "moves the item to the given pane at the given index", -> pane.moveItemToPane(view1, pane2, 1) - expect(pane.getItems()).toEqual [editSession1, view2, editSession2] + expect(pane.getItems()).toEqual [editor1, view2, editor2] expect(pane2.getItems()).toEqual [view3, view1] describe "when it is the last item on the source pane", -> it "removes the source pane, but does not destroy the item", -> pane.removeItem(view1) pane.removeItem(view2) - pane.removeItem(editSession2) + pane.removeItem(editor2) - expect(pane.getItems()).toEqual [editSession1] - pane.moveItemToPane(editSession1, pane2, 1) + expect(pane.getItems()).toEqual [editor1] + pane.moveItemToPane(editor1, pane2, 1) expect(pane.hasParent()).toBeFalsy() - expect(pane2.getItems()).toEqual [view3, editSession1] - expect(editSession1.destroyed).toBeFalsy() + expect(pane2.getItems()).toEqual [view3, editor1] + expect(editor1.destroyed).toBeFalsy() describe "when the item is a jQuery object", -> it "preserves data by detaching instead of removing", -> @@ -303,37 +303,37 @@ describe "Pane", -> containerCloseHandler = jasmine.createSpy("containerCloseHandler") container.on 'core:close', containerCloseHandler - pane.showItem(editSession1) + pane.showItem(editor1) initialItemCount = pane.getItems().length pane.trigger 'core:close' expect(pane.getItems().length).toBe initialItemCount - 1 - expect(editSession1.destroyed).toBeTruthy() + expect(editor1.destroyed).toBeTruthy() expect(containerCloseHandler).not.toHaveBeenCalled() describe "pane:close", -> it "destroys all items and removes the pane", -> - pane.showItem(editSession1) + pane.showItem(editor1) pane.trigger 'pane:close' expect(pane.hasParent()).toBeFalsy() - expect(editSession2.destroyed).toBeTruthy() - expect(editSession1.destroyed).toBeTruthy() + expect(editor2.destroyed).toBeTruthy() + expect(editor1.destroyed).toBeTruthy() describe "pane:close-other-items", -> it "destroys all items except the current", -> - pane.showItem(editSession1) + pane.showItem(editor1) pane.trigger 'pane:close-other-items' - expect(editSession2.destroyed).toBeTruthy() - expect(pane.getItems()).toEqual [editSession1] + expect(editor2.destroyed).toBeTruthy() + expect(pane.getItems()).toEqual [editor1] describe "core:save", -> describe "when the current item has a uri", -> describe "when the current item has a save method", -> it "saves the current item", -> - spyOn(editSession2, 'save') - pane.showItem(editSession2) + spyOn(editor2, 'save') + pane.showItem(editor2) pane.trigger 'core:save' - expect(editSession2.save).toHaveBeenCalled() + expect(editor2.save).toHaveBeenCalled() describe "when the current item has no save method", -> it "does nothing", -> @@ -347,14 +347,14 @@ describe "Pane", -> describe "when the current item has a saveAs method", -> it "opens a save dialog and saves the current item as the selected path", -> - spyOn(editSession2, 'saveAs') - editSession2.buffer.setPath(undefined) - pane.showItem(editSession2) + spyOn(editor2, 'saveAs') + editor2.buffer.setPath(undefined) + pane.showItem(editor2) pane.trigger 'core:save' expect(atom.showSaveDialogSync).toHaveBeenCalled() - expect(editSession2.saveAs).toHaveBeenCalledWith('/selected/path') + expect(editor2.saveAs).toHaveBeenCalledWith('/selected/path') describe "when the current item has no saveAs method", -> it "does nothing", -> @@ -368,13 +368,13 @@ describe "Pane", -> describe "when the current item has a saveAs method", -> it "opens the save dialog and calls saveAs on the item with the selected path", -> - spyOn(editSession2, 'saveAs') - pane.showItem(editSession2) + spyOn(editor2, 'saveAs') + pane.showItem(editor2) pane.trigger 'core:save-as' - expect(atom.showSaveDialogSync).toHaveBeenCalledWith(path.dirname(editSession2.getPath())) - expect(editSession2.saveAs).toHaveBeenCalledWith('/selected/path') + expect(atom.showSaveDialogSync).toHaveBeenCalledWith(path.dirname(editor2.getPath())) + expect(editor2.saveAs).toHaveBeenCalledWith('/selected/path') describe "when the current item does not have a saveAs method", -> it "does nothing", -> @@ -386,11 +386,11 @@ describe "Pane", -> it "advances forward/backward through the pane's items, looping around at either end", -> expect(pane.activeItem).toBe view1 pane.trigger 'pane:show-previous-item' - expect(pane.activeItem).toBe editSession2 + expect(pane.activeItem).toBe editor2 pane.trigger 'pane:show-previous-item' expect(pane.activeItem).toBe view2 pane.trigger 'pane:show-next-item' - expect(pane.activeItem).toBe editSession2 + expect(pane.activeItem).toBe editor2 pane.trigger 'pane:show-next-item' expect(pane.activeItem).toBe view1 @@ -424,8 +424,8 @@ describe "Pane", -> describe ".remove()", -> it "destroys all the pane's items", -> pane.remove() - expect(editSession1.destroyed).toBeTruthy() - expect(editSession2.destroyed).toBeTruthy() + expect(editor1.destroyed).toBeTruthy() + expect(editor2.destroyed).toBeTruthy() it "triggers a 'pane:removed' event with the pane", -> removedHandler = jasmine.createSpy("removedHandler") @@ -438,7 +438,7 @@ describe "Pane", -> [paneToLeft, paneToRight] = [] beforeEach -> - pane.showItem(editSession1) + pane.showItem(editor1) paneToLeft = pane.splitLeft(pane.copyActiveItem()) paneToRight = pane.splitRight(pane.copyActiveItem()) container.attachToDom() @@ -492,7 +492,7 @@ describe "Pane", -> describe ".getNextPane()", -> it "returns the next pane if one exists, wrapping around from the last pane to the first", -> - pane.showItem(editSession1) + pane.showItem(editor1) expect(pane.getNextPane()).toBeUndefined pane2 = pane.splitRight(pane.copyActiveItem()) expect(pane.getNextPane()).toBe pane2 @@ -538,7 +538,7 @@ describe "Pane", -> [pane1, view3, view4] = [] beforeEach -> pane1 = pane - pane.showItem(editSession1) + pane.showItem(editor1) view3 = new TestView(id: 'view-3', text: 'View 3') view4 = new TestView(id: 'view-4', text: 'View 4') @@ -547,8 +547,8 @@ describe "Pane", -> # creates the new pane with a copy of the active item if none are given pane2 = pane1.splitRight(pane1.copyActiveItem()) expect(container.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]] - expect(pane2.items).toEqual [editSession1] - expect(pane2.activeItem).not.toBe editSession1 # it's a copy + expect(pane2.items).toEqual [editor1] + expect(pane2.activeItem).not.toBe editor1 # it's a copy pane3 = pane2.splitRight(view3, view4) expect(pane3.getItems()).toEqual [view3, view4] @@ -571,8 +571,8 @@ describe "Pane", -> # creates the new pane with a copy of the active item if none are given pane2 = pane.splitLeft(pane1.copyActiveItem()) expect(container.find('.row .pane').toArray()).toEqual [pane2[0], pane[0]] - expect(pane2.items).toEqual [editSession1] - expect(pane2.activeItem).not.toBe editSession1 # it's a copy + expect(pane2.items).toEqual [editor1] + expect(pane2.activeItem).not.toBe editor1 # it's a copy pane3 = pane2.splitLeft(view3, view4) expect(pane3.getItems()).toEqual [view3, view4] @@ -583,8 +583,8 @@ describe "Pane", -> # creates the new pane with a copy of the active item if none are given pane2 = pane.splitDown(pane1.copyActiveItem()) expect(container.find('.column .pane').toArray()).toEqual [pane[0], pane2[0]] - expect(pane2.items).toEqual [editSession1] - expect(pane2.activeItem).not.toBe editSession1 # it's a copy + expect(pane2.items).toEqual [editor1] + expect(pane2.activeItem).not.toBe editor1 # it's a copy pane3 = pane2.splitDown(view3, view4) expect(pane3.getItems()).toEqual [view3, view4] @@ -595,8 +595,8 @@ describe "Pane", -> # creates the new pane with a copy of the active item if none are given pane2 = pane.splitUp(pane1.copyActiveItem()) expect(container.find('.column .pane').toArray()).toEqual [pane2[0], pane[0]] - expect(pane2.items).toEqual [editSession1] - expect(pane2.activeItem).not.toBe editSession1 # it's a copy + expect(pane2.items).toEqual [editor1] + expect(pane2.activeItem).not.toBe editor1 # it's a copy pane3 = pane2.splitUp(view3, view4) expect(pane3.getItems()).toEqual [view3, view4] @@ -673,18 +673,18 @@ describe "Pane", -> describe ".itemForUri(uri)", -> it "returns the item for which a call to .getUri() returns the given uri", -> - expect(pane.itemForUri(editSession1.getUri())).toBe editSession1 - expect(pane.itemForUri(editSession2.getUri())).toBe editSession2 + expect(pane.itemForUri(editor1.getUri())).toBe editor1 + expect(pane.itemForUri(editor2.getUri())).toBe editor2 describe "serialization", -> it "can serialize and deserialize the pane and all its items", -> newPane = deserialize(pane.serialize()) - expect(newPane.getItems()).toEqual [view1, editSession1, view2, editSession2] + expect(newPane.getItems()).toEqual [view1, editor1, view2, editor2] it "restores the active item on deserialization", -> - pane.showItem(editSession2) + pane.showItem(editor2) newPane = deserialize(pane.serialize()) - expect(newPane.activeItem).toEqual editSession2 + expect(newPane.activeItem).toEqual editor2 it "does not show items that cannot be deserialized", -> spyOn(console, 'warn') diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index ec04ade66..a74f4bb5e 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -36,58 +36,58 @@ describe "Project", -> describe "when an edit session is destroyed", -> it "removes edit session and calls destroy on buffer (if buffer is not referenced by other edit sessions)", -> - editSession = project.openSync("a") + editor = project.openSync("a") anotherEditSession = project.openSync("a") - expect(project.editSessions.length).toBe 2 - expect(editSession.buffer).toBe anotherEditSession.buffer + expect(project.editors.length).toBe 2 + expect(editor.buffer).toBe anotherEditSession.buffer - editSession.destroy() - expect(project.editSessions.length).toBe 1 + editor.destroy() + expect(project.editors.length).toBe 1 anotherEditSession.destroy() - expect(project.editSessions.length).toBe 0 + expect(project.editors.length).toBe 0 describe "when an edit session is saved and the project has no path", -> it "sets the project's path to the saved file's parent directory", -> tempFile = temp.openSync().path project.setPath(undefined) expect(project.getPath()).toBeUndefined() - editSession = project.openSync() - editSession.saveAs(tempFile) + editor = project.openSync() + editor.saveAs(tempFile) expect(project.getPath()).toBe path.dirname(tempFile) describe "when an edit session is deserialized", -> - it "emits an 'edit-session-created' event and stores the edit session", -> - handler = jasmine.createSpy('editSessionCreatedHandler') - project.on 'edit-session-created', handler + it "emits an 'editor-created' event and stores the edit session", -> + handler = jasmine.createSpy('editorCreatedHandler') + project.on 'editor-created', handler - editSession1 = project.openSync("a") + editor1 = project.openSync("a") expect(handler.callCount).toBe 1 expect(project.getEditSessions().length).toBe 1 - expect(project.getEditSessions()[0]).toBe editSession1 + expect(project.getEditSessions()[0]).toBe editor1 - editSession2 = deserialize(editSession1.serialize()) + editor2 = deserialize(editor1.serialize()) expect(handler.callCount).toBe 2 expect(project.getEditSessions().length).toBe 2 - expect(project.getEditSessions()[0]).toBe editSession1 - expect(project.getEditSessions()[1]).toBe editSession2 + expect(project.getEditSessions()[0]).toBe editor1 + expect(project.getEditSessions()[1]).toBe editor2 describe "when an edit session is copied", -> - it "emits an 'edit-session-created' event and stores the edit session", -> - handler = jasmine.createSpy('editSessionCreatedHandler') - project.on 'edit-session-created', handler + it "emits an 'editor-created' event and stores the edit session", -> + handler = jasmine.createSpy('editorCreatedHandler') + project.on 'editor-created', handler - editSession1 = project.openSync("a") + editor1 = project.openSync("a") expect(handler.callCount).toBe 1 expect(project.getEditSessions().length).toBe 1 - expect(project.getEditSessions()[0]).toBe editSession1 + expect(project.getEditSessions()[0]).toBe editor1 - editSession2 = editSession1.copy() + editor2 = editor1.copy() expect(handler.callCount).toBe 2 expect(project.getEditSessions().length).toBe 2 - expect(project.getEditSessions()[0]).toBe editSession1 - expect(project.getEditSessions()[1]).toBe editSession2 + expect(project.getEditSessions()[0]).toBe editor1 + expect(project.getEditSessions()[1]).toBe editor2 describe ".openSync(path)", -> [fooOpener, barOpener, absolutePath, newBufferHandler, newEditSessionHandler] = [] @@ -96,7 +96,7 @@ describe "Project", -> newBufferHandler = jasmine.createSpy('newBufferHandler') project.on 'buffer-created', newBufferHandler newEditSessionHandler = jasmine.createSpy('newEditSessionHandler') - project.on 'edit-session-created', newEditSessionHandler + project.on 'editor-created', newEditSessionHandler fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/) barOpener = (pathToOpen) -> { bar: pathToOpen } if pathToOpen?.match(/^bar:\/\//) @@ -109,34 +109,34 @@ describe "Project", -> describe "when passed a path that doesn't match a custom opener", -> describe "when given an absolute path that hasn't been opened previously", -> - it "returns a new edit session for the given path and emits 'buffer-created' and 'edit-session-created' events", -> - editSession = project.openSync(absolutePath) - expect(editSession.buffer.getPath()).toBe absolutePath - expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer - expect(newEditSessionHandler).toHaveBeenCalledWith editSession + it "returns a new edit session for the given path and emits 'buffer-created' and 'editor-created' events", -> + editor = project.openSync(absolutePath) + expect(editor.buffer.getPath()).toBe absolutePath + expect(newBufferHandler).toHaveBeenCalledWith editor.buffer + expect(newEditSessionHandler).toHaveBeenCalledWith editor describe "when given a relative path that hasn't been opened previously", -> - it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'edit-session-created' events", -> - editSession = project.openSync('a') - expect(editSession.buffer.getPath()).toBe absolutePath - expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer - expect(newEditSessionHandler).toHaveBeenCalledWith editSession + it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'editor-created' events", -> + editor = project.openSync('a') + expect(editor.buffer.getPath()).toBe absolutePath + expect(newBufferHandler).toHaveBeenCalledWith editor.buffer + expect(newEditSessionHandler).toHaveBeenCalledWith editor describe "when passed the path to a buffer that has already been opened", -> - it "returns a new edit session containing previously opened buffer and emits a 'edit-session-created' event", -> - editSession = project.openSync(absolutePath) + it "returns a new edit session containing previously opened buffer and emits a 'editor-created' event", -> + editor = project.openSync(absolutePath) newBufferHandler.reset() - expect(project.openSync(absolutePath).buffer).toBe editSession.buffer - expect(project.openSync('a').buffer).toBe editSession.buffer + expect(project.openSync(absolutePath).buffer).toBe editor.buffer + expect(project.openSync('a').buffer).toBe editor.buffer expect(newBufferHandler).not.toHaveBeenCalled() - expect(newEditSessionHandler).toHaveBeenCalledWith editSession + expect(newEditSessionHandler).toHaveBeenCalledWith editor describe "when not passed a path", -> - it "returns a new edit session and emits 'buffer-created' and 'edit-session-created' events", -> - editSession = project.openSync() - expect(editSession.buffer.getPath()).toBeUndefined() - expect(newBufferHandler).toHaveBeenCalledWith(editSession.buffer) - expect(newEditSessionHandler).toHaveBeenCalledWith editSession + it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", -> + editor = project.openSync() + expect(editor.buffer.getPath()).toBeUndefined() + expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer) + expect(newEditSessionHandler).toHaveBeenCalledWith editor describe "when passed a path that matches a custom opener", -> it "returns the resource returned by the custom opener", -> @@ -152,7 +152,7 @@ describe "Project", -> newBufferHandler = jasmine.createSpy('newBufferHandler') project.on 'buffer-created', newBufferHandler newEditSessionHandler = jasmine.createSpy('newEditSessionHandler') - project.on 'edit-session-created', newEditSessionHandler + project.on 'editor-created', newEditSessionHandler fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/) barOpener = (pathToOpen) -> { bar: pathToOpen } if pathToOpen?.match(/^bar:\/\//) @@ -165,50 +165,50 @@ describe "Project", -> describe "when passed a path that doesn't match a custom opener", -> describe "when given an absolute path that isn't currently open", -> - it "returns a new edit session for the given path and emits 'buffer-created' and 'edit-session-created' events", -> - editSession = null + it "returns a new edit session for the given path and emits 'buffer-created' and 'editor-created' events", -> + editor = null waitsForPromise -> - project.open(absolutePath).then (o) -> editSession = o + project.open(absolutePath).then (o) -> editor = o runs -> - expect(editSession.buffer.getPath()).toBe absolutePath - expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer - expect(newEditSessionHandler).toHaveBeenCalledWith editSession + expect(editor.buffer.getPath()).toBe absolutePath + expect(newBufferHandler).toHaveBeenCalledWith editor.buffer + expect(newEditSessionHandler).toHaveBeenCalledWith editor describe "when given a relative path that isn't currently opened", -> - it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'edit-session-created' events", -> - editSession = null + it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'editor-created' events", -> + editor = null waitsForPromise -> - project.open(absolutePath).then (o) -> editSession = o + project.open(absolutePath).then (o) -> editor = o runs -> - expect(editSession.buffer.getPath()).toBe absolutePath - expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer - expect(newEditSessionHandler).toHaveBeenCalledWith editSession + expect(editor.buffer.getPath()).toBe absolutePath + expect(newBufferHandler).toHaveBeenCalledWith editor.buffer + expect(newEditSessionHandler).toHaveBeenCalledWith editor describe "when passed the path to a buffer that is currently opened", -> - it "returns a new edit session containing currently opened buffer and emits a 'edit-session-created' event", -> - editSession = null + it "returns a new edit session containing currently opened buffer and emits a 'editor-created' event", -> + editor = null waitsForPromise -> - project.open(absolutePath).then (o) -> editSession = o + project.open(absolutePath).then (o) -> editor = o runs -> newBufferHandler.reset() - expect(project.openSync(absolutePath).buffer).toBe editSession.buffer - expect(project.openSync('a').buffer).toBe editSession.buffer + expect(project.openSync(absolutePath).buffer).toBe editor.buffer + expect(project.openSync('a').buffer).toBe editor.buffer expect(newBufferHandler).not.toHaveBeenCalled() - expect(newEditSessionHandler).toHaveBeenCalledWith editSession + expect(newEditSessionHandler).toHaveBeenCalledWith editor describe "when not passed a path", -> - it "returns a new edit session and emits 'buffer-created' and 'edit-session-created' events", -> - editSession = null + it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", -> + editor = null waitsForPromise -> - project.open().then (o) -> editSession = o + project.open().then (o) -> editor = o runs -> - expect(editSession.buffer.getPath()).toBeUndefined() - expect(newBufferHandler).toHaveBeenCalledWith(editSession.buffer) - expect(newEditSessionHandler).toHaveBeenCalledWith editSession + expect(editor.buffer.getPath()).toBeUndefined() + expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer) + expect(newEditSessionHandler).toHaveBeenCalledWith editor describe "when passed a path that matches a custom opener", -> it "returns the resource returned by the custom opener", -> @@ -336,8 +336,8 @@ describe "Project", -> describe "when a buffer is already open", -> it "replaces properly and saves when not modified", -> - editSession = project.openSync('sample.js') - expect(editSession.isModified()).toBeFalsy() + editor = project.openSync('sample.js') + expect(editor.isModified()).toBeFalsy() results = [] waitsForPromise -> @@ -349,12 +349,12 @@ describe "Project", -> expect(results[0].filePath).toBe filePath expect(results[0].replacements).toBe 6 - expect(editSession.isModified()).toBeFalsy() + expect(editor.isModified()).toBeFalsy() it "does NOT save when modified", -> - editSession = project.openSync('sample.js') - editSession.buffer.change([[0,0],[0,0]], 'omg') - expect(editSession.isModified()).toBeTruthy() + editor = project.openSync('sample.js') + editor.buffer.change([[0,0],[0,0]], 'omg') + expect(editor.isModified()).toBeTruthy() results = [] waitsForPromise -> @@ -366,7 +366,7 @@ describe "Project", -> expect(results[0].filePath).toBe filePath expect(results[0].replacements).toBe 6 - expect(editSession.isModified()).toBeTruthy() + expect(editor.isModified()).toBeTruthy() describe ".scan(options, callback)", -> describe "when called with a regex", -> @@ -519,8 +519,8 @@ describe "Project", -> expect(resultHandler).not.toHaveBeenCalled() it "scans buffer contents if the buffer is modified", -> - editSession = project.openSync("a") - editSession.setText("Elephant") + editor = project.openSync("a") + editor.setText("Elephant") results = [] waitsForPromise -> project.scan /a|Elephant/, (result) -> results.push result diff --git a/spec/root-view-spec.coffee b/spec/root-view-spec.coffee index b9086026b..0782c25d7 100644 --- a/spec/root-view-spec.coffee +++ b/spec/root-view-spec.coffee @@ -163,9 +163,9 @@ describe "RootView", -> describe "when the title of the active pane item changes", -> it "updates the window title based on the item's new title", -> - editSession = rootView.getActivePaneItem() - editSession.buffer.setPath(path.join(temp.dir, 'hi')) - expect(rootView.title).toBe "#{editSession.getTitle()} - #{project.getPath()}" + editor = rootView.getActivePaneItem() + editor.buffer.setPath(path.join(temp.dir, 'hi')) + expect(rootView.title).toBe "#{editor.getTitle()} - #{project.getPath()}" describe "when the active pane's item changes", -> it "updates the title to the new item's title plus the project path", -> @@ -220,34 +220,34 @@ describe "RootView", -> describe "when called with no path", -> it "creates a empty edit session as an item on a new pane, and focuses the pane", -> - editSession = rootView.openSync() - expect(rootView.getActivePane().activeItem).toBe editSession - expect(editSession.getPath()).toBeUndefined() + editor = rootView.openSync() + expect(rootView.getActivePane().activeItem).toBe editor + expect(editor.getPath()).toBeUndefined() expect(rootView.getActivePane().focus).toHaveBeenCalled() it "can create multiple empty edit sessions as an item on a new pane", -> - editSession = rootView.openSync() - editSession2 = rootView.openSync() + editor = rootView.openSync() + editor2 = rootView.openSync() expect(rootView.getActivePane().getItems().length).toBe 2 - expect(editSession).not.toBe editSession2 + expect(editor).not.toBe editor2 describe "when called with a path", -> it "creates an edit session for the given path as an item on a new pane, and focuses the pane", -> - editSession = rootView.openSync('b') - expect(rootView.getActivePane().activeItem).toBe editSession - expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/b') + editor = rootView.openSync('b') + expect(rootView.getActivePane().activeItem).toBe editor + expect(editor.getPath()).toBe require.resolve('./fixtures/dir/b') expect(rootView.getActivePane().focus).toHaveBeenCalled() describe "when the changeFocus option is false", -> it "does not focus the new pane", -> - editSession = rootView.openSync('b', changeFocus: false) + editor = rootView.openSync('b', changeFocus: false) expect(rootView.getActivePane().focus).not.toHaveBeenCalled() describe "when the split option is 'right'", -> it "creates a new pane and opens the file in said pane", -> - editSession = rootView.openSync('b', split: 'right') - expect(rootView.getActivePane().activeItem).toBe editSession - expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/b') + editor = rootView.openSync('b', split: 'right') + expect(rootView.getActivePane().activeItem).toBe editor + expect(editor.getPath()).toBe require.resolve('./fixtures/dir/b') describe "when there is an active pane", -> [activePane, initialItemCount] = [] @@ -258,10 +258,10 @@ describe "RootView", -> describe "when called with no path", -> it "opens an edit session with an empty buffer as an item in the active pane and focuses it", -> - editSession = rootView.openSync() + editor = rootView.openSync() expect(activePane.getItems().length).toBe initialItemCount + 1 - expect(activePane.activeItem).toBe editSession - expect(editSession.getPath()).toBeUndefined() + expect(activePane.activeItem).toBe editor + expect(editor.getPath()).toBeUndefined() expect(activePane.focus).toHaveBeenCalled() describe "when called with a path", -> @@ -269,43 +269,43 @@ describe "RootView", -> it "shows the existing edit session in the pane", -> previousEditSession = activePane.activeItem - editSession = rootView.openSync('b') - expect(activePane.activeItem).toBe editSession - expect(editSession).not.toBe previousEditSession + editor = rootView.openSync('b') + expect(activePane.activeItem).toBe editor + expect(editor).not.toBe previousEditSession - editSession = rootView.openSync(previousEditSession.getPath()) - expect(editSession).toBe previousEditSession - expect(activePane.activeItem).toBe editSession + editor = rootView.openSync(previousEditSession.getPath()) + expect(editor).toBe previousEditSession + expect(activePane.activeItem).toBe editor expect(activePane.focus).toHaveBeenCalled() describe "when the active pane does not have an edit session item for the path being opened", -> it "creates a new edit session for the given path in the active editor", -> - editSession = rootView.openSync('b') + editor = rootView.openSync('b') expect(activePane.items.length).toBe 2 - expect(activePane.activeItem).toBe editSession + expect(activePane.activeItem).toBe editor expect(activePane.focus).toHaveBeenCalled() describe "when the changeFocus option is false", -> it "does not focus the active pane", -> - editSession = rootView.openSync('b', changeFocus: false) + editor = rootView.openSync('b', changeFocus: false) expect(activePane.focus).not.toHaveBeenCalled() describe "when the split option is 'right'", -> it "creates a new pane and opens the file in said pane", -> pane1 = rootView.getActivePane() - editSession = rootView.openSync('b', split: 'right') + editor = rootView.openSync('b', split: 'right') pane2 = rootView.getActivePane() expect(pane2[0]).not.toBe pane1[0] - expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/b') + expect(editor.getPath()).toBe require.resolve('./fixtures/dir/b') expect(rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]] - editSession = rootView.openSync('file1', split: 'right') + editor = rootView.openSync('file1', split: 'right') pane3 = rootView.getActivePane() expect(pane3[0]).toBe pane2[0] - expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/file1') + expect(editor.getPath()).toBe require.resolve('./fixtures/dir/file1') expect(rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]] @@ -372,41 +372,41 @@ describe "RootView", -> describe "when called with no path", -> it "creates a empty edit session as an item on a new pane, and focuses the pane", -> - editSession = null + editor = null waitsForPromise -> - rootView.open().then (o) -> editSession = o + rootView.open().then (o) -> editor = o runs -> - expect(rootView.getActivePane().activeItem).toBe editSession - expect(editSession.getPath()).toBeUndefined() + expect(rootView.getActivePane().activeItem).toBe editor + expect(editor.getPath()).toBeUndefined() expect(rootView.getActivePane().focus).toHaveBeenCalled() it "can create multiple empty edit sessions as items on a pane", -> - editSession1 = null - editSession2 = null + editor1 = null + editor2 = null waitsForPromise -> rootView.open() .then (o) -> - editSession1 = o + editor1 = o rootView.open() .then (o) -> - editSession2 = o + editor2 = o runs -> expect(rootView.getActivePane().getItems().length).toBe 2 - expect(editSession1).not.toBe editSession2 + expect(editor1).not.toBe editor2 describe "when called with a path", -> it "creates an edit session for the given path as an item on a new pane, and focuses the pane", -> - editSession = null + editor = null waitsForPromise -> - rootView.open('b').then (o) -> editSession = o + rootView.open('b').then (o) -> editor = o runs -> - expect(rootView.getActivePane().activeItem).toBe editSession - expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/b') + expect(rootView.getActivePane().activeItem).toBe editor + expect(editor.getPath()).toBe require.resolve('./fixtures/dir/b') expect(rootView.getActivePane().focus).toHaveBeenCalled() describe "when there is an active pane", -> @@ -417,15 +417,15 @@ describe "RootView", -> describe "when called with no path", -> it "opens an edit session with an empty buffer as an item in the active pane and focuses it", -> - editSession = null + editor = null waitsForPromise -> - rootView.open().then (o) -> editSession = o + rootView.open().then (o) -> editor = o runs -> expect(activePane.getItems().length).toBe 2 - expect(activePane.activeItem).toBe editSession - expect(editSession.getPath()).toBeUndefined() + expect(activePane.activeItem).toBe editor + expect(editor.getPath()).toBeUndefined() expect(activePane.focus).toHaveBeenCalled() describe "when called with a path", -> @@ -433,31 +433,31 @@ describe "RootView", -> it "shows the existing edit session in the pane", -> previousEditSession = activePane.activeItem - editSession = null + editor = null waitsForPromise -> - rootView.open('b').then (o) -> editSession = o + rootView.open('b').then (o) -> editor = o runs -> - expect(activePane.activeItem).toBe editSession - expect(editSession).not.toBe previousEditSession + expect(activePane.activeItem).toBe editor + expect(editor).not.toBe previousEditSession waitsForPromise -> - rootView.open(previousEditSession.getPath()).then (o) -> editSession = o + rootView.open(previousEditSession.getPath()).then (o) -> editor = o runs -> - expect(editSession).toBe previousEditSession - expect(activePane.activeItem).toBe editSession + expect(editor).toBe previousEditSession + expect(activePane.activeItem).toBe editor expect(activePane.focus).toHaveBeenCalled() describe "when the active pane does not have an existing item for the given path", -> it "creates a new edit session for the given path in the active pane", -> - editSession = null + editor = null waitsForPromise -> - rootView.open('b').then (o) -> editSession = o + rootView.open('b').then (o) -> editor = o runs -> - expect(activePane.activeItem).toBe editSession + expect(activePane.activeItem).toBe editor expect(activePane.getItems().length).toBe 2 expect(activePane.focus).toHaveBeenCalled() diff --git a/spec/selection-spec.coffee b/spec/selection-spec.coffee index e73f19345..e5b5bb913 100644 --- a/spec/selection-spec.coffee +++ b/spec/selection-spec.coffee @@ -1,12 +1,12 @@ Editor = require '../src/editor' describe "Selection", -> - [buffer, editSession, selection] = [] + [buffer, editor, selection] = [] beforeEach -> buffer = project.bufferForPathSync('sample.js') - editSession = new Editor(buffer: buffer, tabLength: 2) - selection = editSession.getSelection() + editor = new Editor(buffer: buffer, tabLength: 2) + selection = editor.getSelection() afterEach -> buffer.destroy() diff --git a/spec/text-mate-grammar-spec.coffee b/spec/text-mate-grammar-spec.coffee index 00198afff..6d539f29d 100644 --- a/spec/text-mate-grammar-spec.coffee +++ b/spec/text-mate-grammar-spec.coffee @@ -447,25 +447,25 @@ describe "TextMateGrammar", -> describe "when the grammar is added", -> it "retokenizes existing buffers that contain tokens that match the injection selector", -> - editSession = project.openSync('sample.js') - editSession.setText("// http://github.com") + editor = project.openSync('sample.js') + editor.setText("// http://github.com") - {tokens} = editSession.lineForScreenRow(0) + {tokens} = editor.lineForScreenRow(0) expect(tokens[1].value).toBe " http://github.com" expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"] atom.activatePackage('language-hyperlink', sync: true) - {tokens} = editSession.lineForScreenRow(0) + {tokens} = editor.lineForScreenRow(0) expect(tokens[2].value).toBe "http://github.com" expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"] describe "when the grammar is updated", -> it "retokenizes existing buffers that contain tokens that match the injection selector", -> - editSession = project.openSync('sample.js') - editSession.setText("// SELECT * FROM OCTOCATS") + editor = project.openSync('sample.js') + editor.setText("// SELECT * FROM OCTOCATS") - {tokens} = editSession.lineForScreenRow(0) + {tokens} = editor.lineForScreenRow(0) expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS" expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"] @@ -477,13 +477,13 @@ describe "TextMateGrammar", -> patterns: [ { include: "source.sql" } ] )) - {tokens} = editSession.lineForScreenRow(0) + {tokens} = editor.lineForScreenRow(0) expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS" expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"] atom.activatePackage('language-sql', sync: true) - {tokens} = editSession.lineForScreenRow(0) + {tokens} = editor.lineForScreenRow(0) expect(tokens[2].value).toBe "SELECT" expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"] diff --git a/spec/window-spec.coffee b/spec/window-spec.coffee index f5b278729..b053ec8ed 100644 --- a/spec/window-spec.coffee +++ b/spec/window-spec.coffee @@ -61,23 +61,23 @@ describe "Window", -> it "prompts user to save and and calls rootView.confirmClose", -> spyOn(rootView, 'confirmClose').andCallThrough() spyOn(atom, "confirmSync").andReturn(2) - editSession = rootView.openSync("sample.js") - editSession.insertText("I look different, I feel different.") + editor = rootView.openSync("sample.js") + editor.insertText("I look different, I feel different.") $(window).trigger(beforeUnloadEvent) expect(rootView.confirmClose).toHaveBeenCalled() expect(atom.confirmSync).toHaveBeenCalled() it "prompts user to save and handler returns true if don't save", -> spyOn(atom, "confirmSync").andReturn(2) - editSession = rootView.openSync("sample.js") - editSession.insertText("I look different, I feel different.") + editor = rootView.openSync("sample.js") + editor.insertText("I look different, I feel different.") $(window).trigger(beforeUnloadEvent) expect(atom.confirmSync).toHaveBeenCalled() it "prompts user to save and handler returns false if dialog is canceled", -> spyOn(atom, "confirmSync").andReturn(1) - editSession = rootView.openSync("sample.js") - editSession.insertText("I look different, I feel different.") + editor = rootView.openSync("sample.js") + editor.insertText("I look different, I feel different.") $(window).trigger(beforeUnloadEvent) expect(atom.confirmSync).toHaveBeenCalled() diff --git a/src/cursor.coffee b/src/cursor.coffee index 83c42ffb4..a78d6f5e1 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -18,7 +18,7 @@ class Cursor needsAutoscroll: null # Private: Instantiated by an {Editor} - constructor: ({@editSession, @marker}) -> + constructor: ({@editor, @marker}) -> @updateVisibility() @marker.on 'changed', (e) => @updateVisibility() @@ -37,10 +37,10 @@ class Cursor textChanged: textChanged @emit 'moved', movedEvent - @editSession.emit 'cursor-moved', movedEvent + @editor.emit 'cursor-moved', movedEvent @marker.on 'destroyed', => @destroyed = true - @editSession.removeCursor(this) + @editor.removeCursor(this) @emit 'destroyed' @needsAutoscroll = true @@ -124,7 +124,7 @@ class Cursor # # Returns a Boolean. isLastCursor: -> - this == @editSession.getCursor() + this == @editor.getCursor() # Public: Identifies if the cursor is surrounded by whitespace. # @@ -135,7 +135,7 @@ class Cursor isSurroundedByWhitespace: -> {row, column} = @getBufferPosition() range = [[row, Math.min(0, column - 1)], [row, Math.max(0, column + 1)]] - /^\s+$/.test @editSession.getTextInBufferRange(range) + /^\s+$/.test @editor.getTextInBufferRange(range) # Public: Returns whether the cursor is currently between a word and non-word # character. The non-word characters are defined by the @@ -150,7 +150,7 @@ class Cursor {row, column} = @getBufferPosition() range = [[row, column - 1], [row, column + 1]] - [before, after] = @editSession.getTextInBufferRange(range) + [before, after] = @editor.getTextInBufferRange(range) return false if /\s/.test(before) or /\s/.test(after) nonWordCharacters = atom.config.get('editor.nonWordCharacters').split('') @@ -160,7 +160,7 @@ class Cursor isInsideWord: -> {row, column} = @getBufferPosition() range = [[row, column], [row, Infinity]] - @editSession.getTextInBufferRange(range).search(@wordRegExp()) == 0 + @editor.getTextInBufferRange(range).search(@wordRegExp()) == 0 # Public: Prevents this cursor from causing scrolling. clearAutoscroll: -> @@ -189,7 +189,7 @@ class Cursor # Public: Returns the cursor's current buffer row of text excluding its line # ending. getCurrentBufferLine: -> - @editSession.lineForBufferRow(@getBufferRow()) + @editor.lineForBufferRow(@getBufferRow()) # Public: Moves the cursor up one screen row. moveUp: (rowCount = 1, {moveToEndOfSelection}={}) -> @@ -248,7 +248,7 @@ class Cursor # Public: Moves the cursor to the bottom of the buffer. moveToBottom: -> - @setBufferPosition(@editSession.getEofBufferPosition()) + @setBufferPosition(@editor.getEofBufferPosition()) # Public: Moves the cursor to the beginning of the screen line. moveToBeginningOfLine: -> @@ -258,7 +258,7 @@ class Cursor # line. moveToFirstCharacterOfLine: -> {row, column} = @getScreenPosition() - screenline = @editSession.lineForScreenRow(row) + screenline = @editor.lineForScreenRow(row) goalColumn = screenline.text.search(/\S/) return if goalColumn == -1 @@ -272,7 +272,7 @@ class Cursor position = @getBufferPosition() scanRange = @getCurrentLineBufferRange() endOfLeadingWhitespace = null - @editSession.scanInBufferRange /^[ \t]*/, scanRange, ({range}) => + @editor.scanInBufferRange /^[ \t]*/, scanRange, ({range}) => endOfLeadingWhitespace = range.end @setBufferPosition(endOfLeadingWhitespace) if endOfLeadingWhitespace.isGreaterThan(position) @@ -318,11 +318,11 @@ class Cursor getBeginningOfCurrentWordBufferPosition: (options = {}) -> allowPrevious = options.allowPrevious ? true currentBufferPosition = @getBufferPosition() - previousNonBlankRow = @editSession.buffer.previousNonBlankRow(currentBufferPosition.row) + previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row) scanRange = [[previousNonBlankRow, 0], currentBufferPosition] beginningOfWordPosition = null - @editSession.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) => + @editor.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) => if range.end.isGreaterThanOrEqual(currentBufferPosition) or allowPrevious beginningOfWordPosition = range.start if not beginningOfWordPosition?.isEqual(currentBufferPosition) @@ -334,11 +334,11 @@ class Cursor # the current word, or the previous word. getPreviousWordBoundaryBufferPosition: (options = {}) -> currentBufferPosition = @getBufferPosition() - previousNonBlankRow = @editSession.buffer.previousNonBlankRow(currentBufferPosition.row) + previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row) scanRange = [[previousNonBlankRow, 0], currentBufferPosition] beginningOfWordPosition = null - @editSession.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) => + @editor.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) => if range.start.row < currentBufferPosition.row and currentBufferPosition.column > 0 # force it to stop at the beginning of each line beginningOfWordPosition = new Point(currentBufferPosition.row, 0) @@ -356,10 +356,10 @@ class Cursor # the current word, or the previous word. getMoveNextWordBoundaryBufferPosition: (options = {}) -> currentBufferPosition = @getBufferPosition() - scanRange = [currentBufferPosition, @editSession.getEofBufferPosition()] + scanRange = [currentBufferPosition, @editor.getEofBufferPosition()] endOfWordPosition = null - @editSession.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) => + @editor.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) => if range.start.row > currentBufferPosition.row # force it to stop at the beginning of each line endOfWordPosition = new Point(range.start.row, 0) @@ -386,10 +386,10 @@ class Cursor getEndOfCurrentWordBufferPosition: (options = {}) -> allowNext = options.allowNext ? true currentBufferPosition = @getBufferPosition() - scanRange = [currentBufferPosition, @editSession.getEofBufferPosition()] + scanRange = [currentBufferPosition, @editor.getEofBufferPosition()] endOfWordPosition = null - @editSession.scanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) => + @editor.scanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) => if range.start.isLessThanOrEqual(currentBufferPosition) or allowNext endOfWordPosition = range.end if not endOfWordPosition?.isEqual(currentBufferPosition) @@ -407,10 +407,10 @@ class Cursor getBeginningOfNextWordBufferPosition: (options = {}) -> currentBufferPosition = @getBufferPosition() start = if @isInsideWord() then @getEndOfCurrentWordBufferPosition() else currentBufferPosition - scanRange = [start, @editSession.getEofBufferPosition()] + scanRange = [start, @editor.getEofBufferPosition()] beginningOfNextWordPosition = null - @editSession.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) => + @editor.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) => beginningOfNextWordPosition = range.start stop() @@ -432,7 +432,7 @@ class Cursor # + includeNewline: # A boolean which controls whether the Range should include the newline. getCurrentLineBufferRange: (options) -> - @editSession.bufferRangeForBufferRow(@getBufferRow(), options) + @editor.bufferRangeForBufferRow(@getBufferRow(), options) # Public: Retrieves the range for the current paragraph. # @@ -440,11 +440,11 @@ class Cursor # # Returns a {Range}. getCurrentParagraphBufferRange: -> - @editSession.languageMode.rowRangeForParagraphAtBufferRow(@getBufferRow()) + @editor.languageMode.rowRangeForParagraphAtBufferRow(@getBufferRow()) # Public: Returns the characters preceeding the cursor in the current word. getCurrentWordPrefix: -> - @editSession.getTextInBufferRange([@getBeginningOfCurrentWordBufferPosition(), @getBufferPosition()]) + @editor.getTextInBufferRange([@getBeginningOfCurrentWordBufferPosition(), @getBufferPosition()]) # Public: Returns whether the cursor is at the start of a line. isAtBeginningOfLine: -> @@ -452,8 +452,8 @@ class Cursor # Public: Returns the indentation level of the current line. getIndentLevel: -> - if @editSession.getSoftTabs() - @getBufferColumn() / @editSession.getTabLength() + if @editor.getSoftTabs() + @getBufferColumn() / @editor.getTabLength() else @getBufferColumn() @@ -465,13 +465,13 @@ class Cursor # # Returns an {Array} of {String}s. getScopes: -> - @editSession.scopesForBufferPosition(@getBufferPosition()) + @editor.scopesForBufferPosition(@getBufferPosition()) # Public: Returns true if this cursor has no non-whitespace characters before # its current position. hasPrecedingCharactersOnLine: -> bufferPosition = @getBufferPosition() - line = @editSession.lineForBufferRow(bufferPosition.row) + line = @editor.lineForBufferRow(bufferPosition.row) firstCharacterColumn = line.search(/\S/) if firstCharacterColumn is -1 diff --git a/src/editor-view.coffee b/src/editor-view.coffee index bd466424f..436a89309 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -77,16 +77,16 @@ class EditorView extends View # The constructor for setting up an `EditorView` instance. # - # editSessionOrOptions - Either an {Editor}, or an object with one property, `mini`. + # editorOrOptions - Either an {Editor}, or an object with one property, `mini`. # If `mini` is `true`, a "miniature" `Editor` is constructed. # Typically, this is ideal for scenarios where you need an Atom editor, # but without all the chrome, like scrollbars, gutter, _e.t.c._. # - initialize: (editSessionOrOptions) -> - if editSessionOrOptions instanceof Editor - editSession = editSessionOrOptions + initialize: (editorOrOptions) -> + if editorOrOptions instanceof Editor + editor = editorOrOptions else - {editSession, @mini} = editSessionOrOptions ? {} + {editor, @mini} = editorOrOptions ? {} @id = EditorView.nextEditorId++ @lineCache = [] @@ -100,8 +100,8 @@ class EditorView extends View @newCursors = [] @newSelections = [] - if editSession? - @edit(editSession) + if editor? + @edit(editor) else if @mini @edit(new Editor buffer: TextBuffer.createAsRoot() @@ -788,14 +788,14 @@ class EditorView extends View @trigger 'editor:attached', [this] - edit: (editSession) -> - return if editSession is @activeEditSession + edit: (editor) -> + return if editor is @activeEditSession if @activeEditSession @saveScrollPositionForActiveEditSession() @activeEditSession.off(".editor") - @activeEditSession = editSession + @activeEditSession = editor return unless @activeEditSession? @@ -832,19 +832,19 @@ class EditorView extends View @resetDisplay() if @attached and @activeEditSession.buffer.isInConflict() - _.defer => @showBufferConflictAlert(@activeEditSession) # Display after editSession has a chance to display + _.defer => @showBufferConflictAlert(@activeEditSession) # Display after editor has a chance to display getModel: -> @activeEditSession - setModel: (editSession) -> - @edit(editSession) + setModel: (editor) -> + @edit(editor) - showBufferConflictAlert: (editSession) -> + showBufferConflictAlert: (editor) -> atom.confirm( - editSession.getPath(), + editor.getPath(), "Has changed on disk. Do you want to reload it?", - "Reload", (=> editSession.buffer.reload()), + "Reload", (=> editor.buffer.reload()), "Cancel" ) @@ -1183,11 +1183,11 @@ class EditorView extends View @clearRenderedLines() @removeAllCursorAndSelectionViews() - editSessionScrollTop = @activeEditSession.getScrollTop() ? 0 - editSessionScrollLeft = @activeEditSession.getScrollLeft() ? 0 + editorScrollTop = @activeEditSession.getScrollTop() ? 0 + editorScrollLeft = @activeEditSession.getScrollLeft() ? 0 @updateLayerDimensions() - @scrollTop(editSessionScrollTop) - @scrollLeft(editSessionScrollLeft) + @scrollTop(editorScrollTop) + @scrollLeft(editorScrollLeft) @setSoftWrap(@activeEditSession.getSoftWrap()) @newCursors = @activeEditSession.getAllCursors() @newSelections = @activeEditSession.getAllSelections() diff --git a/src/editor.coffee b/src/editor.coffee index 5ec620cf9..f000ea225 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -27,8 +27,8 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # # ## Example # ```coffeescript -# global.rootView.eachEditSession (editSession) -> -# editSession.insertText('Hello World') +# global.rootView.eachEditSession (editor) -> +# editor.insertText('Hello World') # ``` # # ## Collaboration builtin @@ -160,8 +160,8 @@ class Editor newEditSession = new Editor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true}) newEditSession.setScrollTop(@getScrollTop()) newEditSession.setScrollLeft(@getScrollLeft()) - for marker in @findMarkers(editSessionId: @id) - marker.copy(editSessionId: newEditSession.id, preserveFolds: true) + for marker in @findMarkers(editorId: @id) + marker.copy(editorId: newEditSession.id, preserveFolds: true) project.addEditSession(newEditSession) newEditSession @@ -868,7 +868,7 @@ class Editor # Public: Adds and returns a cursor at the given {DisplayBufferMarker} # position. addCursor: (marker) -> - cursor = new Cursor(editSession: this, marker: marker) + cursor = new Cursor(editor: this, marker: marker) if marker.isLocal() @cursors.push(cursor) else @@ -892,7 +892,7 @@ class Editor unless marker.getAttributes().preserveFolds @destroyFoldsIntersectingBufferRange(marker.getBufferRange()) cursor = @addCursor(marker) - selection = new Selection(_.extend({editSession: this, marker, cursor}, options)) + selection = new Selection(_.extend({editor: this, marker, cursor}, options)) if marker.isLocal() @selections.push(selection) @@ -1435,7 +1435,7 @@ class Editor # Private: getSelectionMarkerAttributes: -> - type: 'selection', editSessionId: @id, invalidate: 'never' + type: 'selection', editorId: @id, invalidate: 'never' # Private: getDebugSnapshot: -> diff --git a/src/language-mode.coffee b/src/language-mode.coffee index 32e7c6719..28ee1dc70 100644 --- a/src/language-mode.coffee +++ b/src/language-mode.coffee @@ -12,7 +12,7 @@ class LanguageMode buffer: null grammar: null - editSession: null + editor: null currentGrammarScore: null ### Internal ### @@ -24,9 +24,9 @@ class LanguageMode # Sets up a `LanguageMode` for the given {Editor}. # - # editSession - The {Editor} to associate with - constructor: (@editSession) -> - @buffer = @editSession.buffer + # editor - The {Editor} to associate with + constructor: (@editor) -> + @buffer = @editor.buffer # Wraps the lines between two rows in comments. # @@ -37,7 +37,7 @@ class LanguageMode # # Returns an {Array} of the commented {Ranges}. toggleLineCommentsForBufferRows: (start, end) -> - scopes = @editSession.scopesForBufferPosition([start, 0]) + scopes = @editor.scopesForBufferPosition([start, 0]) properties = atom.syntax.propertiesForScope(scopes, "editor.commentStart")[0] return unless properties @@ -46,7 +46,7 @@ class LanguageMode return unless commentStartString - buffer = @editSession.buffer + buffer = @editor.buffer commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '($1)?') commentStartRegex = new OnigRegExp("^(\\s*)(#{commentStartRegexString})") shouldUncomment = commentStartRegex.test(buffer.lineForRow(start)) @@ -83,8 +83,8 @@ class LanguageMode buffer.change([[row, columnStart], [row, columnEnd]], "") else indent = @minIndentLevelForRowRange(start, end) - indentString = @editSession.buildIndentString(indent) - tabLength = @editSession.getTabLength() + indentString = @editor.buildIndentString(indent) + tabLength = @editor.getTabLength() indentRegex = new RegExp("(\t|[ ]{#{tabLength}}){#{Math.floor(indent)}}") for row in [start..end] line = buffer.lineForRow(row) @@ -98,12 +98,12 @@ class LanguageMode for currentRow in [0..@buffer.getLastRow()] [startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? [] continue unless startRow? - @editSession.createFold(startRow, endRow) + @editor.createFold(startRow, endRow) # Unfolds all the foldable lines in the buffer. unfoldAll: -> for row in [@buffer.getLastRow()..0] - fold.destroy() for fold in @editSession.displayBuffer.foldsStartingAtBufferRow(row) + fold.destroy() for fold in @editor.displayBuffer.foldsStartingAtBufferRow(row) # Fold all comment and code blocks at a given indentLevel # @@ -114,8 +114,8 @@ class LanguageMode continue unless startRow? # assumption: startRow will always be the min indent level for the entire range - if @editSession.indentationForBufferRow(startRow) == indentLevel - @editSession.createFold(startRow, endRow) + if @editor.indentationForBufferRow(startRow) == indentLevel + @editor.createFold(startRow, endRow) # Given a buffer row, creates a fold at it. # @@ -126,14 +126,14 @@ class LanguageMode for currentRow in [bufferRow..0] [startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? [] continue unless startRow? and startRow <= bufferRow <= endRow - fold = @editSession.displayBuffer.largestFoldStartingAtBufferRow(startRow) - return @editSession.createFold(startRow, endRow) unless fold + fold = @editor.displayBuffer.largestFoldStartingAtBufferRow(startRow) + return @editor.createFold(startRow, endRow) unless fold # Given a buffer row, this unfolds it. # # bufferRow - A {Number} indicating the buffer row unfoldBufferRow: (bufferRow) -> - @editSession.displayBuffer.largestFoldContainingBufferRow(bufferRow)?.destroy() + @editor.displayBuffer.largestFoldContainingBufferRow(bufferRow)?.destroy() # Find the row range for a fold at a given bufferRow. Will handle comments # and code. @@ -147,30 +147,30 @@ class LanguageMode rowRange rowRangeForCommentAtBufferRow: (bufferRow) -> - return unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment() + return unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment() startRow = bufferRow for currentRow in [bufferRow-1..0] break if @buffer.isRowBlank(currentRow) - break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment() + break unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment() startRow = currentRow endRow = bufferRow for currentRow in [bufferRow+1..@buffer.getLastRow()] break if @buffer.isRowBlank(currentRow) - break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment() + break unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment() endRow = currentRow return [startRow, endRow] if startRow isnt endRow rowRangeForCodeFoldAtBufferRow: (bufferRow) -> return null unless @doesBufferRowStartFold(bufferRow) - startIndentLevel = @editSession.indentationForBufferRow(bufferRow) - scopes = @editSession.scopesForBufferPosition([bufferRow, 0]) - for row in [(bufferRow + 1)..@editSession.getLastBufferRow()] - continue if @editSession.isBufferRowBlank(row) - indentation = @editSession.indentationForBufferRow(row) + startIndentLevel = @editor.indentationForBufferRow(bufferRow) + scopes = @editor.scopesForBufferPosition([bufferRow, 0]) + for row in [(bufferRow + 1)..@editor.getLastBufferRow()] + continue if @editor.isBufferRowBlank(row) + indentation = @editor.indentationForBufferRow(row) if indentation <= startIndentLevel - includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.search(@editSession.lineForBufferRow(row)) + includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.search(@editor.lineForBufferRow(row)) foldEndRow = row if includeRowInFold break @@ -179,19 +179,19 @@ class LanguageMode [bufferRow, foldEndRow] doesBufferRowStartFold: (bufferRow) -> - return false if @editSession.isBufferRowBlank(bufferRow) - nextNonEmptyRow = @editSession.nextNonBlankBufferRow(bufferRow) + return false if @editor.isBufferRowBlank(bufferRow) + nextNonEmptyRow = @editor.nextNonBlankBufferRow(bufferRow) return false unless nextNonEmptyRow? - @editSession.indentationForBufferRow(nextNonEmptyRow) > @editSession.indentationForBufferRow(bufferRow) + @editor.indentationForBufferRow(nextNonEmptyRow) > @editor.indentationForBufferRow(bufferRow) # Find a row range for a 'paragraph' around specified bufferRow. # Right now, a paragraph is a block of text bounded by and empty line or a # block of text that is not the same type (comments next to source code). rowRangeForParagraphAtBufferRow: (bufferRow) -> - return unless /\w/.test(@editSession.lineForBufferRow(bufferRow)) + return unless /\w/.test(@editor.lineForBufferRow(bufferRow)) isRowComment = (row) => - @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(row).isComment() + @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(row).isComment() if isRowComment(bufferRow) isOriginalRowComment = true @@ -199,22 +199,22 @@ class LanguageMode [firstRow, lastRow] = range or [bufferRow, bufferRow] else isOriginalRowComment = false - [firstRow, lastRow] = [0, @editSession.getLastBufferRow()-1] + [firstRow, lastRow] = [0, @editor.getLastBufferRow()-1] startRow = bufferRow while startRow > firstRow break if isRowComment(startRow - 1) != isOriginalRowComment - break unless /\w/.test(@editSession.lineForBufferRow(startRow - 1)) + break unless /\w/.test(@editor.lineForBufferRow(startRow - 1)) startRow-- endRow = bufferRow - lastRow = @editSession.getLastBufferRow() + lastRow = @editor.getLastBufferRow() while endRow < lastRow break if isRowComment(endRow + 1) != isOriginalRowComment - break unless /\w/.test(@editSession.lineForBufferRow(endRow + 1)) + break unless /\w/.test(@editor.lineForBufferRow(endRow + 1)) endRow++ - new Range([startRow, 0], [endRow, @editSession.lineLengthForBufferRow(endRow)]) + new Range([startRow, 0], [endRow, @editor.lineLengthForBufferRow(endRow)]) # Given a buffer row, this returns a suggested indentation level. # @@ -224,8 +224,8 @@ class LanguageMode # # Returns a {Number}. suggestedIndentForBufferRow: (bufferRow) -> - currentIndentLevel = @editSession.indentationForBufferRow(bufferRow) - scopes = @editSession.scopesForBufferPosition([bufferRow, 0]) + currentIndentLevel = @editor.indentationForBufferRow(bufferRow) + scopes = @editor.scopesForBufferPosition([bufferRow, 0]) return currentIndentLevel unless increaseIndentRegex = @increaseIndentRegexForScopes(scopes) currentLine = @buffer.lineForRow(bufferRow) @@ -233,8 +233,8 @@ class LanguageMode return currentIndentLevel unless precedingRow? precedingLine = @buffer.lineForRow(precedingRow) - desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow) - desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine) and not @editSession.isBufferRowCommented(precedingRow) + desiredIndentLevel = @editor.indentationForBufferRow(precedingRow) + desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine) and not @editor.isBufferRowCommented(precedingRow) return desiredIndentLevel unless decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes) desiredIndentLevel -= 1 if decreaseIndentRegex.test(currentLine) @@ -248,7 +248,7 @@ class LanguageMode # # Returns a {Number} of the indent level of the block of lines. minIndentLevelForRowRange: (startRow, endRow) -> - indents = (@editSession.indentationForBufferRow(row) for row in [startRow..endRow] when not @editSession.isBufferRowBlank(row)) + indents = (@editor.indentationForBufferRow(row) for row in [startRow..endRow] when not @editor.isBufferRowBlank(row)) indents = [0] unless indents.length Math.min(indents...) @@ -264,13 +264,13 @@ class LanguageMode # bufferRow - The row {Number} autoIndentBufferRow: (bufferRow) -> indentLevel = @suggestedIndentForBufferRow(bufferRow) - @editSession.setIndentationForBufferRow(bufferRow, indentLevel) + @editor.setIndentationForBufferRow(bufferRow, indentLevel) # Given a buffer row, this decreases the indentation. # # bufferRow - The row {Number} autoDecreaseIndentForBufferRow: (bufferRow) -> - scopes = @editSession.scopesForBufferPosition([bufferRow, 0]) + scopes = @editor.scopesForBufferPosition([bufferRow, 0]) increaseIndentRegex = @increaseIndentRegexForScopes(scopes) decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes) return unless increaseIndentRegex and decreaseIndentRegex @@ -278,16 +278,16 @@ class LanguageMode line = @buffer.lineForRow(bufferRow) return unless decreaseIndentRegex.test(line) - currentIndentLevel = @editSession.indentationForBufferRow(bufferRow) + currentIndentLevel = @editor.indentationForBufferRow(bufferRow) return if currentIndentLevel is 0 precedingRow = @buffer.previousNonBlankRow(bufferRow) return unless precedingRow? precedingLine = @buffer.lineForRow(precedingRow) - desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow) + desiredIndentLevel = @editor.indentationForBufferRow(precedingRow) desiredIndentLevel -= 1 unless increaseIndentRegex.test(precedingLine) if desiredIndentLevel >= 0 and desiredIndentLevel < currentIndentLevel - @editSession.setIndentationForBufferRow(bufferRow, desiredIndentLevel) + @editor.setIndentationForBufferRow(bufferRow, desiredIndentLevel) tokenizeLine: (line, stack, firstLine) -> {tokens, stack} = @grammar.tokenizeLine(line, stack, firstLine) diff --git a/src/project.coffee b/src/project.coffee index 0071be769..ef8d31d15 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -37,7 +37,7 @@ class Project extends telepath.Model buffer.once 'destroyed', => @removeBuffer(buffer) @openers = [] - @editSessions = [] + @editors = [] @setPath(@path) # Private: Called by telepath. @@ -52,7 +52,7 @@ class Project extends telepath.Model # Private: destroy: -> - editSession.destroy() for editSession in @getEditSessions() + editor.destroy() for editor in @getEditSessions() buffer.release() for buffer in @getBuffers() @destroyRepo() @@ -137,7 +137,7 @@ class Project extends telepath.Model # # * filePath: # The {String} path of the file to associate with - # * editSessionOptions: + # * editorOptions: # Options that you can pass to the {Editor} constructor # # Returns a promise that resolves to an {Editor}. @@ -164,16 +164,16 @@ class Project extends telepath.Model # # Returns an {Array} of {Editor}s. getEditSessions: -> - new Array(@editSessions...) + new Array(@editors...) # Public: Add the given {Editor}. - addEditSession: (editSession) -> - @editSessions.push editSession - @emit 'edit-session-created', editSession + addEditSession: (editor) -> + @editors.push editor + @emit 'editor-created', editor # Public: Return and removes the given {Editor}. - removeEditSession: (editSession) -> - _.remove(@editSessions, editSession) + removeEditSession: (editor) -> + _.remove(@editors, editor) # Private: Retrieves all the {TextBuffer}s in the project; that is, the # buffers for all open files. @@ -331,15 +331,15 @@ class Project extends telepath.Model deferred.promise # Private: - buildEditSessionForBuffer: (buffer, editSessionOptions) -> - editSession = new Editor(_.extend({buffer}, editSessionOptions)) - @addEditSession(editSession) - editSession + buildEditSessionForBuffer: (buffer, editorOptions) -> + editor = new Editor(_.extend({buffer}, editorOptions)) + @addEditSession(editor) + editor # Private: eachEditSession: (callback) -> - callback(editSession) for editSession in @getEditSessions() - @on 'edit-session-created', (editSession) -> callback(editSession) + callback(editor) for editor in @getEditSessions() + @on 'editor-created', (editor) -> callback(editor) # Private: eachBuffer: (args...) -> diff --git a/src/root-view.coffee b/src/root-view.coffee index 73c232882..fd8e02417 100644 --- a/src/root-view.coffee +++ b/src/root-view.coffee @@ -176,19 +176,19 @@ class RootView extends View initialLine = options.initialLine activePane = @getActivePane() - editSession = activePane.itemForUri(project.relativize(filePath)) if activePane and filePath - promise = project.open(filePath, {initialLine}) if not editSession + editor = activePane.itemForUri(project.relativize(filePath)) if activePane and filePath + promise = project.open(filePath, {initialLine}) if not editor - Q(editSession ? promise) - .then (editSession) => + Q(editor ? promise) + .then (editor) => if not activePane - activePane = new Pane(editSession) + activePane = new Pane(editor) @panes.setRoot(activePane) - activePane.showItem(editSession) + activePane.showItem(editor) activePane.focus() if changeFocus @trigger "uri-opened" - editSession + editor .catch (error) -> console.error(error.stack ? error) diff --git a/src/selection.coffee b/src/selection.coffee index 6e3315c98..99c790994 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -9,20 +9,20 @@ class Selection cursor: null marker: null - editSession: null + editor: null initialScreenRange: null wordwise: false needsAutoscroll: null # Private: - constructor: ({@cursor, @marker, @editSession}) -> + constructor: ({@cursor, @marker, @editor}) -> @cursor.selection = this @marker.on 'changed', => @screenRangeChanged() @marker.on 'destroyed', => @destroyed = true - @editSession.removeSelection(this) - @emit 'destroyed' unless @editSession.destroyed + @editor.removeSelection(this) + @emit 'destroyed' unless @editor.destroyed # Private: destroy: -> @@ -65,7 +65,7 @@ class Selection # * options: # + A hash of options matching those found in {.setBufferRange} setScreenRange: (screenRange, options) -> - @setBufferRange(@editSession.bufferRangeForScreenRange(screenRange), options) + @setBufferRange(@editor.bufferRangeForScreenRange(screenRange), options) # Public: Returns the buffer {Range} for the selection. getBufferRange: -> @@ -84,7 +84,7 @@ class Selection bufferRange = Range.fromObject(bufferRange) @needsAutoscroll = options.autoscroll options.isReversed ?= @isReversed() - @editSession.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds + @editor.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds @modifySelection => @cursor.needsAutoscroll = false if options.autoscroll? @marker.setBufferRange(bufferRange, options) @@ -102,7 +102,7 @@ class Selection # Public: Returns the text in the selection. getText: -> - @editSession.buffer.getTextInRange(@getBufferRange()) + @editor.buffer.getTextInRange(@getBufferRange()) # Public: Clears the selection, moving the marker to the head. clear: -> @@ -132,7 +132,7 @@ class Selection # * row: # The line Number to select (default: the row of the cursor) selectLine: (row=@cursor.getBufferPosition().row) -> - range = @editSession.bufferRangeForBufferRow(row, includeNewline: true) + range = @editor.bufferRangeForBufferRow(row, includeNewline: true) @setBufferRange(range) @linewise = true @wordwise = false @@ -202,7 +202,7 @@ class Selection # Public: Selects all the text in the buffer. selectAll: -> - @setBufferRange(@editSession.buffer.getRange(), autoscroll: false) + @setBufferRange(@editor.buffer.getRange(), autoscroll: false) # Public: Selects all the text from the current cursor position to the # beginning of the line. @@ -247,17 +247,17 @@ class Selection range = (@getGoalBufferRange() ? @getBufferRange()).copy() nextRow = range.end.row + 1 - for row in [nextRow..@editSession.getLastBufferRow()] + for row in [nextRow..@editor.getLastBufferRow()] range.start.row = row range.end.row = row - clippedRange = @editSession.clipBufferRange(range) + clippedRange = @editor.clipBufferRange(range) if range.isEmpty() continue if range.end.column > 0 and clippedRange.end.column is 0 else continue if clippedRange.isEmpty() - @editSession.addSelectionForBufferRange(range, goalBufferRange: range) + @editor.addSelectionForBufferRange(range, goalBufferRange: range) break # Public: @@ -274,14 +274,14 @@ class Selection for row in [previousRow..0] range.start.row = row range.end.row = row - clippedRange = @editSession.clipBufferRange(range) + clippedRange = @editor.clipBufferRange(range) if range.isEmpty() continue if range.end.column > 0 and clippedRange.end.column is 0 else continue if clippedRange.isEmpty() - @editSession.addSelectionForBufferRange(range, goalBufferRange: range) + @editor.addSelectionForBufferRange(range, goalBufferRange: range) break # Public: Replaces text at the current selection. @@ -302,7 +302,7 @@ class Selection # if `skip`, skips the undo stack for this operation. insertText: (text, options={}) -> oldBufferRange = @getBufferRange() - @editSession.destroyFoldsContainingBufferRow(oldBufferRange.end.row) + @editor.destroyFoldsContainingBufferRow(oldBufferRange.end.row) wasReversed = @isReversed() @clear() @cursor.needsAutoscroll = @cursor.isLastCursor() @@ -310,18 +310,18 @@ class Selection if options.indentBasis? and not options.autoIndent text = @normalizeIndents(text, options.indentBasis) - newBufferRange = @editSession.buffer.change(oldBufferRange, text, pick(options, 'undo')) + newBufferRange = @editor.buffer.change(oldBufferRange, text, pick(options, 'undo')) if options.select @setBufferRange(newBufferRange, isReversed: wasReversed) else @cursor.setBufferPosition(newBufferRange.end, skipAtomicTokens: true) if wasReversed if options.autoIndent - @editSession.autoIndentBufferRow(row) for row in newBufferRange.getRows() + @editor.autoIndentBufferRow(row) for row in newBufferRange.getRows() else if options.autoIndentNewline and text == '\n' - @editSession.autoIndentBufferRow(newBufferRange.end.row) + @editor.autoIndentBufferRow(newBufferRange.end.row) else if options.autoDecreaseIndent and /\S/.test text - @editSession.autoDecreaseIndentForBufferRow(newBufferRange.start.row) + @editor.autoDecreaseIndentForBufferRow(newBufferRange.start.row) newBufferRange @@ -336,9 +336,9 @@ class Selection isCursorInsideExistingLine = /\S/.test(textPrecedingCursor) lines = text.split('\n') - firstLineIndentLevel = @editSession.indentLevelForLine(lines[0]) + firstLineIndentLevel = @editor.indentLevelForLine(lines[0]) if isCursorInsideExistingLine - minimumIndentLevel = @editSession.indentationForBufferRow(@cursor.getBufferRow()) + minimumIndentLevel = @editor.indentationForBufferRow(@cursor.getBufferRow()) else minimumIndentLevel = @cursor.getIndentLevel() @@ -349,7 +349,7 @@ class Selection else if line == '' # remove all indentation from empty lines indentLevel = 0 else - lineIndentLevel = @editSession.indentLevelForLine(lines[i]) + lineIndentLevel = @editor.indentLevelForLine(lines[i]) indentLevel = minimumIndentLevel + (lineIndentLevel - indentBasis) normalizedLines.push(@setIndentationForLine(line, indentLevel)) @@ -367,13 +367,13 @@ class Selection if @isEmpty() @cursor.skipLeadingWhitespace() - desiredIndent = @editSession.suggestedIndentForBufferRow(row) + desiredIndent = @editor.suggestedIndentForBufferRow(row) delta = desiredIndent - @cursor.getIndentLevel() if autoIndent and delta > 0 - @insertText(@editSession.buildIndentString(delta)) + @insertText(@editor.buildIndentString(delta)) else - @insertText(@editSession.getTabText()) + @insertText(@editor.getTabText()) else @indentSelectedRows() @@ -381,18 +381,18 @@ class Selection indentSelectedRows: -> [start, end] = @getBufferRowRange() for row in [start..end] - @editSession.buffer.insert([row, 0], @editSession.getTabText()) unless @editSession.buffer.lineLengthForRow(row) == 0 + @editor.buffer.insert([row, 0], @editor.getTabText()) unless @editor.buffer.lineLengthForRow(row) == 0 # Public: ? setIndentationForLine: (line, indentLevel) -> desiredIndentLevel = Math.max(0, indentLevel) - desiredIndentString = @editSession.buildIndentString(desiredIndentLevel) + desiredIndentString = @editor.buildIndentString(desiredIndentLevel) line.replace(/^[\t ]*/, desiredIndentString) # Public: Removes the first character before the selection if the selection # is empty otherwise it deletes the selection. backspace: -> - @selectLeft() if @isEmpty() and not @editSession.isFoldedAtScreenRow(@cursor.getScreenRow()) + @selectLeft() if @isEmpty() and not @editor.isFoldedAtScreenRow(@cursor.getScreenRow()) @deleteSelectedText() # Public: Removes from the start of the selection to the beginning of the @@ -414,7 +414,7 @@ class Selection # selection if the selection is empty. delete: -> if @isEmpty() - if @cursor.isAtEndOfLine() and fold = @editSession.largestFoldStartingAtScreenRow(@cursor.getScreenRow() + 1) + if @cursor.isAtEndOfLine() and fold = @editor.largestFoldStartingAtScreenRow(@cursor.getScreenRow() + 1) @selectToBufferPosition(fold.getBufferRange().end) else @selectRight() @@ -429,9 +429,9 @@ class Selection # Public: Removes only the selected text. deleteSelectedText: -> bufferRange = @getBufferRange() - if bufferRange.isEmpty() and fold = @editSession.largestFoldContainingBufferRow(bufferRange.start.row) + if bufferRange.isEmpty() and fold = @editor.largestFoldContainingBufferRow(bufferRange.start.row) bufferRange = bufferRange.union(fold.getBufferRange(includeNewline: true)) - @editSession.buffer.delete(bufferRange) unless bufferRange.isEmpty() + @editor.buffer.delete(bufferRange) unless bufferRange.isEmpty() @cursor?.setBufferPosition(bufferRange.start) # Public: Removes the line at the beginning of the selection if the selection @@ -440,18 +440,18 @@ class Selection deleteLine: -> if @isEmpty() start = @cursor.getScreenRow() - range = @editSession.bufferRowsForScreenRows(start, start + 1) + range = @editor.bufferRowsForScreenRows(start, start + 1) if range[1] > range[0] - @editSession.buffer.deleteRows(range[0], range[1] - 1) + @editor.buffer.deleteRows(range[0], range[1] - 1) else - @editSession.buffer.deleteRow(range[0]) + @editor.buffer.deleteRow(range[0]) else range = @getBufferRange() start = range.start.row end = range.end.row - if end isnt @editSession.buffer.getLastRow() and range.end.column is 0 + if end isnt @editor.buffer.getLastRow() and range.end.column is 0 end-- - @editSession.buffer.deleteRows(start, end) + @editor.buffer.deleteRows(start, end) # Public: Joins the current line with the one below it. # @@ -459,16 +459,16 @@ class Selection joinLine: -> selectedRange = @getBufferRange() if selectedRange.isEmpty() - return if selectedRange.start.row is @editSession.buffer.getLastRow() + return if selectedRange.start.row is @editor.buffer.getLastRow() else - joinMarker = @editSession.markBufferRange(selectedRange, invalidationStrategy: 'never') + joinMarker = @editor.markBufferRange(selectedRange, invalidationStrategy: 'never') rowCount = Math.max(1, selectedRange.getRowCount() - 1) for row in [0...rowCount] @cursor.setBufferPosition([selectedRange.start.row]) @cursor.moveToEndOfLine() nextRow = selectedRange.start.row + 1 - if nextRow <= @editSession.buffer.getLastRow() and @editSession.buffer.lineLengthForRow(nextRow) > 0 + if nextRow <= @editor.buffer.getLastRow() and @editor.buffer.lineLengthForRow(nextRow) > 0 @insertText(' ') @cursor.moveToEndOfLine() @modifySelection => @@ -484,8 +484,8 @@ class Selection # Public: Removes one level of indent from the currently selected rows. outdentSelectedRows: -> [start, end] = @getBufferRowRange() - buffer = @editSession.buffer - leadingTabRegex = new RegExp("^ {1,#{@editSession.getTabLength()}}|\t") + buffer = @editor.buffer + leadingTabRegex = new RegExp("^ {1,#{@editor.getTabLength()}}|\t") for row in [start..end] if matchLength = buffer.lineForRow(row).match(leadingTabRegex)?[0].length buffer.delete [[row, 0], [row, matchLength]] @@ -494,7 +494,7 @@ class Selection # by the relevant grammars. autoIndentSelectedRows: -> [start, end] = @getBufferRowRange() - @editSession.autoIndentBufferRows(start, end) + @editor.autoIndentBufferRows(start, end) # Public: Wraps the selected lines in comments if they aren't currently part # of a comment. @@ -503,7 +503,7 @@ class Selection # # Returns an Array of the commented {Range}s. toggleLineComments: -> - @editSession.toggleLineCommentsForBufferRows(@getBufferRowRange()...) + @editor.toggleLineCommentsForBufferRows(@getBufferRowRange()...) # Public: Cuts the selection until the end of the line. # @@ -527,19 +527,19 @@ class Selection # ? copy: (maintainPasteboard=false) -> return if @isEmpty() - text = @editSession.buffer.getTextInRange(@getBufferRange()) + text = @editor.buffer.getTextInRange(@getBufferRange()) if maintainPasteboard [currentText, metadata] = atom.pasteboard.read() text = currentText + '\n' + text else - metadata = { indentBasis: @editSession.indentationForBufferRow(@getBufferRange().start.row) } + metadata = { indentBasis: @editor.indentationForBufferRow(@getBufferRange().start.row) } atom.pasteboard.write(text, metadata) # Public: Creates a fold containing the current selection. fold: -> range = @getBufferRange() - @editSession.createFold(range.start.row, range.end.row) + @editor.createFold(range.start.row, range.end.row) @cursor.setBufferPosition([range.end.row + 1, 0]) # Public: ? From 2ca738453b110265db81b39f95c232343fee94ee Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 15:24:50 -0800 Subject: [PATCH 11/15] Update benchmarks --- benchmark/benchmark-helper.coffee | 14 +-- benchmark/benchmark-suite.coffee | 136 +++++++++++++++--------------- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/benchmark/benchmark-helper.coffee b/benchmark/benchmark-helper.coffee index 257699616..312d2258d 100644 --- a/benchmark/benchmark-helper.coffee +++ b/benchmark/benchmark-helper.coffee @@ -73,8 +73,8 @@ window.clickEvent = (properties={}) -> window.mouseEvent = (type, properties) -> if properties.point - {point, editor} = properties - {top, left} = @pagePixelPositionForPoint(editor, point) + {point, editorView} = properties + {top, left} = @pagePixelPositionForPoint(editorView, point) properties.pageX = left + 1 properties.pageY = top + 1 properties.originalEvent ?= {detail: 1} @@ -86,14 +86,14 @@ window.mousedownEvent = (properties={}) -> window.mousemoveEvent = (properties={}) -> window.mouseEvent('mousemove', properties) -window.pagePixelPositionForPoint = (editor, point) -> +window.pagePixelPositionForPoint = (editorView, point) -> point = Point.fromObject point - top = editor.lines.offset().top + point.row * editor.lineHeight - left = editor.lines.offset().left + point.column * editor.charWidth - editor.lines.scrollLeft() + top = editorView.lines.offset().top + point.row * editorView.lineHeight + left = editorView.lines.offset().left + point.column * editorView.charWidth - editorView.lines.scrollLeft() { top, left } -window.setEditorWidthInChars = (editor, widthInChars, charWidth=editor.charWidth) -> - editor.width(charWidth * widthInChars + editor.lines.position().left) +window.seteditorViewWidthInChars = (editorView, widthInChars, charWidth=editorView.charWidth) -> + editorView.width(charWidth * widthInChars + editorView.lines.position().left) $.fn.resultOfTrigger = (type) -> event = $.Event(type) diff --git a/benchmark/benchmark-suite.coffee b/benchmark/benchmark-suite.coffee index 92193a634..ad080f64b 100644 --- a/benchmark/benchmark-suite.coffee +++ b/benchmark/benchmark-suite.coffee @@ -2,8 +2,8 @@ require './benchmark-helper' {$, _, RootView} = require 'atom' TokenizedBuffer = require '../src/tokenized-buffer' -describe "editor.", -> - editor = null +describe "editorView.", -> + editorView = null beforeEach -> window.rootViewParentSelector = '#jasmine-content' @@ -12,19 +12,19 @@ describe "editor.", -> rootView.width(1024) rootView.height(768) - rootView.openSync() # open blank editor - editor = rootView.getActiveView() + rootView.openSync() + editorView = rootView.getActiveView() afterEach -> - if editor.pendingDisplayUpdate + if editorView.pendingDisplayUpdate waitsFor "editor to finish rendering", (done) -> - editor.on 'editor:display-updated', done + editorView.on 'editor:display-updated', done describe "keymap.", -> event = null beforeEach -> - event = keydownEvent('x', target: editor.hiddenInput[0]) + event = keydownEvent('x', target: editorView.hiddenInput[0]) benchmark "keydown-event-with-no-binding", 10, -> keymap.handleKeyEvent(event) @@ -35,8 +35,8 @@ describe "editor.", -> describe "empty-file.", -> benchmark "insert-delete", -> - editor.insertText('x') - editor.backspace() + editorView.insertText('x') + editorView.backspace() describe "300-line-file.", -> beforeEach -> @@ -44,81 +44,81 @@ describe "editor.", -> describe "at-begining.", -> benchmark "insert-delete", -> - editor.insertText('x') - editor.backspace() + editorView.insertText('x') + editorView.backspace() benchmark "insert-delete-rehighlight", -> - editor.insertText('"') - editor.backspace() + editorView.insertText('"') + editorView.backspace() describe "at-end.", -> beforeEach -> - editor.moveCursorToBottom() + editorView.moveCursorToBottom() benchmark "insert-delete", -> - editor.insertText('"') - editor.backspace() + editorView.insertText('"') + editorView.backspace() describe "empty-vs-set-innerHTML.", -> [firstRow, lastRow] = [] beforeEach -> - firstRow = editor.getFirstVisibleScreenRow() - lastRow = editor.getLastVisibleScreenRow() + firstRow = editorView.getFirstVisibleScreenRow() + lastRow = editorView.getLastVisibleScreenRow() benchmark "build-gutter-html.", 1000, -> - editor.gutter.renderLineNumbers(null, firstRow, lastRow) + editorView.gutter.renderLineNumbers(null, firstRow, lastRow) benchmark "set-innerHTML.", 1000, -> - editor.gutter.renderLineNumbers(null, firstRow, lastRow) - editor.gutter.lineNumbers[0].innerHtml = '' + editorView.gutter.renderLineNumbers(null, firstRow, lastRow) + editorView.gutter.lineNumbers[0].innerHtml = '' benchmark "empty.", 1000, -> - editor.gutter.renderLineNumbers(null, firstRow, lastRow) - editor.gutter.lineNumbers.empty() + editorView.gutter.renderLineNumbers(null, firstRow, lastRow) + editorView.gutter.lineNumbers.empty() describe "positionLeftForLineAndColumn.", -> line = null beforeEach -> - editor.scrollTop(2000) - editor.resetDisplay() - line = editor.lineElementForScreenRow(106)[0] + editorView.scrollTop(2000) + editorView.resetDisplay() + line = editorView.lineElementForScreenRow(106)[0] describe "one-line.", -> beforeEach -> - editor.clearCharacterWidthCache() + editorView.clearCharacterWidthCache() benchmark "uncached", 5000, -> - editor.positionLeftForLineAndColumn(line, 106, 82) - editor.clearCharacterWidthCache() + editorView.positionLeftForLineAndColumn(line, 106, 82) + editorView.clearCharacterWidthCache() benchmark "cached", 5000, -> - editor.positionLeftForLineAndColumn(line, 106, 82) + editorView.positionLeftForLineAndColumn(line, 106, 82) describe "multiple-lines.", -> [firstRow, lastRow] = [] beforeEach -> - firstRow = editor.getFirstVisibleScreenRow() - lastRow = editor.getLastVisibleScreenRow() + firstRow = editorView.getFirstVisibleScreenRow() + lastRow = editorView.getLastVisibleScreenRow() benchmark "cache-entire-visible-area", 100, -> for i in [firstRow..lastRow] - line = editor.lineElementForScreenRow(i)[0] - editor.positionLeftForLineAndColumn(line, i, Math.max(0, editor.lineLengthForBufferRow(i))) + line = editorView.lineElementForScreenRow(i)[0] + editorView.positionLeftForLineAndColumn(line, i, Math.max(0, editorView.lineLengthForBufferRow(i))) describe "text-rendering.", -> beforeEach -> - editor.scrollTop(2000) + editorView.scrollTop(2000) benchmark "resetDisplay", 50, -> - editor.resetDisplay() + editorView.resetDisplay() benchmark "htmlForScreenRows", 1000, -> - lastRow = editor.getLastScreenRow() - editor.htmlForScreenRows(0, lastRow) + lastRow = editorView.getLastScreenRow() + editorView.htmlForScreenRows(0, lastRow) benchmark "htmlForScreenRows.htmlParsing", 50, -> - lastRow = editor.getLastScreenRow() - html = editor.htmlForScreenRows(0, lastRow) + lastRow = editorView.getLastScreenRow() + html = editorView.htmlForScreenRows(0, lastRow) div = document.createElement('div') div.innerHTML = html @@ -126,44 +126,44 @@ describe "editor.", -> describe "gutter-api.", -> describe "getLineNumberElementsForClass.", -> beforeEach -> - editor.gutter.addClassToLine(20, 'omgwow') - editor.gutter.addClassToLine(40, 'omgwow') + editorView.gutter.addClassToLine(20, 'omgwow') + editorView.gutter.addClassToLine(40, 'omgwow') benchmark "DOM", 20000, -> - editor.gutter.getLineNumberElementsForClass('omgwow') + editorView.gutter.getLineNumberElementsForClass('omgwow') benchmark "getLineNumberElement.DOM", 20000, -> - editor.gutter.getLineNumberElement(12) + editorView.gutter.getLineNumberElement(12) benchmark "toggle-class", 2000, -> - editor.gutter.addClassToLine(40, 'omgwow') - editor.gutter.removeClassFromLine(40, 'omgwow') + editorView.gutter.addClassToLine(40, 'omgwow') + editorView.gutter.removeClassFromLine(40, 'omgwow') describe "find-then-unset.", -> classes = ['one', 'two', 'three', 'four'] benchmark "single-class", 200, -> - editor.gutter.addClassToLine(30, 'omgwow') - editor.gutter.addClassToLine(40, 'omgwow') - editor.gutter.removeClassFromAllLines('omgwow') + editorView.gutter.addClassToLine(30, 'omgwow') + editorView.gutter.addClassToLine(40, 'omgwow') + editorView.gutter.removeClassFromAllLines('omgwow') benchmark "multiple-class", 200, -> - editor.gutter.addClassToLine(30, 'one') - editor.gutter.addClassToLine(30, 'two') + editorView.gutter.addClassToLine(30, 'one') + editorView.gutter.addClassToLine(30, 'two') - editor.gutter.addClassToLine(40, 'two') - editor.gutter.addClassToLine(40, 'three') - editor.gutter.addClassToLine(40, 'four') + editorView.gutter.addClassToLine(40, 'two') + editorView.gutter.addClassToLine(40, 'three') + editorView.gutter.addClassToLine(40, 'four') for klass in classes - editor.gutter.removeClassFromAllLines(klass) + editorView.gutter.removeClassFromAllLines(klass) describe "line-htmlification.", -> div = null html = null beforeEach -> - lastRow = editor.getLastScreenRow() - html = editor.htmlForScreenRows(0, lastRow) + lastRow = editorView.getLastScreenRow() + html = editorView.htmlForScreenRows(0, lastRow) div = document.createElement('div') benchmark "setInnerHTML", 1, -> @@ -178,40 +178,40 @@ describe "editor.", -> rootView.openSync('huge.js') benchmark "moving-to-eof.", 1, -> - editor.moveCursorToBottom() + editorView.moveCursorToBottom() describe "on-first-line.", -> benchmark "inserting-newline", 5, -> - editor.insertNewline() + editorView.insertNewline() describe "on-last-visible-line.", -> beforeEach -> - editor.setCursorScreenPosition([editor.getLastVisibleScreenRow(), 0]) + editorView.setCursorScreenPosition([editorView.getLastVisibleScreenRow(), 0]) benchmark "move-down-and-scroll", 300, -> - editor.trigger 'move-down' + editorView.trigger 'move-down' describe "at-eof.", -> endPosition = null beforeEach -> - editor.moveCursorToBottom() - endPosition = editor.getCursorScreenPosition() + editorView.moveCursorToBottom() + endPosition = editorView.getCursorScreenPosition() benchmark "move-to-beginning-of-word", -> - editor.moveCursorToBeginningOfWord() - editor.setCursorScreenPosition(endPosition) + editorView.moveCursorToBeginningOfWord() + editorView.setCursorScreenPosition(endPosition) benchmark "insert", -> - editor.insertText('x') + editorView.insertText('x') describe "TokenizedBuffer.", -> describe "coffee-script-grammar.", -> [languageMode, buffer] = [] beforeEach -> - editSession = benchmarkFixturesProject.openSync('medium.coffee') - { languageMode, buffer } = editSession + editor = benchmarkFixturesProject.openSync('medium.coffee') + { languageMode, buffer } = editor benchmark "construction", 20, -> new TokenizedBuffer(buffer, { languageMode, tabLength: 2}) From 34cdb23d713168e2343cfcbfafb4f235d300f130 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 15:57:41 -0800 Subject: [PATCH 12/15] Remove file I didn't mean to check this file in. --- test.coffee | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 test.coffee diff --git a/test.coffee b/test.coffee deleted file mode 100644 index 3ab511bc5..000000000 --- a/test.coffee +++ /dev/null @@ -1,7 +0,0 @@ -a = -> - if false - 1 - else - 3 - -console.log a() From c33bd3499659fddc45d4cfb465bcfce48cd6e9a2 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 19 Nov 2013 16:22:29 -0800 Subject: [PATCH 13/15] Add reverse compatability for Editor creation --- src/editor-view.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 436a89309..6e60ebfbd 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -86,7 +86,8 @@ class EditorView extends View if editorOrOptions instanceof Editor editor = editorOrOptions else - {editor, @mini} = editorOrOptions ? {} + {editor, editSession, @mini} = editorOrOptions ? {} + editor ?= editSession # TODO: Remove this line after packages have updated their api to use Editor and EditorView @id = EditorView.nextEditorId++ @lineCache = [] From 2d15f5e49a1d2e4319cbc595991d1be5510079ad Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 20 Nov 2013 10:03:06 -0800 Subject: [PATCH 14/15] Remove pathForRepositoryUrl from atom exports --- exports/atom.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/exports/atom.coffee b/exports/atom.coffee index 580e11961..96da95612 100644 --- a/exports/atom.coffee +++ b/exports/atom.coffee @@ -21,7 +21,6 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE module.exports.$$ = $$ module.exports.$$$ = $$$ module.exports.Editor = require '../src/editor-view' - module.exports.pathForRepositoryUrl = require('../src/project').pathForRepositoryUrl module.exports.RootView = require '../src/root-view' module.exports.SelectList = require '../src/select-list' module.exports.ScrollView = require '../src/scroll-view' From c3de3d8eeaf3e670f2cab0719b1240bb6217269c Mon Sep 17 00:00:00 2001 From: probablycorey Date: Wed, 20 Nov 2013 10:04:28 -0800 Subject: [PATCH 15/15] Update documentation --- src/project.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project.coffee b/src/project.coffee index ef8d31d15..9b4d477a5 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -137,7 +137,7 @@ class Project extends telepath.Model # # * filePath: # The {String} path of the file to associate with - # * editorOptions: + # * options: # Options that you can pass to the {Editor} constructor # # Returns a promise that resolves to an {Editor}.