diff --git a/atom.gyp b/atom.gyp
deleted file mode 100644
index 46eff41c9..000000000
--- a/atom.gyp
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- 'targets': [
- {
- 'target_name': 'Atom',
- 'type': 'none',
- 'postbuilds': [
- {
- 'postbuild_name': 'Create Atom, basically do everything',
- 'action': ['script/constructicon/build'],
- },
- ],
- },
- ],
-}
diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee
index cdca7392a..9e0f1b4eb 100644
--- a/build/Gruntfile.coffee
+++ b/build/Gruntfile.coffee
@@ -151,8 +151,10 @@ module.exports = (grunt) ->
'dot-atom/**/*.coffee'
'exports/**/*.coffee'
'src/**/*.coffee'
- 'tasks/**/*.coffee'
- 'Gruntfile.coffee'
+ ]
+ build: [
+ 'build/tasks/**/*.coffee'
+ 'build/Gruntfile.coffee'
]
test: [
'spec/*.coffee'
@@ -225,7 +227,6 @@ module.exports = (grunt) ->
grunt.registerTask('compile', ['coffee', 'prebuild-less', 'cson', 'peg'])
grunt.registerTask('lint', ['coffeelint', 'csslint', 'lesslint'])
grunt.registerTask('test', ['shell:kill-atom', 'run-specs'])
- grunt.registerTask('ci', ['output-disk-space', 'download-atom-shell', 'build', 'set-development-version', 'lint', 'test', 'publish-build'])
- grunt.registerTask('deploy', ['partial-clean', 'download-atom-shell', 'build', 'codesign'])
+ grunt.registerTask('ci', ['output-disk-space', 'download-atom-shell', 'build', 'set-version', 'lint', 'test', 'codesign', 'publish-build'])
grunt.registerTask('docs', ['markdown:guides', 'build-docs'])
- grunt.registerTask('default', ['download-atom-shell', 'build', 'set-development-version', 'install'])
+ grunt.registerTask('default', ['download-atom-shell', 'build', 'set-version', 'install'])
diff --git a/build/tasks/build-task.coffee b/build/tasks/build-task.coffee
index 1f95e76c4..0e1d47e61 100644
--- a/build/tasks/build-task.coffee
+++ b/build/tasks/build-task.coffee
@@ -39,19 +39,27 @@ module.exports = (grunt) ->
else
nonPackageDirectories.push(directory)
+ # Put any paths here that shouldn't end up in the built Atom.app
+ # so that it doesn't becomes larger than it needs to be.
ignoredPaths = [
path.join('git-utils', 'deps')
path.join('oniguruma', 'deps')
+ path.join('less', 'dist')
+ path.join('less', 'test')
+ path.join('bootstrap', 'docs')
+ path.join('spellchecker', 'vendor')
+ path.join('xmldom', 'test')
path.join('vendor', 'apm')
path.join('resources', 'mac')
path.join('resources', 'win')
]
ignoredPaths = ignoredPaths.map (ignoredPath) -> "(#{ignoredPath})"
nodeModulesFilter = new RegExp(ignoredPaths.join('|'))
+ packageFilter = new RegExp("(#{ignoredPaths.join('|')})|(.+\\.(cson|coffee)$)")
for directory in nonPackageDirectories
cp directory, path.join(appDir, directory), filter: nodeModulesFilter
for directory in packageDirectories
- cp directory, path.join(appDir, directory), filter: /.+\.(cson|coffee)$/
+ cp directory, path.join(appDir, directory), filter: packageFilter
cp 'spec', path.join(appDir, 'spec')
cp 'src', path.join(appDir, 'src'), filter: /.+\.(cson|coffee)$/
diff --git a/build/tasks/codesign-task.coffee b/build/tasks/codesign-task.coffee
index fd4592eba..93920d7a7 100644
--- a/build/tasks/codesign-task.coffee
+++ b/build/tasks/codesign-task.coffee
@@ -3,6 +3,23 @@ module.exports = (grunt) ->
grunt.registerTask 'codesign', 'Codesign the app', ->
done = @async()
+
+ if process.env.XCODE_KEYCHAIN
+ unlockKeychain (error) ->
+ if error?
+ done(error)
+ else
+ signApp(done)
+ else
+ signApp(done)
+
+ unlockKeychain = (callback) ->
+ cmd = 'security'
+ {XCODE_KEYCHAIN_PASSWORD, XCODE_KEYCHAIN} = process.env
+ args = ['unlock-keychain', '-p', XCODE_KEYCHAIN_PASSWORD, XCODE_KEYCHAIN]
+ spawn {cmd, args}, (error) -> callback(error)
+
+ signApp = (callback) ->
cmd = 'codesign'
args = ['-f', '-v', '-s', 'Developer ID Application: GitHub', grunt.config.get('atom.shellAppDir')]
- spawn {cmd, args}, (error) -> done(error)
+ spawn {cmd, args}, (error) -> callback(error)
diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee
index 3f8dc909a..19f0aff90 100644
--- a/build/tasks/publish-build-task.coffee
+++ b/build/tasks/publish-build-task.coffee
@@ -24,13 +24,19 @@ module.exports = (gruntObject) ->
done = @async()
- createRelease (error, release) ->
+ createBuildRelease (error, release) ->
return done(error) if error?
zipApp (error) ->
return done(error) if error?
uploadAsset release, (error) ->
return done(error) if error?
- publishRelease(release, done)
+ publishRelease release, (error) ->
+ return done(error) if error?
+ getAtomDraftRelease (error, release) ->
+ return done(error) if error?
+ deleteExistingAsset release, (error) ->
+ return done(error) if error?
+ uploadAsset(release, done)
logError = (message, error, details) ->
grunt.log.error(message)
@@ -65,6 +71,18 @@ getRelease = (callback) ->
return
callback()
+getAtomDraftRelease = (callback) ->
+ atomRepo = new GitHub({repo: 'atom/atom', token})
+ atomRepo.getReleases (error, releases=[]) ->
+ if error?
+ logError('Fetching atom/atom releases failed', error, releases)
+ callback(error)
+ else
+ for release in releases when release.draft
+ callback(null, release)
+ return
+ callback(new Error('No draft release in atom/atom repo'))
+
deleteRelease = (release) ->
options =
uri: release.url
@@ -92,7 +110,7 @@ deleteExistingAsset = (release, callback) ->
callback()
-createRelease = (callback) ->
+createBuildRelease = (callback) ->
getRelease (error, release) ->
if error?
callback(error)
@@ -123,7 +141,7 @@ createRelease = (callback) ->
uploadAsset = (release, callback) ->
options =
- uri: "https://uploads.github.com/repos/atom/atom-master-builds/releases/#{release.id}/assets?name=#{assetName}"
+ uri: release.upload_url.replace(/\{.*$/, "?name=#{assetName}")
method: 'POST'
headers: _.extend({
'Content-Type': 'application/zip'
diff --git a/build/tasks/set-development-version-task.coffee b/build/tasks/set-version-task.coffee
similarity index 64%
rename from build/tasks/set-development-version-task.coffee
rename to build/tasks/set-version-task.coffee
index 66bdd1089..be41866a8 100644
--- a/build/tasks/set-development-version-task.coffee
+++ b/build/tasks/set-version-task.coffee
@@ -4,15 +4,24 @@ path = require 'path'
module.exports = (grunt) ->
{spawn} = require('./task-helpers')(grunt)
- grunt.registerTask 'set-development-version', 'Sets version to current SHA-1', ->
+ getVersion = (callback) ->
+ if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH is 'master'
+ {version} = require(path.join(grunt.config.get('atom.appDir'), 'package.json'))
+ callback(null, version)
+ else
+ cmd = 'git'
+ args = ['rev-parse', '--short', 'HEAD']
+ spawn {cmd, args}, (error, {stdout}={}, code) ->
+ callback(error, stdout?.trim?())
+
+ grunt.registerTask 'set-version', 'Set the version in the plist and package.json', ->
done = @async()
- cmd = 'git'
- args = ['rev-parse', '--short', 'HEAD']
- spawn {cmd, args}, (error, result, code) ->
- return done(error) if error?
+ getVersion (error, version) ->
+ if error?
+ done(error)
+ return
- version = result.stdout.trim()
appDir = grunt.config.get('atom.appDir')
# Replace version field of package.json.
@@ -32,7 +41,7 @@ module.exports = (grunt) ->
strings =
CompanyName: 'GitHub, Inc.'
- FileDescription: 'The hackable, collaborative editor of tomorrow!'
+ FileDescription: 'The hackable, collaborative editor'
LegalCopyright: 'Copyright (C) 2013 GitHub, Inc. All rights reserved'
ProductName: 'Atom'
ProductVersion: version
diff --git a/package.json b/package.json
index c8a891c1c..fa883f73a 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "atom",
"productName": "Atom",
- "version": "0.45.0",
+ "version": "0.46.0",
"main": "./src/browser/main.js",
"repository": {
"type": "git",
@@ -19,7 +19,7 @@
"atomShellVersion": "0.8.5",
"dependencies": {
"async": "0.2.6",
- "bootstrap": "git://github.com/benogle/bootstrap.git",
+ "bootstrap": "git://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
"clear-cut": "0.2.0",
"coffee-script": "1.6.3",
"coffeestack": "0.6.0",
@@ -28,11 +28,9 @@
"fs-plus": "0.14.0",
"fstream": "0.1.24",
"fuzzaldrin": "0.6.0",
- "git-utils": "0.30.0",
+ "git-utils": "0.33.0",
"guid": "0.0.10",
- "jasmine-focused": "~0.15.0",
- "jasmine-node": "git://github.com/kevinsawicki/jasmine-node.git#short-stacks",
- "jasmine-tagged": "0.2.0",
+ "jasmine-tagged": "0.3.0",
"mkdirp": "0.3.5",
"keytar": "0.15.0",
"less-cache": "0.10.0",
@@ -43,17 +41,18 @@
"pathwatcher": "0.14.0",
"pegjs": "0.8.0",
"q": "0.9.7",
- "scandal": "0.11.0",
+ "scandal": "0.12.0",
"season": "0.14.0",
"semver": "1.1.4",
"space-pen": "3.1.0",
"temp": "0.5.0",
- "text-buffer": "0.12.0",
+ "text-buffer": "0.13.0",
"underscore-plus": "0.6.1",
"vm-compatibility-layer": "0.1.0",
"theorist": "~0.13.0",
"delegato": "~0.4.0",
- "mixto": "~0.4.0"
+ "mixto": "~0.4.0",
+ "property-accessors": "~0.1.0"
},
"packageDependencies": {
"atom-dark-syntax": "0.10.0",
@@ -64,46 +63,46 @@
"solarized-dark-syntax": "0.6.0",
"solarized-light-syntax": "0.2.0",
"archive-view": "0.19.0",
- "autocomplete": "0.19.0",
- "autoflow": "0.11.0",
+ "autocomplete": "0.20.0",
+ "autoflow": "0.12.0",
"autosave": "0.10.0",
"background-tips": "0.4.0",
- "bookmarks": "0.15.0",
- "bracket-matcher": "0.16.0",
+ "bookmarks": "0.16.0",
+ "bracket-matcher": "0.19.0",
"command-logger": "0.9.0",
"command-palette": "0.14.0",
"dev-live-reload": "0.22.0",
"editor-stats": "0.12.0",
"exception-reporting": "0.11.0",
"feedback": "0.22.0",
- "find-and-replace": "0.74.0",
- "fuzzy-finder": "0.30.0",
- "gists": "0.14.0",
- "git-diff": "0.21.0",
+ "find-and-replace": "0.75.0",
+ "fuzzy-finder": "0.31.0",
+ "gists": "0.15.0",
+ "git-diff": "0.22.0",
"github-sign-in": "0.16.0",
- "go-to-line": "0.14.0",
- "grammar-selector": "0.16.0",
+ "go-to-line": "0.15.0",
+ "grammar-selector": "0.17.0",
"image-view": "0.15.0",
"keybinding-resolver": "0.8.0",
"markdown-preview": "0.24.0",
"metrics": "0.21.0",
- "package-generator": "0.23.0",
+ "package-generator": "0.24.0",
"release-notes": "0.15.0",
- "settings-view": "0.55.0",
- "snippets": "0.18.0",
- "spell-check": "0.19.0",
- "status-bar": "0.31.0",
+ "settings-view": "0.56.0",
+ "snippets": "0.19.0",
+ "spell-check": "0.20.0",
+ "status-bar": "0.32.0",
"styleguide": "0.19.0",
- "symbols-view": "0.28.0",
+ "symbols-view": "0.29.0",
"tabs": "0.17.0",
"terminal": "0.24.0",
"timecop": "0.13.0",
"to-the-hubs": "0.17.0",
- "tree-view": "0.59.0",
+ "tree-view": "0.61.0",
"visual-bell": "0.6.0",
"welcome": "0.4.0",
"whitespace": "0.10.0",
- "wrap-guide": "0.11.0",
+ "wrap-guide": "0.12.0",
"language-c": "0.2.0",
"language-clojure": "0.1.0",
"language-coffee-script": "0.4.0",
@@ -122,12 +121,12 @@
"language-objective-c": "0.2.0",
"language-pegjs": "0.1.0",
"language-perl": "0.2.0",
- "language-php": "0.2.0",
+ "language-php": "0.3.0",
"language-property-list": "0.2.0",
"language-puppet": "0.2.0",
"language-python": "0.2.0",
- "language-ruby": "0.6.0",
- "language-ruby-on-rails": "0.3.0",
+ "language-ruby": "0.7.0",
+ "language-ruby-on-rails": "0.4.0",
"language-sass": "0.3.0",
"language-shellscript": "0.2.0",
"language-source": "0.2.0",
diff --git a/script/bootstrap b/script/bootstrap
index 2154a1ef4..d0c9919e0 100755
--- a/script/bootstrap
+++ b/script/bootstrap
@@ -31,6 +31,7 @@ if (!fs.existsSync(path.join(apmInstallPath, 'node_modules')))
fs.mkdirSync(path.join(apmInstallPath, 'node_modules'));
var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? '--no-color' : '';
+var packagesToDedupe = ['nan', 'oniguruma', 'roaster'];
var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo';
var commands = [
'git submodule --quiet sync',
@@ -43,6 +44,7 @@ var commands = [
echoNewLine,
'node apm/node_modules/atom-package-manager/bin/apm clean ' + apmFlags,
'node apm/node_modules/atom-package-manager/bin/apm install --quiet ' + apmFlags,
+ 'node apm/node_modules/atom-package-manager/bin/apm dedupe --quiet ' + apmFlags + ' ' + packagesToDedupe.join(' '),
];
process.chdir(path.dirname(__dirname));
diff --git a/script/cibuild b/script/cibuild
index c5b1a0423..6c7cb8ef5 100755
--- a/script/cibuild
+++ b/script/cibuild
@@ -10,11 +10,9 @@ if (process.platform == 'linux')
var homeDir = process.platform == 'win32' ? process.env.USERPROFILE : process.env.HOME;
-function readEnvironmentVariables() {
- var credentialsPath = '/var/lib/jenkins/config/atomcredentials';
+function loadEnvironmentVariables(filePath) {
try {
- var credentials = fs.readFileSync(credentialsPath, 'utf8');
- var lines = credentials.trim().split('\n');
+ var lines = fs.readFileSync(filePath, 'utf8').trim().split('\n');
for (i in lines) {
var parts = lines[i].split('=');
var key = parts[0].trim();
@@ -24,6 +22,11 @@ function readEnvironmentVariables() {
} catch(error) { }
}
+function readEnvironmentVariables() {
+ loadEnvironmentVariables('/var/lib/jenkins/config/atomcredentials')
+ loadEnvironmentVariables('/var/lib/jenkins/config/xcodekeychain')
+}
+
readEnvironmentVariables();
cp.safeExec.bind(global, 'node script/bootstrap', function(error) {
if (error)
diff --git a/script/constructicon/build b/script/constructicon/build
deleted file mode 100755
index 647108d85..000000000
--- a/script/constructicon/build
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-set -ex
-
-# This entire file is a hack so that constructicon can build Atom via
-# xcode
-
-cd "$(dirname "$0")/../.."
-rm -fr node_modules
-rm -fr vendor/apm/node_modules
-./script/bootstrap --no-color
-./build/node_modules/.bin/grunt --no-color --build-dir="$BUILT_PRODUCTS_DIR" deploy
-
-echo "TARGET_BUILD_DIR=$BUILT_PRODUCTS_DIR"
-echo "FULL_PRODUCT_NAME=Atom.app"
-echo "PRODUCT_NAME=Atom"
diff --git a/script/constructicon/prebuild b/script/constructicon/prebuild
deleted file mode 100755
index 600a56afa..000000000
--- a/script/constructicon/prebuild
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-set -ex
-cd "$(dirname "$0")/../.."
-export PATH="atom-shell/Atom.app/Contents/Resources/:${PATH}"
-
-rm -rf atom.xcodeproj
-gyp --depth=. atom.gyp
diff --git a/spec/editor-view-spec.coffee b/spec/editor-view-spec.coffee
index 6ab18ccdf..bae094249 100644
--- a/spec/editor-view-spec.coffee
+++ b/spec/editor-view-spec.coffee
@@ -21,7 +21,7 @@ describe "EditorView", ->
editorView.calculateHeightInLines = ->
Math.ceil(@height() / @lineHeight)
editorView.attachToDom = ({ heightInLines, widthInChars } = {}) ->
- heightInLines ?= @getBuffer().getLineCount()
+ heightInLines ?= @getEditor().getBuffer().getLineCount()
@height(getLineHeight() * heightInLines)
@width(getCharWidth() * widthInChars) if widthInChars
$('#jasmine-content').append(this)
@@ -51,7 +51,7 @@ describe "EditorView", ->
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)
+ editor.setCursorScreenPosition(row: 2, column: 2)
editorView.attachToDom()
@@ -72,7 +72,7 @@ describe "EditorView", ->
it "does not scroll the editor view (regression)", ->
editorView.attachToDom(heightInLines: 2)
- editorView.selectAll()
+ editor.selectAll()
editorView.hiddenInput.blur()
editorView.focus()
@@ -80,7 +80,7 @@ describe "EditorView", ->
expect($(editorView[0]).scrollTop()).toBe 0
expect($(editorView.scrollView[0]).scrollTop()).toBe 0
- editorView.moveCursorToBottom()
+ editor.moveCursorToBottom()
editorView.hiddenInput.blur()
editorView.scrollTop(0)
editorView.focus()
@@ -105,7 +105,7 @@ describe "EditorView", ->
fs.writeFileSync(filePath, "")
editor = atom.project.openSync(filePath)
editorView.edit(editor)
- editorView.insertText("now the buffer is modified")
+ editor.insertText("now the buffer is modified")
fileChangeHandler = jasmine.createSpy('fileChange')
editor.buffer.file.on 'contents-changed', fileChangeHandler
@@ -134,7 +134,7 @@ describe "EditorView", ->
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])
+ editor.setCursorBufferPosition([6, 13])
editorView.scrollToBottom()
editorView.scrollLeft(150)
previousScrollHeight = editorView.verticalScrollbar.prop('scrollHeight')
@@ -151,7 +151,7 @@ describe "EditorView", ->
expect(editorView.scrollTop()).toBe 900
expect(editorView.scrollLeft()).toBe 0
expect(editorView.getSelectionView().regions[0].position().top).toBe 40 * editorView.lineHeight
- editorView.insertText("hello")
+ newEditor.insertText("hello")
expect(editorView.lineElementForScreenRow(40).text()).toBe "hello3"
editorView.edit(editor)
@@ -162,7 +162,7 @@ describe "EditorView", ->
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")
+ editor.insertText("goodbye")
expect(editorView.lineElementForScreenRow(6).text()).toMatch /^ currentgoodbye/
it "triggers alert if edit session's buffer goes into conflict with changes on disk", ->
@@ -271,7 +271,7 @@ describe "EditorView", ->
it "emits event when buffer's path is changed", ->
eventHandler = jasmine.createSpy('eventHandler')
editorView.on 'editor:path-changed', eventHandler
- editorView.getBuffer().saveAs(filePath)
+ editor.saveAs(filePath)
expect(eventHandler).toHaveBeenCalled()
it "emits event when editor view view receives a new buffer", ->
@@ -282,10 +282,12 @@ describe "EditorView", ->
it "stops listening to events on previously set buffers", ->
eventHandler = jasmine.createSpy('eventHandler')
- oldBuffer = editorView.getBuffer()
+ oldBuffer = editor.getBuffer()
+ newEditor = atom.project.openSync(filePath)
editorView.on 'editor:path-changed', eventHandler
- editorView.edit(atom.project.openSync(filePath))
+
+ editorView.edit(newEditor)
expect(eventHandler).toHaveBeenCalled()
eventHandler.reset()
@@ -293,13 +295,13 @@ describe "EditorView", ->
expect(eventHandler).not.toHaveBeenCalled()
eventHandler.reset()
- editorView.getBuffer().saveAs(path.join(temp.dir, 'atom-new.txt'))
+ newEditor.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'
+ expect(editor.getGrammar().name).toBe 'JavaScript'
+ editor.getBuffer().saveAs(filePath)
+ expect(editor.getGrammar().name).toBe 'Plain Text'
describe "font family", ->
beforeEach ->
@@ -322,7 +324,7 @@ describe "EditorView", ->
editorView.attachToDom(12)
lineHeightBefore = editorView.lineHeight
charWidthBefore = editorView.charWidth
- editorView.setCursorScreenPosition [5, 6]
+ editor.setCursorScreenPosition [5, 6]
atom.config.set("editor.fontFamily", fontFamily)
expect(editorView.css('font-family')).toBe fontFamily
@@ -347,7 +349,7 @@ describe "EditorView", ->
editorView.attachToDom()
lineHeightBefore = editorView.lineHeight
charWidthBefore = editorView.charWidth
- editorView.setCursorScreenPosition [5, 6]
+ editor.setCursorScreenPosition [5, 6]
atom.config.set("editor.fontSize", 30)
expect(editorView.css('font-size')).toBe '30px'
@@ -364,7 +366,7 @@ describe "EditorView", ->
it "updates the position and size of selection regions", ->
atom.config.set("editor.fontSize", 10)
- editorView.setSelectedBufferRange([[5, 2], [5, 7]])
+ editor.setSelectedBufferRange([[5, 2], [5, 7]])
editorView.attachToDom()
atom.config.set("editor.fontSize", 30)
@@ -384,7 +386,7 @@ describe "EditorView", ->
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])
+ editor.setCursorScreenPosition([4, 2])
editorView.attachToDom()
initialLineHeight = editorView.lineHeight
initialCharWidth = editorView.charWidth
@@ -409,17 +411,17 @@ describe "EditorView", ->
describe "single-click", ->
it "re-positions the cursor to the clicked row / column", ->
- expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0)
+ expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [3, 10])
- expect(editorView.getCursorScreenPosition()).toEqual(row: 3, column: 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(editorView, 30)
- expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0)
+ expect(editor.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)
+ expect(editor.getCursorBufferPosition()).toEqual(row: 3, column: 50)
describe "when the editor view view is using a variable-width font", ->
beforeEach ->
@@ -428,62 +430,62 @@ describe "EditorView", ->
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]
+ 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(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0)
+ expect(editor.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"
+ expect(editor.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"
+ expect(editor.getSelectedText()).toBe "return sort(left).concat"
it "stops selecting by word when the selection is emptied", ->
- expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0)
+ expect(editor.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"
+ expect(editor.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]]
+ expect(editor.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)
+ expect(editor.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"
+ expect(editor.getSelectedText()).toBe "function"
- editorView.setCursorBufferPosition([0, 0])
+ editor.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"
+ expect(editor.getSelectedText()).toBe "items"
- editorView.setCursorBufferPosition([0, 0])
+ editor.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 "{"
+ expect(editor.getSelectedText()).toBe "{"
describe "triple/quardruple/etc-click", ->
it "selects the line under the cursor", ->
- expect(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0)
+ expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
# Triple click
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [1, 8], originalEvent: {detail: 1})
@@ -492,7 +494,7 @@ describe "EditorView", ->
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"
+ expect(editor.getSelectedText()).toBe " var sort = function(items) {\n"
# Quad click
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [2, 3], originalEvent: {detail: 1})
@@ -503,7 +505,7 @@ describe "EditorView", ->
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"
+ 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", ->
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 8], originalEvent: {detail: 1})
@@ -512,55 +514,55 @@ describe "EditorView", ->
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]]
+ expect(editor.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]]
+ expect(editor.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()
+ expect(editor.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]]
+ expect(editor.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])
+ editor.setCursorScreenPosition([4, 7])
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [5, 24], shiftKey: true)
- expect(editorView.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]]
+ 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", ->
- editorView.setCursorScreenPosition([4, 7])
+ editor.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]]
+ expect(editor.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]]
+ 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", ->
- editorView.setCursorScreenPosition([4, 7])
+ editor.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]]
+ expect(editor.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]]
+ expect(editor.getSelection().getScreenRange()).toEqual [[4, 7], [5, 24]]
describe "meta-click", ->
it "places an additional cursor", ->
editorView.attachToDom()
setEditorHeightInLines(editorView, 5)
- editorView.setCursorBufferPosition([3, 0])
+ editor.setCursorBufferPosition([3, 0])
editorView.scrollTop(editorView.lineHeight * 6)
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [6, 0], metaKey: true)
@@ -583,10 +585,10 @@ describe "EditorView", ->
# moving changes selection
$(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27])
- range = editorView.getSelection().getScreenRange()
+ range = editor.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)
+ expect(editor.getCursorScreenPosition()).toEqual(row: 5, column: 27)
# mouse up may occur outside of editorView, but still need to halt selection
$(document).trigger 'mouseup'
@@ -594,10 +596,10 @@ describe "EditorView", ->
# moving after mouse up should not change selection
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [8, 8])
- range = editorView.getSelection().getScreenRange()
+ range = editor.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)
+ expect(editor.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
@@ -630,7 +632,7 @@ describe "EditorView", ->
$(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27])
$(document).trigger 'mouseup'
- range = editorView.getSelection().getScreenRange()
+ range = editor.getSelection().getScreenRange()
expect(range.start).toEqual({row: 4, column: 10})
expect(range.end).toEqual({row: 4, column: 10})
@@ -644,33 +646,33 @@ describe "EditorView", ->
$(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27])
$(document).trigger 'mouseup'
- range = editorView.getSelection().getScreenRange()
+ 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(editorView.getCursorScreenPosition()).toEqual(row: 0, column: 0)
+ expect(editor.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"
+ expect(editor.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]
+ expect(editor.getSelectedBufferRange()).toEqual [[0, 4], [1, 10]]
+ expect(editor.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]
+ expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]]
+ expect(editor.getCursorBufferPosition()).toEqual [0, 0]
editorView.renderedLines.trigger 'mouseup'
- expect(editorView.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]]
+ expect(editor.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]]
+ expect(editor.getSelectedBufferRange()).toEqual [[0, 13], [5, 27]]
describe "triple-click and drag", ->
it "expands the initial selection linewise in either direction", ->
@@ -682,17 +684,17 @@ describe "EditorView", ->
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]]
+ expect(editor.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]
+ expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [6, 0]]
+ expect(editor.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]
+ expect(editor.getSelectedBufferRange()).toEqual [[2, 0], [5, 0]]
+ expect(editor.getCursorBufferPosition()).toEqual [2, 0]
# mouse up may occur outside of editorView, but still need to halt selection
$(document).trigger 'mouseup'
@@ -707,7 +709,7 @@ describe "EditorView", ->
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [8, 27], metaKey: true)
editorView.renderedLines.trigger 'mouseup'
- selections = editorView.getSelections()
+ selections = editor.getSelections()
expect(selections.length).toBe 2
[selection1, selection2] = selections
expect(selection1.getScreenRange()).toEqual [[4, 10], [5, 27]]
@@ -716,14 +718,14 @@ describe "EditorView", ->
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)
+ editor.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(editor.getCursorScreenPosition()).toEqual(row: 1, column: 7)
expect(editorView.renderedLines.find('.line:eq(1)')).toHaveText buffer.lineForRow(1)
describe "selection rendering", ->
@@ -733,7 +735,7 @@ describe "EditorView", ->
editorView.attachToDom()
editorView.width(500)
{ charWidth, lineHeight } = editorView
- selection = editorView.getSelection()
+ selection = editor.getSelection()
selectionView = editorView.getSelectionView()
describe "when a selection is added", ->
@@ -845,7 +847,7 @@ describe "EditorView", ->
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()
+ editor.selectAll()
expect(editorView.scrollTop()).toBe 0
# regression: does not scroll the scroll view when the editorView is refocused
@@ -855,7 +857,7 @@ describe "EditorView", ->
expect(editorView.scrollView.scrollTop()).toBe 0
# does autoscroll when the selection is cleared
- editorView.moveCursorDown()
+ editor.moveCursorDown()
expect(editorView.scrollTop()).toBeGreaterThan(0)
describe "selection autoscrolling and highlighting when setting selected buffer range", ->
@@ -864,24 +866,24 @@ describe "EditorView", ->
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)
+ editor.setSelectedBufferRange([[2, 0], [4, 0]], autoscroll: true)
expect(editorView.scrollTop()).toBe 0
- editorView.setSelectedBufferRange([[6, 0], [8, 0]], autoscroll: true)
+ editor.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)
+ editor.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)
+ editor.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)
+ editor.setSelectedBufferRange([[2, 0], [4, 0]], autoscroll: true)
expect(editorView.getSelectionView().removeClass).toHaveBeenCalledWith('highlighted')
expect(editorView.getSelectionView()).toHaveClass 'highlighted'
@@ -892,13 +894,13 @@ describe "EditorView", ->
it "does not scroll to the selection or the cursor", ->
editorView.scrollToBottom()
scrollTopBefore = editorView.scrollTop()
- editorView.setSelectedBufferRange([[0, 0], [1, 0]], autoscroll: false)
+ editor.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]])
+ editor.setSelectedBufferRange([[0, 0], [1, 0]])
expect(editorView.scrollTop()).toBe 0
describe "cursor rendering", ->
@@ -912,24 +914,24 @@ describe "EditorView", ->
{charWidth} = editorView
it "repositions the cursor's view on screen", ->
- editorView.setCursorScreenPosition(row: 2, column: 2)
+ editor.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(editor.getSelection().isEmpty()).toBeTruthy()
expect(cursorView).toBeVisible()
- editorView.setSelectedBufferRange([[0, 0], [3, 0]])
- expect(editorView.getSelection().isEmpty()).toBeFalsy()
+ editor.setSelectedBufferRange([[0, 0], [3, 0]])
+ expect(editor.getSelection().isEmpty()).toBeFalsy()
expect(cursorView).toBeHidden()
- editorView.setCursorBufferPosition([1, 3])
- expect(editorView.getSelection().isEmpty()).toBeTruthy()
+ editor.setCursorBufferPosition([1, 3])
+ expect(editor.getSelection().isEmpty()).toBeTruthy()
expect(cursorView).toBeVisible()
it "moves the hiddenInput to the same position with cursor's view", ->
- editorView.setCursorScreenPosition(row: 2, column: 2)
+ editor.setCursorScreenPosition(row: 2, column: 2)
expect(editorView.getCursorView().offset()).toEqual(editorView.hiddenInput.offset())
describe "when the editor view is using a variable-width font", ->
@@ -938,23 +940,23 @@ describe "EditorView", ->
describe "on #darwin or #linux", ->
it "correctly positions the cursor", ->
- editorView.setCursorBufferPosition([3, 30])
+ editor.setCursorBufferPosition([3, 30])
expect(editorView.getCursorView().position()).toEqual {top: 3 * editorView.lineHeight, left: 178}
- editorView.setCursorBufferPosition([3, Infinity])
+ editor.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])
+ editor.setCursorBufferPosition([3, 30])
expect(editorView.getCursorView().position()).toEqual {top: 3 * editorView.lineHeight, left: 175}
- editorView.setCursorBufferPosition([3, Infinity])
+ editor.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()
+ editor.setCursorBufferPosition([11,0])
+ editor.addCursorAtBufferPosition([6,50])
+ [cursor1, cursor2] = editor.getCursors()
spyOn(editorView, 'scrollToPixelPosition')
cursor1.setScreenPosition([10, 10])
@@ -964,37 +966,37 @@ describe "EditorView", ->
expect(editorView.scrollToPixelPosition).toHaveBeenCalled()
it "does not autoscroll if the 'autoscroll' option is false", ->
- editorView.setCursorBufferPosition([11,0])
+ editor.setCursorBufferPosition([11,0])
spyOn(editorView, 'scrollToPixelPosition')
- editorView.setCursorScreenPosition([10, 10], autoscroll: false)
+ editor.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])
+ editor.setCursorScreenPosition([4, 10], autoscroll: false)
+ editor.setCursorScreenPosition([4, 10])
expect(editorView.scrollToPixelPosition).toHaveBeenCalled()
editorView.scrollToPixelPosition.reset()
- editorView.setCursorBufferPosition([4, 10])
+ editor.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])
+ editor.addCursorAtBufferPosition([lastVisibleRow, 0])
spyOn(editorView, 'scrollToPixelPosition')
buffer.insert([lastVisibleRow, 0], "\n\n")
expect(editorView.scrollToPixelPosition).not.toHaveBeenCalled()
- editorView.insertText('\n\n')
+ editor.insertText('\n\n')
expect(editorView.scrollToPixelPosition.callCount).toBe 1
it "autoscrolls on undo/redo", ->
spyOn(editorView, 'scrollToPixelPosition')
- editorView.insertText('\n\n')
+ editor.insertText('\n\n')
expect(editorView.scrollToPixelPosition.callCount).toBe 1
- editorView.undo()
+ editor.undo()
expect(editorView.scrollToPixelPosition.callCount).toBe 2
- editorView.redo()
+ editor.redo()
expect(editorView.scrollToPixelPosition.callCount).toBe 3
describe "when the last cursor exceeds the upper or lower scroll margins", ->
@@ -1002,32 +1004,32 @@ describe "EditorView", ->
it "sets the scrollTop so the cursor remains within the scroll margin", ->
setEditorHeightInLines(editorView, 10)
- _.times 6, -> editorView.moveCursorDown()
+ _.times 6, -> editor.moveCursorDown()
expect(editorView.scrollTop()).toBe(0)
- editorView.moveCursorDown()
+ editor.moveCursorDown()
expect(editorView.scrollTop()).toBe(editorView.lineHeight)
- editorView.moveCursorDown()
+ editor.moveCursorDown()
expect(editorView.scrollTop()).toBe(editorView.lineHeight * 2)
- _.times 3, -> editorView.moveCursorUp()
+ _.times 3, -> editor.moveCursorUp()
- editorView.moveCursorUp()
+ editor.moveCursorUp()
expect(editorView.scrollTop()).toBe(editorView.lineHeight)
- editorView.moveCursorUp()
+ editor.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()
+ _.times 3, -> editor.moveCursorDown()
expect(editorView.scrollTop()).toBe(editorView.lineHeight)
- editorView.moveCursorUp()
+ editor.moveCursorUp()
expect(editorView.renderedLines.css('top')).toBe "0px"
describe "when the last cursor exceeds the right or left scroll margins", ->
@@ -1037,23 +1039,23 @@ describe "EditorView", ->
setEditorWidthInChars(editorView, 30)
# moving right
- editorView.setCursorScreenPosition([2, 24])
+ editor.setCursorScreenPosition([2, 24])
expect(editorView.scrollLeft()).toBe 0
- editorView.setCursorScreenPosition([2, 25])
+ editor.setCursorScreenPosition([2, 25])
expect(editorView.scrollLeft()).toBe charWidth
- editorView.setCursorScreenPosition([2, 28])
+ editor.setCursorScreenPosition([2, 28])
expect(editorView.scrollLeft()).toBe charWidth * 4
# moving left
- editorView.setCursorScreenPosition([2, 9])
+ editor.setCursorScreenPosition([2, 9])
expect(editorView.scrollLeft()).toBe charWidth * 4
- editorView.setCursorScreenPosition([2, 8])
+ editor.setCursorScreenPosition([2, 8])
expect(editorView.scrollLeft()).toBe charWidth * 3
- editorView.setCursorScreenPosition([2, 5])
+ editor.setCursorScreenPosition([2, 5])
expect(editorView.scrollLeft()).toBe 0
describe "when the editor view is narrower than twice the horizontal scroll margin", ->
@@ -1061,15 +1063,15 @@ describe "EditorView", ->
editorView.hScrollMargin = 6
setEditorWidthInChars(editorView, 7)
- editorView.setCursorScreenPosition([2, 3])
+ editor.setCursorScreenPosition([2, 3])
window.advanceClock()
expect(editorView.scrollLeft()).toBe(0)
- editorView.setCursorScreenPosition([2, 4])
+ editor.setCursorScreenPosition([2, 4])
window.advanceClock()
expect(editorView.scrollLeft()).toBe(charWidth)
- editorView.setCursorScreenPosition([2, 3])
+ editor.setCursorScreenPosition([2, 3])
window.advanceClock()
expect(editorView.scrollLeft()).toBe(0)
@@ -1081,23 +1083,23 @@ describe "EditorView", ->
editorView.width(charWidth * 30)
# moving right
- editorView.setCursorScreenPosition([2, 24])
+ editor.setCursorScreenPosition([2, 24])
expect(editorView.scrollLeft()).toBe 0
- editorView.setCursorScreenPosition([2, 25])
+ editor.setCursorScreenPosition([2, 25])
expect(editorView.scrollLeft()).toBe 0
- editorView.setCursorScreenPosition([2, 28])
+ editor.setCursorScreenPosition([2, 28])
expect(editorView.scrollLeft()).toBe 0
# moving left
- editorView.setCursorScreenPosition([2, 9])
+ editor.setCursorScreenPosition([2, 9])
expect(editorView.scrollLeft()).toBe 0
- editorView.setCursorScreenPosition([2, 8])
+ editor.setCursorScreenPosition([2, 8])
expect(editorView.scrollLeft()).toBe 0
- editorView.setCursorScreenPosition([2, 5])
+ editor.setCursorScreenPosition([2, 5])
expect(editorView.scrollLeft()).toBe 0
describe "when editor:toggle-soft-wrap is toggled", ->
@@ -1105,7 +1107,7 @@ describe "EditorView", ->
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.")
+ 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.")
editorView.scrollLeft(editorView.charWidth * 30)
editorView.trigger "editor:toggle-soft-wrap"
expect(editorView.scrollLeft()).toBe 0
@@ -1154,7 +1156,7 @@ describe "EditorView", ->
expect(line12.children('span:eq(1)')).toMatchSelector '.keyword'
it "wraps hard tabs in a span", ->
- editorView.setText('\t<- hard tab')
+ editor.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'
@@ -1169,7 +1171,7 @@ describe "EditorView", ->
describe "when the line has trailing whitespace", ->
it "wraps trailing whitespace in a span", ->
- editorView.setText('trailing whitespace -> ')
+ editor.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'
@@ -1206,25 +1208,25 @@ describe "EditorView", ->
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)
+ editor.insertText("1\n")
+ _.times 4, -> editor.moveCursorDown()
+ expect(editorView.renderedLines.find('.line:eq(2)').text()).toBe editor.lineForBufferRow(2)
+ expect(editorView.renderedLines.find('.line:eq(7)').text()).toBe editor.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)
+ editor.getBuffer().delete([[0,0],[1,0]])
+ expect(editorView.renderedLines.find('.line:eq(0)').text()).toBe editor.lineForBufferRow(0)
+ expect(editorView.renderedLines.find('.line:eq(5)').text()).toBe editor.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)
+ expect(editorView.renderedLines.find('.line:first').text()).toBe editor.lineForBufferRow(1)
+ expect(editorView.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 = editorView.scrollView.prop('scrollHeight')
- fold = editorView.createFold(1, 9)
+ fold = editor.createFold(1, 9)
fold.destroy()
expect(editorView.scrollView.prop('scrollHeight')).toBe scrollHeightBeforeFold
@@ -1240,8 +1242,8 @@ describe "EditorView", ->
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 = editor.createFold(1, 9)
+ editor.setCursorBufferPosition([10, 0])
fold.destroy()
expect(editorView.renderedLines.find('.line').length).toBe 8
@@ -1371,7 +1373,7 @@ describe "EditorView", ->
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()
+ maxLineLength = editor.getMaxScreenLineLength()
setEditorWidthInChars(editorView, maxLineLength)
widthBefore = editorView.renderedLines.width()
expect(widthBefore).toBe editorView.scrollView.width() + 20
@@ -1383,7 +1385,7 @@ describe "EditorView", ->
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()
+ maxLineLength = editor.getMaxScreenLineLength()
setEditorWidthInChars(editorView, maxLineLength)
buffer.change([[12,0], [12,0]], [1..maxLineLength*2].join(''))
expect(editorView.renderedLines.width()).toBeGreaterThan editorView.scrollView.width()
@@ -1431,8 +1433,8 @@ describe "EditorView", ->
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')
+ editor.setCursorScreenPosition([Infinity, Infinity])
+ editor.insertText('\n\n\n')
editorView.scrollToBottom()
expect(buffer.getLineCount()).toBe 16
@@ -1441,7 +1443,7 @@ describe "EditorView", ->
expect(editorView.firstRenderedScreenRow).toBe 9
expect(editorView.lastRenderedScreenRow).toBe 15
- editorView.backspace()
+ editor.backspace()
expect(editorView.scrollTop()).toBeLessThan initialScrollTop
expect(editorView.firstRenderedScreenRow).toBe 9
@@ -1449,13 +1451,13 @@ describe "EditorView", ->
expect(editorView.find('.line').length).toBe 6
- editorView.backspace()
+ editor.backspace()
expect(editorView.firstRenderedScreenRow).toBe 9
expect(editorView.lastRenderedScreenRow).toBe 13
expect(editorView.find('.line').length).toBe 5
- editorView.backspace()
+ editor.backspace()
expect(editorView.firstRenderedScreenRow).toBe 6
expect(editorView.lastRenderedScreenRow).toBe 12
@@ -1487,7 +1489,7 @@ describe "EditorView", ->
expect(editorView.renderedLines.find('.line').length).toBe 8
- editorView.moveCursorToBottom()
+ editor.moveCursorToBottom()
expect(editorView.renderedLines.find('.line').length).toBe 8
@@ -1499,7 +1501,7 @@ describe "EditorView", ->
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 "
+ editor.setText " a line with tabs\tand spaces "
editorView.attachToDom()
expect(atom.config.get("editor.showInvisibles")).toBeFalsy()
@@ -1520,18 +1522,18 @@ describe "EditorView", ->
it "displays newlines as their own token outside of the other tokens scope", ->
editorView.setShowInvisibles(true)
editorView.attachToDom()
- editorView.setText "var"
+ editor.setText "var"
expect(editorView.find('.line').html()).toBe 'var¬'
it "allows invisible glyphs to be customized via the editor.invisibles config", ->
- editorView.setText(" \t ")
+ editor.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"
+ editor.setText "a line that ends with a carriage return\r\n"
editorView.attachToDom()
expect(atom.config.get("editor.showInvisibles")).toBeFalsy()
@@ -1549,7 +1551,7 @@ describe "EditorView", ->
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"
+ editor.setText "a line that wraps"
editorView.attachToDom()
editorView.setWidthInChars(6)
atom.config.set "editor.showInvisibles", true
@@ -1561,7 +1563,7 @@ describe "EditorView", ->
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"
+ editor.setText "a line that\r\n"
editorView.attachToDom()
editorView.setWidthInChars(6)
atom.config.set "editor.showInvisibles", true
@@ -1628,8 +1630,8 @@ describe "EditorView", ->
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()
+ editor.setCursorBufferPosition([9])
+ editor.indentSelectedRows()
expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2
expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' '
@@ -1642,8 +1644,8 @@ describe "EditorView", ->
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()
+ editor.setCursorBufferPosition([11])
+ editor.indentSelectedRows()
expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2
expect(editorView.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' '
@@ -1653,10 +1655,10 @@ describe "EditorView", ->
editorView.attachToDom()
atom.config.set("editor.showIndentGuide", true)
- editorView.setCursorBufferPosition([10])
- editorView.indent()
- editorView.indent()
- expect(editorView.getCursorBufferPosition()).toEqual [10, 4]
+ editor.setCursorBufferPosition([10])
+ editor.indent()
+ editor.indent()
+ expect(editor.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 ' '
@@ -1664,9 +1666,9 @@ describe "EditorView", ->
editorView.attachToDom()
atom.config.set("editor.showIndentGuide", true)
- editorView.setCursorBufferPosition([1, Infinity])
- editorView.insertNewline()
- expect(editorView.getCursorBufferPosition()).toEqual [2, 0]
+ editor.setCursorBufferPosition([1, Infinity])
+ editor.insertNewline()
+ expect(editor.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 ' '
@@ -1675,7 +1677,7 @@ describe "EditorView", ->
editorView.attachToDom()
atom.config.set("editor.showIndentGuide", true)
- editorView.insertText("/*\n * \n*/")
+ editor.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')
@@ -1690,8 +1692,8 @@ describe "EditorView", ->
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()
+ editor.setCursorBufferPosition([9])
+ editor.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} "
@@ -1711,13 +1713,13 @@ describe "EditorView", ->
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)
+ editor.setCursorBufferPosition([3, 51], wrapAtSoftNewlines: true)
expect(editorView.find('.cursor').offset()).toEqual(editorView.renderedLines.find('.line:eq(4)').offset())
- editorView.setCursorBufferPosition([4, 0])
+ editor.setCursorBufferPosition([4, 0])
expect(editorView.find('.cursor').offset()).toEqual(editorView.renderedLines.find('.line:eq(5)').offset())
- editorView.getSelection().setBufferRange([[6, 30], [6, 55]])
+ editor.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)
@@ -1729,12 +1731,12 @@ describe "EditorView", ->
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])
+ editor.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]
+ expect(editor.bufferPositionForScreenPosition(editor.getCursorScreenPosition())).toEqual [3, 60]
it "does not wrap the lines of any newly assigned buffers", ->
otherEditor = atom.project.openSync()
@@ -1747,26 +1749,26 @@ describe "EditorView", ->
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]
+ _.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", ->
- editorView.setCursorScreenPosition([11, 15])
- editorView.moveCursorUp()
- expect(editorView.getCursorScreenPosition()).toEqual [10, 10]
- editorView.moveCursorUp()
- editorView.moveCursorUp()
- expect(editorView.getCursorScreenPosition()).toEqual [8, 15]
+ 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", ->
- editorView.setCursorScreenPosition([11, 0])
- editorView.moveCursorLeft()
- expect(editorView.getCursorScreenPosition()).toEqual [10, 10]
+ editor.setCursorScreenPosition([11, 0])
+ editor.moveCursorLeft()
+ expect(editor.getCursorScreenPosition()).toEqual [10, 10]
- editorView.moveCursorRight()
- expect(editorView.getCursorScreenPosition()).toEqual [11, 0]
+ editor.moveCursorRight()
+ expect(editor.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(editor: atom.project.openSync('sample.js'))
@@ -1842,7 +1844,7 @@ describe "EditorView", ->
describe "when there are folds", ->
it "skips line numbers covered by the fold and updates them when the fold changes", ->
- editorView.createFold(3, 5)
+ editor.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
@@ -1856,14 +1858,14 @@ describe "EditorView", ->
it "redraws gutter numbers when lines are unfolded", ->
setEditorHeightInLines(editorView, 20)
- fold = editorView.createFold(2, 12)
+ fold = editor.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)
+ editor.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
@@ -1914,7 +1916,7 @@ describe "EditorView", ->
it "doesn't highlight the only line", ->
miniEditor = new EditorView(mini: true)
miniEditor.attachToDom()
- expect(miniEditor.getCursorBufferPosition().row).toBe 0
+ expect(miniEditor.getEditor().getCursorBufferPosition().row).toBe 0
expect(miniEditor.find('.line.cursor-line').length).toBe 0
it "doesn't show the end of line invisible", ->
@@ -1925,26 +1927,26 @@ describe "EditorView", ->
expect(space).toBeTruthy()
tab = miniEditor.invisibles?.tab
expect(tab).toBeTruthy()
- miniEditor.setText(" a line with tabs\tand spaces ")
+ miniEditor.getEditor().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")
+ miniEditor.getEditor().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
+ miniEditor.getEditor().setText("var something")
+ previousTokens = miniEditor.getEditor().lineForScreenRow(0).tokens
+ miniEditor.getEditor().setGrammar(atom.syntax.selectGrammar('something.js'))
+ expect(miniEditor.getEditor().getGrammar().name).toBe "JavaScript"
+ expect(previousTokens).not.toEqual miniEditor.getEditor().lineForScreenRow(0).tokens
# doesn't allow regular editors to set grammars
- expect(-> editorView.setGrammar()).toThrow()
+ expect(-> editor.setGrammar()).toThrow()
describe "placeholderText", ->
it "is hidden and shown when appropriate", ->
@@ -1953,10 +1955,10 @@ describe "EditorView", ->
expect(miniEditor.underlayer.find('.placeholder-text')).toExist()
- miniEditor.setText("var something")
+ miniEditor.getEditor().setText("var something")
expect(miniEditor.underlayer.find('.placeholder-text')).not.toExist()
- miniEditor.setText("")
+ miniEditor.getEditor().setText("")
expect(miniEditor.underlayer.find('.placeholder-text')).toExist()
it "can be set", ->
@@ -2026,13 +2028,13 @@ describe "EditorView", ->
describe "when there is no wrapping", ->
it "highlights the line where the initial cursor position is", ->
- expect(editorView.getCursorBufferPosition().row).toBe 0
+ expect(editor.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
+ editor.setCursorBufferPosition([1,0])
+ expect(editor.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
@@ -2043,13 +2045,13 @@ describe "EditorView", ->
setEditorWidthInChars(editorView, 20)
it "highlights the line where the initial cursor position is", ->
- expect(editorView.getCursorBufferPosition().row).toBe 0
+ expect(editor.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
+ editor.setCursorBufferPosition([1,0])
+ expect(editor.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
@@ -2058,24 +2060,24 @@ describe "EditorView", ->
editorView.attachToDom(30)
it "highlights the foreground of the gutter", ->
- editorView.getSelection().setBufferRange([[0,0],[2,2]])
- expect(editorView.getSelection().isSingleScreenLine()).toBe false
+ editor.getSelection().setBufferRange([[0,0],[2,2]])
+ expect(editor.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
+ editor.getSelection().setBufferRange([[0,0],[2,0]])
+ expect(editor.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
+ editor.getSelection().setBufferRange([[0,0],[1,0]])
+ expect(editor.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()
+ editor.setCursorScreenPosition([1,0])
+ editor.backspace()
expect(editorView.find('.line-number.cursor-line').length).toBe 1
expect(editorView.find('.line-number.cursor-line').intValue()).toBe 1
@@ -2085,19 +2087,19 @@ describe "EditorView", ->
describe "when there is no wrapping", ->
it "highlights the line where the initial cursor position is", ->
- expect(editorView.getCursorBufferPosition().row).toBe 0
+ expect(editor.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
+ editor.setCursorBufferPosition([1,0])
+ expect(editor.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()
+ editor.setCursorScreenPosition([1,0])
+ editor.backspace()
expect(editorView.find('.line.cursor-line').length).toBe 1
describe "when there is wrapping", ->
@@ -2106,19 +2108,19 @@ describe "EditorView", ->
setEditorWidthInChars(editorView, 20)
it "highlights the line where the initial cursor position is", ->
- expect(editorView.getCursorBufferPosition().row).toBe 0
+ expect(editor.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
+ editor.setCursorBufferPosition([1,0])
+ expect(editor.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]])
+ editor.setSelectedBufferRange([[1, 0], [1, 1]])
expect(editorView.find('.line.cursor-line').length).toBe 0
describe "folding", ->
@@ -2130,25 +2132,25 @@ describe "EditorView", ->
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]])
+ editor.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]
+ expect(editor.getSelection().isEmpty()).toBeTruthy()
+ expect(editor.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]])
+ editor.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])
+ editor.setCursorBufferPosition([3,0])
editor.createFold(3, 5)
foldLine = editorView.find('.line.fold')
@@ -2160,43 +2162,43 @@ describe "EditorView", ->
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]
+ 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", ->
- editorView.setCursorBufferPosition([3,0])
+ editor.setCursorBufferPosition([3,0])
editorView.trigger 'editor:fold-current-row'
- editorView.setCursorBufferPosition([3,0])
+ editor.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]
+ 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", ->
- editorView.createFold(2, 4)
+ editor.createFold(2, 4)
- editorView.setSelectedBufferRange([[1, 0], [2, 0]], preserveFolds: true, isReversed: true)
+ editor.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)
+ editor.setSelectedBufferRange([[1, 0], [1, 1]], preserveFolds: true)
expect(editorView.lineElementForScreenRow(2)).not.toMatchSelector('.fold.fold-selected')
- editorView.setSelectedBufferRange([[1, 0], [5, 0]], preserveFolds: true)
+ editor.setSelectedBufferRange([[1, 0], [5, 0]], preserveFolds: true)
expect(editorView.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected')
- editorView.setCursorScreenPosition([3,0])
+ editor.setCursorScreenPosition([3,0])
expect(editorView.lineElementForScreenRow(2)).not.toMatchSelector('.fold.fold-selected')
- editorView.setCursorScreenPosition([2,0])
+ editor.setCursorScreenPosition([2,0])
expect(editorView.lineElementForScreenRow(2)).toMatchSelector('.fold.fold-selected')
expect(editorView.find('.cursor')).toBeHidden()
- editorView.setCursorScreenPosition([3,0])
+ editor.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)", ->
@@ -2204,8 +2206,8 @@ describe "EditorView", ->
setEditorHeightInLines(editorView, 5)
editorView.resetDisplay()
- editorView.createFold(2, 4)
- editorView.setSelectedBufferRange([[1, 0], [5, 0]], preserveFolds: true)
+ editor.createFold(2, 4)
+ editor.setSelectedBufferRange([[1, 0], [5, 0]], preserveFolds: true)
expect(editorView.renderedLines.find('.fold.fold-selected')).toExist()
editorView.scrollToBottom()
@@ -2219,13 +2221,13 @@ describe "EditorView", ->
editorView.attachToDom()
it "moves to the last line when page down is repeated from the first line", ->
- rows = editorView.getLineCount() - 1
+ rows = editor.getLineCount() - 1
expect(rows).toBeGreaterThan(0)
- row = editorView.getCursor().getScreenPosition().row
+ row = editor.getCursor().getScreenPosition().row
expect(row).toBe(0)
while row < rows
editorView.pageDown()
- newRow = editorView.getCursor().getScreenPosition().row
+ newRow = editor.getCursor().getScreenPosition().row
expect(newRow).toBeGreaterThan(row)
if (newRow <= row)
break
@@ -2234,12 +2236,12 @@ describe "EditorView", ->
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
+ editor.moveCursorToBottom()
+ row = editor.getCursor().getScreenPosition().row
expect(row).toBeGreaterThan(0)
while row > 0
editorView.pageUp()
- newRow = editorView.getCursor().getScreenPosition().row
+ newRow = editor.getCursor().getScreenPosition().row
expect(newRow).toBeLessThan(row)
if (newRow >= row)
break
@@ -2248,11 +2250,11 @@ describe "EditorView", ->
expect(editorView.getFirstVisibleScreenRow()).toBe(0)
it "resets to original position when down is followed by up", ->
- expect(editorView.getCursor().getScreenPosition().row).toBe(0)
+ expect(editor.getCursor().getScreenPosition().row).toBe(0)
editorView.pageDown()
- expect(editorView.getCursor().getScreenPosition().row).toBeGreaterThan(0)
+ expect(editor.getCursor().getScreenPosition().row).toBeGreaterThan(0)
editorView.pageUp()
- expect(editorView.getCursor().getScreenPosition().row).toBe(0)
+ expect(editor.getCursor().getScreenPosition().row).toBe(0)
expect(editorView.getFirstVisibleScreenRow()).toBe(0)
describe ".checkoutHead()", ->
@@ -2261,17 +2263,18 @@ describe "EditorView", ->
beforeEach ->
filePath = atom.project.resolve('git/working-dir/file.txt')
originalPathText = fs.readFileSync(filePath, 'utf8')
- editorView.edit(atom.project.openSync(filePath))
+ editor = atom.project.openSync(filePath)
+ editorView.edit(editor)
afterEach ->
fs.writeFileSync(filePath, originalPathText)
it "restores the contents of the editor view to the HEAD revision", ->
- editorView.setText('')
- editorView.getBuffer().save()
+ editor.setText('')
+ editor.save()
fileChangeHandler = jasmine.createSpy('fileChange')
- editorView.getBuffer().file.on 'contents-changed', fileChangeHandler
+ editor.getBuffer().file.on 'contents-changed', fileChangeHandler
editorView.checkoutHead()
@@ -2279,7 +2282,7 @@ describe "EditorView", ->
fileChangeHandler.callCount > 0
runs ->
- expect(editorView.getText()).toBe(originalPathText)
+ expect(editor.getText()).toBe(originalPathText)
describe ".pixelPositionForBufferPosition(position)", ->
describe "when the editor view is detached", ->
@@ -2316,22 +2319,22 @@ describe "EditorView", ->
describe "when single clicking", ->
it "moves the cursor to the start of the selected line", ->
- expect(editorView.getCursorScreenPosition()).toEqual [0,0]
+ expect(editor.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]
+ expect(editor.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]]
+ expect(editor.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]]
+ 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", ->
@@ -2348,7 +2351,7 @@ describe "EditorView", ->
$(document).trigger 'mouseup'
- expect(editorView.getSelection().getScreenRange()).toEqual [[1,0], [6,0]]
+ expect(editor.getSelection().getScreenRange()).toEqual [[1,0], [6,0]]
describe "when selecting from bottom to top", ->
it "selects the lines", ->
@@ -2364,24 +2367,25 @@ describe "EditorView", ->
$(document).trigger 'mouseup'
- expect(editorView.getSelection().getScreenRange()).toEqual [[1,0], [6,0]]
+ expect(editor.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]
+ expect(editor.getCursorScreenPosition()).toEqual [0,0]
event = mousedownEvent(editorView: editorView, point: [Infinity, 10])
editorView.underlayer.trigger event
- expect(editorView.getCursorScreenPosition()).toEqual [12,2]
+ expect(editor.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]]
+ expect(editor.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]]
+ expect(editor.getSelection().getScreenRange()).toEqual [[0,0], [12,2]]
+ # TODO: Move to editor-spec
describe ".reloadGrammar()", ->
[filePath] = []
@@ -2394,11 +2398,12 @@ describe "EditorView", ->
fs.removeSync(filePath) if fs.existsSync(filePath)
it "updates all the rendered lines when the grammar changes", ->
- editorView.edit(atom.project.openSync(filePath))
- expect(editorView.getGrammar().name).toBe 'Plain Text'
+ editor = atom.project.openSync(filePath)
+ editorView.edit(editor)
+ expect(editor.getGrammar().name).toBe 'Plain Text'
atom.syntax.setGrammarOverrideForPath(filePath, 'source.js')
- editorView.reloadGrammar()
- expect(editorView.getGrammar().name).toBe 'JavaScript'
+ editor.reloadGrammar()
+ expect(editor.getGrammar().name).toBe 'JavaScript'
tokenizedBuffer = editorView.editor.displayBuffer.tokenizedBuffer
line0 = tokenizedBuffer.lineForScreenRow(0)
@@ -2406,24 +2411,25 @@ describe "EditorView", ->
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'
+ expect(editor.getGrammar().name).toBe 'JavaScript'
spyOn(editorView, 'updateDisplay').andCallThrough()
- editorView.reloadGrammar()
- expect(editorView.reloadGrammar()).toBeFalsy()
+ editor.reloadGrammar()
+ expect(editor.reloadGrammar()).toBeFalsy()
expect(editorView.updateDisplay).not.toHaveBeenCalled()
- expect(editorView.getGrammar().name).toBe 'JavaScript'
+ expect(editor.getGrammar().name).toBe 'JavaScript'
it "emits an editor:grammar-changed event when updated", ->
- editorView.edit(atom.project.openSync(filePath))
+ editor = atom.project.openSync(filePath)
+ editorView.edit(editor)
eventHandler = jasmine.createSpy('eventHandler')
editorView.on('editor:grammar-changed', eventHandler)
- editorView.reloadGrammar()
+ editor.reloadGrammar()
expect(eventHandler).not.toHaveBeenCalled()
atom.syntax.setGrammarOverrideForPath(filePath, 'source.js')
- editorView.reloadGrammar()
+ editor.reloadGrammar()
expect(eventHandler).toHaveBeenCalled()
describe ".replaceSelectedText()", ->
@@ -2434,7 +2440,7 @@ describe "EditorView", ->
replaced = true
'new'
- editorView.moveCursorToTop()
+ editor.moveCursorToTop()
edited = editorView.replaceSelectedText(replacer)
expect(replaced).toBe false
expect(edited).toBe false
@@ -2446,8 +2452,8 @@ describe "EditorView", ->
replaced = true
'new'
- editorView.moveCursorToTop()
- editorView.selectToEndOfLine()
+ editor.moveCursorToTop()
+ editor.selectToEndOfLine()
edited = editorView.replaceSelectedText(replacer)
expect(replaced).toBe true
expect(edited).toBe true
@@ -2459,8 +2465,8 @@ describe "EditorView", ->
replaced = true
null
- editorView.moveCursorToTop()
- editorView.selectToEndOfLine()
+ editor.moveCursorToTop()
+ editor.selectToEndOfLine()
edited = editorView.replaceSelectedText(replacer)
expect(replaced).toBe true
expect(edited).toBe false
@@ -2472,8 +2478,8 @@ describe "EditorView", ->
replaced = true
undefined
- editorView.moveCursorToTop()
- editorView.selectToEndOfLine()
+ editor.moveCursorToTop()
+ editor.selectToEndOfLine()
edited = editorView.replaceSelectedText(replacer)
expect(replaced).toBe true
expect(edited).toBe false
@@ -2481,33 +2487,33 @@ describe "EditorView", ->
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()
+ 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", ->
- editorView.setCursorBufferPosition([1,0])
+ editor.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])
+ editor.setCursorBufferPosition([1,2])
editorView.trigger 'editor:move-line-up'
- expect(editorView.getCursorBufferPosition()).toEqual [0,2]
+ expect(editor.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'
+ editor.setSelectedBufferRange([[1, 2], [1, 5]])
+ expect(editor.getSelectedText()).toBe 'var'
editorView.trigger 'editor:move-line-up'
- expect(editorView.getSelectedBufferRange()).toEqual [[0, 2], [0, 5]]
- expect(editorView.getSelectedText()).toBe 'var'
+ 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", ->
- editorView.setSelectedBufferRange([[2, 0], [3, Infinity]])
+ editor.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;'
@@ -2515,20 +2521,20 @@ describe "EditorView", ->
expect(buffer.lineForRow(3)).toBe ' var sort = function(items) {'
it "maintains the selection", ->
- editorView.setSelectedBufferRange([[2, 0], [3, 62]])
+ editor.setSelectedBufferRange([[2, 0], [3, 62]])
editorView.trigger 'editor:move-line-up'
- expect(editorView.getSelectedBufferRange()).toEqual [[1, 0], [2, 62]]
+ expect(editor.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]])
+ editor.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]])
+ editor.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 '};'
@@ -2536,48 +2542,48 @@ describe "EditorView", ->
describe "when the cursor is on the first line", ->
it "does not move the line", ->
- editorView.setCursorBufferPosition([0,0])
- originalText = editorView.getText()
+ editor.setCursorBufferPosition([0,0])
+ originalText = editor.getText()
editorView.trigger 'editor:move-line-up'
- expect(editorView.getText()).toBe originalText
+ expect(editor.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()
+ editor.moveCursorToBottom()
+ editor.insertNewline()
+ editor.moveCursorToBottom()
+ originalText = editor.getText()
editorView.trigger 'editor:move-line-up'
- expect(editorView.getText()).toBe originalText
+ 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", ->
- editorView.setCursorBufferPosition([4, 0])
- editorView.foldCurrentRow()
+ editor.setCursorBufferPosition([4, 0])
+ editor.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()
+ 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", ->
- editorView.setCursorBufferPosition([4, 0])
- editorView.foldCurrentRow()
- editorView.setCursorBufferPosition([3, 4])
- editorView.selectDown()
- expect(editorView.isFoldedAtScreenRow(4)).toBeTruthy()
+ editor.setCursorBufferPosition([4, 0])
+ editor.foldCurrentRow()
+ editor.setCursorBufferPosition([3, 4])
+ editor.selectDown()
+ expect(editor.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()
+ 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", ->
- editorView.setCursorBufferPosition([1])
- editorView.selectToEndOfLine()
- editorView.selectRight()
+ editor.setCursorBufferPosition([1])
+ editor.selectToEndOfLine()
+ editor.selectRight()
editorView.trigger 'editor:move-line-up'
expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {'
expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {'
@@ -2585,26 +2591,26 @@ describe "EditorView", ->
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])
+ editor.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])
+ editor.setCursorBufferPosition([0, 2])
editorView.trigger 'editor:move-line-down'
- expect(editorView.getCursorBufferPosition()).toEqual [1, 2]
+ expect(editor.getCursorBufferPosition()).toEqual [1, 2]
describe "when the cursor is on the last line", ->
it "does not move the line", ->
- editorView.moveCursorToBottom()
+ editor.moveCursorToBottom()
editorView.trigger 'editor:move-line-down'
expect(buffer.lineForRow(12)).toBe '};'
- expect(editorView.getSelectedBufferRange()).toEqual [[12, 2], [12, 2]]
+ expect(editor.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])
+ editor.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));'
@@ -2612,26 +2618,26 @@ describe "EditorView", ->
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])
+ editor.moveCursorToBottom()
+ editor.insertNewline()
+ editor.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]]
+ 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", ->
- editorView.setSelectedBufferRange([[1, 2], [1, 5]])
- expect(editorView.getSelectedText()).toBe 'var'
+ editor.setSelectedBufferRange([[1, 2], [1, 5]])
+ expect(editor.getSelectedText()).toBe 'var'
editorView.trigger 'editor:move-line-down'
- expect(editorView.getSelectedBufferRange()).toEqual [[2, 2], [2, 5]]
- expect(editorView.getSelectedText()).toBe 'var'
+ 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", ->
- editorView.setSelectedBufferRange([[2, 0], [3, Infinity]])
+ editor.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;'
@@ -2639,39 +2645,39 @@ describe "EditorView", ->
expect(buffer.lineForRow(5)).toBe ' current = items.shift();'
it "maintains the selection", ->
- editorView.setSelectedBufferRange([[2, 0], [3, 62]])
+ editor.setSelectedBufferRange([[2, 0], [3, 62]])
editorView.trigger 'editor:move-line-down'
- expect(editorView.getSelectedBufferRange()).toEqual [[3, 0], [4, 62]]
+ 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", ->
- editorView.setCursorBufferPosition([4, 0])
- editorView.foldCurrentRow()
+ editor.setCursorBufferPosition([4, 0])
+ editor.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()
+ 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", ->
- editorView.setCursorBufferPosition([4, 0])
- editorView.foldCurrentRow()
- editorView.setCursorBufferPosition([3, 4])
- editorView.selectDown()
- expect(editorView.isFoldedAtScreenRow(4)).toBeTruthy()
+ editor.setCursorBufferPosition([4, 0])
+ editor.foldCurrentRow()
+ editor.setCursorBufferPosition([3, 4])
+ editor.selectDown()
+ expect(editor.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()
+ 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", ->
- editorView.setCursorBufferPosition([1])
- editorView.selectToEndOfLine()
- editorView.selectRight()
+ editor.setCursorBufferPosition([1])
+ editor.selectToEndOfLine()
+ editor.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) {'
@@ -2680,20 +2686,20 @@ describe "EditorView", ->
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])
+ editor.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]
+ 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", ->
- editorView.setCursorBufferPosition([4])
- editorView.foldCurrentRow()
+ editor.setCursorBufferPosition([4])
+ editor.foldCurrentRow()
editorView.trigger 'editor:duplicate-line'
- expect(editorView.getCursorScreenPosition()).toEqual [5]
- expect(editorView.isFoldedAtScreenRow(4)).toBeTruthy()
- expect(editorView.isFoldedAtScreenRow(5)).toBeTruthy()
+ 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);'
@@ -2701,39 +2707,39 @@ describe "EditorView", ->
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()
+ editor.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]
+ 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", ->
- editorView.moveCursorToBottom()
- editorView.insertNewline()
- editorView.moveCursorToBottom()
+ editor.moveCursorToBottom()
+ editor.insertNewline()
+ editor.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]
+ 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", ->
- editorView.moveCursorToBottom()
- editorView.insertNewline()
- editorView.setCursorBufferPosition([12])
+ editor.moveCursorToBottom()
+ editor.insertNewline()
+ editor.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]
+ expect(editor.getCursorBufferPosition()).toEqual [13, 0]
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", ->
- atom.keymap.bindKeys 'name', '.editor', 'escape': 'test-event'
+ atom.keymap.bindKeys 'name', '.editor', {'escape': 'test-event'}
testEventHandler = jasmine.createSpy("testEventHandler")
editorView.on 'test-event', testEventHandler
@@ -2759,8 +2765,8 @@ describe "EditorView", ->
editorView.getPane().activateItem(view)
expect(editorView.isVisible()).toBeFalsy()
- editorView.setText('hidden changes')
- editorView.setCursorBufferPosition([0,4])
+ editor.setText('hidden changes')
+ editor.setCursorBufferPosition([0,4])
displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler")
editorView.on 'editor:display-updated', displayUpdatedHandler
@@ -2776,8 +2782,8 @@ describe "EditorView", ->
it "redraws the editor view when it is next reattached", ->
editorView.attachToDom()
editorView.hide()
- editorView.setText('hidden changes')
- editorView.setCursorBufferPosition([0,4])
+ editor.setText('hidden changes')
+ editor.setCursorBufferPosition([0,4])
editorView.detach()
displayUpdatedHandler = jasmine.createSpy("displayUpdatedHandler")
@@ -2794,7 +2800,7 @@ describe "EditorView", ->
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])
+ editor.setCursorBufferPosition([1, 2])
editorView.scrollToBottom()
expect(editorView.getFirstVisibleScreenRow()).not.toBe 0
expect(editorView.getLastVisibleScreenRow()).not.toBe 2
@@ -2817,10 +2823,10 @@ describe "EditorView", ->
describe "when setInvisibles is toggled (regression)", ->
it "renders inserted newlines properly", ->
editorView.setShowInvisibles(true)
- editorView.setCursorBufferPosition([0, 0])
+ editor.setCursorBufferPosition([0, 0])
editorView.attachToDom(heightInLines: 20)
editorView.setShowInvisibles(false)
- editorView.insertText("\n")
+ editor.insertText("\n")
for rowNumber in [1..5]
expect(editorView.lineElementForScreenRow(rowNumber).text()).toBe buffer.lineForRow(rowNumber)
@@ -2838,7 +2844,7 @@ describe "EditorView", ->
describe "when soft wrap is enabled", ->
it "correctly calculates the the position left for a column", ->
editor.setSoftWrap(true)
- editorView.setText('lllll 00000')
+ editor.setText('lllll 00000')
editorView.setFontFamily('serif')
editorView.setFontSize(10)
editorView.attachToDom()
@@ -2855,7 +2861,7 @@ describe "EditorView", ->
describe "when the editor contains hard tabs", ->
it "correctly calculates the the position left for a column", ->
- editorView.setText('\ttest')
+ editor.setText('\ttest')
editorView.attachToDom()
expect(editorView.pixelPositionForScreenPosition([0, editor.getTabLength()]).left).toEqual 20
diff --git a/spec/jasmine-helper.coffee b/spec/jasmine-helper.coffee
index c57a5dc37..5ff4ee868 100644
--- a/spec/jasmine-helper.coffee
+++ b/spec/jasmine-helper.coffee
@@ -4,8 +4,7 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
{$, $$} = require 'atom'
window[key] = value for key, value of require '../vendor/jasmine'
- require 'jasmine-focused'
- require 'jasmine-tagged'
+ {TerminalReporter} = require 'jasmine-tagged'
TimeReporter = require './time-reporter'
timeReporter = new TimeReporter()
@@ -18,8 +17,7 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
process.stderr.write(str)
if atom.getLoadSettings().exitWhenDone
- {jasmineNode} = require 'jasmine-node/lib/jasmine-node/reporter'
- reporter = new jasmineNode.TerminalReporter
+ reporter = new TerminalReporter
print: (str) ->
log(str)
onComplete: (runner) ->
diff --git a/spec/pane-container-model-spec.coffee b/spec/pane-container-spec.coffee
similarity index 100%
rename from spec/pane-container-model-spec.coffee
rename to spec/pane-container-spec.coffee
diff --git a/spec/pane-container-view-spec.coffee b/spec/pane-container-view-spec.coffee
index fa0bcb83d..c68180c1d 100644
--- a/spec/pane-container-view-spec.coffee
+++ b/spec/pane-container-view-spec.coffee
@@ -42,7 +42,7 @@ describe "PaneContainerView", ->
describe ".focusPreviousPane()", ->
it "focuses the pane preceding the focused pane or the last pane if no pane has focus", ->
container.attachToDom()
- $(document.body).focus() # clear focus
+ container.getPanes()[0].focus() # activate first pane
container.focusPreviousPane()
expect(pane3.activeItem).toMatchSelector ':focus'
@@ -121,7 +121,7 @@ describe "PaneContainerView", ->
describe "serialization", ->
it "can be serialized and deserialized, and correctly adjusts dimensions of deserialized panes after attach", ->
- newContainer = atom.deserializers.deserialize(container.serialize())
+ newContainer = new PaneContainerView(container.model.testSerialization())
expect(newContainer.find('.pane-row > :contains(1)')).toExist()
expect(newContainer.find('.pane-row > .pane-column > :contains(2)')).toExist()
expect(newContainer.find('.pane-row > .pane-column > :contains(3)')).toExist()
@@ -133,7 +133,7 @@ describe "PaneContainerView", ->
it "removes empty panes on deserialization", ->
# only deserialize pane 1's view successfully
TestView.deserialize = ({name}) -> new TestView(name) if name is '1'
- newContainer = atom.deserializers.deserialize(container.serialize())
+ newContainer = new PaneContainerView(container.model.testSerialization())
expect(newContainer.find('.pane-row, .pane-column')).not.toExist()
expect(newContainer.find('> :contains(1)')).toExist()
diff --git a/spec/pane-model-spec.coffee b/spec/pane-model-spec.coffee
deleted file mode 100644
index 0c15683a4..000000000
--- a/spec/pane-model-spec.coffee
+++ /dev/null
@@ -1,134 +0,0 @@
-{Model} = require 'theorist'
-Pane = require '../src/pane'
-PaneAxis = require '../src/pane-axis'
-PaneContainer = require '../src/pane-container'
-
-describe "Pane", ->
- describe "split methods", ->
- [pane1, container] = []
-
- beforeEach ->
- pane1 = new Pane(items: ["A"])
- container = new PaneContainer(root: pane1)
-
- describe "::splitLeft(params)", ->
- describe "when the parent is the container root", ->
- it "replaces itself with a row and inserts a new pane to the left of itself", ->
- pane2 = pane1.splitLeft(items: ["B"])
- pane3 = pane1.splitLeft(items: ["C"])
- expect(container.root.orientation).toBe 'horizontal'
- expect(container.root.children).toEqual [pane2, pane3, pane1]
-
- describe "when the parent is a column", ->
- it "replaces itself with a row and inserts a new pane to the left of itself", ->
- pane1.splitDown()
- pane2 = pane1.splitLeft(items: ["B"])
- pane3 = pane1.splitLeft(items: ["C"])
- row = container.root.children[0]
- expect(row.orientation).toBe 'horizontal'
- expect(row.children).toEqual [pane2, pane3, pane1]
-
- describe "::splitRight(params)", ->
- describe "when the parent is the container root", ->
- it "replaces itself with a row and inserts a new pane to the right of itself", ->
- pane2 = pane1.splitRight(items: ["B"])
- pane3 = pane1.splitRight(items: ["C"])
- expect(container.root.orientation).toBe 'horizontal'
- expect(container.root.children).toEqual [pane1, pane3, pane2]
-
- describe "when the parent is a column", ->
- it "replaces itself with a row and inserts a new pane to the right of itself", ->
- pane1.splitDown()
- pane2 = pane1.splitRight(items: ["B"])
- pane3 = pane1.splitRight(items: ["C"])
- row = container.root.children[0]
- expect(row.orientation).toBe 'horizontal'
- expect(row.children).toEqual [pane1, pane3, pane2]
-
- describe "::splitUp(params)", ->
- describe "when the parent is the container root", ->
- it "replaces itself with a column and inserts a new pane above itself", ->
- pane2 = pane1.splitUp(items: ["B"])
- pane3 = pane1.splitUp(items: ["C"])
- expect(container.root.orientation).toBe 'vertical'
- expect(container.root.children).toEqual [pane2, pane3, pane1]
-
- describe "when the parent is a row", ->
- it "replaces itself with a column and inserts a new pane above itself", ->
- pane1.splitRight()
- pane2 = pane1.splitUp(items: ["B"])
- pane3 = pane1.splitUp(items: ["C"])
- column = container.root.children[0]
- expect(column.orientation).toBe 'vertical'
- expect(column.children).toEqual [pane2, pane3, pane1]
-
- describe "::splitDown(params)", ->
- describe "when the parent is the container root", ->
- it "replaces itself with a column and inserts a new pane below itself", ->
- pane2 = pane1.splitDown(items: ["B"])
- pane3 = pane1.splitDown(items: ["C"])
- expect(container.root.orientation).toBe 'vertical'
- expect(container.root.children).toEqual [pane1, pane3, pane2]
-
- describe "when the parent is a row", ->
- it "replaces itself with a column and inserts a new pane below itself", ->
- pane1.splitRight()
- pane2 = pane1.splitDown(items: ["B"])
- pane3 = pane1.splitDown(items: ["C"])
- column = container.root.children[0]
- expect(column.orientation).toBe 'vertical'
- expect(column.children).toEqual [pane1, pane3, pane2]
-
- it "sets up the new pane to be focused", ->
- expect(pane1.focused).toBe false
- pane2 = pane1.splitRight()
- expect(pane2.focused).toBe true
-
- describe "::destroyItem(item)", ->
- describe "when the last item is destroyed", ->
- it "destroys the pane", ->
- pane = new Pane(items: ["A", "B"])
- pane.destroyItem("A")
- pane.destroyItem("B")
- expect(pane.isDestroyed()).toBe true
-
- describe "when an item emits a destroyed event", ->
- it "removes it from the list of items", ->
- pane = new Pane(items: [new Model, new Model, new Model])
- [item1, item2, item3] = pane.items
- pane.items[1].destroy()
- expect(pane.items).toEqual [item1, item3]
-
- describe "::destroy()", ->
- [pane1, container] = []
-
- beforeEach ->
- pane1 = new Pane(items: [new Model, new Model])
- container = new PaneContainer(root: pane1)
-
- it "destroys the pane's destroyable items", ->
- [item1, item2] = pane1.items
- pane1.destroy()
- expect(item1.isDestroyed()).toBe true
- expect(item2.isDestroyed()).toBe true
-
- describe "if the pane's parent has more than two children", ->
- it "removes the pane from its parent", ->
- pane2 = pane1.splitRight()
- pane3 = pane2.splitRight()
-
- expect(container.root.children).toEqual [pane1, pane2, pane3]
- pane2.destroy()
- expect(container.root.children).toEqual [pane1, pane3]
-
- describe "if the pane's parent has two children", ->
- it "replaces the parent with its last remaining child", ->
- pane2 = pane1.splitRight()
- pane3 = pane2.splitDown()
-
- expect(container.root.children[0]).toBe pane1
- expect(container.root.children[1].children).toEqual [pane2, pane3]
- pane3.destroy()
- expect(container.root.children).toEqual [pane1, pane2]
- pane2.destroy()
- expect(container.root).toBe pane1
diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee
new file mode 100644
index 000000000..71c6606ac
--- /dev/null
+++ b/spec/pane-spec.coffee
@@ -0,0 +1,437 @@
+{Model} = require 'theorist'
+Pane = require '../src/pane'
+PaneAxis = require '../src/pane-axis'
+PaneContainer = require '../src/pane-container'
+
+describe "Pane", ->
+ class Item extends Model
+ @deserialize: ({name, uri}) -> new this(name, uri)
+ constructor: (@name, @uri) ->
+ getUri: -> @uri
+ getPath: -> @path
+ serialize: -> {deserializer: 'Item', @name, @uri}
+ isEqual: (other) -> @name is other?.name
+
+ beforeEach ->
+ atom.deserializers.add(Item)
+
+ afterEach ->
+ atom.deserializers.remove(Item)
+
+ describe "construction", ->
+ it "sets the active item to the first item", ->
+ pane = new Pane(items: [new Item("A"), new Item("B")])
+ expect(pane.activeItem).toBe pane.items[0]
+
+ describe "::activateItem(item)", ->
+ pane = null
+
+ beforeEach ->
+ pane = new Pane(items: [new Item("A"), new Item("B")])
+
+ it "changes the active item to the current item", ->
+ expect(pane.activeItem).toBe pane.items[0]
+ pane.activateItem(pane.items[1])
+ expect(pane.activeItem).toBe pane.items[1]
+
+ it "adds the given item if it isn't present in ::items", ->
+ item = new Item("C")
+ pane.activateItem(item)
+ expect(item in pane.items).toBe true
+ expect(pane.activeItem).toBe item
+
+ describe "::activateNextItem() and ::activatePreviousItem()", ->
+ it "sets the active item to the next/previous item, looping around at either end", ->
+ pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")])
+ [item1, item2, item3] = pane.items
+
+ expect(pane.activeItem).toBe item1
+ pane.activatePreviousItem()
+ expect(pane.activeItem).toBe item3
+ pane.activatePreviousItem()
+ expect(pane.activeItem).toBe item2
+ pane.activateNextItem()
+ expect(pane.activeItem).toBe item3
+ pane.activateNextItem()
+ expect(pane.activeItem).toBe item1
+
+ describe "::activateItemAtIndex(index)", ->
+ it "activates the item at the given index", ->
+ pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")])
+ [item1, item2, item3] = pane.items
+ pane.activateItemAtIndex(2)
+ expect(pane.activeItem).toBe item3
+ pane.activateItemAtIndex(1)
+ expect(pane.activeItem).toBe item2
+ pane.activateItemAtIndex(0)
+ expect(pane.activeItem).toBe item1
+
+ # Doesn't fail with out-of-bounds indices
+ pane.activateItemAtIndex(100)
+ expect(pane.activeItem).toBe item1
+ pane.activateItemAtIndex(-1)
+ expect(pane.activeItem).toBe item1
+
+ describe "::destroyItem(item)", ->
+ [pane, item1, item2, item3] = []
+
+ beforeEach ->
+ pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")])
+ [item1, item2, item3] = pane.items
+
+ it "removes the item from the items list and activates the next item if it was the active item", ->
+ expect(pane.activeItem).toBe item1
+ pane.destroyItem(item2)
+ expect(item2 in pane.items).toBe false
+ expect(pane.activeItem).toBe item1
+
+ pane.destroyItem(item1)
+ expect(item1 in pane.items).toBe false
+ expect(pane.activeItem).toBe item3
+
+ it "emits 'item-removed' with the item, its index, and true indicating the item is being destroyed", ->
+ pane.on 'item-removed', itemRemovedHandler = jasmine.createSpy("itemRemovedHandler")
+ pane.destroyItem(item2)
+ expect(itemRemovedHandler).toHaveBeenCalledWith(item2, 1, true)
+
+ describe "if the item is modified", ->
+ itemUri = null
+
+ beforeEach ->
+ item1.shouldPromptToSave = -> true
+ item1.save = jasmine.createSpy("save")
+ item1.saveAs = jasmine.createSpy("saveAs")
+ item1.getUri = -> itemUri
+
+ describe "if the [Save] option is selected", ->
+ describe "when the item has a uri", ->
+ it "saves the item before destroying it", ->
+ itemUri = "test"
+ spyOn(atom, 'confirm').andReturn(0)
+ pane.destroyItem(item1)
+
+ expect(item1.save).toHaveBeenCalled()
+ expect(item1 in pane.items).toBe false
+ expect(item1.isDestroyed()).toBe true
+
+ 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", ->
+ itemUri = null
+
+ spyOn(atom, 'showSaveDialogSync').andReturn("/selected/path")
+ spyOn(atom, 'confirm').andReturn(0)
+ pane.destroyItem(item1)
+
+ expect(atom.showSaveDialogSync).toHaveBeenCalled()
+ expect(item1.saveAs).toHaveBeenCalledWith("/selected/path")
+ expect(item1 in pane.items).toBe false
+ expect(item1.isDestroyed()).toBe true
+
+ describe "if the [Don't Save] option is selected", ->
+ it "removes and destroys the item without saving it", ->
+ spyOn(atom, 'confirm').andReturn(2)
+ pane.destroyItem(item1)
+
+ expect(item1.save).not.toHaveBeenCalled()
+ expect(item1 in pane.items).toBe false
+ expect(item1.isDestroyed()).toBe true
+
+ describe "if the [Cancel] option is selected", ->
+ it "does not save, remove, or destroy the item", ->
+ spyOn(atom, 'confirm').andReturn(1)
+ pane.destroyItem(item1)
+
+ expect(item1.save).not.toHaveBeenCalled()
+ expect(item1 in pane.items).toBe true
+ expect(item1.isDestroyed()).toBe false
+
+ describe "when the last item is destroyed", ->
+ it "destroys the pane", ->
+ pane.destroyItem(item) for item in pane.getItems()
+ expect(pane.isDestroyed()).toBe true
+
+ describe "::destroyItems()", ->
+ it "destroys all items and the pane", ->
+ pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")])
+ [item1, item2, item3] = pane.items
+ pane.destroyItems()
+ expect(item1.isDestroyed()).toBe true
+ expect(item2.isDestroyed()).toBe true
+ expect(item3.isDestroyed()).toBe true
+ expect(pane.isDestroyed()).toBe true
+ expect(pane.items).toEqual []
+
+ describe "when an item emits a destroyed event", ->
+ it "removes it from the list of items", ->
+ pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")])
+ [item1, item2, item3] = pane.items
+ pane.items[1].destroy()
+ expect(pane.items).toEqual [item1, item3]
+
+ describe "::destroyInactiveItems()", ->
+ it "destroys all items but the active item", ->
+ pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C")])
+ [item1, item2, item3] = pane.items
+ pane.activateItem(item2)
+ pane.destroyInactiveItems()
+ expect(pane.items).toEqual [item2]
+
+ describe "::saveActiveItem()", ->
+ pane = null
+
+ beforeEach ->
+ pane = new Pane(items: [new Item("A")])
+ spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path')
+
+ describe "when the active item has a uri", ->
+ beforeEach ->
+ pane.activeItem.uri = "test"
+
+ describe "when the active item has a save method", ->
+ it "saves the current item", ->
+ pane.activeItem.save = jasmine.createSpy("save")
+ pane.saveActiveItem()
+ expect(pane.activeItem.save).toHaveBeenCalled()
+
+ describe "when the current item has no save method", ->
+ it "does nothing", ->
+ expect(pane.activeItem.save).toBeUndefined()
+ pane.saveActiveItem()
+
+ describe "when the current item has no uri", ->
+ describe "when the current item has a saveAs method", ->
+ it "opens a save dialog and saves the current item as the selected path", ->
+ pane.activeItem.saveAs = jasmine.createSpy("saveAs")
+ pane.saveActiveItem()
+ expect(atom.showSaveDialogSync).toHaveBeenCalled()
+ expect(pane.activeItem.saveAs).toHaveBeenCalledWith('/selected/path')
+
+ describe "when the current item has no saveAs method", ->
+ it "does nothing", ->
+ expect(pane.activeItem.saveAs).toBeUndefined()
+ pane.saveActiveItem()
+ expect(atom.showSaveDialogSync).not.toHaveBeenCalled()
+
+ describe "::saveActiveItemAs()", ->
+ pane = null
+
+ beforeEach ->
+ pane = new Pane(items: [new Item("A")])
+ spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path')
+
+ describe "when the current item has a saveAs method", ->
+ it "opens the save dialog and calls saveAs on the item with the selected path", ->
+ pane.activeItem.path = __filename
+ pane.activeItem.saveAs = jasmine.createSpy("saveAs")
+ pane.saveActiveItemAs()
+ expect(atom.showSaveDialogSync).toHaveBeenCalledWith(__dirname)
+ expect(pane.activeItem.saveAs).toHaveBeenCalledWith('/selected/path')
+
+ describe "when the current item does not have a saveAs method", ->
+ it "does nothing", ->
+ expect(pane.activeItem.saveAs).toBeUndefined()
+ pane.saveActiveItemAs()
+ expect(atom.showSaveDialogSync).not.toHaveBeenCalled()
+
+ describe "::itemForUri(uri)", ->
+ it "returns the item for which a call to .getUri() returns the given uri", ->
+ pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")])
+ [item1, item2, item3] = pane.items
+ item1.uri = "a"
+ item2.uri = "b"
+ expect(pane.itemForUri("a")).toBe item1
+ expect(pane.itemForUri("b")).toBe item2
+ expect(pane.itemForUri("bogus")).toBeUndefined()
+
+ describe "::moveItem(item, index)", ->
+ it "moves the item to the given index and emits an 'item-moved' event with the item and its new index", ->
+ pane = new Pane(items: [new Item("A"), new Item("B"), new Item("C"), new Item("D")])
+ [item1, item2, item3, item4] = pane.items
+ pane.on 'item-moved', itemMovedHandler = jasmine.createSpy("itemMovedHandler")
+
+ pane.moveItem(item1, 2)
+ expect(pane.getItems()).toEqual [item2, item3, item1, item4]
+ expect(itemMovedHandler).toHaveBeenCalledWith(item1, 2)
+ itemMovedHandler.reset()
+
+ pane.moveItem(item2, 3)
+ expect(pane.getItems()).toEqual [item3, item1, item4, item2]
+ expect(itemMovedHandler).toHaveBeenCalledWith(item2, 3)
+ itemMovedHandler.reset()
+
+ pane.moveItem(item2, 1)
+ expect(pane.getItems()).toEqual [item3, item2, item1, item4]
+ expect(itemMovedHandler).toHaveBeenCalledWith(item2, 1)
+
+ describe "::moveItemToPane(item, pane, index)", ->
+ [container, pane1, pane2] = []
+ [item1, item2, item3, item4, item5] = []
+
+ beforeEach ->
+ pane1 = new Pane(items: [new Item("A"), new Item("B"), new Item("C")])
+ container = new PaneContainer(root: pane1)
+ pane2 = pane1.splitRight(items: [new Item("D"), new Item("E")])
+ [item1, item2, item3] = pane1.items
+ [item4, item5] = pane2.items
+
+ it "moves the item to the given pane at the given index", ->
+ pane1.moveItemToPane(item2, pane2, 1)
+ expect(pane1.items).toEqual [item1, item3]
+ expect(pane2.items).toEqual [item4, item2, item5]
+
+ describe "when the moved item the last item in the source pane", ->
+ it "destroys the pane, but not the item", ->
+ item5.destroy()
+ pane2.moveItemToPane(item4, pane1, 0)
+ expect(pane2.isDestroyed()).toBe true
+ expect(item4.isDestroyed()).toBe false
+
+ describe "split methods", ->
+ [pane1, container] = []
+
+ beforeEach ->
+ pane1 = new Pane(items: ["A"])
+ container = new PaneContainer(root: pane1)
+
+ describe "::splitLeft(params)", ->
+ describe "when the parent is the container root", ->
+ it "replaces itself with a row and inserts a new pane to the left of itself", ->
+ pane2 = pane1.splitLeft(items: ["B"])
+ pane3 = pane1.splitLeft(items: ["C"])
+ expect(container.root.orientation).toBe 'horizontal'
+ expect(container.root.children).toEqual [pane2, pane3, pane1]
+
+ describe "when the parent is a column", ->
+ it "replaces itself with a row and inserts a new pane to the left of itself", ->
+ pane1.splitDown()
+ pane2 = pane1.splitLeft(items: ["B"])
+ pane3 = pane1.splitLeft(items: ["C"])
+ row = container.root.children[0]
+ expect(row.orientation).toBe 'horizontal'
+ expect(row.children).toEqual [pane2, pane3, pane1]
+
+ describe "::splitRight(params)", ->
+ describe "when the parent is the container root", ->
+ it "replaces itself with a row and inserts a new pane to the right of itself", ->
+ pane2 = pane1.splitRight(items: ["B"])
+ pane3 = pane1.splitRight(items: ["C"])
+ expect(container.root.orientation).toBe 'horizontal'
+ expect(container.root.children).toEqual [pane1, pane3, pane2]
+
+ describe "when the parent is a column", ->
+ it "replaces itself with a row and inserts a new pane to the right of itself", ->
+ pane1.splitDown()
+ pane2 = pane1.splitRight(items: ["B"])
+ pane3 = pane1.splitRight(items: ["C"])
+ row = container.root.children[0]
+ expect(row.orientation).toBe 'horizontal'
+ expect(row.children).toEqual [pane1, pane3, pane2]
+
+ describe "::splitUp(params)", ->
+ describe "when the parent is the container root", ->
+ it "replaces itself with a column and inserts a new pane above itself", ->
+ pane2 = pane1.splitUp(items: ["B"])
+ pane3 = pane1.splitUp(items: ["C"])
+ expect(container.root.orientation).toBe 'vertical'
+ expect(container.root.children).toEqual [pane2, pane3, pane1]
+
+ describe "when the parent is a row", ->
+ it "replaces itself with a column and inserts a new pane above itself", ->
+ pane1.splitRight()
+ pane2 = pane1.splitUp(items: ["B"])
+ pane3 = pane1.splitUp(items: ["C"])
+ column = container.root.children[0]
+ expect(column.orientation).toBe 'vertical'
+ expect(column.children).toEqual [pane2, pane3, pane1]
+
+ describe "::splitDown(params)", ->
+ describe "when the parent is the container root", ->
+ it "replaces itself with a column and inserts a new pane below itself", ->
+ pane2 = pane1.splitDown(items: ["B"])
+ pane3 = pane1.splitDown(items: ["C"])
+ expect(container.root.orientation).toBe 'vertical'
+ expect(container.root.children).toEqual [pane1, pane3, pane2]
+
+ describe "when the parent is a row", ->
+ it "replaces itself with a column and inserts a new pane below itself", ->
+ pane1.splitRight()
+ pane2 = pane1.splitDown(items: ["B"])
+ pane3 = pane1.splitDown(items: ["C"])
+ column = container.root.children[0]
+ expect(column.orientation).toBe 'vertical'
+ expect(column.children).toEqual [pane1, pane3, pane2]
+
+ it "sets up the new pane to be focused", ->
+ expect(pane1.focused).toBe false
+ pane2 = pane1.splitRight()
+ expect(pane2.focused).toBe true
+
+ describe "::destroy()", ->
+ [pane1, container] = []
+
+ beforeEach ->
+ pane1 = new Pane(items: [new Model, new Model])
+ container = new PaneContainer(root: pane1)
+
+ it "destroys the pane's destroyable items", ->
+ [item1, item2] = pane1.items
+ pane1.destroy()
+ expect(item1.isDestroyed()).toBe true
+ expect(item2.isDestroyed()).toBe true
+
+ describe "if the pane is active", ->
+ it "makes the next pane active", ->
+ pane2 = pane1.splitRight()
+ expect(pane2.isActive()).toBe true
+ pane2.destroy()
+ expect(pane1.isActive()).to
+
+ describe "if the pane's parent has more than two children", ->
+ it "removes the pane from its parent", ->
+ pane2 = pane1.splitRight()
+ pane3 = pane2.splitRight()
+
+ expect(container.root.children).toEqual [pane1, pane2, pane3]
+ pane2.destroy()
+ expect(container.root.children).toEqual [pane1, pane3]
+
+ describe "if the pane's parent has two children", ->
+ it "replaces the parent with its last remaining child", ->
+ pane2 = pane1.splitRight()
+ pane3 = pane2.splitDown()
+
+ expect(container.root.children[0]).toBe pane1
+ expect(container.root.children[1].children).toEqual [pane2, pane3]
+ pane3.destroy()
+ expect(container.root.children).toEqual [pane1, pane2]
+ pane2.destroy()
+ expect(container.root).toBe pane1
+
+ describe "serialization", ->
+ pane = null
+
+ beforeEach ->
+ pane = new Pane(items: [new Item("A", "a"), new Item("B", "b"), new Item("C", "c")])
+
+ it "can serialize and deserialize the pane and all its items", ->
+ newPane = pane.testSerialization()
+ expect(newPane.items).toEqual pane.items
+
+ it "restores the active item on deserialization", ->
+ pane.activateItemAtIndex(1)
+ newPane = pane.testSerialization()
+ expect(newPane.activeItem).toEqual newPane.items[1]
+
+ it "does not include items that cannot be deserialized", ->
+ spyOn(console, 'warn')
+ unserializable = {}
+ pane.activateItem(unserializable)
+
+ newPane = pane.testSerialization()
+ expect(newPane.activeItem).toEqual pane.items[0]
+ expect(newPane.items.length).toBe pane.items.length - 1
+
+ it "includes the pane's focus state in the serialized state", ->
+ pane.focus()
+ newPane = pane.testSerialization()
+ expect(newPane.focused).toBe true
diff --git a/spec/pane-view-spec.coffee b/spec/pane-view-spec.coffee
index 7440f7e73..fb1815308 100644
--- a/spec/pane-view-spec.coffee
+++ b/spec/pane-view-spec.coffee
@@ -5,7 +5,7 @@ path = require 'path'
temp = require 'temp'
describe "PaneView", ->
- [container, view1, view2, editor1, editor2, pane] = []
+ [container, view1, view2, editor1, editor2, pane, paneModel] = []
class TestView extends View
@deserialize: ({id, text}) -> new TestView({id, text})
@@ -23,377 +23,120 @@ describe "PaneView", ->
editor1 = atom.project.openSync('sample.js')
editor2 = atom.project.openSync('sample.txt')
pane = new PaneView(view1, editor1, view2, editor2)
+ paneModel = pane.model
container.setRoot(pane)
afterEach ->
atom.deserializers.remove(TestView)
- describe "::initialize(items...)", ->
- it "displays the first item in the pane", ->
- expect(pane.itemViews.find('#view-1')).toExist()
-
- describe "::activateItem(item)", ->
+ describe "when the active pane item changes", ->
it "hides all item views except the one being shown and sets the activeItem", ->
expect(pane.activeItem).toBe view1
+ expect(view1.css('display')).not.toBe 'none'
+
pane.activateItem(view2)
expect(view1.css('display')).toBe 'none'
expect(view2.css('display')).not.toBe 'none'
- expect(pane.activeItem).toBe view2
- it "triggers 'pane:active-item-changed' if the item isn't already the activeItem", ->
- pane.activate()
+ it "triggers 'pane:active-item-changed'", ->
itemChangedHandler = jasmine.createSpy("itemChangedHandler")
container.on 'pane:active-item-changed', itemChangedHandler
expect(pane.activeItem).toBe view1
- pane.activateItem(view2)
- pane.activateItem(view2)
+ paneModel.activateItem(view2)
+ paneModel.activateItem(view2)
+
expect(itemChangedHandler.callCount).toBe 1
expect(itemChangedHandler.argsForCall[0][1]).toBe view2
itemChangedHandler.reset()
- pane.activateItem(editor1)
+ paneModel.activateItem(editor1)
expect(itemChangedHandler).toHaveBeenCalled()
expect(itemChangedHandler.argsForCall[0][1]).toBe editor1
itemChangedHandler.reset()
- describe "if the pane's active view is focused before calling activateItem", ->
- it "focuses the new active view", ->
- container.attachToDom()
- pane.focus()
- expect(pane.activeView).not.toBe view2
- expect(pane.activeView).toMatchSelector ':focus'
- pane.activateItem(view2)
- expect(view2).toMatchSelector ':focus'
+ it "transfers focus to the new active view if the previous view was focused", ->
+ container.attachToDom()
+ pane.focus()
+ expect(pane.activeView).not.toBe view2
+ expect(pane.activeView).toMatchSelector ':focus'
+ paneModel.activateItem(view2)
+ expect(view2).toMatchSelector ':focus'
- describe "when the given item isn't yet in the items list on the pane", ->
- view3 = null
- beforeEach ->
- view3 = new TestView(id: 'view-3', text: "View 3")
- pane.activateItem(editor1)
- expect(pane.getActiveItemIndex()).toBe 1
+ describe "when the new activeItem is a model", ->
+ it "shows the item's view or creates and shows a new view for the item if none exists", ->
+ initialViewCount = pane.itemViews.find('.test-view').length
- it "adds it to the items list after the active item", ->
- pane.activateItem(view3)
- expect(pane.getItems()).toEqual [view1, editor1, view3, view2, editor2]
- expect(pane.activeItem).toBe view3
- expect(pane.getActiveItemIndex()).toBe 2
+ model1 =
+ id: 'test-model-1'
+ text: 'Test Model 1'
+ serialize: -> {@id, @text}
+ getViewClass: -> TestView
- it "triggers the 'item-added' event with the item and its index before the 'active-item-changed' event", ->
- events = []
- container.on 'pane:item-added', (e, item, index) -> events.push(['pane:item-added', item, index])
- container.on 'pane:active-item-changed', (e, item) -> events.push(['pane:active-item-changed', item])
- pane.activateItem(view3)
- expect(events).toEqual [['pane:item-added', view3, 2], ['pane:active-item-changed', view3]]
+ model2 =
+ id: 'test-model-2'
+ text: 'Test Model 2'
+ serialize: -> {@id, @text}
+ getViewClass: -> TestView
- 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.activateItem(editor1)
- editorView = pane.activeView
- expect(editorView.css('display')).not.toBe 'none'
- expect(editorView.editor).toBe editor1
+ paneModel.activateItem(model1)
+ paneModel.activateItem(model2)
+ expect(pane.itemViews.find('.test-view').length).toBe initialViewCount + 2
- describe "when a valid view has already been appended for another item", ->
- it "multiple views are created for multiple items", ->
- pane.activateItem(editor1)
- pane.activateItem(editor2)
- expect(pane.itemViews.find('.editor').length).toBe 2
- editorView = pane.activeView
- expect(editorView.css('display')).not.toBe 'none'
- expect(editorView.editor).toBe editor2
+ paneModel.activatePreviousItem()
+ expect(pane.itemViews.find('.test-view').length).toBe initialViewCount + 2
- it "creates a new view with the item", ->
- initialViewCount = pane.itemViews.find('.test-view').length
+ paneModel.destroyItem(model2)
+ expect(pane.itemViews.find('.test-view').length).toBe initialViewCount + 1
- model1 =
- id: 'test-model-1'
- text: 'Test Model 1'
- serialize: -> {@id, @text}
- getViewClass: -> TestView
+ paneModel.destroyItem(model1)
+ expect(pane.itemViews.find('.test-view').length).toBe initialViewCount
- model2 =
- id: 'test-model-2'
- text: 'Test Model 2'
- serialize: -> {@id, @text}
- getViewClass: -> TestView
-
- pane.activateItem(model1)
- pane.activateItem(model2)
- expect(pane.itemViews.find('.test-view').length).toBe initialViewCount + 2
-
- pane.activatePreviousItem()
- expect(pane.itemViews.find('.test-view').length).toBe initialViewCount + 2
-
- pane.destroyItem(model2)
- expect(pane.itemViews.find('.test-view').length).toBe initialViewCount + 1
-
- pane.destroyItem(model1)
- expect(pane.itemViews.find('.test-view').length).toBe initialViewCount
-
- describe "when showing a view item", ->
+ describe "when the new activeItem is a view", ->
it "appends it to the itemViews div if it hasn't already been appended and shows it", ->
expect(pane.itemViews.find('#view-2')).not.toExist()
- pane.activateItem(view2)
+ paneModel.activateItem(view2)
expect(pane.itemViews.find('#view-2')).toExist()
- expect(pane.activeView).toBe view2
+ paneModel.activateItem(view1)
+ paneModel.activateItem(view2)
+ expect(pane.itemViews.find('#view-2').length).toBe 1
- describe "::destroyItem(item)", ->
- describe "if the item is not modified", ->
- it "removes the item and tries to call destroy on it", ->
- pane.destroyItem(editor2)
- expect(pane.getItems().indexOf(editor2)).toBe -1
- expect(editor2.isDestroyed()).toBe true
-
- describe "if the item is modified", ->
- beforeEach ->
- jasmine.unspy(editor2, 'shouldPromptToSave')
- spyOn(editor2, 'save')
- spyOn(editor2, 'saveAs')
-
- 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, 'confirm').andReturn(0)
- pane.destroyItem(editor2)
-
- expect(editor2.save).toHaveBeenCalled()
- expect(pane.getItems().indexOf(editor2)).toBe -1
- expect(editor2.isDestroyed()).toBe true
-
- 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", ->
- editor2.buffer.setPath(undefined)
-
- spyOn(atom, 'showSaveDialogSync').andReturn("/selected/path")
- spyOn(atom, 'confirm').andReturn(0)
- pane.destroyItem(editor2)
-
- expect(atom.showSaveDialogSync).toHaveBeenCalled()
-
- expect(editor2.saveAs).toHaveBeenCalledWith("/selected/path")
- expect(pane.getItems().indexOf(editor2)).toBe -1
- expect(editor2.isDestroyed()).toBe true
-
- describe "if the [Don't Save] option is selected", ->
- it "removes and destroys the item without saving it", ->
- spyOn(atom, 'confirm').andReturn(2)
- pane.destroyItem(editor2)
-
- expect(editor2.save).not.toHaveBeenCalled()
- expect(pane.getItems().indexOf(editor2)).toBe -1
- expect(editor2.isDestroyed()).toBe true
-
- describe "if the [Cancel] option is selected", ->
- it "does not save, remove, or destroy the item", ->
- spyOn(atom, 'confirm').andReturn(1)
- pane.destroyItem(editor2)
-
- expect(editor2.save).not.toHaveBeenCalled()
- expect(pane.getItems().indexOf(editor2)).not.toBe -1
- expect(editor2.isDestroyed()).toBe false
-
- it "removes the item's associated view", ->
- view1.remove = (selector, keepData) -> @wasRemoved = not keepData
- pane.destroyItem(view1)
- expect(view1.wasRemoved).toBe true
-
- it "removes the item from the items list and shows the next item if it was showing", ->
- pane.destroyItem(view1)
- expect(pane.getItems()).toEqual [editor1, view2, editor2]
- expect(pane.activeItem).toBe editor1
-
- pane.activateItem(editor2)
- pane.destroyItem(editor2)
- expect(pane.getItems()).toEqual [editor1, view2]
- expect(pane.activeItem).toBe editor1
-
- it "triggers 'pane:item-removed' with the item and its former index", ->
+ describe "when an item is destroyed", ->
+ it "triggers the 'pane:item-removed' event with the item and its former index", ->
itemRemovedHandler = jasmine.createSpy("itemRemovedHandler")
pane.on 'pane:item-removed', itemRemovedHandler
- pane.destroyItem(editor1)
+ paneModel.destroyItem(editor1)
expect(itemRemovedHandler).toHaveBeenCalled()
expect(itemRemovedHandler.argsForCall[0][1..2]).toEqual [editor1, 1]
- describe "when removing the last item", ->
- it "removes the pane", ->
- pane.destroyItem(item) for item in pane.getItems()
- expect(pane.hasParent()).toBeFalsy()
-
- describe "when the pane is focused", ->
- it "shifts focus to the next pane", ->
- expect(container.getRoot()).toBe pane
- container.attachToDom()
- pane2 = pane.splitRight(new TestView(id: 'view-3', text: 'View 3'))
- pane.focus()
- expect(pane).toMatchSelector(':has(:focus)')
- pane.destroyItem(item) for item in pane.getItems()
- expect(pane2).toMatchSelector ':has(:focus)'
-
- describe "when the item is a view", ->
+ describe "when the destroyed item is a view", ->
it "removes the item from the 'item-views' div", ->
expect(view1.parent()).toMatchSelector pane.itemViews
- pane.destroyItem(view1)
+ paneModel.destroyItem(view1)
expect(view1.parent()).not.toMatchSelector pane.itemViews
- describe "when the item is a model", ->
- it "removes the associated view only when all items that require it have been removed", ->
- pane.activateItem(editor1)
- pane.activateItem(editor2)
- pane.destroyItem(editor2)
- expect(pane.itemViews.find('.editor')).toExist()
+ describe "when the destroyed item is a model", ->
+ it "removes the associated view", ->
+ paneModel.activateItem(editor1)
+ expect(pane.itemViews.find('.editor').length).toBe 1
pane.destroyItem(editor1)
- expect(pane.itemViews.find('.editor')).not.toExist()
+ expect(pane.itemViews.find('.editor').length).toBe 0
- describe "::moveItem(item, index)", ->
- it "moves the item to the given index and emits a 'pane:item-moved' event with the item and the new index", ->
- itemMovedHandler = jasmine.createSpy("itemMovedHandler")
- pane.on 'pane:item-moved', itemMovedHandler
-
- pane.moveItem(view1, 2)
- expect(pane.getItems()).toEqual [editor1, view2, view1, editor2]
+ describe "when an item is moved within the same pane", ->
+ it "emits a 'pane:item-moved' event with the item and the new index", ->
+ pane.on 'pane:item-moved', itemMovedHandler = jasmine.createSpy("itemMovedHandler")
+ paneModel.moveItem(view1, 2)
expect(itemMovedHandler).toHaveBeenCalled()
expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [view1, 2]
- itemMovedHandler.reset()
- pane.moveItem(editor1, 3)
- expect(pane.getItems()).toEqual [view2, view1, editor2, editor1]
- expect(itemMovedHandler).toHaveBeenCalled()
- expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editor1, 3]
- itemMovedHandler.reset()
-
- pane.moveItem(editor1, 1)
- expect(pane.getItems()).toEqual [view2, editor1, view1, editor2]
- expect(itemMovedHandler).toHaveBeenCalled()
- expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editor1, 1]
- itemMovedHandler.reset()
-
- describe "::moveItemToPane(item, pane, index)", ->
- [pane2, view3] = []
-
- beforeEach ->
- view3 = new TestView(id: 'view-3', text: "View 3")
- pane2 = pane.splitRight(view3)
-
- it "moves the item to the given pane at the given index", ->
- pane.moveItemToPane(view1, pane2, 1)
- 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.destroyItem(view1)
- pane.destroyItem(view2)
- pane.destroyItem(editor2)
-
- expect(pane.getItems()).toEqual [editor1]
- pane.moveItemToPane(editor1, pane2, 1)
-
- expect(pane.hasParent()).toBeFalsy()
- expect(pane2.getItems()).toEqual [view3, editor1]
- expect(editor1.isDestroyed()).toBe false
-
- describe "when the item is a jQuery object", ->
- it "preserves data by detaching instead of removing", ->
- view1.data('preservative', 1234)
- pane.moveItemToPane(view1, pane2, 1)
- pane2.activateItemAtIndex(1)
- expect(pane2.activeView.data('preservative')).toBe 1234
-
- describe "pane:close", ->
- it "destroys all items and removes the pane", ->
- pane.activateItem(editor1)
- pane.trigger 'pane:close'
- expect(pane.hasParent()).toBeFalsy()
- expect(editor2.isDestroyed()).toBe true
- expect(editor1.isDestroyed()).toBe true
-
- describe "pane:close-other-items", ->
- it "destroys all items except the current", ->
- pane.activateItem(editor1)
- pane.trigger 'pane:close-other-items'
- expect(editor2.isDestroyed()).toBe true
- expect(pane.getItems()).toEqual [editor1]
-
- describe "::saveActiveItem()", ->
- describe "when the current item has a uri", ->
- describe "when the current item has a save method", ->
- it "saves the current item", ->
- spyOn(editor2, 'save')
- pane.activateItem(editor2)
- pane.saveActiveItem()
- expect(editor2.save).toHaveBeenCalled()
-
- describe "when the current item has no save method", ->
- it "does nothing", ->
- pane.activeItem.getUri = -> 'you are eye'
- expect(pane.activeItem.save).toBeUndefined()
- pane.saveActiveItem()
-
- describe "when the current item has no uri", ->
- beforeEach ->
- spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path')
-
- describe "when the current item has a saveAs method", ->
- it "opens a save dialog and saves the current item as the selected path", ->
- newEditor = atom.project.openSync()
- spyOn(newEditor, 'saveAs')
- pane.activateItem(newEditor)
-
- pane.saveActiveItem()
-
- expect(atom.showSaveDialogSync).toHaveBeenCalled()
- expect(newEditor.saveAs).toHaveBeenCalledWith('/selected/path')
-
- describe "when the current item has no saveAs method", ->
- it "does nothing", ->
- expect(pane.activeItem.saveAs).toBeUndefined()
- pane.saveActiveItem()
- expect(atom.showSaveDialogSync).not.toHaveBeenCalled()
-
- describe "::saveActiveItemAs()", ->
- beforeEach ->
- spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path')
-
- 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(editor2, 'saveAs')
- pane.activateItem(editor2)
-
- pane.saveActiveItemAs()
-
- 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", ->
- expect(pane.activeItem.saveAs).toBeUndefined()
- pane.saveActiveItemAs()
- expect(atom.showSaveDialogSync).not.toHaveBeenCalled()
-
- describe "pane:show-next-item and pane:show-previous-item", ->
- 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 editor2
- pane.trigger 'pane:show-previous-item'
- expect(pane.activeItem).toBe view2
- pane.trigger 'pane:show-next-item'
- expect(pane.activeItem).toBe editor2
- pane.trigger 'pane:show-next-item'
- expect(pane.activeItem).toBe view1
-
- describe "pane:show-item-N events", ->
- it "shows the (n-1)th item if it exists", ->
- pane.trigger 'pane:show-item-2'
- expect(pane.activeItem).toBe pane.itemAtIndex(1)
- pane.trigger 'pane:show-item-1'
- expect(pane.activeItem).toBe pane.itemAtIndex(0)
- pane.trigger 'pane:show-item-9' # don't fail on out-of-bounds indices
- expect(pane.activeItem).toBe pane.itemAtIndex(0)
+ describe "when an item is moved to another pane", ->
+ it "detaches the item's view rather than removing it", ->
+ paneModel2 = paneModel.splitRight()
+ view1.data('preservative', 1234)
+ paneModel.moveItemToPane(view1, paneModel2, 1)
+ expect(view1.data('preservative')).toBe 1234
+ paneModel2.activateItemAtIndex(1)
+ expect(view1.data('preservative')).toBe 1234
describe "when the title of the active item changes", ->
it "emits pane:active-item-title-changed", ->
@@ -424,12 +167,7 @@ describe "PaneView", ->
waitsFor ->
pane.items.length == 4
- describe "::remove()", ->
- it "destroys all the pane's items", ->
- pane.remove()
- expect(editor1.isDestroyed()).toBe true
- expect(editor2.isDestroyed()).toBe true
-
+ describe "when a pane is destroyed", ->
it "triggers a 'pane:removed' event with the pane", ->
removedHandler = jasmine.createSpy("removedHandler")
container.on 'pane:removed', removedHandler
@@ -437,52 +175,28 @@ describe "PaneView", ->
expect(removedHandler).toHaveBeenCalled()
expect(removedHandler.argsForCall[0][1]).toBe pane
- describe "when there are other panes", ->
+ describe "if the destroyed pane has focus", ->
[paneToLeft, paneToRight] = []
- beforeEach ->
- pane.activateItem(editor1)
- paneToLeft = pane.splitLeft(pane.copyActiveItem())
- paneToRight = pane.splitRight(pane.copyActiveItem())
- container.attachToDom()
+ describe "if it is not the last pane in the container", ->
+ it "focuses the next pane", ->
+ paneModel.activateItem(editor1)
+ pane2Model = paneModel.splitRight(items: [paneModel.copyActiveItem()])
+ pane2 = pane2Model._view
+ container.attachToDom()
+ expect(pane.hasFocus()).toBe false
+ pane2Model.destroy()
+ expect(pane.hasFocus()).toBe true
- describe "when the removed pane is active", ->
- it "makes the next the next pane active and focuses it", ->
- pane.activate()
- pane.remove()
- expect(paneToLeft.isActive()).toBeFalsy()
- expect(paneToRight.isActive()).toBeTruthy()
- expect(paneToRight).toMatchSelector ':has(:focus)'
-
- describe "when the removed pane is not active", ->
- it "does not affect the active pane or the focus", ->
- paneToLeft.focus()
- expect(paneToLeft.isActive()).toBeTruthy()
- expect(paneToRight.isActive()).toBeFalsy()
-
- pane.remove()
- expect(paneToLeft.isActive()).toBeTruthy()
- expect(paneToRight.isActive()).toBeFalsy()
- expect(paneToLeft).toMatchSelector ':has(:focus)'
-
- describe "when it is the last pane", ->
- beforeEach ->
- expect(container.getPanes().length).toBe 1
- atom.workspaceView = focus: jasmine.createSpy("workspaceView.focus")
-
- describe "when the removed pane is focused", ->
- it "calls focus on workspaceView so we don't lose focus", ->
+ describe "if it is the last pane in the container", ->
+ it "shifts focus to the workspace view", ->
+ atom.workspaceView = {focus: jasmine.createSpy("atom.workspaceView.focus")}
container.attachToDom()
pane.focus()
- pane.remove()
+ expect(container.hasFocus()).toBe true
+ paneModel.destroy()
expect(atom.workspaceView.focus).toHaveBeenCalled()
- describe "when the removed pane is not focused", ->
- it "does not call focus on root view", ->
- expect(pane).not.toMatchSelector ':has(:focus)'
- pane.remove()
- expect(atom.workspaceView.focus).not.toHaveBeenCalled()
-
describe "::getNextPane()", ->
it "returns the next pane if one exists, wrapping around from the last pane to the first", ->
pane.activateItem(editor1)
@@ -491,148 +205,78 @@ describe "PaneView", ->
expect(pane.getNextPane()).toBe pane2
expect(pane2.getNextPane()).toBe pane
+ describe "when the pane's active status changes", ->
+ [pane2, pane2Model] = []
+
+ beforeEach ->
+ pane2Model = paneModel.splitRight(items: [pane.copyActiveItem()])
+ pane2 = pane2Model._view
+ expect(pane2Model.isActive()).toBe true
+
+ it "adds or removes the .active class as appropriate", ->
+ expect(pane).not.toHaveClass('active')
+ paneModel.activate()
+ expect(pane).toHaveClass('active')
+ pane2Model.activate()
+ expect(pane).not.toHaveClass('active')
+
+ it "triggers 'pane:became-active' or 'pane:became-inactive' according to the current status", ->
+ pane.on 'pane:became-active', becameActiveHandler = jasmine.createSpy("becameActiveHandler")
+ pane.on 'pane:became-inactive', becameInactiveHandler = jasmine.createSpy("becameInactiveHandler")
+ paneModel.activate()
+
+ expect(becameActiveHandler.callCount).toBe 1
+ expect(becameInactiveHandler.callCount).toBe 0
+
+ pane2Model.activate()
+ expect(becameActiveHandler.callCount).toBe 1
+ expect(becameInactiveHandler.callCount).toBe 1
+
describe "when the pane is focused", ->
beforeEach ->
container.attachToDom()
- it "focuses the active item view", ->
+ it "transfers focus to the active view", ->
focusHandler = jasmine.createSpy("focusHandler")
pane.activeItem.on 'focus', focusHandler
pane.focus()
expect(focusHandler).toHaveBeenCalled()
- it "triggers 'pane:became-active' if it was not previously active", ->
- pane2 = pane.splitRight(view2) # Make pane inactive
+ it "makes the pane active", ->
+ paneModel.splitRight(items: [pane.copyActiveItem()])
+ expect(paneModel.isActive()).toBe false
+ pane.focus()
+ expect(paneModel.isActive()).toBe true
- becameActiveHandler = jasmine.createSpy("becameActiveHandler")
- pane.on 'pane:became-active', becameActiveHandler
- expect(pane.isActive()).toBeFalsy()
- pane.focusin()
- expect(pane.isActive()).toBeTruthy()
- pane.focusin()
-
- expect(becameActiveHandler.callCount).toBe 1
-
- it "triggers 'pane:became-inactive' when it was previously active", ->
- pane2 = pane.splitRight(view2) # Make pane inactive
-
- becameInactiveHandler = jasmine.createSpy("becameInactiveHandler")
- pane.on 'pane:became-inactive', becameInactiveHandler
-
- expect(pane.isActive()).toBeFalsy()
- pane.focusin()
- expect(pane.isActive()).toBeTruthy()
- pane.splitRight(pane.copyActiveItem())
- expect(pane.isActive()).toBeFalsy()
-
- expect(becameInactiveHandler.callCount).toBe 1
-
- describe "split methods", ->
- [pane1, view3, view4] = []
- beforeEach ->
+ describe "when a pane is split", ->
+ it "builds the appropriate pane-row and pane-column views", ->
pane1 = pane
+ pane1Model = pane.model
pane.activateItem(editor1)
- view3 = new TestView(id: 'view-3', text: 'View 3')
- view4 = new TestView(id: 'view-4', text: 'View 4')
- describe "splitRight(items...)", ->
- it "builds a row if needed, then appends a new pane after itself", ->
- # creates the new pane with a copy of the active item if none are given
- pane2 = pane1.splitRight(pane1.copyActiveItem())
- expect(container.find('.pane-row .pane').toArray()).toEqual [pane1[0], pane2[0]]
- expect(pane2.items).toEqual [editor1]
- expect(pane2.activeItem).not.toBe editor1 # it's a copy
+ pane2Model = pane1Model.splitRight(items: [pane1Model.copyActiveItem()])
+ pane3Model = pane2Model.splitDown(items: [pane2Model.copyActiveItem()])
+ pane2 = pane2Model._view
+ pane3 = pane3Model._view
- pane3 = pane2.splitRight(view3, view4)
- expect(pane3.getItems()).toEqual [view3, view4]
- expect(container.find('.pane-row .pane').toArray()).toEqual [pane[0], pane2[0], pane3[0]]
+ expect(container.find('> .pane-row > .pane').toArray()).toEqual [pane1[0]]
+ expect(container.find('> .pane-row > .pane-column > .pane').toArray()).toEqual [pane2[0], pane3[0]]
- it "builds a row if needed, then appends a new pane after itself ", ->
- # creates the new pane with a copy of the active item if none are given
- pane2 = pane1.splitRight()
- expect(container.find('.pane-row .pane').toArray()).toEqual [pane1[0], pane2[0]]
- expect(pane2.items).toEqual []
- expect(pane2.activeItem).toBeUndefined()
-
- pane3 = pane2.splitRight()
- expect(container.find('.pane-row .pane').toArray()).toEqual [pane1[0], pane2[0], pane3[0]]
- expect(pane3.items).toEqual []
- expect(pane3.activeItem).toBeUndefined()
-
- describe "splitLeft(items...)", ->
- it "builds a row if needed, then appends a new pane before itself", ->
- # creates the new pane with a copy of the active item if none are given
- pane2 = pane.splitLeft(pane1.copyActiveItem())
- expect(container.find('.pane-row .pane').toArray()).toEqual [pane2[0], pane[0]]
- 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]
- expect(container.find('.pane-row .pane').toArray()).toEqual [pane3[0], pane2[0], pane[0]]
-
- describe "splitDown(items...)", ->
- it "builds a column if needed, then appends a new pane after itself", ->
- # creates the new pane with a copy of the active item if none are given
- pane2 = pane.splitDown(pane1.copyActiveItem())
- expect(container.find('.pane-column .pane').toArray()).toEqual [pane[0], pane2[0]]
- 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]
- expect(container.find('.pane-column .pane').toArray()).toEqual [pane[0], pane2[0], pane3[0]]
-
- describe "splitUp(items...)", ->
- it "builds a column if needed, then appends a new pane before itself", ->
- # creates the new pane with a copy of the active item if none are given
- pane2 = pane.splitUp(pane1.copyActiveItem())
- expect(container.find('.pane-column .pane').toArray()).toEqual [pane2[0], pane[0]]
- 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]
- expect(container.find('.pane-column .pane').toArray()).toEqual [pane3[0], pane2[0], pane[0]]
-
- describe "::itemForUri(uri)", ->
- it "returns the item for which a call to .getUri() returns the given uri", ->
- expect(pane.itemForUri(editor1.getUri())).toBe editor1
- expect(pane.itemForUri(editor2.getUri())).toBe editor2
+ pane1Model.destroy()
+ expect(container.find('> .pane-column > .pane').toArray()).toEqual [pane2[0], pane3[0]]
describe "serialization", ->
- it "can serialize and deserialize the pane and all its items", ->
- newPane = pane.testSerialization()
- expect(newPane.getItems()).toEqual [view1, editor1, view2, editor2]
-
- it "restores the active item on deserialization", ->
- pane.activateItem(editor2)
- newPane = pane.testSerialization()
- expect(newPane.activeItem).toEqual editor2
-
- it "does not show items that cannot be deserialized", ->
- spyOn(console, 'warn')
-
- class Unserializable
- getViewClass: -> TestView
-
- pane.activateItem(new Unserializable)
-
- newPane = pane.testSerialization()
- expect(newPane.activeItem).toEqual pane.items[0]
- expect(newPane.items.length).toBe pane.items.length - 1
-
it "focuses the pane after attach only if had focus when serialized", ->
container.attachToDom()
pane.focus()
- container2 = container.testSerialization()
+ container2 = new PaneContainerView(container.model.testSerialization())
pane2 = container2.getRoot()
container2.attachToDom()
expect(pane2).toMatchSelector(':has(:focus)')
$(document.activeElement).blur()
- container3 = container.testSerialization()
+ container3 = new PaneContainerView(container.model.testSerialization())
pane3 = container3.getRoot()
container3.attachToDom()
expect(pane3).not.toMatchSelector(':has(:focus)')
diff --git a/spec/select-list-spec.coffee b/spec/select-list-spec.coffee
index 9c1c64555..152ba64ef 100644
--- a/spec/select-list-spec.coffee
+++ b/spec/select-list-spec.coffee
@@ -33,7 +33,7 @@ describe "SelectList", ->
selectList.attachToDom()
it "filters the elements in the list based on the scoreElement function and selects the first item", ->
- miniEditor.insertText('la')
+ miniEditor.getEditor().insertText('la')
window.advanceClock(selectList.inputThrottle)
expect(list.find('li').length).toBe 2
@@ -43,13 +43,13 @@ describe "SelectList", ->
expect(selectList.error).not.toBeVisible()
it "displays an error if there are no matches, removes error when there are matches", ->
- miniEditor.insertText('nothing will match this')
+ miniEditor.getEditor().insertText('nothing will match this')
window.advanceClock(selectList.inputThrottle)
expect(list.find('li').length).toBe 0
expect(selectList.error).not.toBeHidden()
- miniEditor.setText('la')
+ miniEditor.getEditor().setText('la')
window.advanceClock(selectList.inputThrottle)
expect(list.find('li').length).toBe 2
@@ -58,7 +58,7 @@ describe "SelectList", ->
it "displays no elements until the array has been set on the list", ->
selectList.array = null
selectList.list.empty()
- miniEditor.insertText('la')
+ miniEditor.getEditor().insertText('la')
window.advanceClock(selectList.inputThrottle)
expect(list.find('li').length).toBe 0
@@ -124,7 +124,7 @@ describe "SelectList", ->
selectList.attachToDom()
it "does not trigger the confirmed hook", ->
- miniEditor.insertText("i will never match anything")
+ miniEditor.getEditor().insertText("i will never match anything")
window.advanceClock(selectList.inputThrottle)
expect(list.find('li')).not.toExist()
@@ -132,7 +132,7 @@ describe "SelectList", ->
expect(selectList.confirmed).not.toHaveBeenCalled()
it "does trigger the cancelled hook", ->
- miniEditor.insertText("i will never match anything")
+ miniEditor.getEditor().insertText("i will never match anything")
window.advanceClock(selectList.inputThrottle)
expect(list.find('li')).not.toExist()
diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee
index 9c672e7a9..8e939d03d 100644
--- a/spec/spec-helper.coffee
+++ b/spec/spec-helper.coffee
@@ -107,7 +107,7 @@ afterEach ->
atom.workspaceView?.remove?()
atom.workspaceView = null
- delete atom.state.workspaceView
+ delete atom.state.workspace
atom.project?.destroy?()
atom.project = null
diff --git a/spec/window-spec.coffee b/spec/window-spec.coffee
index 53f992555..78f90d3b7 100644
--- a/spec/window-spec.coffee
+++ b/spec/window-spec.coffee
@@ -88,12 +88,12 @@ describe "Window", ->
describe ".unloadEditorWindow()", ->
it "saves the serialized state of the window so it can be deserialized after reload", ->
- workspaceViewState = atom.workspaceView.serialize()
+ workspaceState = atom.workspace.serialize()
syntaxState = atom.syntax.serialize()
atom.unloadEditorWindow()
- expect(atom.state.workspaceView).toEqual workspaceViewState
+ expect(atom.state.workspace).toEqual workspaceState
expect(atom.state.syntax).toEqual syntaxState
expect(atom.saveSync).toHaveBeenCalled()
diff --git a/spec/workspace-view-spec.coffee b/spec/workspace-view-spec.coffee
index f91fb8845..5fcd7beb0 100644
--- a/spec/workspace-view-spec.coffee
+++ b/spec/workspace-view-spec.coffee
@@ -3,6 +3,7 @@ Q = require 'q'
path = require 'path'
temp = require 'temp'
PaneView = require '../src/pane-view'
+Workspace = require '../src/workspace'
describe "WorkspaceView", ->
pathToOpen = null
@@ -10,7 +11,8 @@ describe "WorkspaceView", ->
beforeEach ->
atom.project.setPath(atom.project.resolve('dir'))
pathToOpen = atom.project.resolve('a')
- atom.workspaceView = new WorkspaceView
+ atom.workspace = new Workspace
+ atom.workspaceView = new WorkspaceView(atom.workspace)
atom.workspaceView.enableKeymap()
atom.workspaceView.openSync(pathToOpen)
atom.workspaceView.focus()
@@ -19,20 +21,21 @@ describe "WorkspaceView", ->
viewState = null
simulateReload = ->
- workspaceState = atom.workspaceView.serialize()
+ workspaceState = atom.workspace.serialize()
projectState = atom.project.serialize()
atom.workspaceView.remove()
atom.project = atom.deserializers.deserialize(projectState)
- atom.workspaceView = WorkspaceView.deserialize(workspaceState)
+ atom.workspace = Workspace.deserialize(workspaceState)
+ atom.workspaceView = new WorkspaceView(atom.workspace)
atom.workspaceView.attachToDom()
describe "when the serialized WorkspaceView has an unsaved buffer", ->
it "constructs the view with the same panes", ->
atom.workspaceView.attachToDom()
atom.workspaceView.openSync()
- editor1 = atom.workspaceView.getActiveView()
- buffer = editor1.getBuffer()
- editor1.splitRight()
+ editorView1 = atom.workspaceView.getActiveView()
+ buffer = editorView1.getEditor().getBuffer()
+ editorView1.splitRight()
expect(atom.workspaceView.getActivePane()).toBe atom.workspaceView.getPanes()[1]
simulateReload()
@@ -58,31 +61,31 @@ describe "WorkspaceView", ->
simulateReload()
expect(atom.workspaceView.getEditorViews().length).toBe 4
- editor1 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(0)').view()
- editor3 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(1)').view()
- editor2 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(0)').view()
- editor4 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(1)').view()
+ editorView1 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(0)').view()
+ editorView3 = atom.workspaceView.panes.find('.pane-row > .pane .editor:eq(1)').view()
+ editorView2 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(0)').view()
+ editorView4 = atom.workspaceView.panes.find('.pane-row > .pane-column > .pane .editor:eq(1)').view()
- expect(editor1.getPath()).toBe atom.project.resolve('a')
- expect(editor2.getPath()).toBe atom.project.resolve('b')
- expect(editor3.getPath()).toBe atom.project.resolve('../sample.js')
- expect(editor3.getCursorScreenPosition()).toEqual [2, 4]
- expect(editor4.getPath()).toBe atom.project.resolve('../sample.txt')
- expect(editor4.getCursorScreenPosition()).toEqual [0, 2]
+ expect(editorView1.getEditor().getPath()).toBe atom.project.resolve('a')
+ expect(editorView2.getEditor().getPath()).toBe atom.project.resolve('b')
+ expect(editorView3.getEditor().getPath()).toBe atom.project.resolve('../sample.js')
+ expect(editorView3.getEditor().getCursorScreenPosition()).toEqual [2, 4]
+ expect(editorView4.getEditor().getPath()).toBe atom.project.resolve('../sample.txt')
+ expect(editorView4.getEditor().getCursorScreenPosition()).toEqual [0, 2]
# ensure adjust pane dimensions is called
- expect(editor1.width()).toBeGreaterThan 0
- expect(editor2.width()).toBeGreaterThan 0
- expect(editor3.width()).toBeGreaterThan 0
- expect(editor4.width()).toBeGreaterThan 0
+ expect(editorView1.width()).toBeGreaterThan 0
+ expect(editorView2.width()).toBeGreaterThan 0
+ expect(editorView3.width()).toBeGreaterThan 0
+ expect(editorView4.width()).toBeGreaterThan 0
- # ensure correct editor is focused again
- expect(editor2.isFocused).toBeTruthy()
- expect(editor1.isFocused).toBeFalsy()
- expect(editor3.isFocused).toBeFalsy()
- expect(editor4.isFocused).toBeFalsy()
+ # ensure correct editorView is focused again
+ expect(editorView2.isFocused).toBeTruthy()
+ expect(editorView1.isFocused).toBeFalsy()
+ expect(editorView3.isFocused).toBeFalsy()
+ expect(editorView4.isFocused).toBeFalsy()
- expect(atom.workspaceView.title).toBe "#{path.basename(editor2.getPath())} - #{atom.project.getPath()}"
+ expect(atom.workspaceView.title).toBe "#{path.basename(editorView2.getEditor().getPath())} - #{atom.project.getPath()}"
describe "where there are no open editors", ->
it "constructs the view with no open editors", ->
@@ -187,7 +190,7 @@ describe "WorkspaceView", ->
describe "when the root view is deserialized", ->
it "updates the title to contain the project's path", ->
- workspaceView2 = atom.deserializers.deserialize(atom.workspaceView.serialize())
+ workspaceView2 = new WorkspaceView(atom.workspace.testSerialization())
item = atom.workspaceView.getActivePaneItem()
expect(workspaceView2.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
workspaceView2.remove()
@@ -462,27 +465,27 @@ describe "WorkspaceView", ->
it "shows/hides invisibles in all open and future editors", ->
atom.workspaceView.height(200)
atom.workspaceView.attachToDom()
- rightEditor = atom.workspaceView.getActiveView()
- rightEditor.setText(" \t ")
- leftEditor = rightEditor.splitLeft()
- expect(rightEditor.find(".line:first").text()).toBe " "
- expect(leftEditor.find(".line:first").text()).toBe " "
+ rightEditorView = atom.workspaceView.getActiveView()
+ rightEditorView.getEditor().setText(" \t ")
+ leftEditorView = rightEditorView.splitLeft()
+ expect(rightEditorView.find(".line:first").text()).toBe " "
+ expect(leftEditorView.find(".line:first").text()).toBe " "
- withInvisiblesShowing = "#{rightEditor.invisibles.space}#{rightEditor.invisibles.tab} #{rightEditor.invisibles.space}#{rightEditor.invisibles.eol}"
+ withInvisiblesShowing = "#{rightEditorView.invisibles.space}#{rightEditorView.invisibles.tab} #{rightEditorView.invisibles.space}#{rightEditorView.invisibles.eol}"
atom.workspaceView.trigger "window:toggle-invisibles"
- expect(rightEditor.find(".line:first").text()).toBe withInvisiblesShowing
- expect(leftEditor.find(".line:first").text()).toBe withInvisiblesShowing
+ expect(rightEditorView.find(".line:first").text()).toBe withInvisiblesShowing
+ expect(leftEditorView.find(".line:first").text()).toBe withInvisiblesShowing
- lowerLeftEditor = leftEditor.splitDown()
- expect(lowerLeftEditor.find(".line:first").text()).toBe withInvisiblesShowing
+ lowerLeftEditorView = leftEditorView.splitDown()
+ expect(lowerLeftEditorView.find(".line:first").text()).toBe withInvisiblesShowing
atom.workspaceView.trigger "window:toggle-invisibles"
- expect(rightEditor.find(".line:first").text()).toBe " "
- expect(leftEditor.find(".line:first").text()).toBe " "
+ expect(rightEditorView.find(".line:first").text()).toBe " "
+ expect(leftEditorView.find(".line:first").text()).toBe " "
- lowerRightEditor = rightEditor.splitDown()
- expect(lowerRightEditor.find(".line:first").text()).toBe " "
+ lowerRightEditorView = rightEditorView.splitDown()
+ expect(lowerRightEditorView.find(".line:first").text()).toBe " "
describe ".eachEditorView(callback)", ->
beforeEach ->
diff --git a/src/atom.coffee b/src/atom.coffee
index 4be78d895..f4cc5371e 100644
--- a/src/atom.coffee
+++ b/src/atom.coffee
@@ -232,8 +232,10 @@ class Atom extends Model
# Private:
deserializeWorkspaceView: ->
+ Workspace = require './workspace'
WorkspaceView = require './workspace-view'
- @workspaceView = @deserializers.deserialize(@state.workspaceView) ? new WorkspaceView
+ @workspace = Workspace.deserialize(@state.workspace) ? new Workspace
+ @workspaceView = new WorkspaceView(@workspace)
$(@workspaceViewParentSelector).append(@workspaceView)
# Private:
@@ -279,7 +281,7 @@ class Atom extends Model
return if not @project and not @workspaceView
@state.syntax = @syntax.serialize()
- @state.workspaceView = @workspaceView.serialize()
+ @state.workspace = @workspace.serialize()
@packages.deactivatePackages()
@state.packageStates = @packages.packageStates
@saveSync()
diff --git a/src/cursor-view.coffee b/src/cursor-view.coffee
index 5a5bff89f..f76de9436 100644
--- a/src/cursor-view.coffee
+++ b/src/cursor-view.coffee
@@ -49,7 +49,7 @@ class CursorView extends View
else if !@startBlinkingTimeout
@startBlinking()
- @setVisible(@cursor.isVisible() and not @editorView.isFoldedAtScreenRow(screenPosition.row))
+ @setVisible(@cursor.isVisible() and not @editorView.getEditor().isFoldedAtScreenRow(screenPosition.row))
# Override for speed. The base function checks the computedStyle
isHidden: ->
diff --git a/src/editor-view.coffee b/src/editor-view.coffee
index ccf6d7919..d8a2a947d 100644
--- a/src/editor-view.coffee
+++ b/src/editor-view.coffee
@@ -119,393 +119,118 @@ class EditorView extends View
# 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
+ 'core:move-left': => @editor.moveCursorLeft()
+ 'core:move-right': => @editor.moveCursorRight()
+ 'core:select-left': => @editor.selectLeft()
+ 'core:select-right': => @editor.selectRight()
+ 'core:select-all': => @editor.selectAll()
+ 'core:backspace': => @editor.backspace()
+ 'core:delete': => @editor.delete()
+ 'core:undo': => @editor.undo()
+ 'core:redo': => @editor.redo()
+ 'core:cut': => @editor.cutSelectedText()
+ 'core:copy': => @editor.copySelectedText()
+ 'core:paste': => @editor.pasteText()
+ 'editor:move-to-previous-word': => @editor.moveCursorToPreviousWord()
+ 'editor:select-word': => @editor.selectWord()
+ 'editor:consolidate-selections': (event) => @consolidateSelections(event)
+ 'editor:backspace-to-beginning-of-word': => @editor.backspaceToBeginningOfWord()
+ 'editor:backspace-to-beginning-of-line': => @editor.backspaceToBeginningOfLine()
+ 'editor:delete-to-end-of-word': => @editor.deleteToEndOfWord()
+ 'editor:delete-line': => @editor.deleteLine()
+ 'editor:cut-to-end-of-line': => @editor.cutToEndOfLine()
'editor:move-to-beginning-of-screen-line': => @editor.moveCursorToBeginningOfScreenLine()
- 'editor:move-to-beginning-of-line': @moveCursorToBeginningOfLine
+ 'editor:move-to-beginning-of-line': => @editor.moveCursorToBeginningOfLine()
'editor:move-to-end-of-screen-line': => @editor.moveCursorToEndOfScreenLine()
- '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
+ 'editor:move-to-end-of-line': => @editor.moveCursorToEndOfLine()
+ 'editor:move-to-first-character-of-line': => @editor.moveCursorToFirstCharacterOfLine()
+ 'editor:move-to-beginning-of-word': => @editor.moveCursorToBeginningOfWord()
+ 'editor:move-to-end-of-word': => @editor.moveCursorToEndOfWord()
+ 'editor:move-to-beginning-of-next-word': => @editor.moveCursorToBeginningOfNextWord()
+ 'editor:move-to-previous-word-boundary': => @editor.moveCursorToPreviousWordBoundary()
+ 'editor:move-to-next-word-boundary': => @editor.moveCursorToNextWordBoundary()
+ 'editor:select-to-end-of-line': => @editor.selectToEndOfLine()
+ 'editor:select-to-beginning-of-line': => @editor.selectToBeginningOfLine()
+ 'editor:select-to-end-of-word': => @editor.selectToEndOfWord()
+ 'editor:select-to-beginning-of-word': => @editor.selectToBeginningOfWord()
+ 'editor:select-to-beginning-of-next-word': => @editor.selectToBeginningOfNextWord()
+ 'editor:select-to-next-word-boundary': => @editor.selectToNextWordBoundary()
+ 'editor:select-to-previous-word-boundary': => @editor.selectToPreviousWordBoundary()
+ 'editor:select-to-first-character-of-line': => @editor.selectToFirstCharacterOfLine()
+ 'editor:select-line': => @editor.selectLine()
+ 'editor:transpose': => @editor.transpose()
+ 'editor:upper-case': => @editor.upperCase()
+ 'editor:lower-case': => @editor.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
+ 'core:move-up': => @editor.moveCursorUp()
+ 'core:move-down': => @editor.moveCursorDown()
+ 'core:move-to-top': => @editor.moveCursorToTop()
+ 'core:move-to-bottom': => @editor.moveCursorToBottom()
+ 'core:page-down': => @editor.pageDown()
+ 'core:page-up': => @editor.pageUp()
+ 'core:select-up': => @editor.selectUp()
+ 'core:select-down': => @editor.selectDown()
+ 'core:select-to-top': => @editor.selectToTop()
+ 'core:select-to-bottom': => @editor.selectToBottom()
+ 'editor:indent': => @editor.indent()
+ 'editor:auto-indent': => @editor.autoIndent()
+ 'editor:indent-selected-rows': => @editor.indentSelectedRows()
+ 'editor:outdent-selected-rows': => @editor.outdentSelectedRows()
+ 'editor:newline': => @editor.insertNewline()
+ 'editor:newline-below': => @editor.insertNewlineBelow()
+ 'editor:newline-above': => @editor.insertNewlineAbove()
+ 'editor:add-selection-below': => @editor.addSelectionBelow()
+ 'editor:add-selection-above': => @editor.addSelectionAbove()
'editor:split-selections-into-lines': => @editor.splitSelectionsIntoLines()
- '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-soft-tabs': => @toggleSoftTabs()
+ 'editor:toggle-soft-wrap': => @toggleSoftWrap()
+ 'editor:fold-all': => @editor.foldAll()
+ 'editor:unfold-all': => @editor.unfoldAll()
+ 'editor:fold-current-row': => @editor.foldCurrentRow()
+ 'editor:unfold-current-row': => @editor.unfoldCurrentRow()
+ 'editor:fold-selection': => @editor.foldSelection()
+ 'editor:fold-at-indent-level-1': => @editor.foldAllAtIndentLevel(0)
+ 'editor:fold-at-indent-level-2': => @editor.foldAllAtIndentLevel(1)
+ 'editor:fold-at-indent-level-3': => @editor.foldAllAtIndentLevel(2)
+ 'editor:fold-at-indent-level-4': => @editor.foldAllAtIndentLevel(3)
+ 'editor:fold-at-indent-level-5': => @editor.foldAllAtIndentLevel(4)
+ 'editor:fold-at-indent-level-6': => @editor.foldAllAtIndentLevel(5)
+ 'editor:fold-at-indent-level-7': => @editor.foldAllAtIndentLevel(6)
+ 'editor:fold-at-indent-level-8': => @editor.foldAllAtIndentLevel(7)
+ 'editor:fold-at-indent-level-9': => @editor.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': => @editor.moveLineUp()
+ 'editor:move-line-down': => @editor.moveLineDown()
+ 'editor:duplicate-line': => @editor.duplicateLine()
+ 'editor:join-line': => @editor.joinLine()
'editor:toggle-indent-guide': => atom.config.toggle('editor.showIndentGuide')
'editor:toggle-line-numbers': => atom.config.toggle('editor.showLineNumbers')
- 'editor:scroll-to-cursor': @scrollToCursorPosition
+ 'editor:scroll-to-cursor': => @scrollToCursorPosition()
documentation = {}
for name, method of editorBindings
do (name, method) =>
- @command name, (e) => method.call(this, e); false
+ @command name, (e) -> method(e); false
- # {Delegates to: Editor.getCursor}
- getCursor: -> @editor.getCursor()
+ getEditor: ->
+ @editor
- # {Delegates to: Editor.getCursors}
- getCursors: -> @editor.getCursors()
+ # {Delegates to: Editor.getText}
+ getText: ->
+ @editor.getText()
- # {Delegates to: Editor.addCursorAtScreenPosition}
- addCursorAtScreenPosition: (screenPosition) -> @editor.addCursorAtScreenPosition(screenPosition)
-
- # {Delegates to: Editor.addCursorAtBufferPosition}
- addCursorAtBufferPosition: (bufferPosition) -> @editor.addCursorAtBufferPosition(bufferPosition)
-
- # {Delegates to: Editor.moveCursorUp}
- moveCursorUp: -> @editor.moveCursorUp()
-
- # {Delegates to: Editor.moveCursorDown}
- moveCursorDown: -> @editor.moveCursorDown()
-
- # {Delegates to: Editor.moveCursorLeft}
- moveCursorLeft: -> @editor.moveCursorLeft()
-
- # {Delegates to: Editor.moveCursorRight}
- moveCursorRight: -> @editor.moveCursorRight()
-
- # {Delegates to: Editor.moveCursorToBeginningOfWord}
- moveCursorToBeginningOfWord: -> @editor.moveCursorToBeginningOfWord()
-
- # {Delegates to: Editor.moveCursorToEndOfWord}
- moveCursorToEndOfWord: -> @editor.moveCursorToEndOfWord()
-
- # {Delegates to: Editor.moveCursorToBeginningOfNextWord}
- moveCursorToBeginningOfNextWord: -> @editor.moveCursorToBeginningOfNextWord()
-
- # {Delegates to: Editor.moveCursorToTop}
- moveCursorToTop: -> @editor.moveCursorToTop()
-
- # {Delegates to: Editor.moveCursorToBottom}
- moveCursorToBottom: -> @editor.moveCursorToBottom()
-
- # {Delegates to: Editor.moveCursorToBeginningOfLine}
- moveCursorToBeginningOfLine: -> @editor.moveCursorToBeginningOfLine()
-
- # {Delegates to: Editor.moveCursorToFirstCharacterOfLine}
- moveCursorToFirstCharacterOfLine: -> @editor.moveCursorToFirstCharacterOfLine()
-
- # {Delegates to: Editor.moveCursorToPreviousWordBoundary}
- moveCursorToPreviousWordBoundary: -> @editor.moveCursorToPreviousWordBoundary()
-
- # {Delegates to: Editor.moveCursorToNextWordBoundary}
- moveCursorToNextWordBoundary: -> @editor.moveCursorToNextWordBoundary()
-
- # {Delegates to: Editor.moveCursorToEndOfLine}
- moveCursorToEndOfLine: -> @editor.moveCursorToEndOfLine()
-
- # {Delegates to: Editor.moveLineUp}
- moveLineUp: -> @editor.moveLineUp()
-
- # {Delegates to: Editor.moveLineDown}
- moveLineDown: -> @editor.moveLineDown()
-
- # {Delegates to: Editor.setCursorScreenPosition}
- setCursorScreenPosition: (position, options) -> @editor.setCursorScreenPosition(position, options)
-
- # {Delegates to: Editor.duplicateLine}
- duplicateLine: -> @editor.duplicateLine()
-
- # {Delegates to: Editor.joinLine}
- joinLine: -> @editor.joinLine()
-
- # {Delegates to: Editor.getCursorScreenPosition}
- getCursorScreenPosition: -> @editor.getCursorScreenPosition()
-
- # {Delegates to: Editor.getCursorScreenRow}
- getCursorScreenRow: -> @editor.getCursorScreenRow()
-
- # {Delegates to: Editor.setCursorBufferPosition}
- setCursorBufferPosition: (position, options) -> @editor.setCursorBufferPosition(position, options)
-
- # {Delegates to: Editor.getCursorBufferPosition}
- getCursorBufferPosition: -> @editor.getCursorBufferPosition()
-
- # {Delegates to: Editor.getCurrentParagraphBufferRange}
- getCurrentParagraphBufferRange: -> @editor.getCurrentParagraphBufferRange()
-
- # {Delegates to: Editor.getWordUnderCursor}
- getWordUnderCursor: (options) -> @editor.getWordUnderCursor(options)
-
- # {Delegates to: Editor.getSelection}
- getSelection: (index) -> @editor.getSelection(index)
-
- # {Delegates to: Editor.getSelections}
- getSelections: -> @editor.getSelections()
-
- # {Delegates to: Editor.getSelectionsOrderedByBufferPosition}
- getSelectionsOrderedByBufferPosition: -> @editor.getSelectionsOrderedByBufferPosition()
-
- # {Delegates to: Editor.getLastSelectionInBuffer}
- getLastSelectionInBuffer: -> @editor.getLastSelectionInBuffer()
-
- # {Delegates to: Editor.getSelectedText}
- getSelectedText: -> @editor.getSelectedText()
-
- # {Delegates to: Editor.getSelectedBufferRanges}
- getSelectedBufferRanges: -> @editor.getSelectedBufferRanges()
-
- # {Delegates to: Editor.getSelectedBufferRange}
- getSelectedBufferRange: -> @editor.getSelectedBufferRange()
-
- # {Delegates to: Editor.setSelectedBufferRange}
- setSelectedBufferRange: (bufferRange, options) -> @editor.setSelectedBufferRange(bufferRange, options)
-
- # {Delegates to: Editor.setSelectedBufferRanges}
- setSelectedBufferRanges: (bufferRanges, options) -> @editor.setSelectedBufferRanges(bufferRanges, options)
-
- # {Delegates to: Editor.addSelectionForBufferRange}
- addSelectionForBufferRange: (bufferRange, options) -> @editor.addSelectionForBufferRange(bufferRange, options)
-
- # {Delegates to: Editor.selectRight}
- selectRight: -> @editor.selectRight()
-
- # {Delegates to: Editor.selectLeft}
- selectLeft: -> @editor.selectLeft()
-
- # {Delegates to: Editor.selectUp}
- selectUp: -> @editor.selectUp()
-
- # {Delegates to: Editor.selectDown}
- selectDown: -> @editor.selectDown()
-
- # {Delegates to: Editor.selectToTop}
- selectToTop: -> @editor.selectToTop()
-
- # {Delegates to: Editor.selectToBottom}
- selectToBottom: -> @editor.selectToBottom()
-
- # {Delegates to: Editor.selectAll}
- selectAll: -> @editor.selectAll()
-
- # {Delegates to: Editor.selectToBeginningOfLine}
- selectToBeginningOfLine: -> @editor.selectToBeginningOfLine()
-
- # {Delegates to: Editor.selectToFirstCharacterOfLine}
- selectToFirstCharacterOfLine: -> @editor.selectToFirstCharacterOfLine()
-
- # {Delegates to: Editor.selectToEndOfLine}
- selectToEndOfLine: -> @editor.selectToEndOfLine()
-
- # {Delegates to: Editor.selectToPreviousWordBoundary}
- selectToPreviousWordBoundary: -> @editor.selectToPreviousWordBoundary()
-
- # {Delegates to: Editor.selectToNextWordBoundary}
- selectToNextWordBoundary: -> @editor.selectToNextWordBoundary()
-
- # {Delegates to: Editor.addSelectionBelow}
- addSelectionBelow: -> @editor.addSelectionBelow()
-
- # {Delegates to: Editor.addSelectionAbove}
- addSelectionAbove: -> @editor.addSelectionAbove()
-
- # {Delegates to: Editor.selectToBeginningOfWord}
- selectToBeginningOfWord: -> @editor.selectToBeginningOfWord()
-
- # {Delegates to: Editor.selectToEndOfWord}
- selectToEndOfWord: -> @editor.selectToEndOfWord()
-
- # {Delegates to: Editor.selectToBeginningOfNextWord}
- selectToBeginningOfNextWord: -> @editor.selectToBeginningOfNextWord()
-
- # {Delegates to: Editor.selectWord}
- selectWord: -> @editor.selectWord()
-
- # {Delegates to: Editor.selectLine}
- selectLine: -> @editor.selectLine()
-
- # {Delegates to: Editor.selectToScreenPosition}
- selectToScreenPosition: (position) -> @editor.selectToScreenPosition(position)
-
- # {Delegates to: Editor.transpose}
- transpose: -> @editor.transpose()
-
- # {Delegates to: Editor.upperCase}
- upperCase: -> @editor.upperCase()
-
- # {Delegates to: Editor.lowerCase}
- lowerCase: -> @editor.lowerCase()
-
- # {Delegates to: Editor.clearSelections}
- clearSelections: -> @editor.clearSelections()
-
- # {Delegates to: Editor.backspace}
- backspace: -> @editor.backspace()
-
- # {Delegates to: Editor.backspaceToBeginningOfWord}
- backspaceToBeginningOfWord: -> @editor.backspaceToBeginningOfWord()
-
- # {Delegates to: Editor.backspaceToBeginningOfLine}
- backspaceToBeginningOfLine: -> @editor.backspaceToBeginningOfLine()
-
- # {Delegates to: Editor.delete}
- delete: -> @editor.delete()
-
- # {Delegates to: Editor.deleteToEndOfWord}
- deleteToEndOfWord: -> @editor.deleteToEndOfWord()
-
- # {Delegates to: Editor.deleteLine}
- deleteLine: -> @editor.deleteLine()
-
- # {Delegates to: Editor.cutToEndOfLine}
- cutToEndOfLine: -> @editor.cutToEndOfLine()
+ # {Delegates to: Editor.setText}
+ setText: (text) ->
+ @editor.setText(text)
# {Delegates to: Editor.insertText}
- insertText: (text, options) -> @editor.insertText(text, options)
-
- # {Delegates to: Editor.insertNewline}
- insertNewline: -> @editor.insertNewline()
-
- # {Delegates to: Editor.insertNewlineBelow}
- insertNewlineBelow: -> @editor.insertNewlineBelow()
-
- # {Delegates to: Editor.insertNewlineAbove}
- insertNewlineAbove: -> @editor.insertNewlineAbove()
-
- # {Delegates to: Editor.indent}
- indent: (options) -> @editor.indent(options)
-
- # {Delegates to: Editor.autoIndentSelectedRows}
- autoIndent: (options) -> @editor.autoIndentSelectedRows()
-
- # {Delegates to: Editor.indentSelectedRows}
- indentSelectedRows: -> @editor.indentSelectedRows()
-
- # {Delegates to: Editor.outdentSelectedRows}
- outdentSelectedRows: -> @editor.outdentSelectedRows()
-
- # {Delegates to: Editor.cutSelectedText}
- cutSelection: -> @editor.cutSelectedText()
-
- # {Delegates to: Editor.copySelectedText}
- copySelection: -> @editor.copySelectedText()
-
- # {Delegates to: Editor.pasteText}
- paste: (options) -> @editor.pasteText(options)
-
- # {Delegates to: Editor.undo}
- undo: -> @editor.undo()
-
- # {Delegates to: Editor.redo}
- redo: -> @editor.redo()
-
- # {Delegates to: Editor.createFold}
- createFold: (startRow, endRow) -> @editor.createFold(startRow, endRow)
-
- # {Delegates to: Editor.foldCurrentRow}
- foldCurrentRow: -> @editor.foldCurrentRow()
-
- # {Delegates to: Editor.unfoldCurrentRow}
- unfoldCurrentRow: -> @editor.unfoldCurrentRow()
-
- # {Delegates to: Editor.foldAll}
- foldAll: -> @editor.foldAll()
-
- # {Delegates to: Editor.unfoldAll}
- unfoldAll: -> @editor.unfoldAll()
-
- # {Delegates to: Editor.foldSelection}
- foldSelection: -> @editor.foldSelection()
-
- # {Delegates to: Editor.destroyFoldsContainingBufferRow}
- destroyFoldsContainingBufferRow: (bufferRow) -> @editor.destroyFoldsContainingBufferRow(bufferRow)
-
- # {Delegates to: Editor.isFoldedAtScreenRow}
- isFoldedAtScreenRow: (screenRow) -> @editor.isFoldedAtScreenRow(screenRow)
-
- # {Delegates to: Editor.isFoldedAtBufferRow}
- isFoldedAtBufferRow: (bufferRow) -> @editor.isFoldedAtBufferRow(bufferRow)
-
- # {Delegates to: Editor.isFoldedAtCursorRow}
- isFoldedAtCursorRow: -> @editor.isFoldedAtCursorRow()
-
- foldAllAtIndentLevel: (indentLevel) -> @editor.foldAllAtIndentLevel(indentLevel)
-
- # {Delegates to: Editor.lineForScreenRow}
- lineForScreenRow: (screenRow) -> @editor.lineForScreenRow(screenRow)
-
- # {Delegates to: Editor.linesForScreenRows}
- linesForScreenRows: (start, end) -> @editor.linesForScreenRows(start, end)
-
- # {Delegates to: Editor.getScreenLineCount}
- getScreenLineCount: -> @editor.getScreenLineCount()
+ insertText: (text, options) ->
+ @editor.insertText(text, options)
# Private:
setHeightInLines: (heightInLines)->
@@ -517,30 +242,6 @@ class EditorView extends View
widthInChars ?= @calculateWidthInChars()
@editor.setEditorWidthInChars(widthInChars) if widthInChars
- # {Delegates to: Editor.getMaxScreenLineLength}
- getMaxScreenLineLength: -> @editor.getMaxScreenLineLength()
-
- # {Delegates to: Editor.getLastScreenRow}
- getLastScreenRow: -> @editor.getLastScreenRow()
-
- # {Delegates to: Editor.clipScreenPosition}
- clipScreenPosition: (screenPosition, options={}) -> @editor.clipScreenPosition(screenPosition, options)
-
- # {Delegates to: Editor.screenPositionForBufferPosition}
- screenPositionForBufferPosition: (position, options) -> @editor.screenPositionForBufferPosition(position, options)
-
- # {Delegates to: Editor.bufferPositionForScreenPosition}
- bufferPositionForScreenPosition: (position, options) -> @editor.bufferPositionForScreenPosition(position, options)
-
- # {Delegates to: Editor.screenRangeForBufferRange}
- screenRangeForBufferRange: (range) -> @editor.screenRangeForBufferRange(range)
-
- # {Delegates to: Editor.bufferRangeForScreenRange}
- bufferRangeForScreenRange: (range) -> @editor.bufferRangeForScreenRange(range)
-
- # {Delegates to: Editor.bufferRowsForScreenRows}
- bufferRowsForScreenRows: (startRow, endRow) -> @editor.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
@@ -600,51 +301,9 @@ class EditorView extends View
# Checkout the HEAD revision of this editor's file.
checkoutHead: ->
- if path = @getPath()
+ if path = @editor.getPath()
atom.project.getRepo()?.checkoutHead(path)
- # {Delegates to: Editor.setText}
- setText: (text) -> @editor.setText(text)
-
- # {Delegates to: Editor.save}
- save: -> @editor.save()
-
- # {Delegates to: Editor.getText}
- getText: -> @editor.getText()
-
- # {Delegates to: Editor.getPath}
- getPath: -> @editor?.getPath()
-
- # {Delegates to: Editor.transact}
- transact: (fn) -> @editor.transact(fn)
-
- # {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: ->
@@ -695,11 +354,11 @@ class EditorView extends View
screenPosition = @screenPositionFromMouseEvent(e)
if clickCount == 1
if e.metaKey
- @addCursorAtScreenPosition(screenPosition)
+ @editor.addCursorAtScreenPosition(screenPosition)
else if e.shiftKey
- @selectToScreenPosition(screenPosition)
+ @editor.selectToScreenPosition(screenPosition)
else
- @setCursorScreenPosition(screenPosition)
+ @editor.setCursorScreenPosition(screenPosition)
else if clickCount == 2
@editor.selectWord() unless e.shiftKey
else if clickCount == 3
@@ -744,9 +403,9 @@ class EditorView extends View
selectedText = @getSelectedText()
@hiddenInput.css('width', '100%')
@hiddenInput.on 'compositionupdate', (e) =>
- @insertText(e.originalEvent.data, {select: true, undo: 'skip'})
+ @editor.insertText(e.originalEvent.data, {select: true, undo: 'skip'})
@hiddenInput.on 'compositionend', =>
- @insertText(selectedText, {select: true, undo: 'skip'})
+ @editor.insertText(selectedText, {select: true, undo: 'skip'})
@hiddenInput.css('width', '1px')
lastInput = ''
@@ -757,7 +416,7 @@ class EditorView extends View
@selectLeft()
lastInput = e.originalEvent.data
- @insertText(lastInput)
+ @editor.insertText(lastInput)
@hiddenInput.val(lastInput)
false
@@ -768,7 +427,7 @@ class EditorView extends View
lastMoveEvent = null
moveHandler = (event = lastMoveEvent) =>
if event
- @selectToScreenPosition(@screenPositionFromMouseEvent(event))
+ @editor.selectToScreenPosition(@screenPositionFromMouseEvent(event))
lastMoveEvent = event
$(document).on "mousemove.editor-#{@id}", moveHandler
@@ -814,6 +473,7 @@ class EditorView extends View
@trigger 'editor:attached', [this]
+ # TODO: This should be private and only called from the constructor
edit: (editor) ->
return if editor is @editor
@@ -834,7 +494,7 @@ class EditorView extends View
@showBufferConflictAlert(@editor)
@editor.on "path-changed.editor", =>
- @reloadGrammar()
+ @editor.reloadGrammar()
@trigger 'editor:path-changed'
@editor.on "grammar-changed.editor", =>
@@ -917,20 +577,15 @@ class EditorView extends View
### Public ###
- # Retrieves the {Editor}'s buffer.
- #
- # Returns the current {TextBuffer}.
- getBuffer: -> @editor.buffer
-
# Scrolls the editor to the bottom.
scrollToBottom: ->
- @scrollBottom(@getScreenLineCount() * @lineHeight)
+ @scrollBottom(@editor.getScreenLineCount() * @lineHeight)
# Scrolls the editor to the position of the most recently added cursor.
#
# The editor is also centered.
scrollToCursorPosition: ->
- @scrollToBufferPosition(@getCursorBufferPosition(), center: true)
+ @scrollToBufferPosition(@editor.getCursorBufferPosition(), center: true)
# Scrolls the editor to the given buffer position.
#
@@ -966,7 +621,7 @@ class EditorView extends View
#
# bufferRange - The {Range} to check.
highlightFoldsContainingBufferRange: (bufferRange) ->
- screenLines = @linesForScreenRows(@firstRenderedScreenRow, @lastRenderedScreenRow)
+ screenLines = @editor.linesForScreenRows(@firstRenderedScreenRow, @lastRenderedScreenRow)
for screenLine, i in screenLines
if fold = screenLine.fold
screenRow = @firstRenderedScreenRow + i
@@ -1180,7 +835,7 @@ class EditorView extends View
@setHeightInLines()
updateLayerDimensions: ->
- height = @lineHeight * @getScreenLineCount()
+ height = @lineHeight * @editor.getScreenLineCount()
unless @layerHeight == height
@layerHeight = height
@underlayer.height(@layerHeight)
@@ -1189,7 +844,7 @@ class EditorView extends View
@verticalScrollbarContent.height(@layerHeight)
@scrollBottom(height) if @scrollBottom() > height
- minWidth = Math.max(@charWidth * @getMaxScreenLineLength() + 20, @scrollView.width())
+ minWidth = Math.max(@charWidth * @editor.getMaxScreenLineLength() + 20, @scrollView.width())
unless @layerMinWidth == minWidth
@renderedLines.css('min-width', minWidth)
@underlayer.css('min-width', minWidth)
@@ -1303,9 +958,9 @@ class EditorView extends View
updatePlaceholderText: ->
return unless @mini
- if (not @placeholderText) or @getText()
+ if (not @placeholderText) or @editor.getText()
@find('.placeholder-text').remove()
- else if @placeholderText and not @getText()
+ else if @placeholderText and not @editor.getText()
element = @find('.placeholder-text')
if element.length
element.text(@placeholderText)
@@ -1315,7 +970,7 @@ class EditorView extends View
updateRenderedLines: ->
firstVisibleScreenRow = @getFirstVisibleScreenRow()
lastScreenRowToRender = firstVisibleScreenRow + @heightInLines - 1
- lastScreenRow = @getLastScreenRow()
+ lastScreenRow = @editor.getLastScreenRow()
if @firstRenderedScreenRow? and firstVisibleScreenRow >= @firstRenderedScreenRow and lastScreenRowToRender <= @lastRenderedScreenRow
renderFrom = Math.min(lastScreenRow, @firstRenderedScreenRow)
@@ -1344,15 +999,15 @@ class EditorView extends View
if change.bufferDelta?
afterStart = change.end + change.bufferDelta + 1
- if @lineForBufferRow(afterStart) is ''
+ if @editor.lineForBufferRow(afterStart) is ''
afterEnd = afterStart
- afterEnd++ while @lineForBufferRow(afterEnd + 1) is ''
+ afterEnd++ while @editor.lineForBufferRow(afterEnd + 1) is ''
emptyLineChanges.push({start: afterStart, end: afterEnd, screenDelta: 0})
beforeEnd = change.start - 1
- if @lineForBufferRow(beforeEnd) is ''
+ if @editor.lineForBufferRow(beforeEnd) is ''
beforeStart = beforeEnd
- beforeStart-- while @lineForBufferRow(beforeStart - 1) is ''
+ beforeStart-- while @editor.lineForBufferRow(beforeStart - 1) is ''
emptyLineChanges.push({start: beforeStart, end: beforeEnd, screenDelta: 0})
emptyLineChanges
@@ -1461,7 +1116,7 @@ class EditorView extends View
@renderedLines.css('padding-top', paddingTop)
@gutter.lineNumbers.css('padding-top', paddingTop)
- paddingBottom = (@getLastScreenRow() - @lastRenderedScreenRow) * @lineHeight
+ paddingBottom = (@editor.getLastScreenRow() - @lastRenderedScreenRow) * @lineHeight
@renderedLines.css('padding-bottom', paddingBottom)
@gutter.lineNumbers.css('padding-bottom', paddingBottom)
@@ -1480,7 +1135,7 @@ class EditorView extends View
# Returns a {Number}.
getLastVisibleScreenRow: ->
calculatedRow = Math.ceil((@scrollTop() + @scrollView.height()) / @lineHeight) - 1
- screenRow = Math.max(0, Math.min(@getScreenLineCount() - 1, calculatedRow))
+ screenRow = Math.max(0, Math.min(@editor.getScreenLineCount() - 1, calculatedRow))
screenRow = 0 if isNaN(screenRow)
screenRow
@@ -1585,7 +1240,7 @@ class EditorView extends View
#
# Returns an object with two values: `top` and `left`, representing the pixel positions.
pixelPositionForBufferPosition: (position) ->
- @pixelPositionForScreenPosition(@screenPositionForBufferPosition(position))
+ @pixelPositionForScreenPosition(@editor.screenPositionForBufferPosition(position))
# Converts a screen position to a pixel position.
#
@@ -1734,31 +1389,15 @@ class EditorView extends View
return if @mini
@highlightedLine?.removeClass('cursor-line')
- if @getSelection().isEmpty()
- @highlightedLine = @lineElementForScreenRow(@getCursorScreenRow())
+ if @editor.getSelection().isEmpty()
+ @highlightedLine = @lineElementForScreenRow(@editor.getCursorScreenRow())
@highlightedLine.addClass('cursor-line')
else
@highlightedLine = null
- # {Delegates to: Editor.getGrammar}
- getGrammar: ->
- @editor.getGrammar()
-
- # {Delegates to: Editor.setGrammar}
- setGrammar: (grammar) ->
- @editor.setGrammar(grammar)
-
- # {Delegates to: Editor.reloadGrammar}
- reloadGrammar: ->
- @editor.reloadGrammar()
-
- # {Delegates to: Editor.scopesForBufferPosition}
- scopesForBufferPosition: (bufferPosition) ->
- @editor.scopesForBufferPosition(bufferPosition)
-
# Copies the current file path to the native clipboard.
copyPathToPasteboard: ->
- path = @getPath()
+ path = @editor.getPath()
atom.pasteboard.write(path) if path?
### Internal ###
@@ -1845,13 +1484,13 @@ class EditorView extends View
' '
replaceSelectedText: (replaceFn) ->
- selection = @getSelection()
+ selection = @editor.getSelection()
return false if selection.isEmpty()
- text = replaceFn(@getTextInRange(selection.getBufferRange()))
+ text = replaceFn(@editor.getTextInRange(selection.getBufferRange()))
return false if text is null or text is undefined
- @insertText(text, select: true)
+ @editor.insertText(text, select: true)
true
consolidateSelections: (e) -> e.abortKeyBinding() unless @editor.consolidateSelections()
@@ -1859,12 +1498,6 @@ class EditorView extends View
logCursorScope: ->
console.log @editor.getCursorScopes()
- beginTransaction: -> @editor.beginTransaction()
-
- commitTransaction: -> @editor.commitTransaction()
-
- abortTransaction: -> @editor.abortTransaction()
-
logScreenLines: (start, end) ->
@editor.logScreenLines(start, end)
diff --git a/src/editor.coffee b/src/editor.coffee
index 7e72e43ba..40615a4bf 100644
--- a/src/editor.coffee
+++ b/src/editor.coffee
@@ -930,7 +930,7 @@ class Editor extends Model
# Public:
#
- # FIXME: What does this do?
+ # Removes all but one cursor (if there are multiple cursors)
consolidateSelections: ->
selections = @getSelections()
if selections.length > 1
diff --git a/src/gutter.coffee b/src/gutter.coffee
index be02dc6d4..9aff208ea 100644
--- a/src/gutter.coffee
+++ b/src/gutter.coffee
@@ -34,21 +34,22 @@ class Gutter extends View
handleMouseEvents: (e) ->
editorView = @getEditorView()
+ editor = @getEditor()
startRow = editorView.screenPositionFromMouseEvent(e).row
if e.shiftKey
- editorView.selectToScreenPosition([startRow + 1, 0])
+ editor.selectToScreenPosition([startRow + 1, 0])
return
else
- editorView.getSelection().setScreenRange([[startRow, 0], [startRow, 0]])
+ editor.getSelection().setScreenRange([[startRow, 0], [startRow, 0]])
moveHandler = (e) =>
start = startRow
end = editorView.screenPositionFromMouseEvent(e).row
if end > start then end++ else start++
- editorView.getSelection().setScreenRange([[start, 0], [end, 0]])
+ editor.getSelection().setScreenRange([[start, 0], [end, 0]])
- $(document).on "mousemove.gutter-#{@getEditorView().id}", moveHandler
- $(document).one "mouseup.gutter-#{@getEditorView().id}", => $(document).off 'mousemove', moveHandler
+ $(document).on "mousemove.gutter-#{editorView.id}", moveHandler
+ $(document).one "mouseup.gutter-#{editorView.id}", => $(document).off 'mousemove', moveHandler
### Public ###
@@ -58,6 +59,9 @@ class Gutter extends View
getEditorView: ->
@parentView
+ getEditor: ->
+ @getEditorView().getEditor()
+
# Defines whether to show the gutter or not.
#
# showLineNumbers - A {Boolean} which, if `false`, hides the gutter
@@ -192,9 +196,9 @@ class Gutter extends View
@elementBuilder.children
buildLineElementsHtml: (startScreenRow, endScreenRow) =>
- editorView = @getEditorView()
- maxDigits = editorView.getLineCount().toString().length
- rows = editorView.bufferRowsForScreenRows(startScreenRow, endScreenRow)
+ editor = @getEditor()
+ maxDigits = editor.getLineCount().toString().length
+ rows = editor.bufferRowsForScreenRows(startScreenRow, endScreenRow)
html = ''
for row in rows
@@ -204,7 +208,7 @@ class Gutter extends View
rowValue = (row + 1).toString()
classes = "line-number line-number-#{row}"
- classes += ' fold' if editorView.isFoldedAtBufferRow(row)
+ classes += ' fold' if editor.isFoldedAtBufferRow(row)
rowValuePadding = _.multiplyString(' ', maxDigits - rowValue.length)
@@ -230,10 +234,11 @@ class Gutter extends View
@highlightedLineNumbers.push(highlightedLineNumber)
highlightLines: ->
- return unless @getEditorView().editor?.isAlive()
+ editor = @getEditor()
+ return unless editor?.isAlive()
- if @getEditorView().getSelection().isEmpty()
- row = @getEditorView().getCursorScreenPosition().row
+ if editor.getSelection().isEmpty()
+ row = editor.getCursorScreenPosition().row
rowRange = new Range([row, 0], [row, 0])
return if @selectionEmpty and @highlightedRows?.isEqual(rowRange)
@@ -242,7 +247,7 @@ class Gutter extends View
@highlightedRows = rowRange
@selectionEmpty = true
else
- selectedRows = @getEditorView().getSelection().getScreenRange()
+ selectedRows = editor.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/pane-container-view.coffee b/src/pane-container-view.coffee
index a55a1d65b..7c1ee5533 100644
--- a/src/pane-container-view.coffee
+++ b/src/pane-container-view.coffee
@@ -1,4 +1,4 @@
-Serializable = require 'serializable'
+Delegator = require 'delegato'
{$, View} = require './space-pen-extensions'
PaneView = require './pane-view'
PaneContainer = require './pane-container'
@@ -6,11 +6,9 @@ PaneContainer = require './pane-container'
# Private: Manages the list of panes within a {WorkspaceView}
module.exports =
class PaneContainerView extends View
- atom.deserializers.add(this)
- Serializable.includeInto(this)
+ Delegator.includeInto(this)
- @deserialize: (state) ->
- new this(PaneContainer.deserialize(state.model))
+ @delegatesMethod 'saveAll', toProperty: 'model'
@content: ->
@div class: 'panes'
@@ -29,14 +27,8 @@ class PaneContainerView extends View
viewClass = model.getViewClass()
model._view ?= new viewClass(model)
- serializeParams: ->
- model: @model.serialize()
-
### Public ###
- itemDestroyed: (item) ->
- @trigger 'item-destroyed', [item]
-
getRoot: ->
@children().first().view()
@@ -65,9 +57,6 @@ class PaneContainerView extends View
@setRoot(null)
@trigger 'pane:removed', [child] if child instanceof PaneView
- saveAll: ->
- pane.saveItems() for pane in @getPanes()
-
confirmClose: ->
saved = true
for pane in @getPanes()
@@ -105,28 +94,10 @@ class PaneContainerView extends View
@getActivePane()?.activeView
paneForUri: (uri) ->
- for pane in @getPanes()
- view = pane.itemForUri(uri)
- return pane if view?
- null
+ @viewForModel(@model.paneForUri(uri))
focusNextPane: ->
- panes = @getPanes()
- if panes.length > 1
- currentIndex = panes.indexOf(@getFocusedPane())
- nextIndex = (currentIndex + 1) % panes.length
- panes[nextIndex].focus()
- true
- else
- false
+ @model.activateNextPane()
focusPreviousPane: ->
- panes = @getPanes()
- if panes.length > 1
- currentIndex = panes.indexOf(@getFocusedPane())
- previousIndex = currentIndex - 1
- previousIndex = panes.length - 1 if previousIndex < 0
- panes[previousIndex].focus()
- true
- else
- false
+ @model.activatePreviousPane()
diff --git a/src/pane-container.coffee b/src/pane-container.coffee
index 14803afc8..9f0dfc7ea 100644
--- a/src/pane-container.coffee
+++ b/src/pane-container.coffee
@@ -1,3 +1,4 @@
+{find} = require 'underscore-plus'
{Model} = require 'theorist'
Serializable = require 'serializable'
Pane = require './pane'
@@ -36,14 +37,32 @@ class PaneContainer extends Model
getPanes: ->
@root?.getPanes() ? []
+ paneForUri: (uri) ->
+ find @getPanes(), (pane) -> pane.itemForUri(uri)?
+
+ saveAll: ->
+ pane.saveItems() for pane in @getPanes()
+
activateNextPane: ->
panes = @getPanes()
if panes.length > 1
currentIndex = panes.indexOf(@activePane)
nextIndex = (currentIndex + 1) % panes.length
panes[nextIndex].activate()
+ true
else
- @activePane = null
+ false
+
+ activatePreviousPane: ->
+ panes = @getPanes()
+ if panes.length > 1
+ currentIndex = panes.indexOf(@activePane)
+ previousIndex = currentIndex - 1
+ previousIndex = panes.length - 1 if previousIndex < 0
+ panes[previousIndex].activate()
+ true
+ else
+ false
onRootChanged: (root) =>
@unsubscribe(@previousRoot) if @previousRoot?
@@ -64,3 +83,6 @@ class PaneContainer extends Model
destroyEmptyPanes: ->
pane.destroy() for pane in @getPanes() when pane.items.length is 0
+
+ itemDestroyed: (item) ->
+ @emit 'item-destroyed', item
diff --git a/src/pane-model.coffee b/src/pane-model.coffee
deleted file mode 100644
index a6902968a..000000000
--- a/src/pane-model.coffee
+++ /dev/null
@@ -1,307 +0,0 @@
-{find, compact, extend} = require 'underscore-plus'
-{dirname} = require 'path'
-{Model, Sequence} = require 'theorist'
-Serializable = require 'serializable'
-PaneAxis = require './pane-axis'
-PaneView = null
-
-# Public: A container for multiple items, one of which is *active* at a given
-# time. With the default packages, a tab is displayed for each item and the
-# active item's view is displayed.
-module.exports =
-class PaneModel extends Model
- atom.deserializers.add(this)
- Serializable.includeInto(this)
-
- @properties
- container: null
- activeItem: null
- focused: false
-
- # Public: Only one pane is considered *active* at a time. A pane is activated
- # when it is focused, and when focus returns to the pane container after
- # moving to another element such as a panel, it returns to the active pane.
- @behavior 'active', ->
- @$container
- .switch((container) -> container?.$activePane)
- .map((activePane) => activePane is this)
- .distinctUntilChanged()
-
- # Private:
- constructor: (params) ->
- super
-
- @items = Sequence.fromArray(params?.items ? [])
- @activeItem ?= @items[0]
-
- @subscribe @items.onEach (item) =>
- if typeof item.on is 'function'
- @subscribe item, 'destroyed', => @removeItem(item)
-
- @subscribe @items.onRemoval (item, index) =>
- @unsubscribe item if typeof item.on is 'function'
-
- @activate() if params?.active
-
- # Private: Called by the Serializable mixin during serialization.
- serializeParams: ->
- items: compact(@items.map((item) -> item.serialize?()))
- activeItemUri: @activeItem?.getUri?()
- focused: @focused
- active: @active
-
- # Private: Called by the Serializable mixin during deserialization.
- deserializeParams: (params) ->
- {items, activeItemUri} = params
- params.items = compact(items.map (itemState) -> atom.deserializers.deserialize(itemState))
- params.activeItem = find params.items, (item) -> item.getUri?() is activeItemUri
- params
-
- # Private: Called by the view layer to construct a view for this model.
- getViewClass: -> PaneView ?= require './pane-view'
-
- isActive: -> @active
-
- # Private: Called by the view layer to indicate that the pane has gained focus.
- focus: ->
- @focused = true
- @activate() unless @isActive()
-
- # Private: Called by the view layer to indicate that the pane has lost focus.
- blur: ->
- @focused = false
- true # if this is called from an event handler, don't cancel it
-
- # Public: Makes this pane the *active* pane, causing it to gain focus
- # immediately.
- activate: ->
- @container?.activePane = this
- @emit 'activated'
-
- # Private:
- getPanes: -> [this]
-
- # Public:
- getItems: ->
- @items.slice()
-
- # Public: Returns the item at the specified index.
- itemAtIndex: (index) ->
- @items[index]
-
- # Public: Makes the next item active.
- activateNextItem: ->
- index = @getActiveItemIndex()
- if index < @items.length - 1
- @activateItemAtIndex(index + 1)
- else
- @activateItemAtIndex(0)
-
- # Public: Makes the previous item active.
- activatePreviousItem: ->
- index = @getActiveItemIndex()
- if index > 0
- @activateItemAtIndex(index - 1)
- else
- @activateItemAtIndex(@items.length - 1)
-
- # Public: Returns the index of the current active item.
- getActiveItemIndex: ->
- @items.indexOf(@activeItem)
-
- # Public: Makes the item at the given index active.
- activateItemAtIndex: (index) ->
- @activateItem(@itemAtIndex(index))
-
- # Public: Makes the given item active, adding the item if necessary.
- activateItem: (item) ->
- if item?
- @addItem(item)
- @activeItem = item
-
- # Public: Adds the item to the pane.
- #
- # * item:
- # The item to add. It can be a model with an associated view or a view.
- # * index:
- # An optional index at which to add the item. If omitted, the item is
- # added to the end.
- #
- # Returns the added item
- addItem: (item, index=@getActiveItemIndex() + 1) ->
- return if item in @items
-
- @items.splice(index, 0, item)
- @emit 'item-added', item, index
- item
-
- # Private:
- removeItem: (item, destroying) ->
- index = @items.indexOf(item)
- return if index is -1
- @activateNextItem() if item is @activeItem and @items.length > 1
- @items.splice(index, 1)
- @emit 'item-removed', item, index, destroying
- @destroy() if @items.length is 0
-
- # Public: Moves the given item to the specified index.
- moveItem: (item, newIndex) ->
- oldIndex = @items.indexOf(item)
- @items.splice(oldIndex, 1)
- @items.splice(newIndex, 0, item)
- @emit 'item-moved', item, newIndex
-
- # Public: Moves the given item to the given index at another pane.
- moveItemToPane: (item, pane, index) ->
- pane.addItem(item, index)
- @removeItem(item)
-
- # Public: Destroys the currently active item and make the next item active.
- destroyActiveItem: ->
- @destroyItem(@activeItem)
- false
-
- # Public: Destroys the given item. If it is the active item, activate the next
- # one. If this is the last item, also destroys the pane.
- destroyItem: (item) ->
- @emit 'before-item-destroyed', item
- if @promptToSaveItem(item)
- @emit 'item-destroyed', item
- @removeItem(item, true)
- item.destroy?()
- true
- else
- false
-
- # Public: Destroys all items and destroys the pane.
- destroyItems: ->
- @destroyItem(item) for item in @getItems()
-
- # Public: Destroys all items but the active one.
- destroyInactiveItems: ->
- @destroyItem(item) for item in @getItems() when item isnt @activeItem
-
- # Private: Called by model superclass.
- destroyed: ->
- @container.activateNextPane() if @isActive()
- item.destroy?() for item in @items.slice()
-
- # Public: Prompts the user to save the given item if it can be saved and is
- # currently unsaved.
- promptToSaveItem: (item) ->
- return true unless item.shouldPromptToSave?()
-
- uri = item.getUri()
- chosen = atom.confirm
- message: "'#{item.getTitle?() ? item.getUri()}' has changes, do you want to save them?"
- detailedMessage: "Your changes will be lost if you close this item without saving."
- buttons: ["Save", "Cancel", "Don't Save"]
-
- switch chosen
- when 0 then @saveItem(item, -> true)
- when 1 then false
- when 2 then true
-
- # Public: Saves the active item.
- saveActiveItem: ->
- @saveItem(@activeItem)
-
- # Public: Saves the active item at a prompted-for location.
- saveActiveItemAs: ->
- @saveItemAs(@activeItem)
-
- # Public: Saves the specified item.
- #
- # * item: The item to save.
- # * nextAction: An optional function which will be called after the item is saved.
- saveItem: (item, nextAction) ->
- if item.getUri?()
- item.save?()
- nextAction?()
- else
- @saveItemAs(item, nextAction)
-
- # Public: Saves the given item at a prompted-for location.
- #
- # * item: The item to save.
- # * nextAction: An optional function which will be called after the item is saved.
- saveItemAs: (item, nextAction) ->
- return unless item.saveAs?
-
- itemPath = item.getPath?()
- itemPath = dirname(itemPath) if itemPath
- path = atom.showSaveDialogSync(itemPath)
- if path
- item.saveAs(path)
- nextAction?()
-
- # Public: Saves all items.
- saveItems: ->
- @saveItem(item) for item in @getItems()
-
- # Public: Returns the first item that matches the given URI or undefined if
- # none exists.
- itemForUri: (uri) ->
- find @items, (item) -> item.getUri?() is uri
-
- # Public: Activates the first item that matches the given URI. Returns a
- # boolean indicating whether a matching item was found.
- activateItemForUri: (uri) ->
- if item = @itemForUri(uri)
- @activateItem(item)
- true
- else
- false
-
- # Private:
- copyActiveItem: ->
- @activeItem.copy?() ? atom.deserializers.deserialize(@activeItem.serialize())
-
- # Public: Creates a new pane to the left of the receiver.
- #
- # * params:
- # + items: An optional array of items with which to construct the new pane.
- #
- # Returns the new {PaneModel}.
- splitLeft: (params) ->
- @split('horizontal', 'before', params)
-
- # Public: Creates a new pane to the right of the receiver.
- #
- # * params:
- # + items: An optional array of items with which to construct the new pane.
- #
- # Returns the new {PaneModel}.
- splitRight: (params) ->
- @split('horizontal', 'after', params)
-
- # Public: Creates a new pane above the receiver.
- #
- # * params:
- # + items: An optional array of items with which to construct the new pane.
- #
- # Returns the new {PaneModel}.
- splitUp: (params) ->
- @split('vertical', 'before', params)
-
- # Public: Creates a new pane below the receiver.
- #
- # * params:
- # + items: An optional array of items with which to construct the new pane.
- #
- # Returns the new {PaneModel}.
- splitDown: (params) ->
- @split('vertical', 'after', params)
-
- # Private:
- split: (orientation, side, params) ->
- if @parent.orientation isnt orientation
- @parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this]}))
-
- newPane = new @constructor(extend({focused: true}, params))
- switch side
- when 'before' then @parent.insertChildBefore(this, newPane)
- when 'after' then @parent.insertChildAfter(this, newPane)
-
- newPane.activate()
- newPane
diff --git a/src/pane-view.coffee b/src/pane-view.coffee
index fe9da3f31..11b4a94cd 100644
--- a/src/pane-view.coffee
+++ b/src/pane-view.coffee
@@ -1,6 +1,6 @@
{$, View} = require './space-pen-extensions'
-Serializable = require 'serializable'
Delegator = require 'delegato'
+PropertyAccessors = require 'property-accessors'
Pane = require './pane'
@@ -12,14 +12,11 @@ Pane = require './pane'
# building a package that deals with switching between panes or tiems.
module.exports =
class PaneView extends View
- Serializable.includeInto(this)
Delegator.includeInto(this)
+ PropertyAccessors.includeInto(this)
@version: 1
- @deserialize: (state) ->
- new this(Pane.deserialize(state.model))
-
@content: (wrappedView) ->
@div class: 'pane', tabindex: -1, =>
@div class: 'item-views', outlet: 'itemViews'
@@ -47,14 +44,11 @@ class PaneView extends View
@handleEvents()
handleEvents: ->
- @subscribe @model, 'destroyed', => @remove()
-
@subscribe @model.$activeItem, @onActiveItemChanged
@subscribe @model, 'item-added', @onItemAdded
@subscribe @model, 'item-removed', @onItemRemoved
@subscribe @model, 'item-moved', @onItemMoved
@subscribe @model, 'before-item-destroyed', @onBeforeItemDestroyed
- @subscribe @model, 'item-destroyed', @onItemDestroyed
@subscribe @model, 'activated', @onActivated
@subscribe @model.$active, @onActiveStatusChanged
@@ -85,13 +79,6 @@ class PaneView extends View
@command 'pane:close', => @destroyItems()
@command 'pane:close-other-items', => @destroyInactiveItems()
- deserializeParams: (params) ->
- params.model = Pane.deserialize(params.model)
- params
-
- serializeParams: ->
- model: @model.serialize()
-
# Deprecated: Use ::destroyItem
removeItem: (item) -> @destroyItem(item)
@@ -153,7 +140,6 @@ class PaneView extends View
view.show() if @attached
view.focus() if hasFocus
- @activeView = view
@trigger 'pane:active-item-changed', [item]
onItemAdded: (item, index) =>
@@ -166,7 +152,6 @@ class PaneView extends View
@viewsByItem.delete(item)
if viewToRemove?
- viewToRemove.setModel?(null)
if destroyed
viewToRemove.remove()
else
@@ -181,15 +166,13 @@ class PaneView extends View
@unsubscribe(item) if typeof item.off is 'function'
@trigger 'pane:before-item-destroyed', [item]
- onItemDestroyed: (item) =>
- @getContainer()?.itemDestroyed(item)
-
# Private:
activeItemTitleChanged: =>
@trigger 'pane:active-item-title-changed'
# Private:
viewForItem: (item) ->
+ return unless item?
if item instanceof $
item
else if view = @viewsByItem.get(item)
@@ -201,8 +184,7 @@ class PaneView extends View
view
# Private:
- viewForActiveItem: ->
- @viewForItem(@activeItem)
+ @::accessor 'activeView', -> @viewForItem(@activeItem)
splitLeft: (items...) -> @model.splitLeft({items})._view
diff --git a/src/pane.coffee b/src/pane.coffee
index 746cfb989..346f46bce 100644
--- a/src/pane.coffee
+++ b/src/pane.coffee
@@ -36,7 +36,7 @@ class Pane extends Model
@subscribe @items.onEach (item) =>
if typeof item.on is 'function'
- @subscribe item, 'destroyed', => @removeItem(item)
+ @subscribe item, 'destroyed', => @removeItem(item, true)
@subscribe @items.onRemoval (item, index) =>
@unsubscribe item if typeof item.on is 'function'
@@ -142,6 +142,7 @@ class Pane extends Model
@activateNextItem() if item is @activeItem and @items.length > 1
@items.splice(index, 1)
@emit 'item-removed', item, index, destroying
+ @container?.itemDestroyed(item) if destroying
@destroy() if @items.length is 0
# Public: Moves the given item to the specified index.
@@ -166,7 +167,6 @@ class Pane extends Model
destroyItem: (item) ->
@emit 'before-item-destroyed', item
if @promptToSaveItem(item)
- @emit 'item-destroyed', item
@removeItem(item, true)
item.destroy?()
true
diff --git a/src/select-list.coffee b/src/select-list.coffee
index 21cb270de..415560aed 100644
--- a/src/select-list.coffee
+++ b/src/select-list.coffee
@@ -30,7 +30,7 @@ class SelectList extends View
# This method can be overridden by subclasses but `super` should always
# be called.
initialize: ->
- @miniEditor.getBuffer().on 'changed', => @schedulePopulateList()
+ @miniEditor.getEditor().getBuffer().on 'changed', => @schedulePopulateList()
@miniEditor.hiddenInput.on 'focusout', => @cancel() unless @cancelling
@on 'core:move-up', => @selectPreviousItem()
@on 'core:move-down', => @selectNextItem()
@@ -98,7 +98,7 @@ class SelectList extends View
#
# Returns a {String} to use when fuzzy filtering the elements to display.
getFilterQuery: ->
- @miniEditor.getText()
+ @miniEditor.getEditor().getText()
# Public: Build the DOM elements using the array from the last call to
# {.setArray}.
@@ -207,7 +207,7 @@ class SelectList extends View
# Private:
cancelled: ->
- @miniEditor.setText('')
+ @miniEditor.getEditor().setText('')
@miniEditor.updateDisplay()
# Public: Cancel and close the select list dialog.
diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee
index b5bdff230..8c7f8b4ac 100644
--- a/src/workspace-view.coffee
+++ b/src/workspace-view.coffee
@@ -1,10 +1,11 @@
ipc = require 'ipc'
path = require 'path'
Q = require 'q'
-{$, $$, View} = require './space-pen-extensions'
_ = require 'underscore-plus'
+Delegator = require 'delegato'
+{$, $$, View} = require './space-pen-extensions'
fs = require 'fs-plus'
-Serializable = require 'serializable'
+Workspace = require './workspace'
EditorView = require './editor-view'
PaneView = require './pane-view'
PaneColumnView = require './pane-column-view'
@@ -38,10 +39,14 @@ Editor = require './editor'
#
module.exports =
class WorkspaceView extends View
- Serializable.includeInto(this)
- atom.deserializers.add(this, PaneView, PaneRowView, PaneColumnView, EditorView)
+ Delegator.includeInto(this)
- @version: 2
+ @delegatesProperty 'fullScreen', 'destroyedItemUris', toProperty: 'model'
+ @delegatesMethods 'open', 'openSync', 'openSingletonSync', 'reopenItemSync',
+ 'saveActivePaneItem', 'saveActivePaneItemAs', 'saveAll', 'destroyActivePaneItem',
+ toProperty: 'model'
+
+ @version: 4
@configDefaults:
ignoredNames: [".git", ".svn", ".DS_Store"]
@@ -59,13 +64,14 @@ class WorkspaceView extends View
@div class: 'panes', outlet: 'panes'
# Private:
- initialize: ({panes, @fullScreen}={}) ->
- panes ?= new PaneContainerView
+ initialize: (@model) ->
+ @model ?= new Workspace
+
+ panes = new PaneContainerView(@model.paneContainer)
@panes.replaceWith(panes)
@panes = panes
- @destroyedItemUris = []
- @subscribe @panes, 'item-destroyed', @onPaneItemDestroyed
+ @subscribe @model, 'uri-opened', => @trigger 'uri-opened'
@updateTitle()
@@ -116,16 +122,6 @@ class WorkspaceView extends View
@command 'core:save', => @saveActivePaneItem()
@command 'core:save-as', => @saveActivePaneItemAs()
- # Private:
- deserializeParams: (params) ->
- params.panes = atom.deserializers.deserialize(params.panes)
- params
-
- # Private:
- serializeParams: ->
- panes: @panes.serialize()
- fullScreen: atom.isFullScreen()
-
# Private:
handleFocus: (e) ->
if @getActivePane()
@@ -149,81 +145,6 @@ class WorkspaceView extends View
confirmClose: ->
@panes.confirmClose()
- # Public: Asynchronously opens a given a filepath in Atom.
- #
- # * filePath: A file path
- # * options
- # + initialLine: The buffer line number to open to.
- #
- # Returns a promise that resolves to the {Editor} for the file URI.
- open: (filePath, options={}) ->
- changeFocus = options.changeFocus ? true
- filePath = atom.project.resolve(filePath)
- initialLine = options.initialLine
- activePane = @getActivePane()
-
- editor = activePane.itemForUri(atom.project.relativize(filePath)) if activePane and filePath
- promise = atom.project.open(filePath, {initialLine}) if not editor
-
- Q(editor ? promise)
- .then (editor) =>
- if not activePane
- activePane = new PaneView(editor)
- @panes.setRoot(activePane)
-
- @itemOpened(editor)
- activePane.activateItem(editor)
- activePane.activate() if changeFocus
- @trigger "uri-opened"
- editor
- .catch (error) ->
- console.error(error.stack ? error)
-
- # Private: Only used in specs
- openSync: (uri, {changeFocus, initialLine, pane, split}={}) ->
- changeFocus ?= true
- pane ?= @getActivePane()
- uri = atom.project.relativize(uri)
-
- if pane
- if uri
- paneItem = pane.itemForUri(uri) ? atom.project.openSync(uri, {initialLine})
- else
- paneItem = atom.project.openSync()
-
- if split == 'right'
- panes = @getPanes()
- if panes.length == 1
- pane = panes[0].splitRight()
- else
- pane = _.last(panes)
- else if split == 'left'
- pane = @getPanes()[0]
-
- pane.activateItem(paneItem)
- else
- paneItem = atom.project.openSync(uri, {initialLine})
- pane = new PaneView(paneItem)
- @panes.setRoot(pane)
-
- @itemOpened(paneItem)
-
- pane.activate() if changeFocus
- paneItem
-
- openSingletonSync: (uri, {changeFocus, initialLine, split}={}) ->
- changeFocus ?= true
- uri = atom.project.relativize(uri)
- pane = @panes.paneForUri(uri)
-
- if pane
- paneItem = pane.itemForUri(uri)
- pane.activateItem(paneItem)
- pane.activate() if changeFocus
- paneItem
- else
- @openSync(uri, {changeFocus, initialLine, split})
-
# Public: Updates the application's title, based on whichever file is open.
updateTitle: ->
if projectPath = atom.project.getPath()
@@ -242,22 +163,6 @@ class WorkspaceView extends View
getEditorViews: ->
@panes.find('.pane > .item-views > .editor').map(-> $(this).view()).toArray()
- # Private: Retrieves all of the modified buffers that are open and unsaved.
- #
- # Returns an {Array} of {TextBuffer}s.
- getModifiedBuffers: ->
- modifiedBuffers = []
- for pane in @getPanes()
- for item in pane.getItems() when item instanceof Editor
- modifiedBuffers.push item.buffer if item.buffer.isModified()
- modifiedBuffers
-
- # Private: Retrieves all of the paths to open files.
- #
- # Returns an {Array} of {String}s.
- getOpenBufferPaths: ->
- _.uniq(_.flatten(@getEditorViews().map (editorView) -> editorView.getOpenBufferPaths()))
-
# Public: Prepends the element to the top of the window.
prependToTop: (element) ->
@vertical.prepend(element)
@@ -296,39 +201,23 @@ class WorkspaceView extends View
# Public: Returns the currently focused item from within the focused {PaneView}
getActivePaneItem: ->
- @panes.getActivePaneItem()
+ @model.activePaneItem
# Public: Returns the view of the currently focused item.
getActiveView: ->
@panes.getActiveView()
- # Public: destroy/close the active item.
- destroyActivePaneItem: ->
- @getActivePane()?.destroyActiveItem()
-
- # Public: save the active item.
- saveActivePaneItem: ->
- @getActivePane()?.saveActiveItem()
-
- # Public: save the active item as.
- saveActivePaneItemAs: ->
- @getActivePane()?.saveActiveItemAs()
-
# Public: Focuses the previous pane by id.
- focusPreviousPane: -> @panes.focusPreviousPane()
+ focusPreviousPane: -> @model.activatePreviousPane()
# Public: Focuses the next pane by id.
- focusNextPane: -> @panes.focusNextPane()
+ focusNextPane: -> @model.activateNextPane()
# Public:
#
# FIXME: Difference between active and focused pane?
getFocusedPane: -> @panes.getFocusedPane()
- # Public: Saves all of the open items within panes.
- saveAll: ->
- @panes.saveAll()
-
# Public: Fires a callback on each open {PaneView}.
eachPane: (callback) ->
@panes.eachPane(callback)
@@ -350,20 +239,6 @@ class WorkspaceView extends View
# Private: Destroys everything.
remove: ->
+ @model.destroy()
editorView.remove() for editorView in @getEditorViews()
super
-
- # Private: Adds the destroyed item's uri to the list of items to reopen.
- onPaneItemDestroyed: (e, item) =>
- if uri = item.getUri?()
- @destroyedItemUris.push(uri)
-
- # Public: Reopens the last-closed item uri if it hasn't already been reopened.
- reopenItemSync: ->
- if uri = @destroyedItemUris.pop()
- @openSync(uri)
-
- # Private: Removes the item's uri from the list of potential items to reopen.
- itemOpened: (item) ->
- if uri = item.getUri?()
- _.remove(@destroyedItemUris, uri)
diff --git a/src/workspace.coffee b/src/workspace.coffee
new file mode 100644
index 000000000..39f730e0a
--- /dev/null
+++ b/src/workspace.coffee
@@ -0,0 +1,143 @@
+{remove, last} = require 'underscore-plus'
+{Model} = require 'theorist'
+Q = require 'q'
+Serializable = require 'serializable'
+Delegator = require 'delegato'
+PaneContainer = require './pane-container'
+Pane = require './pane'
+
+# Public: Represents the view state of the entire window, including the panes at
+# the center and panels around the periphery. You can access the singleton
+# instance via `atom.workspace`.
+module.exports =
+class Workspace extends Model
+ atom.deserializers.add(this)
+ Serializable.includeInto(this)
+
+ @delegatesProperty 'activePane', 'activePaneItem', toProperty: 'paneContainer'
+ @delegatesMethod 'getPanes', 'saveAll', 'activateNextPane', 'activatePreviousPane',
+ toProperty: 'paneContainer'
+
+ @properties
+ paneContainer: -> new PaneContainer
+ fullScreen: false
+ destroyedItemUris: -> []
+
+ # Private:
+ constructor: ->
+ super
+ @subscribe @paneContainer, 'item-destroyed', @onPaneItemDestroyed
+
+ # Private: Called by the Serializable mixin during deserialization
+ deserializeParams: (params) ->
+ params.paneContainer = PaneContainer.deserialize(params.paneContainer)
+ params
+
+ # Private: Called by the Serializable mixin during serialization.
+ serializeParams: ->
+ paneContainer: @paneContainer.serialize()
+ fullScreen: atom.isFullScreen()
+
+ # Public: Asynchronously opens a given a filepath in Atom.
+ #
+ # * filePath: A file path
+ # * options
+ # + initialLine: The buffer line number to open to.
+ #
+ # Returns a promise that resolves to the {Editor} for the file URI.
+ open: (filePath, options={}) ->
+ changeFocus = options.changeFocus ? true
+ filePath = atom.project.resolve(filePath)
+ initialLine = options.initialLine
+ activePane = @activePane
+
+ editor = activePane.itemForUri(atom.project.relativize(filePath)) if activePane and filePath
+ promise = atom.project.open(filePath, {initialLine}) if not editor
+
+ Q(editor ? promise)
+ .then (editor) =>
+ if not activePane
+ activePane = new Pane(items: [editor])
+ @paneContainer.root = activePane
+
+ @itemOpened(editor)
+ activePane.activateItem(editor)
+ activePane.activate() if changeFocus
+ @emit "uri-opened"
+ editor
+ .catch (error) ->
+ console.error(error.stack ? error)
+
+ # Private: Only used in specs
+ openSync: (uri, {changeFocus, initialLine, pane, split}={}) ->
+ changeFocus ?= true
+ pane ?= @activePane
+ uri = atom.project.relativize(uri)
+
+ if pane
+ if uri
+ paneItem = pane.itemForUri(uri) ? atom.project.openSync(uri, {initialLine})
+ else
+ paneItem = atom.project.openSync()
+
+ if split == 'right'
+ panes = @getPanes()
+ if panes.length == 1
+ pane = panes[0].splitRight()
+ else
+ pane = last(panes)
+ else if split == 'left'
+ pane = @getPanes()[0]
+
+ pane.activateItem(paneItem)
+ else
+ paneItem = atom.project.openSync(uri, {initialLine})
+ pane = new Pane(items: [paneItem])
+ @paneContainer.root = pane
+
+ @itemOpened(paneItem)
+
+ pane.activate() if changeFocus
+ paneItem
+
+ # Public: Synchronously open an editor for the given URI or activate an existing
+ # editor in any pane if one already exists.
+ openSingletonSync: (uri, {changeFocus, initialLine, split}={}) ->
+ changeFocus ?= true
+ uri = atom.project.relativize(uri)
+ pane = @paneContainer.paneForUri(uri)
+
+ if pane
+ paneItem = pane.itemForUri(uri)
+ pane.activateItem(paneItem)
+ pane.activate() if changeFocus
+ paneItem
+ else
+ @openSync(uri, {changeFocus, initialLine, split})
+
+ # Public: Reopens the last-closed item uri if it hasn't already been reopened.
+ reopenItemSync: ->
+ if uri = @destroyedItemUris.pop()
+ @openSync(uri)
+
+ # Public: save the active item.
+ saveActivePaneItem: ->
+ @activePane?.saveActiveItem()
+
+ # Public: save the active item as.
+ saveActivePaneItemAs: ->
+ @activePane?.saveActiveItemAs()
+
+ # Public: destroy/close the active item.
+ destroyActivePaneItem: ->
+ @activePane?.destroyActiveItem()
+
+ # Private: Removes the item's uri from the list of potential items to reopen.
+ itemOpened: (item) ->
+ if uri = item.getUri?()
+ remove(@destroyedItemUris, uri)
+
+ # Private: Adds the destroyed item's uri to the list of items to reopen.
+ onPaneItemDestroyed: (item) =>
+ if uri = item.getUri?()
+ @destroyedItemUris.push(uri)
diff --git a/vendor/apm b/vendor/apm
index 35edbb07f..b843d54a8 160000
--- a/vendor/apm
+++ b/vendor/apm
@@ -1 +1 @@
-Subproject commit 35edbb07fb4abba49dd97d12a1ad8c4adb71625f
+Subproject commit b843d54a8ac495231efd680ab3648dfd9247896c