diff --git a/.atom/config.json b/.atom/config.json
new file mode 100644
index 000000000..50770e810
--- /dev/null
+++ b/.atom/config.json
@@ -0,0 +1,11 @@
+{
+ "editor": {
+ "fontSize": 16
+ },
+ "core": {
+ "themes": [
+ "atom-dark-ui",
+ "atom-dark-syntax"
+ ]
+ }
+}
diff --git a/.atom/packages/Readme.md b/.atom/packages/Readme.md
deleted file mode 100644
index e69de29bb..000000000
diff --git a/.atom/themes/README.md b/.atom/themes/README.md
new file mode 100644
index 000000000..dbedd5e13
--- /dev/null
+++ b/.atom/themes/README.md
@@ -0,0 +1 @@
+All themes in this directory will be automatically loaded
diff --git a/.atom/atom.coffee b/.atom/user.coffee
similarity index 100%
rename from .atom/atom.coffee
rename to .atom/user.coffee
diff --git a/.atom/user.css b/.atom/user.css
new file mode 100644
index 000000000..d63ad257e
--- /dev/null
+++ b/.atom/user.css
@@ -0,0 +1,8 @@
+/* User styles */
+.tree-view {
+
+}
+
+.editor {
+
+}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ac09dc3e8..0c48073b2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -15,6 +15,8 @@
styleguides
* Include thoughtfully worded [Jasmine](http://pivotal.github.com/jasmine/)
specs
+ * Style new elements in both the light and dark default themes when
+ appropriate
* New packages go in `src/packages/`
* Add 3rd-party packages by submoduling in `vendor/packages/`
* Commit messages are in the present tense
diff --git a/README.md b/README.md
index f6e23611e..04459faa3 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Requirements
Atom is installed! Type `atom [path]` from the commmand line or find it in `/Applications/Atom.app`
## Your ~/.atom Directory
-A basic ~/.atom directory is installed when you run `rake install`. Take a look at ~/.atom/atom.coffee for more information.
+A basic ~/.atom directory is installed when you run `rake install`. Take a look at ~/.atom/user.coffee for more information.
## Basic Keyboard shortcuts
Atom doesn't have much in the way of menus yet. Use these keyboard shortcuts to
@@ -53,7 +53,7 @@ Most default OS X keybindings also work.
## Init Script
-Atom will require `~/.atom/atom.coffee` whenever a window is opened or reloaded if it is present in your
+Atom will require `~/.atom/user.coffee` whenever a window is opened or reloaded if it is present in your
home directory. This is a rudimentary jumping off point for your own customizations.
## Command Panel
diff --git a/Rakefile b/Rakefile
index e6adbba94..e0dd5abd1 100644
--- a/Rakefile
+++ b/Rakefile
@@ -76,14 +76,26 @@ task "create-dot-atom" do
dot_atom_template_path = ATOM_SRC_PATH + "/.atom"
replace_dot_atom = false
- next if File.exists?(DOT_ATOM_PATH)
+
+ if File.exists?(DOT_ATOM_PATH)
+ user_config = "#{DOT_ATOM_PATH}/user.coffee"
+ old_user_config = "#{DOT_ATOM_PATH}/atom.coffee"
+
+ if File.exists?(old_user_config)
+ `mv #{old_user_config} #{user_config}`
+ puts "\033[32mRenamed #{old_user_config} to #{user_config}\033[0m"
+ end
+
+ next
+ end
`rm -rf "#{DOT_ATOM_PATH}"`
`mkdir "#{DOT_ATOM_PATH}"`
- `cp "#{dot_atom_template_path}/atom.coffee" "#{DOT_ATOM_PATH}"`
- `cp "#{dot_atom_template_path}/packages" "#{DOT_ATOM_PATH}"`
+
+ `cp "#{dot_atom_template_path}/user.coffee" "#{DOT_ATOM_PATH}"`
+ `cp "#{dot_atom_template_path}/user.css" "#{DOT_ATOM_PATH}"`
+ `cp -r "#{dot_atom_template_path}/packages" "#{DOT_ATOM_PATH}"`
`cp -r "#{ATOM_SRC_PATH}/themes" "#{DOT_ATOM_PATH}"`
- `cp "#{ATOM_SRC_PATH}/vendor/themes/IR_Black.tmTheme" "#{DOT_ATOM_PATH}/themes"`
end
desc "Clone default bundles into vendor/bundles directory"
diff --git a/docs/styling.md b/docs/styling.md
index 1632c4e54..847df3fbb 100644
--- a/docs/styling.md
+++ b/docs/styling.md
@@ -9,8 +9,8 @@ gutter.
You can change the background color using the following CSS:
```css
-.editor.focused .line.cursor-line,
-.editor.focused .line-number.cursor-line {
+.editor.is-focused .line.cursor-line,
+.editor.is-focused .line-number.cursor-line {
background-color: green;
}
```
@@ -18,7 +18,7 @@ You can change the background color using the following CSS:
You can change the line number foreground color using the following CSS:
```css
-.editor.focused .line-number.cursor-line {
+.editor.is-focused .line-number.cursor-line {
color: blue;
}
```
diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee
index a02c84d97..73474a2a1 100644
--- a/spec/app/atom-spec.coffee
+++ b/spec/app/atom-spec.coffee
@@ -26,17 +26,20 @@ describe "the `atom` global", ->
describe "keymap loading", ->
describe "when package.json does not contain a 'keymaps' manifest", ->
- it "loads all keymaps in the directory", ->
+ it "loads all the .cson/.json files in the keymaps directory", ->
element1 = $$ -> @div class: 'test-1'
element2 = $$ -> @div class: 'test-2'
+ element3 = $$ -> @div class: 'test-3'
expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined()
expect(keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined()
+ expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined()
atom.loadPackage("package-with-module")
expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1"
expect(keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2"
+ expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined()
describe "when package.json contains a 'keymaps' manifest", ->
it "loads only the keymaps specified by the manifest, in the specified order", ->
diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee
index 9304d9df0..8bfb4a2f6 100644
--- a/spec/app/editor-spec.coffee
+++ b/spec/app/editor-spec.coffee
@@ -111,11 +111,11 @@ describe "Editor", ->
editor.isFocused = false
editor.hiddenInput.focus()
expect(editor.isFocused).toBeTruthy()
- expect(editor).toHaveClass('focused')
+ expect(editor).toHaveClass('is-focused')
editor.hiddenInput.focusout()
expect(editor.isFocused).toBeFalsy()
- expect(editor).not.toHaveClass('focused')
+ expect(editor).not.toHaveClass('is-focused')
describe "when the activeEditSession's file is modified on disk", ->
it "triggers an alert", ->
@@ -520,9 +520,8 @@ describe "Editor", ->
beforeEach ->
expect(editor.css('font-family')).not.toBe 'Courier'
- it "sets the initial font family based on the value from config", ->
- expect($("head style.font-family")).toExist()
- expect($("head style.font-family").text()).toMatch "{font-family: #{config.get('editor.fontFamily')}}"
+ it "when there is no config in fontFamily don't set it", ->
+ expect($("head style.font-family")).not.toExist()
describe "when the font family changes", ->
it "updates the font family on new and existing editors", ->
@@ -544,7 +543,7 @@ describe "Editor", ->
lineHeightBefore = editor.lineHeight
charWidthBefore = editor.charWidth
- config.set("editor.fontFamily", "Courier")
+ config.set("editor.fontFamily", "Inconsolata")
editor.setCursorScreenPosition [5, 6]
expect(editor.charWidth).not.toBe charWidthBefore
expect(editor.getCursorView().position()).toEqual { top: 5 * editor.lineHeight, left: 6 * editor.charWidth }
@@ -553,6 +552,7 @@ describe "Editor", ->
describe "font size", ->
beforeEach ->
expect(editor.css('font-size')).not.toBe "20px"
+ expect(editor.css('font-size')).not.toBe "10px"
it "sets the initial font size based on the value from config", ->
expect($("head style.font-size")).toExist()
@@ -615,6 +615,23 @@ describe "Editor", ->
config.set("editor.fontSize", 10)
expect(editor.renderedLines.find(".line").length).toBeGreaterThan originalLineCount
+ describe "when the editor is detached", ->
+ it "updates the font-size correctly and recalculates the dimensions by placing the rendered lines on the DOM", ->
+ rootView.attachToDom()
+ rootView.height(200)
+ rootView.width(200)
+
+ newEditor = editor.splitRight()
+ newEditorParent = newEditor.parent()
+ newEditor.detach()
+ config.set("editor.fontSize", 10)
+ newEditorParent.append(newEditor)
+
+ expect(newEditor.lineHeight).toBe editor.lineHeight
+ expect(newEditor.charWidth).toBe editor.charWidth
+ expect(newEditor.getCursorView().position()).toEqual editor.getCursorView().position()
+ expect(newEditor.verticalScrollbarContent.height()).toBe editor.verticalScrollbarContent.height()
+
describe "mouse events", ->
beforeEach ->
editor.attachToDom()
diff --git a/spec/app/syntax-spec.coffee b/spec/app/syntax-spec.coffee
index d15eb5c74..9660fcecb 100644
--- a/spec/app/syntax-spec.coffee
+++ b/spec/app/syntax-spec.coffee
@@ -23,8 +23,7 @@ describe "the `syntax` global", ->
expect(syntax.grammarForFilePath("/tmp/.git/config").name).toBe "Git Config"
it "uses plain text if no grammar can be found", ->
- filePath = require.resolve("this-is-not-a-real-file")
- expect(syntax.grammarForFilePath(filePath).name).toBe "Plain Text"
+ expect(syntax.grammarForFilePath("this-is-not-a-real-file").name).toBe "Plain Text"
describe ".getProperty(scopeDescriptor)", ->
it "returns the property with the most specific scope selector", ->
diff --git a/spec/app/text-mate-theme-spec.coffee b/spec/app/text-mate-theme-spec.coffee
index 5191ced55..e1c04ec90 100644
--- a/spec/app/text-mate-theme-spec.coffee
+++ b/spec/app/text-mate-theme-spec.coffee
@@ -42,7 +42,7 @@ describe "TextMateTheme", ->
selector: ".invalid.deprecated"
properties:
'color': "#D2A8A1"
- # 'font-style': 'italic'
+ 'font-style': 'italic'
'text-decoration': 'underline'
expect(rulesets[13]).toEqual
diff --git a/spec/app/window-spec.coffee b/spec/app/window-spec.coffee
index 2471d6cc3..c8a61920b 100644
--- a/spec/app/window-spec.coffee
+++ b/spec/app/window-spec.coffee
@@ -13,6 +13,14 @@ describe "Window", ->
atom.setRootViewStateForPath(rootView.project.getPath(), null)
$(window).off 'beforeunload'
+ describe "window is loaded", ->
+ it "has .is-focused on the body tag", ->
+ expect($("body").hasClass("is-focused")).toBe true
+
+ it "doesn't have .is-focused on the window blur", ->
+ $(window).blur()
+ expect($("body").hasClass("is-focused")).toBe false
+
describe ".close()", ->
it "is triggered by the 'core:close' event", ->
spyOn window, 'close'
diff --git a/spec/fixtures/packages/package-with-module/keymaps/keymap-3.cjson b/spec/fixtures/packages/package-with-module/keymaps/keymap-3.cjson
new file mode 100644
index 000000000..3c95c85a5
--- /dev/null
+++ b/spec/fixtures/packages/package-with-module/keymaps/keymap-3.cjson
@@ -0,0 +1,2 @@
+".test-3":
+ "ctrl-z": "test-3"
diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee
index a0e49740a..1a4657488 100644
--- a/spec/spec-helper.coffee
+++ b/spec/spec-helper.coffee
@@ -85,7 +85,7 @@ jasmine.unspy = (object, methodName) ->
throw new Error("Not a spy") unless object[methodName].originalValue?
object[methodName] = object[methodName].originalValue
-jasmine.getEnv().defaultTimeoutInterval = 500
+jasmine.getEnv().defaultTimeoutInterval = 1000
window.keyIdentifierForKey = (key) ->
if key.length > 1 # named key
diff --git a/spec/stdlib/cson-spec.coffee b/spec/stdlib/cson-spec.coffee
new file mode 100644
index 000000000..d14ef3467
--- /dev/null
+++ b/spec/stdlib/cson-spec.coffee
@@ -0,0 +1,60 @@
+CSON = require 'cson'
+
+describe "CSON", ->
+ describe "@stringify(object)", ->
+ describe "when the object is undefined", ->
+ it "throws an exception", ->
+ expect(-> CSON.stringify()).toThrow()
+
+ describe "when the object is a function", ->
+ it "throws an exception", ->
+ expect(-> CSON.stringify(-> 'function')).toThrow()
+
+ describe "when the object contains a function", ->
+ it "throws an exception", ->
+ expect(-> CSON.stringify(a: -> 'function')).toThrow()
+
+ describe "when formatting an undefined key", ->
+ it "does not include the key in the formatted CSON", ->
+ expect(CSON.stringify(b: 1, c: undefined)).toBe "'b': 1"
+
+ describe "when formatting an empty object", ->
+ it "returns the empty string", ->
+ expect(CSON.stringify({})).toBe ""
+
+ describe "when formatting a string", ->
+ it "returns formatted CSON", ->
+ expect(CSON.stringify(a: 'b')).toBe "'a': 'b'"
+
+ it "escapes single quotes", ->
+ expect(CSON.stringify(a: "'b'")).toBe "'a': '\\\'b\\\''"
+
+ it "doesn't escape double quotes", ->
+ expect(CSON.stringify(a: '"b"')).toBe "'a': '\"b\"'"
+
+ describe "when formatting a boolean", ->
+ it "returns formatted CSON", ->
+ expect(CSON.stringify(a: true)).toBe "'a': true"
+ expect(CSON.stringify(a: false)).toBe "'a': false"
+
+ describe "when formatting a number", ->
+ it "returns formatted CSON", ->
+ expect(CSON.stringify(a: 14)).toBe "'a': 14"
+ expect(CSON.stringify(a: 1.23)).toBe "'a': 1.23"
+
+ describe "when formatting null", ->
+ it "returns formatted CSON", ->
+ expect(CSON.stringify(a: null)).toBe "'a': null"
+
+ describe "when formatting an array", ->
+ describe "when the array is empty", ->
+ it "puts the array on a single line", ->
+ expect(CSON.stringify([])).toBe "[]"
+
+ it "returns formatted CSON", ->
+ expect(CSON.stringify(a: ['b'])).toBe "'a': [\n 'b'\n]"
+ expect(CSON.stringify(a: ['b', 4])).toBe "'a': [\n 'b'\n 4\n]"
+
+ describe "when formatting an object", ->
+ it "returns formatted CSON", ->
+ expect(CSON.stringify(a: {b: 'c'})).toBe "'a':\n 'b': 'c'"
diff --git a/spec/stdlib/fs-spec.coffee b/spec/stdlib/fs-spec.coffee
index ffcdaf31b..b0a6fae5f 100644
--- a/spec/stdlib/fs-spec.coffee
+++ b/spec/stdlib/fs-spec.coffee
@@ -128,3 +128,8 @@ describe "fs", ->
describe ".md5ForPath(path)", ->
it "returns the MD5 hash of the file at the given path", ->
expect(fs.md5ForPath(require.resolve('fixtures/sample.js'))).toBe 'dd38087d0d7e3e4802a6d3f9b9745f2b'
+
+ describe ".list(path, extensions)", ->
+ it "returns the paths with the specified extensions", ->
+ path = require.resolve('fixtures/css.css')
+ expect(fs.list(require.resolve('fixtures'), ['.css'])).toEqual [path]
diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee
index bb1ce071b..15a4e465a 100644
--- a/src/app/atom-package.coffee
+++ b/src/app/atom-package.coffee
@@ -26,15 +26,12 @@ class AtomPackage extends Package
@metadata = fs.readObject(metadataPath)
loadKeymaps: ->
- for keymapPath in @getKeymapPaths()
- keymap.load(keymapPath)
-
- getKeymapPaths: ->
if keymaps = @metadata?.keymaps
- keymaps.map (relativePath) =>
+ keymaps = keymaps.map (relativePath) =>
fs.resolve(@keymapsDirPath, relativePath, ['cson', 'json', ''])
+ keymap.load(keymapPath) for keymapPath in keymaps
else
- fs.list(@keymapsDirPath)
+ keymap.loadDirectory(@keymapsDirPath)
loadStylesheets: ->
for stylesheetPath in @getStylesheetPaths()
diff --git a/src/app/atom-theme.coffee b/src/app/atom-theme.coffee
index f955402b5..b52ed3111 100644
--- a/src/app/atom-theme.coffee
+++ b/src/app/atom-theme.coffee
@@ -3,9 +3,16 @@ Theme = require 'theme'
module.exports =
class AtomTheme extends Theme
+
+ loadStylesheet: (stylesheetPath)->
+ @stylesheets[stylesheetPath] = fs.read(stylesheetPath)
+
load: ->
- json = fs.read(fs.join(@path, "package.json"))
- for stylesheetName in JSON.parse(json).stylesheets
- stylesheetPath = fs.join(@path, stylesheetName)
- @stylesheets[stylesheetPath] = fs.read(stylesheetPath)
+ if /\.css$/.test(@path)
+ @loadStylesheet @path
+ else
+ json = fs.read(fs.join(@path, "package.json"))
+ for stylesheetName in JSON.parse(json).stylesheets
+ stylesheetPath = fs.join(@path, stylesheetName)
+ @loadStylesheet stylesheetPath
super
diff --git a/src/app/atom.coffee b/src/app/atom.coffee
index 455382926..e5eb0197f 100644
--- a/src/app/atom.coffee
+++ b/src/app/atom.coffee
@@ -50,15 +50,21 @@ _.extend atom,
.filter (name) -> not _.contains(disabledPackages, name)
loadThemes: ->
- themeNames = config.get("core.themes") ? ['Atom - Dark', 'IR_Black']
+ themeNames = config.get("core.themes") ? ['atom-dark-ui', 'atom-dark-syntax']
themeNames = [themeNames] unless _.isArray(themeNames)
@loadTheme(themeName) for themeName in themeNames
+ @loadUserStylesheet()
loadTheme: (name) ->
@loadedThemes.push Theme.load(name)
+ loadUserStylesheet: ->
+ userStylesheetPath = fs.join(config.configDirPath, 'user.css')
+ if fs.isFile(userStylesheetPath)
+ applyStylesheet(userStylesheetPath, fs.read(userStylesheetPath), 'userTheme')
+
getAtomThemeStylesheets: ->
- themeNames = config.get("core.themes") ? ['Atom - Dark', 'IR_Black']
+ themeNames = config.get("core.themes") ? ['atom-dark-ui', 'atom-dark-syntax']
themeNames = [themeNames] unless _.isArray(themeNames)
open: (args...) ->
diff --git a/src/app/config.coffee b/src/app/config.coffee
index bf35eff63..26efbd674 100644
--- a/src/app/config.coffee
+++ b/src/app/config.coffee
@@ -4,7 +4,7 @@ EventEmitter = require 'event-emitter'
configDirPath = fs.absolute("~/.atom")
configJsonPath = fs.join(configDirPath, "config.json")
-userInitScriptPath = fs.join(configDirPath, "atom.coffee")
+userInitScriptPath = fs.join(configDirPath, "user.coffee")
bundledPackagesDirPath = fs.join(resourcePath, "src/packages")
bundledThemesDirPath = fs.join(resourcePath, "themes")
vendoredPackagesDirPath = fs.join(resourcePath, "vendor/packages")
diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee
index 1900995ad..c19088d87 100644
--- a/src/app/edit-session.coffee
+++ b/src/app/edit-session.coffee
@@ -18,7 +18,7 @@ class EditSession
if fs.exists(state.buffer)
session = project.buildEditSessionForPath(state.buffer)
else
- console.warn "Could not build edit session for path '#{state.buffer}' because that file no longer exists"
+ console.warn "Could not build edit session for path '#{state.buffer}' because that file no longer exists" if state.buffer
session = project.buildEditSessionForPath(null)
session.setScrollTop(state.scrollTop)
session.setScrollLeft(state.scrollLeft)
diff --git a/src/app/editor.coffee b/src/app/editor.coffee
index fcc9a9409..1c0782304 100644
--- a/src/app/editor.coffee
+++ b/src/app/editor.coffee
@@ -14,7 +14,6 @@ _ = require 'underscore'
module.exports =
class Editor extends View
@configDefaults:
- fontFamily: "Inconsolata, Monaco, Courier"
fontSize: 20
showInvisibles: false
autosave: false
@@ -352,11 +351,11 @@ class Editor extends View
@hiddenInput.on 'focus', =>
@rootView()?.editorFocused(this)
@isFocused = true
- @addClass 'focused'
+ @addClass 'is-focused'
@hiddenInput.on 'focusout', =>
@isFocused = false
- @removeClass 'focused'
+ @removeClass 'is-focused'
@autosave() if config.get "editor.autosave"
@underlayer.on 'click', (e) =>
@@ -697,6 +696,7 @@ class Editor extends View
parseInt(@css("font-size"))
setFontFamily: (fontFamily) ->
+ return if fontFamily == undefined
headTag = $("head")
styleTag = headTag.find("style.font-family")
if styleTag.length == 0
@@ -804,6 +804,10 @@ class Editor extends View
@overlayer.append(view)
calculateDimensions: ->
+ if not @isOnDom()
+ detachedEditorParent = _.last(@parents()) ? this
+ $(document.body).append(detachedEditorParent)
+
fragment = $('
x')
@renderedLines.append(fragment)
@@ -815,6 +819,8 @@ class Editor extends View
@height(@lineHeight) if @mini
fragment.remove()
+ $(detachedEditorParent).detach()
+
updateLayerDimensions: ->
@gutter.calculateWidth()
diff --git a/src/app/git.coffee b/src/app/git.coffee
index f862fe6b8..db1376b17 100644
--- a/src/app/git.coffee
+++ b/src/app/git.coffee
@@ -1,4 +1,3 @@
-$ = require 'jquery'
_ = require 'underscore'
Subscriber = require 'subscriber'
GitRepository = require 'git-repository'
@@ -6,9 +5,9 @@ GitRepository = require 'git-repository'
module.exports =
class Git
- @open: (path) ->
+ @open: (path, options) ->
try
- new Git(path)
+ new Git(path, options)
catch e
null
@@ -24,9 +23,12 @@ class Git
working_dir_typechange: 1 << 10
ignore: 1 << 14
- constructor: (path) ->
+ constructor: (path, options={}) ->
@repo = new GitRepository(path)
- @subscribe $(window), 'focus', => @refreshIndex()
+ refreshIndexOnFocus = options.refreshIndexOnFocus ? true
+ if refreshIndexOnFocus
+ $ = require 'jquery'
+ @subscribe $(window), 'focus', => @refreshIndex()
getRepo: ->
unless @repo?
diff --git a/src/app/keymap.coffee b/src/app/keymap.coffee
index 1918a429d..97cf4303b 100644
--- a/src/app/keymap.coffee
+++ b/src/app/keymap.coffee
@@ -35,7 +35,7 @@ class Keymap
@loadDirectory(fs.join(config.configDirPath, 'keymaps'))
loadDirectory: (directoryPath) ->
- @load(filePath) for filePath in fs.list(directoryPath)
+ @load(filePath) for filePath in fs.list(directoryPath, ['.cson', '.json'])
load: (path) ->
@add(fs.readObject(path))
diff --git a/src/app/load-text-mate-packages-task.coffee b/src/app/load-text-mate-packages-task.coffee
index 2eb904676..0bb0ee805 100644
--- a/src/app/load-text-mate-packages-task.coffee
+++ b/src/app/load-text-mate-packages-task.coffee
@@ -1,4 +1,4 @@
-Task = require 'Task'
+Task = require 'task'
module.exports =
class LoadTextMatePackagesTask extends Task
diff --git a/src/app/text-mate-theme.coffee b/src/app/text-mate-theme.coffee
index ee78cdea7..f2c1d1f92 100644
--- a/src/app/text-mate-theme.coffee
+++ b/src/app/text-mate-theme.coffee
@@ -44,17 +44,17 @@ class TextMateTheme extends Theme
'color': @translateColor(foreground)
@rulesets.push
- selector: '.editor.focused .cursor'
+ selector: '.editor.is-focused .cursor'
properties:
'border-color': @translateColor(caret)
@rulesets.push
- selector: '.editor.focused .selection .region'
+ selector: '.editor.is-focused .selection .region'
properties:
'background-color': @translateColor(selection)
@rulesets.push
- selector: '.editor.focused .line-number.cursor-line-no-selection, .editor.focused .line.cursor-line'
+ selector: '.editor.is-focused .line-number.cursor-line-no-selection, .editor.is-focused .line.cursor-line'
properties:
'background-color': @translateColor(lineHighlight)
@@ -75,8 +75,8 @@ class TextMateTheme extends Theme
if fontStyle
fontStyles = fontStyle.split(/\s+/)
- # properties['font-weight'] = 'bold' if _.contains(fontStyles, 'bold')
- # properties['font-style'] = 'italic' if _.contains(fontStyles, 'italic')
+ properties['font-weight'] = 'bold' if _.contains(fontStyles, 'bold')
+ properties['font-style'] = 'italic' if _.contains(fontStyles, 'italic')
properties['text-decoration'] = 'underline' if _.contains(fontStyles, 'underline')
properties['color'] = @translateColor(foreground) if foreground
diff --git a/src/app/theme.coffee b/src/app/theme.coffee
index c3f574977..b16a7ef1c 100644
--- a/src/app/theme.coffee
+++ b/src/app/theme.coffee
@@ -11,7 +11,7 @@ class Theme
if fs.exists(name)
path = name
else
- path = fs.resolve(config.themeDirPaths..., name, ['', '.tmTheme'])
+ path = fs.resolve(config.themeDirPaths..., name, ['', '.tmTheme', '.css'])
throw new Error("No theme exists named '#{name}'") unless path
diff --git a/src/app/window.coffee b/src/app/window.coffee
index d990b28a4..d0cad8b32 100644
--- a/src/app/window.coffee
+++ b/src/app/window.coffee
@@ -28,6 +28,7 @@ windowAdditions =
$(window).on 'core:close', => @close()
$(window).command 'window:close', => @close()
+ $(window).on 'focus blur', => $("body").toggleClass("is-focused")
# This method is intended only to be run when starting a normal application
# Note: RootView assigns itself on window on initialization so that
diff --git a/src/packages/command-logger/spec/command-logger-spec.coffee b/src/packages/command-logger/spec/command-logger-spec.coffee
index c01f24320..e2a06da2b 100644
--- a/src/packages/command-logger/spec/command-logger-spec.coffee
+++ b/src/packages/command-logger/spec/command-logger-spec.coffee
@@ -6,9 +6,8 @@ describe "CommandLogger", ->
beforeEach ->
rootView = new RootView(require.resolve('fixtures/sample.js'))
- atom.loadPackage('command-logger').getInstance()
+ commandLogger = atom.loadPackage('command-logger')
editor = rootView.getActiveEditor()
- commandLogger = CommandLogger.instance
afterEach ->
rootView.deactivate()
@@ -44,9 +43,11 @@ describe "CommandLogger", ->
describe "when an event is ignored", ->
it "does not create a node for that event", ->
- commandLogger.ignoredEvents.push 'editor:delete-line'
+ commandLoggerView = commandLogger.getInstance()
+ commandLoggerView.ignoredEvents.push 'editor:delete-line'
editor.trigger 'editor:delete-line'
- nodes = commandLogger.createNodes()
+ commandLoggerView.eventLog = commandLogger.eventLog
+ nodes = commandLoggerView.createNodes()
for node in nodes
continue unless node.name is 'Editor'
for child in node.children
diff --git a/src/packages/command-logger/src/command-logger-view.coffee b/src/packages/command-logger/src/command-logger-view.coffee
index 4a5f89df5..9dfa03360 100644
--- a/src/packages/command-logger/src/command-logger-view.coffee
+++ b/src/packages/command-logger/src/command-logger-view.coffee
@@ -34,6 +34,7 @@ class CommandLoggerView extends ScrollView
super
@command 'core:cancel', => @detach()
+ @on 'blur', => @detach() unless document.activeElement is this[0]
toggle: (@eventLog={}) ->
if @hasParent()
@@ -143,10 +144,10 @@ class CommandLoggerView extends ScrollView
.append('div')
.style('width', "#{w}px")
.style('height', "#{h}px")
- .append('svg:svg')
+ .append('svg')
.attr('width', w)
.attr('height', h)
- .append('svg:g')
+ .append('g')
.attr('transform', 'translate(.5,.5)')
nodes = treemap.nodes(root).filter((d) -> not d.children)
@@ -154,17 +155,17 @@ class CommandLoggerView extends ScrollView
cell = svg.selectAll('g')
.data(nodes)
.enter()
- .append('svg:g')
+ .append('g')
.attr('class', 'node')
.attr('transform', (d) -> "translate(#{d.x},#{d.y})")
.on('click', (d) -> if node is d.parent then zoom(root) else zoom(d.parent))
- cell.append('svg:rect')
+ cell.append('rect')
.attr('width', (d) -> d.dx - 1)
.attr('height', (d) -> d.dy - 1)
.style('fill', (d) -> color(d.parent.name))
- cell.append('svg:foreignObject')
+ cell.append('foreignObject')
.attr('width', (d) -> d.dx - 1)
.attr('height', (d) -> d.dy - 1)
.attr('class', 'foreign-object')
@@ -180,8 +181,11 @@ class CommandLoggerView extends ScrollView
@focus()
detach: ->
- super()
+ return if @detaching
+ @detaching = true
+ super
@rootView.focus()
+ @detaching = false
serialize: ->
eventLog: @eventLog
diff --git a/src/packages/command-panel/spec/command-panel-spec.coffee b/src/packages/command-panel/spec/command-panel-spec.coffee
index 635613912..a63ae410b 100644
--- a/src/packages/command-panel/spec/command-panel-spec.coffee
+++ b/src/packages/command-panel/spec/command-panel-spec.coffee
@@ -438,13 +438,13 @@ describe "CommandPanel", ->
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0]
describe "when core:confirm is triggered on the preview list", ->
- it "opens the operation's buffer, selects and scrolls to the search result, and focuses the active editor", ->
+ it "opens the operation's buffer, selects and scrolls to the search result, and refocuses the preview list", ->
rootView.height(200)
rootView.attachToDom()
waitsForPromise -> commandPanel.execute('X x/apply/') # use apply because it is at the end of the file
runs ->
- spyOn(rootView, 'focus')
+ spyOn(previewList, 'focus')
executeHandler = jasmine.createSpy('executeHandler')
commandPanel.on 'core:confirm', executeHandler
@@ -458,13 +458,13 @@ describe "CommandPanel", ->
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
expect(editor.isScreenRowVisible(editor.getCursorScreenRow())).toBeTruthy()
- expect(rootView.focus).toHaveBeenCalled()
+ expect(previewList.focus).toHaveBeenCalled()
expect(executeHandler).not.toHaveBeenCalled()
describe "when an operation in the preview list is clicked", ->
- it "opens the operation's buffer, selects the search result, and focuses the active editor", ->
- spyOn(rootView, 'focus')
+ it "opens the operation's buffer, selects the search result, and refocuses the preview list", ->
+ spyOn(previewList, 'focus')
operation = previewList.getOperations()[4]
previewList.find('li.operation:eq(4) span').mousedown()
@@ -473,4 +473,4 @@ describe "CommandPanel", ->
editSession = rootView.getActiveEditSession()
expect(editSession.buffer.getPath()).toBe project.resolve(operation.getPath())
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
- expect(rootView.focus).toHaveBeenCalled()
+ expect(previewList.focus).toHaveBeenCalled()
diff --git a/src/packages/command-panel/src/preview-list.coffee b/src/packages/command-panel/src/preview-list.coffee
index 34cbd240c..cb0296d46 100644
--- a/src/packages/command-panel/src/preview-list.coffee
+++ b/src/packages/command-panel/src/preview-list.coffee
@@ -83,7 +83,7 @@ class PreviewList extends ScrollView
editSession = @rootView.open(operation.getPath())
bufferRange = operation.execute(editSession)
editSession.setSelectedBufferRange(bufferRange, autoscroll: true) if bufferRange
- @rootView.focus()
+ @focus()
false
getPathCount: ->
diff --git a/src/packages/editor-stats/index.coffee b/src/packages/editor-stats/index.coffee
new file mode 100644
index 000000000..e743c0f18
--- /dev/null
+++ b/src/packages/editor-stats/index.coffee
@@ -0,0 +1,16 @@
+DeferredAtomPackage = require 'deferred-atom-package'
+Stats = require './src/stats'
+
+module.exports =
+class EditorStats extends DeferredAtomPackage
+ loadEvents: ['editor-stats:toggle']
+ instanceClass: 'editor-stats/src/editor-stats-view'
+ stats: new Stats
+
+ activate: (rootView) ->
+ super
+
+ rootView.on 'keydown', => @stats.track()
+ rootView.on 'mouseup', => @stats.track()
+
+ onLoadEvent: (event, instance) -> instance.toggle(@stats)
diff --git a/src/packages/editor-stats/keymaps/editor-stats.cson b/src/packages/editor-stats/keymaps/editor-stats.cson
new file mode 100644
index 000000000..819b7c04f
--- /dev/null
+++ b/src/packages/editor-stats/keymaps/editor-stats.cson
@@ -0,0 +1,2 @@
+'body':
+ 'meta-alt-s': 'editor-stats:toggle'
diff --git a/src/packages/editor-stats/spec/editor-stats-spec.coffee b/src/packages/editor-stats/spec/editor-stats-spec.coffee
new file mode 100644
index 000000000..ca274a252
--- /dev/null
+++ b/src/packages/editor-stats/spec/editor-stats-spec.coffee
@@ -0,0 +1,46 @@
+$ = require 'jquery'
+RootView = require 'root-view'
+EditorStats = require 'editor-stats/src/editor-stats-view'
+
+describe "EditorStats", ->
+ [rootView, editorStats, time] = []
+
+ simulateKeyUp = (key) ->
+ e = $.Event "keydown", keyCode: key.charCodeAt(0)
+ rootView.trigger(e)
+
+ simulateClick = ->
+ e = $.Event "mouseup"
+ rootView.trigger(e)
+
+ beforeEach ->
+ rootView = new RootView(require.resolve('fixtures/sample.js'))
+
+ date = new Date()
+ mins = date.getMinutes()
+ hours = date.getHours()
+
+ mins = if mins == 60 then '01' else mins + 1
+ time = "#{hours}:#{mins}"
+
+ editorStatsPackage = atom.loadPackage('editor-stats')
+ editorStatsPackage.getInstance()
+ editorStats = editorStatsPackage.stats
+ editorStats.clear()
+
+ afterEach ->
+ rootView.deactivate()
+
+ describe "when a keyup event is triggered", ->
+ it "records the number of times a keyup is triggered", ->
+ simulateKeyUp('a')
+ expect(editorStats.eventLog[time]).toBe 1
+ simulateKeyUp('b')
+ expect(editorStats.eventLog[time]).toBe 2
+
+ describe "when a mouseup event is triggered", ->
+ it "records the number of times a mouseup is triggered", ->
+ simulateClick()
+ expect(editorStats.eventLog[time]).toBe 1
+ simulateClick()
+ expect(editorStats.eventLog[time]).toBe 2
diff --git a/src/packages/editor-stats/src/editor-stats-view.coffee b/src/packages/editor-stats/src/editor-stats-view.coffee
new file mode 100644
index 000000000..aea6ca303
--- /dev/null
+++ b/src/packages/editor-stats/src/editor-stats-view.coffee
@@ -0,0 +1,103 @@
+ScrollView = require 'scroll-view'
+d3 = require 'd3.v3'
+_ = require 'underscore'
+$ = require 'jquery'
+
+module.exports =
+class EditorStatsView extends ScrollView
+ @activate: (rootView, state) ->
+ @instance = new EditorStatsView(rootView)
+
+ @content: (rootView) ->
+ @div class: 'editor-stats-wrapper', tabindex: -1, =>
+ @div class: 'editor-stats', outlet: 'editorStats'
+
+ pt: 15
+ pl: 10
+ pb: 3
+ pr: 25
+
+ initialize: (@rootView) ->
+ super
+
+ resizer = =>
+ return unless @isOnDom()
+ @draw()
+ @update()
+ @subscribe $(window), 'resize', _.debounce(resizer, 300)
+
+ draw: ->
+ @editorStats.empty()
+ @x ?= d3.scale.ordinal().domain d3.range(@stats.hours * 60)
+ @y ?= d3.scale.linear()
+ w = @rootView.vertical.width()
+ h = @height()
+ data = d3.entries @stats.eventLog
+ max = d3.max data, (d) -> d.value
+
+ @x.rangeBands [0, w - @pl - @pr], 0.2
+ @y.domain([0, max]).range [h - @pt - @pb, 0]
+
+ @xaxis ?= d3.svg.axis().scale(@x).orient('top')
+ .tickSize(-h + @pt + @pb)
+ .tickFormat (d) =>
+ d = new Date(@stats.startDate.getTime() + (d * 6e4))
+ mins = d.getMinutes()
+ mins = "0#{mins}" if mins <= 9
+ "#{d.getHours()}:#{mins}"
+
+ vis = d3.select(@editorStats.get(0)).append('svg')
+ .attr('width', w)
+ .attr('height', h)
+ .append('g')
+ .attr('transform', "translate(#{@pl},#{@pt})")
+
+ vis.append('g')
+ .attr('class', 'x axis')
+ .call(@xaxis)
+ .selectAll('g')
+ .classed('minor', (d, i) -> i % 5 == 0 && i % 15 != 0)
+ .style 'display', (d, i) ->
+ if i % 15 == 0 || i % 5 == 0 || i == data.length - 1
+ 'block'
+ else
+ 'none'
+
+ @bars = vis.selectAll('rect.bar')
+ .data(data)
+ .enter().append('rect')
+ .attr('x', (d, i) => @x i)
+ .attr('height', (d, i) => h - @y(d.value) - @pt - @pb)
+ .attr('y', (d) => @y(d.value))
+ .attr('width', @x.rangeBand())
+ .attr('class', 'bar')
+
+ clearInterval(@updateInterval)
+ updater = => @update() if @isOnDom()
+ setTimeout(updater, 100)
+ @updateInterval = setInterval(updater, 5000)
+
+ update: ->
+ newData = d3.entries @stats.eventLog
+ max = d3.max newData, (d) -> d.value
+ @y.domain [0, max]
+ h = @height()
+ @bars.data(newData).transition()
+ .attr('height', (d, i) => h - @y(d.value) - @pt - @pb)
+ .attr('y', (d, i) => @y(d.value))
+ @bars.classed('max', (d, i) -> d.value == max)
+
+ toggle: (@stats) ->
+ if @hasParent()
+ @detach()
+ else
+ @attach()
+
+ attach: ->
+ @rootView.vertical.append(@)
+ @draw()
+
+ detach: ->
+ super()
+ clearInterval(@updateInterval)
+ @rootView.focus()
diff --git a/src/packages/editor-stats/src/stats.coffee b/src/packages/editor-stats/src/stats.coffee
new file mode 100644
index 000000000..5e9c6700d
--- /dev/null
+++ b/src/packages/editor-stats/src/stats.coffee
@@ -0,0 +1,29 @@
+module.exports =
+class Stats
+ startDate: new Date
+ hours: 6
+ eventLog: []
+
+ constructor: ->
+ date = new Date(@startDate)
+ future = new Date(date.getTime() + (36e5 * @hours))
+ @eventLog[@time(date)] = 0
+
+ while date < future
+ @eventLog[@time(date)] = 0
+
+ clear: ->
+ @eventLog = []
+
+ track: ->
+ date = new Date
+ times = @time date
+ @eventLog[times] ?= 0
+ @eventLog[times] += 1
+ @eventLog.shift() if @eventLog.length > (@hours * 60)
+
+ time: (date) ->
+ date.setTime(date.getTime() + 6e4)
+ hour = date.getHours()
+ minute = date.getMinutes()
+ "#{hour}:#{minute}"
diff --git a/src/packages/editor-stats/stylesheets/editor-stats.css b/src/packages/editor-stats/stylesheets/editor-stats.css
new file mode 100644
index 000000000..a7d5e3ff2
--- /dev/null
+++ b/src/packages/editor-stats/stylesheets/editor-stats.css
@@ -0,0 +1,45 @@
+.editor-stats-wrapper {
+ padding: 5px;
+ box-sizing: border-box;
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
+ z-index: 9999;
+}
+
+.editor-stats {
+ height: 50px;
+ width: 100%;
+ background: #1d1f21;
+ border: 1px solid rgba(0, 0, 0, 0.3);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ border-right: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.editor-stats rect.bar {
+ fill: rgba(255, 255, 255, 0.2);
+ shape-rendering: crispedges;
+}
+
+.editor-stats rect.bar.max {
+ fill: rgba(0, 163, 255, 1);
+}
+
+.editor-stats text {
+ font-size: 10px;
+ fill: rgba(255, 255, 255, 0.2);
+ font-family: Courier;
+}
+
+.editor-stats .minor text {
+ display: none;
+}
+
+.editor-stats line {
+ stroke: #ccc;
+ stroke-opacity: 0.05;
+ stroke-width: 1px;
+ shape-rendering: crispedges;
+}
+
+.editor-stats path.domain {
+ fill: none;
+}
diff --git a/src/packages/fuzzy-finder/index.coffee b/src/packages/fuzzy-finder/index.coffee
index 1d815057e..66f212187 100644
--- a/src/packages/fuzzy-finder/index.coffee
+++ b/src/packages/fuzzy-finder/index.coffee
@@ -1,8 +1,8 @@
DeferredAtomPackage = require 'deferred-atom-package'
+LoadPathsTask = require './src/load-paths-task'
module.exports =
class FuzzyFinder extends DeferredAtomPackage
-
loadEvents: [
'fuzzy-finder:toggle-file-finder'
'fuzzy-finder:toggle-buffer-finder'
@@ -11,7 +11,18 @@ class FuzzyFinder extends DeferredAtomPackage
instanceClass: 'fuzzy-finder/src/fuzzy-finder-view'
+ activate: (rootView) ->
+ super
+
+ if rootView.project.getPath()?
+ callback = (paths) => @projectPaths = paths
+ new LoadPathsTask(rootView, callback).start()
+
onLoadEvent: (event, instance) ->
+ if @projectPaths? and not @instance.projectPaths?
+ @instance.projectPaths = @projectPaths
+ @instance.reloadProjectPaths = false
+
switch event.type
when 'fuzzy-finder:toggle-file-finder'
instance.toggleFileFinder()
diff --git a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee
index ad40e0010..76f8bd476 100644
--- a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee
+++ b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee
@@ -1,5 +1,6 @@
RootView = require 'root-view'
FuzzyFinder = require 'fuzzy-finder/src/fuzzy-finder-view'
+LoadPathsTask = require 'fuzzy-finder/src/load-paths-task'
$ = require 'jquery'
{$$} = require 'space-pen'
fs = require 'fs'
@@ -48,14 +49,13 @@ describe 'FuzzyFinder', ->
expect(finder.find(".loading")).toBeVisible()
expect(finder.find(".loading")).toHaveText "Indexing..."
- waitsForPromise ->
- rootView.project.getFilePaths().done (foundPaths) -> paths = foundPaths
-
- waitsFor ->
- finder.list.children('li').length > 0
+ waitsFor "all project paths to load", 5000, ->
+ if finder.projectPaths?.length > 0
+ paths = finder.projectPaths
+ true
runs ->
- expect(finder.list.children('li').length).toBe paths.length, finder.maxResults
+ expect(finder.list.children('li').length).toBe paths.length
for path in paths
expect(finder.list.find("li:contains(#{fs.base(path)})")).toExist()
expect(finder.list.children().first()).toHaveClass 'selected'
@@ -222,15 +222,15 @@ describe 'FuzzyFinder', ->
describe "cached file paths", ->
it "caches file paths after first time", ->
- spyOn(rootView.project, "getFilePaths").andCallThrough()
+ spyOn(LoadPathsTask.prototype, "start").andCallThrough()
rootView.trigger 'fuzzy-finder:toggle-file-finder'
waitsFor ->
finder.list.children('li').length > 0
runs ->
- expect(rootView.project.getFilePaths).toHaveBeenCalled()
- rootView.project.getFilePaths.reset()
+ expect(finder.loadPathsTask.start).toHaveBeenCalled()
+ finder.loadPathsTask.start.reset()
rootView.trigger 'fuzzy-finder:toggle-file-finder'
rootView.trigger 'fuzzy-finder:toggle-file-finder'
@@ -238,45 +238,44 @@ describe 'FuzzyFinder', ->
finder.list.children('li').length > 0
runs ->
- expect(rootView.project.getFilePaths).not.toHaveBeenCalled()
+ expect(finder.loadPathsTask.start).not.toHaveBeenCalled()
it "doesn't cache buffer paths", ->
- spyOn(rootView.project, "getFilePaths").andCallThrough()
+ spyOn(rootView, "getOpenBufferPaths").andCallThrough()
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
waitsFor ->
finder.list.children('li').length > 0
runs ->
- expect(rootView.project.getFilePaths).not.toHaveBeenCalled()
- rootView.project.getFilePaths.reset()
+ expect(rootView.getOpenBufferPaths).toHaveBeenCalled()
+ rootView.getOpenBufferPaths.reset()
+ rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
- rootView.trigger 'fuzzy-finder:toggle-file-finder'
waitsFor ->
finder.list.children('li').length > 0
runs ->
- expect(rootView.project.getFilePaths).toHaveBeenCalled()
+ expect(rootView.getOpenBufferPaths).toHaveBeenCalled()
it "busts the cache when the window gains focus", ->
- spyOn(rootView.project, "getFilePaths").andCallThrough()
+ spyOn(LoadPathsTask.prototype, "start").andCallThrough()
rootView.trigger 'fuzzy-finder:toggle-file-finder'
waitsFor ->
finder.list.children('li').length > 0
runs ->
- expect(rootView.project.getFilePaths).toHaveBeenCalled()
- rootView.project.getFilePaths.reset()
+ expect(finder.loadPathsTask.start).toHaveBeenCalled()
+ finder.loadPathsTask.start.reset()
$(window).trigger 'focus'
rootView.trigger 'fuzzy-finder:toggle-file-finder'
rootView.trigger 'fuzzy-finder:toggle-file-finder'
- expect(rootView.project.getFilePaths).toHaveBeenCalled()
+ expect(finder.loadPathsTask.start).toHaveBeenCalled()
describe "path ignoring", ->
it "ignores paths that match entries in config.fuzzyFinder.ignoredNames", ->
- spyOn(rootView.project, "getFilePaths").andCallThrough()
config.set("fuzzyFinder.ignoredNames", ["tree-view.js"])
rootView.trigger 'fuzzy-finder:toggle-file-finder'
finder.maxItems = Infinity
@@ -293,7 +292,6 @@ describe 'FuzzyFinder', ->
beforeEach ->
editor = rootView.getActiveEditor()
rootView.attachToDom()
- spyOn(rootView.project, "getFilePaths").andCallThrough()
it "opens the fuzzy finder window when there are multiple matches", ->
editor.setText("sample")
diff --git a/src/packages/fuzzy-finder/src/fuzzy-finder-view.coffee b/src/packages/fuzzy-finder/src/fuzzy-finder-view.coffee
index 2365fc4d7..ac5a3a3a5 100644
--- a/src/packages/fuzzy-finder/src/fuzzy-finder-view.coffee
+++ b/src/packages/fuzzy-finder/src/fuzzy-finder-view.coffee
@@ -3,6 +3,7 @@ SelectList = require 'select-list'
_ = require 'underscore'
$ = require 'jquery'
fs = require 'fs'
+LoadPathsTask = require 'fuzzy-finder/src/load-paths-task'
module.exports =
class FuzzyFinderView extends SelectList
@@ -126,16 +127,9 @@ class FuzzyFinderView extends SelectList
@setLoading("Indexing...")
if @reloadProjectPaths
- @rootView.project.getFilePaths().done (paths) =>
- ignoredNames = config.get("fuzzyFinder.ignoredNames") or []
- ignoredNames = ignoredNames.concat(config.get("core.ignoredNames") or [])
+ @loadPathsTask?.terminate()
+ callback = (paths) =>
@projectPaths = paths
- if ignoredNames
- @projectPaths = @projectPaths.filter (path) ->
- for segment in path.split("/")
- return false if _.contains(ignoredNames, segment)
- return true
-
@reloadProjectPaths = false
listedItems =
if options.filter?
@@ -146,6 +140,8 @@ class FuzzyFinderView extends SelectList
@setArray(listedItems)
options.done(listedItems) if options.done?
+ @loadPathsTask = new LoadPathsTask(@rootView, callback)
+ @loadPathsTask.start()
populateOpenBufferPaths: ->
@paths = @rootView.getOpenBufferPaths().map (path) =>
diff --git a/src/packages/fuzzy-finder/src/load-paths-handler.coffee b/src/packages/fuzzy-finder/src/load-paths-handler.coffee
new file mode 100644
index 000000000..41ed34fa8
--- /dev/null
+++ b/src/packages/fuzzy-finder/src/load-paths-handler.coffee
@@ -0,0 +1,20 @@
+fs = require 'fs'
+_ = require 'underscore'
+Git = require 'git'
+
+module.exports =
+ loadPaths: (rootPath, ignoredNames, ignoreGitIgnoredFiles) ->
+ paths = []
+ repo = Git.open(rootPath, refreshIndexOnFocus: false) if ignoreGitIgnoredFiles
+ isIgnored = (path) ->
+ for segment in path.split('/')
+ return true if _.contains(ignoredNames, segment)
+ return true if repo?.isPathIgnored(fs.join(rootPath, path))
+ false
+ onFile = (path) ->
+ paths.push(path) unless isIgnored(path)
+ onDirectory = (path) ->
+ not isIgnored(path)
+ fs.traverseTree(rootPath, onFile, onDirectory)
+ repo?.destroy()
+ callTaskMethod('pathsLoaded', paths)
diff --git a/src/packages/fuzzy-finder/src/load-paths-task.coffee b/src/packages/fuzzy-finder/src/load-paths-task.coffee
new file mode 100644
index 000000000..7f7a31baa
--- /dev/null
+++ b/src/packages/fuzzy-finder/src/load-paths-task.coffee
@@ -0,0 +1,17 @@
+Task = require 'task'
+
+module.exports =
+class LoadPathsTask extends Task
+ constructor: (@rootView, @callback)->
+ super('fuzzy-finder/src/load-paths-handler')
+
+ started: ->
+ ignoredNames = config.get("fuzzyFinder.ignoredNames") ? []
+ ignoredNames = ignoredNames.concat(config.get("core.ignoredNames") ? [])
+ ignoreGitIgnoredFiles = config.get("core.hideGitIgnoredFiles")
+ rootPath = @rootView.project.getPath()
+ @callWorkerMethod('loadPaths', rootPath, ignoredNames, ignoreGitIgnoredFiles)
+
+ pathsLoaded: (paths) ->
+ @terminate()
+ @callback(paths)
diff --git a/src/packages/snippets/spec/snippets-spec.coffee b/src/packages/snippets/spec/snippets-spec.coffee
index 046807746..c9582a336 100644
--- a/src/packages/snippets/spec/snippets-spec.coffee
+++ b/src/packages/snippets/spec/snippets-spec.coffee
@@ -277,6 +277,7 @@ describe "Snippets extension", ->
it "terminates the worker when loading completes", ->
jasmine.unspy(LoadSnippetsTask.prototype, 'loadAtomSnippets')
+ spyOn(console, "warn")
spyOn(Worker.prototype, 'terminate').andCallThrough()
snippets.loaded = false
snippets.loadAll()
@@ -284,6 +285,8 @@ describe "Snippets extension", ->
waitsFor "all snippets to load", 5000, -> snippets.loaded
runs ->
+ expect(console.warn).toHaveBeenCalled()
+ expect(console.warn.argsForCall[0]).toMatch /Error reading snippets file '.*?\/spec\/fixtures\/packages\/package-with-snippets\/snippets\/junk-file'/
expect(Worker.prototype.terminate).toHaveBeenCalled()
expect(Worker.prototype.terminate.calls.length).toBe 1
diff --git a/src/packages/snippets/src/load-snippets-task.coffee b/src/packages/snippets/src/load-snippets-task.coffee
index bbef9d681..e32d70dde 100644
--- a/src/packages/snippets/src/load-snippets-task.coffee
+++ b/src/packages/snippets/src/load-snippets-task.coffee
@@ -1,4 +1,4 @@
-Task = require 'Task'
+Task = require 'task'
TextMatePackage = require 'text-mate-package'
module.exports =
diff --git a/src/packages/tree-view/spec/tree-view-spec.coffee b/src/packages/tree-view/spec/tree-view-spec.coffee
index c788842bf..ab6d16d1a 100644
--- a/src/packages/tree-view/spec/tree-view-spec.coffee
+++ b/src/packages/tree-view/spec/tree-view-spec.coffee
@@ -770,6 +770,9 @@ describe "TreeView", ->
treeView.trigger "tree-view:move"
moveDialog = rootView.find(".tree-view-dialog").view()
+ afterEach ->
+ waits 50 # The move specs cause too many false positives because of their async nature, so wait a little bit before we cleanup
+
it "opens a move dialog with the file's current path (excluding extension) populated", ->
extension = fs.extension(filePath)
fileNameWithoutExtension = fs.base(filePath, extension)
diff --git a/src/stdlib/cson.coffee b/src/stdlib/cson.coffee
new file mode 100644
index 000000000..eab575a11
--- /dev/null
+++ b/src/stdlib/cson.coffee
@@ -0,0 +1,79 @@
+_ = require 'underscore'
+
+module.exports =
+ stringifyIndent: (level=0) -> _.multiplyString(' ', Math.max(level, 0))
+
+ stringifyString: (string) ->
+ string = JSON.stringify(string)
+ string = string[1...-1] # Remove surrounding double quotes
+ string = string.replace(/\\"/g, '"') # Unescape escaped double quotes
+ string = string.replace(/'/g, '\\\'') # Escape single quotes
+ "'#{string}'" # Wrap in single quotes
+
+ stringifyBoolean: (boolean) -> "#{boolean}"
+
+ stringifyNumber: (number) -> "#{number}"
+
+ stringifyNull: -> 'null'
+
+ stringifyArray: (array, indentLevel=0) ->
+ return '[]' if array.length is 0
+
+ cson = '[\n'
+ for value in array
+ cson += @stringifyIndent(indentLevel + 2)
+ if _.isString(value)
+ cson += @stringifyString(value)
+ else if _.isBoolean(value)
+ cson += @stringifyBoolean(value)
+ else if _.isNumber(value)
+ cson += @stringifyNumber(value)
+ else if _.isNull(value)
+ cson += @stringifyNull(value)
+ else if _.isArray(value)
+ cson += @stringifyArray(value, indentLevel + 2)
+ else if _.isObject(value)
+ cson += @stringifyObject(value, indentLevel + 2)
+ else
+ throw new Error("Unrecognized type for array value: #{value}")
+ cson += '\n'
+ "#{cson}#{@stringifyIndent(indentLevel)}]"
+
+ stringifyObject: (object, indentLevel=0) ->
+ cson = ''
+ prefix = ''
+ for key, value of object
+ continue if value is undefined
+ if _.isFunction(value)
+ throw new Error("Function specified as value to key: #{key}")
+
+ cson += "#{prefix}#{@stringifyIndent(indentLevel)}'#{key}':"
+ if _.isString(value)
+ cson += " #{@stringifyString(value)}"
+ else if _.isBoolean(value)
+ cson += " #{@stringifyBoolean(value)}"
+ else if _.isNumber(value)
+ cson += " #{@stringifyNumber(value)}"
+ else if _.isNull(value)
+ cson += " #{@stringifyNull(value)}"
+ else if _.isArray(value)
+ cson += " #{@stringifyArray(value, indentLevel)}"
+ else if _.isObject(value)
+ cson += "\n#{@stringifyObject(value, indentLevel + 2)}"
+ else
+ throw new Error("Unrecognized value type for key: #{key} with value: #{value}")
+ prefix = '\n'
+ cson
+
+ stringify: (object) ->
+ throw new Error("Cannot stringify undefined object") if object is undefined
+ throw new Error("Cannot stringify function: #{object}") if _.isFunction(object)
+
+ return @stringifyString(object) if _.isString(object)
+ return @stringifyBoolean(object) if _.isBoolean(object)
+ return @stringifyNumber(object) if _.isNumber(object)
+ return @stringifyNull(object) if _.isNull(object)
+ return @stringifyArray(object) if _.isArray(object)
+ return @stringifyObject(object) if _.isObject(object)
+
+ throw new Error("Unrecognized type to stringify: #{object}")
diff --git a/src/stdlib/fs.coffee b/src/stdlib/fs.coffee
index a9eb755da..fcf8904a9 100644
--- a/src/stdlib/fs.coffee
+++ b/src/stdlib/fs.coffee
@@ -59,11 +59,16 @@ module.exports =
# Returns an array with all the names of files contained
# in the directory path.
- list: (rootPath) ->
+ list: (rootPath, extensions) ->
paths = []
- onPath = (path) =>
- paths.push(@join(rootPath, path))
- false
+ if extensions
+ onPath = (path) =>
+ paths.push(@join(rootPath, path)) if _.contains(extensions, @extension(path))
+ false
+ else
+ onPath = (path) =>
+ paths.push(@join(rootPath, path))
+ false
@traverseTree(rootPath, onPath, onPath)
paths
diff --git a/src/stdlib/jquery-extensions.coffee b/src/stdlib/jquery-extensions.coffee
index 365c2b5a8..089363577 100644
--- a/src/stdlib/jquery-extensions.coffee
+++ b/src/stdlib/jquery-extensions.coffee
@@ -25,6 +25,9 @@ $.fn.pageUp = ->
$.fn.pageDown = ->
@scrollTop(@scrollTop() + @height())
+$.fn.isOnDom = ->
+ @closest(document.body).length is 1
+
$.fn.containsElement = (element) ->
(element[0].compareDocumentPosition(this[0]) & 8) == 8
diff --git a/static/editor.css b/static/editor.css
index 0b8cfb452..ebd85aeaf 100644
--- a/static/editor.css
+++ b/static/editor.css
@@ -56,7 +56,6 @@
overflow-x: hidden;
}
-
.editor .underlayer, .editor .lines, .editor .overlayer {
width: 100%;
height: 100%;
@@ -83,11 +82,11 @@
.editor .cursor {
position: absolute;
- border-left: 2px solid;
+ border-left: 1px solid;
}
-.editor:not(.focused) .cursor,
-.editor.focused .cursor.blink-off {
+.editor:not(.is-focused) .cursor,
+.editor.is-focused .cursor.blink-off {
visibility: hidden;
}
diff --git a/static/jasmine.css b/static/jasmine.css
index 6bf9eef9c..a1000e0fc 100644
--- a/static/jasmine.css
+++ b/static/jasmine.css
@@ -1,170 +1,80 @@
-.jasmine_reporter {
- font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
- font-size: 16px;
-}
+body { background-color: #eeeeee; padding: 0; overflow-y: scroll; }
-body {
- background: #eee;
-}
+#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
+#HTMLReporter a { text-decoration: none; }
+#HTMLReporter a:hover { text-decoration: underline; }
+#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
+#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
+#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
+#HTMLReporter .version { color: #aaaaaa; }
+#HTMLReporter .banner { margin-top: 14px; }
+#HTMLReporter .duration { color: #aaaaaa; float: right; }
+#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
+#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
+#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
+#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
+#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
+#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
+#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
+#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
+#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
+#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
+#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
+#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
+#HTMLReporter .runningAlert { background-color: #666666; }
+#HTMLReporter .skippedAlert { background-color: #aaaaaa; }
+#HTMLReporter .skippedAlert:first-child { background-color: #333333; }
+#HTMLReporter .passingAlert { background-color: #a6b779; }
+#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
+#HTMLReporter .failingAlert { background-color: #cf867e; }
+#HTMLReporter .failingAlert:first-child { background-color: #b03911; }
+#HTMLReporter .results { margin-top: 5px }
+#HTMLReporter #details { display: none; }
+#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
+#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
+#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; }
+#HTMLReporter.showDetails .summary { display: none; }
+#HTMLReporter.showDetails #details { display: block; }
+#HTMLReporter .summaryMenuItem { font-weight: bold; }
+#HTMLReporter .summary { margin-top: 14px; }
+#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
+#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
+#HTMLReporter .summary .specSummary.failed a { color: #b03911; }
+#HTMLReporter .description + .suite { margin-top: 0; }
+#HTMLReporter .suite { margin-top: 14px; }
+#HTMLReporter .suite a { color: #333333; }
+#HTMLReporter #details .specDetail { margin-bottom: 28px; }
+#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; font-size: 14px; padding: 3px 9px }
+#HTMLReporter .resultMessage { padding-top: 5px; color: #333333; }
+#HTMLReporter .resultMessage span.result { display: block; }
+#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 500px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
-.jasmine_reporter a:visited, .jasmine_reporter a {
- color: #303;
-}
-
-.jasmine_reporter a:hover, .jasmine_reporter a:active {
- color: blue;
-}
-
-.run_spec {
- float:right;
- padding-right: 5px;
- font-size: .8em;
- text-decoration: none;
-}
-
-.jasmine_reporter {
- margin: 0 5px;
-}
-
-.banner {
- color: #303;
- background-color: #fef;
- padding: 5px;
-}
-
-.logo {
- float: left;
- font-size: 1.1em;
- padding-left: 5px;
-}
-
-.logo .version {
- font-size: .6em;
- padding-left: 1em;
-}
-
-.runner.running {
- background-color: yellow;
-}
-
-
-.options {
- text-align: right;
- font-size: .8em;
-}
-
-
-
-
-.suite {
- border: 1px outset gray;
- margin: 5px 0;
- padding-left: 1em;
-}
-
-.suite .suite {
- margin: 5px;
-}
-
-.suite.passed {
- background-color: #dfd;
-}
-
-.suite.failed {
- background-color: #fdd;
-}
-
-.spec {
- margin: 5px;
- padding-left: 1em;
- clear: both;
-}
-
-.spec.failed, .spec.passed, .spec.skipped {
- padding-bottom: 5px;
- border: 1px solid gray;
-}
-
-.spec.failed {
- background-color: #fbb;
- border-color: red;
-}
-
-.spec.passed {
- background-color: #bfb;
- border-color: green;
-}
-
-.spec.skipped {
- background-color: #bbb;
-}
-
-.messages {
- border-left: 1px dashed gray;
- padding-left: 1em;
- padding-right: 1em;
-}
-
-.passed {
- background-color: #cfc;
- display: none;
-}
-
-.failed {
- background-color: #fbb;
-}
-
-.skipped {
- color: #777;
- background-color: #eee;
- display: none;
-}
-
-
-/*.resultMessage {*/
- /*white-space: pre;*/
-/*}*/
-
-.resultMessage span.result {
- display: block;
- line-height: 2em;
- color: black;
-}
-
-.resultMessage .mismatch {
- color: black;
-}
-
-.stackTrace {
- white-space: pre;
- font-size: .8em;
- margin-left: 10px;
- max-height: 5em;
- overflow: auto;
- border: 1px inset red;
- padding: 1em;
- background: #eef;
-}
-
-.finished-at {
- padding-left: 1em;
- font-size: .6em;
-}
-
-.show-passed .passed,
-.show-skipped .skipped {
- display: block;
-}
-
-
-#jasmine_content {
- position:fixed;
- right: 100%;
-}
-
-.runner {
- border: 1px solid gray;
- display: block;
- margin: 5px 0;
- padding: 2px 0 2px 10px;
-}
+#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
+#TrivialReporter a:visited, #TrivialReporter a { color: #303; }
+#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
+#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
+#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
+#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
+#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
+#TrivialReporter .runner.running { background-color: yellow; }
+#TrivialReporter .options { text-align: right; font-size: .8em; }
+#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
+#TrivialReporter .suite .suite { margin: 5px; }
+#TrivialReporter .suite.passed { background-color: #dfd; }
+#TrivialReporter .suite.failed { background-color: #fdd; }
+#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
+#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
+#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
+#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
+#TrivialReporter .spec.skipped { background-color: #bbb; }
+#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
+#TrivialReporter .passed { background-color: #cfc; display: none; }
+#TrivialReporter .failed { background-color: #fbb; }
+#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
+#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
+#TrivialReporter .resultMessage .mismatch { color: black; }
+#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
+#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
+#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
+#TrivialReporter #jasmine_content { position: fixed; right: 100%; }
+#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
diff --git a/themes/Atom - Dark/wrap-guide.css b/themes/Atom - Dark/wrap-guide.css
deleted file mode 100644
index 51660ea4c..000000000
--- a/themes/Atom - Dark/wrap-guide.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.wrap-guide {
- background: rgba(150, 150, 150, .30);
-}
diff --git a/themes/Atom - Light/wrap-guide.css b/themes/Atom - Light/wrap-guide.css
deleted file mode 100644
index 51660ea4c..000000000
--- a/themes/Atom - Light/wrap-guide.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.wrap-guide {
- background: rgba(150, 150, 150, .30);
-}
diff --git a/themes/atom-dark-syntax.css b/themes/atom-dark-syntax.css
new file mode 100644
index 000000000..92f39d650
--- /dev/null
+++ b/themes/atom-dark-syntax.css
@@ -0,0 +1,269 @@
+.editor, .editor .gutter {
+ background-color: #1d1f21;
+ color: #c5c8c6;
+}
+
+.editor.is-focused .cursor {
+ border-color: #FFFFFF;
+}
+
+.editor.is-focused .selection .region {
+ background-color: #333333;
+}
+
+.editor.is-focused .line-number.cursor-line-no-selection, .editor.is-focused .line.cursor-line {
+ background-color: rgba(255, 255, 255, 0.14);
+}
+
+.comment {
+ color: #7C7C7C;
+}
+
+.entity {
+ color: #FFD2A7;
+}
+
+.keyword {
+ color: #96CBFE;
+}
+
+.keyword.control {
+ color: #96CBFE;
+}
+
+.keyword.operator {
+ color: #EDEDED;
+}
+
+.entity.name.type {
+ text-decoration: underline;
+ color: #FFFFB6;
+}
+
+.support {
+ color: #FFFFB6;
+}
+
+.storage {
+ color: #CFCB90;
+}
+
+.storage.modifier {
+ color: #96CBFE;
+}
+
+.constant {
+ color: #99CC99;
+}
+
+.string {
+ color: #A8FF60;
+}
+
+.constant.numeric {
+ color: #FF73FD;
+}
+
+.punctuation {
+}
+
+.variable {
+ color: #C6C5FE;
+}
+
+.invalid.deprecated {
+ text-decoration: underline;
+ color: #FD5FF1;
+}
+
+.invalid.illegal {
+ color: #FD5FF1;
+ background-color: rgba(86, 45, 86, 0.75);
+}
+
+.text .source {
+ background-color: rgba(177, 179, 186, 0.03);
+}
+
+.entity.other.inherited-class {
+ color: #9B5C2E;
+}
+
+.source .string .source {
+ color: #EDEDED;
+}
+
+.source .string .source .punctuation.section.embedded {
+ color: #00A0A0;
+}
+
+.string .constant {
+ color: #00A0A0;
+}
+
+.string.regexp {
+ color: #E9C062;
+}
+
+.string.regexp .constant.character.escape, .string.regexp .source.ruby.embedded, .string.regexp .string.regexp.arbitrary-repitition {
+ color: #FF8000;
+}
+
+.string.regexp.group {
+ color: #C6A24F;
+ background-color: rgba(255, 255, 255, 0.06);
+}
+
+.string.regexp.character-class {
+ color: #B18A3D;
+}
+
+.string .variable {
+ color: #8A9A95;
+}
+
+.support.function {
+ color: #DAD085;
+}
+
+.support.constant {
+ color: #FFD2A7;
+}
+
+.meta.preprocessor.c {
+ color: #8996A8;
+}
+
+.meta.preprocessor.c .keyword {
+ color: #AFC4DB;
+}
+
+.meta.cast {
+ color: #676767;
+}
+
+.meta.sgml.html .meta.doctype, .meta.sgml.html .meta.doctype .entity, .meta.sgml.html .meta.doctype .string, .meta.xml-processing, .meta.xml-processing .entity, .meta.xml-processing .string {
+ color: #494949;
+}
+
+.meta.tag, .meta.tag .entity {
+ color: #96CBFE;
+}
+
+.source .entity.name.tag, .source .entity.other.attribute-name, .meta.tag.inline, .meta.tag.inline .entity {
+ color: #96CBFE;
+}
+
+.entity.other.attribute-name {
+ color: #FFD7B1;
+}
+
+.entity.name.tag.namespace, .entity.other.attribute-name.namespace {
+ color: #E18964;
+}
+
+.meta.selector.css .entity.name.tag {
+ text-decoration: underline;
+ color: #96CBFE;
+}
+
+.meta.selector.css .entity.other.attribute-name.tag.pseudo-class {
+ color: #8F9D6A;
+}
+
+.meta.selector.css .entity.other.attribute-name.id {
+ color: #8B98AB;
+}
+
+.meta.selector.css .entity.other.attribute-name.class {
+ color: #62B1FE;
+}
+
+.support.type.property-name.css {
+ color: #EDEDED;
+}
+
+.meta.property-group .support.constant.property-value.css, .meta.property-value .support.constant.property-value.css {
+ color: #F9EE98;
+}
+
+.meta.preprocessor.at-rule .keyword.control.at-rule {
+ color: #8693A5;
+}
+
+.meta.property-value .support.constant.named-color.css, .meta.property-value .constant {
+ color: #87C38A;
+}
+
+.meta.constructor.argument.css {
+ color: #8F9D6A;
+}
+
+.meta.diff, .meta.diff.header {
+ color: #F8F8F8;
+ background-color: #0E2231;
+}
+
+.markup.deleted {
+ color: #F8F8F8;
+ background-color: #420E09;
+}
+
+.markup.changed {
+ color: #F8F8F8;
+ background-color: #4A410D;
+}
+
+.markup.inserted {
+ color: #F8F8F8;
+ background-color: #253B22;
+}
+
+.markup.italic {
+ color: #E9C062;
+}
+
+.markup.bold {
+ color: #E9C062;
+}
+
+.markup.underline {
+ text-decoration: underline;
+ color: #E18964;
+}
+
+.markup.quote {
+ color: #E1D4B9;
+ background-color: rgba(254, 224, 156, 0.07);
+}
+
+.markup.heading, .markup.heading .entity {
+ color: #FEDCC5;
+ background-color: #632D04;
+}
+
+.markup.list {
+ color: #E1D4B9;
+}
+
+.markup.raw {
+ color: #578BB3;
+ background-color: rgba(177, 179, 186, 0.03);
+}
+
+.markup .comment {
+ color: #F67B37;
+}
+
+.meta.separator {
+ color: #60A633;
+ background-color: #242424;
+}
+
+.meta.line.entry.logfile, .meta.line.exit.logfile {
+ background-color: rgba(238, 238, 238, 0.16);
+}
+
+.meta.line.error.logfile {
+ background-color: #751012;
+}
\ No newline at end of file
diff --git a/themes/Atom - Dark/atom.css b/themes/atom-dark-ui/atom.css
similarity index 59%
rename from themes/Atom - Dark/atom.css
rename to themes/atom-dark-ui/atom.css
index 2e5a1355b..73a667189 100644
--- a/themes/Atom - Dark/atom.css
+++ b/themes/atom-dark-ui/atom.css
@@ -4,23 +4,16 @@ html, body,
background-color: #333333;
}
-#root-view #panes:before {
- display: block;
- content: "\f208";
- font-family: 'Octicons Regular';
- color: #303030;
- -webkit-font-smoothing: antialiased;
- font-size: 100vmin;
- line-height: 100vmin;
- text-align: center;
-}
-
#root-view #panes .row > * + * {
- border-left: 5px solid #515151;
+ -webkit-box-shadow:
+ -2px 0 rgba(0, 0, 0, 0.3),
+ -1px 0 rgba(255, 255, 255, 0.2);
}
#root-view #panes .column > * + * {
- border-top: 5px solid #515151;
+ -webkit-box-shadow:
+ 0 -2px rgba(0, 0, 0, 0.3),
+ 0 -1px rgba(255, 255, 255, 0.2);
}
.error {
diff --git a/themes/Atom - Dark/autocomplete.css b/themes/atom-dark-ui/autocomplete.css
similarity index 100%
rename from themes/Atom - Dark/autocomplete.css
rename to themes/atom-dark-ui/autocomplete.css
diff --git a/themes/Atom - Dark/command-logger.css b/themes/atom-dark-ui/command-logger.css
similarity index 100%
rename from themes/Atom - Dark/command-logger.css
rename to themes/atom-dark-ui/command-logger.css
diff --git a/themes/Atom - Dark/command-palette.css b/themes/atom-dark-ui/command-palette.css
similarity index 100%
rename from themes/Atom - Dark/command-palette.css
rename to themes/atom-dark-ui/command-palette.css
diff --git a/themes/Atom - Dark/command-panel.css b/themes/atom-dark-ui/command-panel.css
similarity index 87%
rename from themes/Atom - Dark/command-panel.css
rename to themes/atom-dark-ui/command-panel.css
index 5e129e7cc..6d0f9775b 100644
--- a/themes/Atom - Dark/command-panel.css
+++ b/themes/atom-dark-ui/command-panel.css
@@ -1,18 +1,21 @@
.command-panel {
background-color: #303030;
border: 1px solid #252525;
- color: #ededed;
+ color: #dedede;
padding: 5px;
}
.command-panel .preview-list {
max-height: 300px;
overflow: auto;
- margin-bottom: 3px;
+ margin: 0 1px 5px 10px;
position: relative;
- background-color: #000000;
- color: #ededed;
+ background-color: #1e1e1e;
+ color: #C5C8C6;
cursor: default;
+ border: 1px solid rgba(0, 0, 0, 0.5);
+ border-bottom: 1px solid rgba(180, 180, 180, 0.2);
+ border-right: 1px solid rgba(180, 180, 180, 0.2);
}
.command-panel .preview-count {
@@ -32,7 +35,7 @@
.command-panel .preview-list .path {
padding-left: 5px;
- color: #00a693;
+ color: #fff;
}
.command-panel .preview-list .path:before {
@@ -73,6 +76,7 @@
background-color: rgba(255, 255, 255, .2);
-webkit-border-radius: 2px;
padding: 1px;
+ color: yellow;
}
.command-panel .prompt-and-editor {
diff --git a/themes/Atom - Dark/editor.css b/themes/atom-dark-ui/editor.css
similarity index 75%
rename from themes/Atom - Dark/editor.css
rename to themes/atom-dark-ui/editor.css
index b2daa3586..9dfb302ac 100644
--- a/themes/Atom - Dark/editor.css
+++ b/themes/atom-dark-ui/editor.css
@@ -1,5 +1,6 @@
.editor {
font-family: Inconsolata, Monaco, Courier;
+ line-height: 1.3;
}
.editor.mini {
@@ -17,7 +18,7 @@
}
.editor .gutter .line-number {
- padding-right: 1.3em;
+ padding-right: .5em;
min-width: 35px;
box-sizing: border-box;
text-align: right;
@@ -52,16 +53,28 @@
opacity: 1;
}
-.editor .fold-marker:before {
- content: '\f060';
- -webkit-transform: rotate(90deg);
+.editor .gutter .line-number:after {
+ font-size: 0.8em;
+ content: '\f078';
font-family: 'Octicons Regular';
- display: inline-block;
- margin-left: .3em;
- margin-top: .1em;
- line-height: .8em;
-webkit-font-smoothing: antialiased;
color: #fba0e3;
+ visibility: hidden;
+}
+
+.editor .gutter .line-number.fold:after {
+ visibility: visible;
+}
+
+.editor .fold-marker:after {
+ content: '\2026';
+ opacity: .8;
+ color: #fba0e3;
+ padding-left: .2em;
+}
+
+.editor .line.cursor-line .fold-marker {
+ opacity: 1;
}
.editor .invisible {
diff --git a/themes/Atom - Dark/fuzzy-finder.css b/themes/atom-dark-ui/fuzzy-finder.css
similarity index 100%
rename from themes/Atom - Dark/fuzzy-finder.css
rename to themes/atom-dark-ui/fuzzy-finder.css
diff --git a/themes/Atom - Dark/gists.css b/themes/atom-dark-ui/gists.css
similarity index 100%
rename from themes/Atom - Dark/gists.css
rename to themes/atom-dark-ui/gists.css
diff --git a/themes/Atom - Dark/go-to-line.css b/themes/atom-dark-ui/go-to-line.css
similarity index 100%
rename from themes/Atom - Dark/go-to-line.css
rename to themes/atom-dark-ui/go-to-line.css
diff --git a/themes/Atom - Dark/grammar-view.css b/themes/atom-dark-ui/grammar-view.css
similarity index 100%
rename from themes/Atom - Dark/grammar-view.css
rename to themes/atom-dark-ui/grammar-view.css
diff --git a/themes/Atom - Dark/markdown-preview.css b/themes/atom-dark-ui/markdown-preview.css
similarity index 100%
rename from themes/Atom - Dark/markdown-preview.css
rename to themes/atom-dark-ui/markdown-preview.css
diff --git a/themes/Atom - Dark/package.json b/themes/atom-dark-ui/package.json
similarity index 100%
rename from themes/Atom - Dark/package.json
rename to themes/atom-dark-ui/package.json
diff --git a/themes/Atom - Dark/select-list.css b/themes/atom-dark-ui/select-list.css
similarity index 100%
rename from themes/Atom - Dark/select-list.css
rename to themes/atom-dark-ui/select-list.css
diff --git a/themes/Atom - Dark/status-bar.css b/themes/atom-dark-ui/status-bar.css
similarity index 100%
rename from themes/Atom - Dark/status-bar.css
rename to themes/atom-dark-ui/status-bar.css
diff --git a/themes/Atom - Dark/symbols-view.css b/themes/atom-dark-ui/symbols-view.css
similarity index 100%
rename from themes/Atom - Dark/symbols-view.css
rename to themes/atom-dark-ui/symbols-view.css
diff --git a/themes/Atom - Dark/tabs.css b/themes/atom-dark-ui/tabs.css
similarity index 62%
rename from themes/Atom - Dark/tabs.css
rename to themes/atom-dark-ui/tabs.css
index 09942bec6..91a635180 100644
--- a/themes/Atom - Dark/tabs.css
+++ b/themes/atom-dark-ui/tabs.css
@@ -2,10 +2,11 @@
background: #333333;
border-bottom: 4px solid #424242;
font: caption;
- box-shadow: inset 0 -1px 0 #2e2e2e;
+ box-shadow: inset 0 -1px 0 #2e2e2e, 0 1px 0 #191919;
+ margin-bottom: 1px;
}
-.tab {
+.is-focused .tab {
cursor: default;
padding: 2px 21px 2px 9px;
background-image: -webkit-linear-gradient(#444, #3d3d3d);
@@ -15,6 +16,42 @@
box-shadow: inset 0 0 5px #383838, 0 1px 0 #585858, inset -1px 0 0 #4a4a4a, inset 1px 0 0 #4a4a4a;
}
+.is-focused .tab:first-child {
+ box-shadow: inset 0 0 5px #383838, 0 1px 0 #585858, inset -1px 0 0 #4a4a4a;
+}
+
+.is-focused .tab.active,
+.is-focused .tab.active:hover {
+ border-top: 1px solid #4a4a4a;
+ box-shadow: inset -1px 0 0 #595959, inset 1px 0 0 #595959;
+ border-bottom-color: #424242;
+ background-image: -webkit-linear-gradient(#555555, #424242);
+}
+
+.tab {
+ cursor: default;
+ padding: 2px 21px 2px 9px;
+ background-color: #555;
+ background-image: none;
+ border-top: 1px solid #383838;
+ border-right: 1px solid #2e2e2e;
+ border-bottom: 1px solid #2e2e2e;
+ box-shadow: inset 0 0 5px #555, 0 1px 0 #585858, inset -1px 0 0 #4a4a4a, inset 1px 0 0 #4a4a4a;
+}
+
+.tab:first-child {
+ box-shadow: inset 0 0 5px #555, 0 1px 0 #585858, inset -1px 0 0 #4a4a4a;
+}
+
+.tab.active,
+.tab.active:hover {
+ border-top: 1px solid #4a4a4a;
+ box-shadow: inset -1px 0 0 #595959, inset 1px 0 0 #595959;
+ border-bottom-color: #424242;
+ background-image: none;
+ background-color: #424242;
+}
+
.tab,
.tab .close-icon {
color: #aaa;
@@ -24,9 +61,9 @@
border-color: #aaa;
}
-.tab.active,
-.tab.active:hover,
-.tab.active .close-icon {
+.is-focused .tab.active,
+.is-focused .tab.active:hover,
+.is-focused .tab.active .close-icon {
color: #e6e6e6;
}
@@ -48,23 +85,11 @@
content: "";
}
-.tab:first-child {
- box-shadow: inset 0 0 5px #383838, 0 1px 0 #585858, inset -1px 0 0 #4a4a4a;
-}
-
-.tab.active:first-child,
-.tab.active:first-child:hover {
+.is-focused .tab.active:first-child,
+.is-focused .tab.active:first-child:hover {
box-shadow: inset -1px 0 0 #595959;
}
-.tab.active,
-.tab.active:hover {
- border-top: 1px solid #4a4a4a;
- box-shadow: inset -1px 0 0 #595959, inset 1px 0 0 #595959;
- border-bottom-color: #424242;
- background-image: -webkit-linear-gradient(#555555, #424242);
-}
-
.tab.active:before,
.tab.active:after {
position: absolute;
@@ -75,6 +100,19 @@
z-index: 3;
border: 1px solid #595959;
}
+
+.is-focused .tab.active:before {
+ border-bottom-right-radius: 4px;
+ border-width: 0 1px 1px 0;
+ box-shadow: 2px 2px 0 #424242;
+ left: -4px;
+}
+.is-focused .tab.active:after {
+ right: -4px;
+ border-bottom-left-radius: 4px;
+ border-width: 0 0 1px 1px;
+ box-shadow: -2px 2px 0 #424242;
+}
.tab.active:before {
border-bottom-right-radius: 4px;
border-width: 0 1px 1px 0;
@@ -87,7 +125,7 @@
border-width: 0 0 1px 1px;
box-shadow: -2px 2px 0 #424242;
}
-.tab.active:first-child:before {
+.is-focused .tab.active:first-child:before {
display: none;
}
diff --git a/themes/Atom - Dark/tree-view.css b/themes/atom-dark-ui/tree-view.css
similarity index 93%
rename from themes/Atom - Dark/tree-view.css
rename to themes/atom-dark-ui/tree-view.css
index ea27fd587..7a282e53a 100644
--- a/themes/Atom - Dark/tree-view.css
+++ b/themes/atom-dark-ui/tree-view.css
@@ -1,6 +1,11 @@
-.tree-view {
+.is-focused .tree-view {
background: #1e1e1e;
- border-right: 2px solid #191919;
+ border-right: 1px solid #191919;
+}
+
+.tree-view {
+ background: #2e2e2e;
+ border-right: 1px solid #191919;
}
.tree-view .entry {
@@ -20,10 +25,15 @@
color: #d2d2d2;
}
-.tree-view .selected > .highlight {
+.is-focused .tree-view .selected > .highlight {
background-image: -webkit-linear-gradient(#4e4e4e, #434343);
}
+.tree-view .selected > .highlight {
+ background-image: none;
+ background-color: #6e6e6e;
+}
+
.tree-view:focus .selected > .highlight {
background-image: -webkit-linear-gradient(#7e7e7e, #737373);
}
diff --git a/themes/atom-dark-ui/wrap-guide.css b/themes/atom-dark-ui/wrap-guide.css
new file mode 100644
index 000000000..8e7837e5d
--- /dev/null
+++ b/themes/atom-dark-ui/wrap-guide.css
@@ -0,0 +1,3 @@
+.wrap-guide {
+ background: rgba(150, 150, 150, 0.1);
+}
diff --git a/themes/atom-light-syntax.css b/themes/atom-light-syntax.css
new file mode 100644
index 000000000..c86205d69
--- /dev/null
+++ b/themes/atom-light-syntax.css
@@ -0,0 +1,168 @@
+.editor, .editor .gutter {
+ background-color: #FFFFFF;
+ color: #555;
+}
+
+.editor.is-focused .cursor {
+ border-color: #000;
+}
+
+.editor.is-focused .selection .region {
+ background-color: #afc4da;
+}
+
+.editor.is-focused .line-number.cursor-line-no-selection, .editor.is-focused .line.cursor-line {
+ background-color: rgba(255, 255, 134, 0.34);
+}
+
+.editor .comment {
+ color: #999988;
+ font-style: italic;
+}
+
+.editor .string {
+ color: #D14;
+}
+
+.editor .constant.numeric {
+ color: #D14;
+}
+
+.editor .constant.language {
+ color: #606aa1;
+}
+
+.editor .constant.character, .editor .constant.other {
+ color: #606aa1;
+}
+
+.editor .constant.symbol {
+ color: #990073;
+}
+
+.editor .variable {
+ color: #008080;
+}
+
+/* Keywords */
+.editor .keyword {
+ color: #222;
+ font-weight: bold;
+}
+
+.editor .keyword.unit {
+ color: #445588;
+}
+
+.editor .keyword.special-method {
+ color: #0086B3;
+}
+
+.editor .storage {
+ color: #222;
+}
+
+.editor .storage.type {
+ color: #222;
+}
+
+.editor .entity.name.class {
+ text-decoration: underline;
+ color: #606aa1;
+}
+
+.editor .entity.other.inherited-class {
+ text-decoration: underline;
+ color: #606aa1;
+}
+
+.editor .entity.name.function {
+ color: #900;
+}
+
+.editor .variable.parameter {
+ color: #606aa1;
+}
+
+.editor .entity.name.tag {
+ color: #008080;
+}
+
+.editor .entity.other.attribute-name {
+ color: #458;
+ font-weight: bold;
+}
+
+.editor .support.function {
+ color: #458;
+}
+
+.editor .support.constant {
+ color: #458;
+}
+
+.editor .support.type {
+ color: #458;
+}
+
+.editor .support.class {
+ color: #008080;
+}
+
+.editor .invalid {
+ color: #F8F8F0;
+ background-color: #00A8C6;
+}
+
+.editor .invalid.deprecated {
+ color: #F8F8F0;
+ background-color: #8FBE00;
+}
+
+.editor .meta.structure.dictionary.json > .string.quoted.double.json,
+.editor .meta.structure.dictionary.json > .string.quoted.double.json .punctuation.string {
+ color: #000080;
+}
+
+.editor .meta.structure.dictionary.value.json > .string.quoted.double.json {
+ color: #d14;
+}
+
+.editor .meta.diff, .editor .meta.diff.header {
+ color: #75715E;
+}
+
+.editor .meta.function span {
+ color: #990000;
+ font-weight: bold;
+}
+
+.editor .markup.deleted {
+ color: #00A8C6;
+}
+
+.editor .markup.inserted {
+ color: #A6E22E;
+}
+
+.editor .markup.changed {
+ color: #E6DB74;
+}
+
+.editor .constant.numeric.line-number.find-in-files .- .match {
+ color: rgba(143, 190, 0, 0.63);
+}
+
+.editor .entity.name.filename.find-in-files {
+ color: #E6DB74;
+}
+
+/* CSS Styles */
+.editor .css.support.property-name {
+ font-weight: bold;
+ color: #333;
+}
+
+.editor .css.constant {
+ color: #099;
+}
\ No newline at end of file
diff --git a/themes/Atom - Light/atom.css b/themes/atom-light-ui/atom.css
similarity index 70%
rename from themes/Atom - Light/atom.css
rename to themes/atom-light-ui/atom.css
index 772922301..544df9367 100644
--- a/themes/Atom - Light/atom.css
+++ b/themes/atom-light-ui/atom.css
@@ -5,11 +5,15 @@ html, body,
}
#root-view #panes .row > * + * {
- border-left: 1px solid #989898;
+ -webkit-box-shadow:
+ -2px 0 rgba(0, 0, 0, 0.3),
+ -1px 0 rgba(255, 255, 255, 0.2);
}
#root-view #panes .column > * + * {
- border-top: 1px solid #989898;
+ -webkit-box-shadow:
+ 0 -2px rgba(0, 0, 0, 0.3),
+ 0 -1px rgba(255, 255, 255, 0.2);
}
.error {
diff --git a/themes/Atom - Light/autocomplete.css b/themes/atom-light-ui/autocomplete.css
similarity index 100%
rename from themes/Atom - Light/autocomplete.css
rename to themes/atom-light-ui/autocomplete.css
diff --git a/themes/Atom - Light/command-logger.css b/themes/atom-light-ui/command-logger.css
similarity index 100%
rename from themes/Atom - Light/command-logger.css
rename to themes/atom-light-ui/command-logger.css
diff --git a/themes/Atom - Light/command-palette.css b/themes/atom-light-ui/command-palette.css
similarity index 100%
rename from themes/Atom - Light/command-palette.css
rename to themes/atom-light-ui/command-palette.css
diff --git a/themes/Atom - Light/command-panel.css b/themes/atom-light-ui/command-panel.css
similarity index 100%
rename from themes/Atom - Light/command-panel.css
rename to themes/atom-light-ui/command-panel.css
diff --git a/themes/Atom - Light/editor.css b/themes/atom-light-ui/editor.css
similarity index 76%
rename from themes/Atom - Light/editor.css
rename to themes/atom-light-ui/editor.css
index 26dec9cb1..3a3652b0b 100644
--- a/themes/Atom - Light/editor.css
+++ b/themes/atom-light-ui/editor.css
@@ -1,5 +1,6 @@
.editor {
font-family: Inconsolata, Monaco, Courier;
+ line-height: 1.3;
}
.editor.mini {
@@ -20,7 +21,7 @@
}
.editor .gutter .line-number {
- padding-right: 1.3em;
+ padding-right: .5em;
min-width: 35px;
box-sizing: border-box;
text-align: right;
@@ -55,16 +56,28 @@
opacity: 1;
}
-.editor .fold-marker:before {
- content: '\f060';
- -webkit-transform: rotate(90deg);
+.editor .gutter .line-number:after {
+ font-size: 0.8em;
+ content: '\f078';
font-family: 'Octicons Regular';
- display: inline-block;
- margin-left: .3em;
- margin-top: .1em;
- line-height: .8em;
-webkit-font-smoothing: antialiased;
color: #fba0e3;
+ visibility: hidden;
+}
+
+.editor .gutter .line-number.fold:after {
+ visibility: visible;
+}
+
+.editor .fold-marker:after {
+ content: '\2026';
+ opacity: .8;
+ color: #fba0e3;
+ padding-left: .2em;
+}
+
+.editor .line.cursor-line .fold-marker {
+ opacity: 1;
}
.editor .invisible {
diff --git a/themes/Atom - Light/fuzzy-finder.css b/themes/atom-light-ui/fuzzy-finder.css
similarity index 100%
rename from themes/Atom - Light/fuzzy-finder.css
rename to themes/atom-light-ui/fuzzy-finder.css
diff --git a/themes/Atom - Light/gists.css b/themes/atom-light-ui/gists.css
similarity index 100%
rename from themes/Atom - Light/gists.css
rename to themes/atom-light-ui/gists.css
diff --git a/themes/Atom - Light/go-to-line.css b/themes/atom-light-ui/go-to-line.css
similarity index 100%
rename from themes/Atom - Light/go-to-line.css
rename to themes/atom-light-ui/go-to-line.css
diff --git a/themes/Atom - Light/grammar-view.css b/themes/atom-light-ui/grammar-view.css
similarity index 100%
rename from themes/Atom - Light/grammar-view.css
rename to themes/atom-light-ui/grammar-view.css
diff --git a/themes/Atom - Light/markdown-preview.css b/themes/atom-light-ui/markdown-preview.css
similarity index 100%
rename from themes/Atom - Light/markdown-preview.css
rename to themes/atom-light-ui/markdown-preview.css
diff --git a/themes/Atom - Light/package.json b/themes/atom-light-ui/package.json
similarity index 100%
rename from themes/Atom - Light/package.json
rename to themes/atom-light-ui/package.json
diff --git a/themes/Atom - Light/select-list.css b/themes/atom-light-ui/select-list.css
similarity index 100%
rename from themes/Atom - Light/select-list.css
rename to themes/atom-light-ui/select-list.css
diff --git a/themes/Atom - Light/status-bar.css b/themes/atom-light-ui/status-bar.css
similarity index 100%
rename from themes/Atom - Light/status-bar.css
rename to themes/atom-light-ui/status-bar.css
diff --git a/themes/Atom - Light/symbols-view.css b/themes/atom-light-ui/symbols-view.css
similarity index 100%
rename from themes/Atom - Light/symbols-view.css
rename to themes/atom-light-ui/symbols-view.css
diff --git a/themes/Atom - Light/tabs.css b/themes/atom-light-ui/tabs.css
similarity index 83%
rename from themes/Atom - Light/tabs.css
rename to themes/atom-light-ui/tabs.css
index 6b286ad61..ffa248c8f 100644
--- a/themes/Atom - Light/tabs.css
+++ b/themes/atom-light-ui/tabs.css
@@ -2,13 +2,26 @@
background: #e3e3e3;
border-bottom: 4px solid #e5e5e5;
font: caption;
- box-shadow: inset 0 -1px 0 #959595;
+ box-shadow: inset 0 -1px 0 #959595, 0 1px 0 #989898;
+ margin-bottom: 1px;
+}
+
+.is-focused .tab {
+ cursor: default;
+ padding: 2px 21px 2px 9px;
+ background-image: -webkit-linear-gradient(#e0e0e0, #bfbfbf);
+ border-top: none;
+ border-right: 1px solid #959595;
+ border-bottom: 1px solid #959595;
+ box-shadow: inset 0 0 5px #eee, 0 1px 0 #eee, inset -1px 0 0 #e0e0e0, inset 1px 0 0 #e0e0e0;
+ color: #323232;
}
.tab {
cursor: default;
padding: 2px 21px 2px 9px;
- background-image: -webkit-linear-gradient(#e0e0e0, #bfbfbf);
+ background-image: none;
+ background-color: #e0e0e0);
border-top: none;
border-right: 1px solid #959595;
border-bottom: 1px solid #959595;
diff --git a/themes/Atom - Light/tree-view.css b/themes/atom-light-ui/tree-view.css
similarity index 87%
rename from themes/Atom - Light/tree-view.css
rename to themes/atom-light-ui/tree-view.css
index c0f599fc2..7a833b7a2 100644
--- a/themes/Atom - Light/tree-view.css
+++ b/themes/atom-light-ui/tree-view.css
@@ -1,8 +1,13 @@
-.tree-view {
+.is-focused .tree-view {
background: #dde3e8;
border-right: 1px solid #989898;
}
+.tree-view {
+ background: #f3f3f3;
+ border-right: 1px solid #c5c5c5;
+}
+
.tree-view .entry {
text-shadow: 0 1px 0 #fff;
}
@@ -20,7 +25,7 @@
color: #262626;
}
-.tree-view .selected > .highlight {
+.is-focused .tree-view .selected > .highlight {
box-sizing: border-box;
border-top: 1px solid #97a4a7;
border-bottom: 1px solid #97a4a7;
@@ -28,12 +33,27 @@
background-image: -webkit-linear-gradient(#cad5d8, #bcccce);
}
-.tree-view:focus .selected > .highlight {
+.tree-view .selected > .highlight {
+ box-sizing: border-box;
+ border-top: 1px solid #97a4a7;
+ border-bottom: 1px solid #97a4a7;
+ background-image: none;
+ background-color: #DFDFDF;
+}
+
+.is-focused .tree-view:focus .selected > .highlight {
border-top: 1px solid #3D4552;
border-bottom: 1px solid #3D4552;
background-image: -webkit-linear-gradient(#7e868d, #69717b);
}
+.tree-view:focus .selected > .highlight {
+ border-top: 1px solid #3D4552;
+ border-bottom: 1px solid #3D4552;
+ background-image: none;
+ background-color: #69717b;
+}
+
.tree-view:focus .directory.selected > .header > .name,
.tree-view:focus .selected > .name,
.tree-view:focus .directory.selected > .header > .name:before,
@@ -50,10 +70,14 @@
color: #262626;
}
-.tree-view .name:before {
+.is-focused .tree-view .name:before {
color: #7e8692;
}
+.tree-view .name:before {
+ color: #7e7e7e;
+}
+
.tree-view .entry:hover,
.tree-view .directory .header:hover .name,
.tree-view .directory .header:hover .disclosure-arrow {
diff --git a/themes/atom-light-ui/wrap-guide.css b/themes/atom-light-ui/wrap-guide.css
new file mode 100644
index 000000000..f4ff6269c
--- /dev/null
+++ b/themes/atom-light-ui/wrap-guide.css
@@ -0,0 +1,3 @@
+.wrap-guide {
+ background: rgba(150, 150, 150, 0.3);
+}
diff --git a/vendor/jasmine-atom-reporter.js b/vendor/jasmine-atom-reporter.js
index dd896b373..6feb1dd41 100644
--- a/vendor/jasmine-atom-reporter.js
+++ b/vendor/jasmine-atom-reporter.js
@@ -1,10 +1,6 @@
-jasmine.AtomReporter = function(doc) {
- this.document = doc || document;
- this.suiteDivs = {};
- this.logRunningSpecs = false;
-};
+jasmine.AtomReporterHelpers = {};
-jasmine.AtomReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
+jasmine.AtomReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
var el = document.createElement(type);
for (var i = 2; i < arguments.length; i++) {
@@ -13,7 +9,9 @@ jasmine.AtomReporter.prototype.createDom = function(type, attrs, childrenVarArgs
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else {
- if (child) { el.appendChild(child); }
+ if (child) {
+ el.appendChild(child);
+ }
}
}
@@ -28,117 +26,344 @@ jasmine.AtomReporter.prototype.createDom = function(type, attrs, childrenVarArgs
return el;
};
-jasmine.AtomReporter.prototype.reportRunnerStarting = function(runner) {
- var showPassed, showSkipped;
-
- this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
- this.createDom('div', { className: 'banner' },
- this.createDom('div', { className: 'logo' },
- this.createDom('span', { className: 'title' }, "Jasmine"),
- this.createDom('span', { className: 'version' }, runner.env.versionString())),
- this.createDom('div', { className: 'options' },
- "Show ",
- showPassed = this.createDom('input', { id: "__jasmine_AtomReporter_showPassed__", type: 'checkbox' }),
- this.createDom('label', { "for": "__jasmine_AtomReporter_showPassed__" }, " passed "),
- showSkipped = this.createDom('input', { id: "__jasmine_AtomReporter_showSkipped__", type: 'checkbox' }),
- this.createDom('label', { "for": "__jasmine_AtomReporter_showSkipped__" }, " skipped")
- )
- ),
-
- this.runnerDiv = this.createDom('div', { className: 'runner running' },
- this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
- this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
- this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
- );
-
- this.document.body.appendChild(this.outerDiv);
-
- var suites = runner.suites();
- for (var i = 0; i < suites.length; i++) {
- var suite = suites[i];
- var suiteDiv = this.createDom('div', { className: 'suite' },
- this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
- this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
- this.suiteDivs[suite.id] = suiteDiv;
- var parentDiv = this.outerDiv;
- if (suite.parentSuite) {
- parentDiv = this.suiteDivs[suite.parentSuite.id];
- }
- parentDiv.appendChild(suiteDiv);
- }
-
- this.startedAt = new Date();
-
- var self = this;
- showPassed.onclick = function(evt) {
- if (showPassed.checked) {
- self.outerDiv.className += ' show-passed';
- } else {
- self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
- }
- };
-
- showSkipped.onclick = function(evt) {
- if (showSkipped.checked) {
- self.outerDiv.className += ' show-skipped';
- } else {
- self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
- }
- };
-};
-
-jasmine.AtomReporter.prototype.reportRunnerResults = function(runner) {
- var results = runner.results();
- var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
- this.runnerDiv.setAttribute("class", className);
- //do it twice for IE
- this.runnerDiv.setAttribute("className", className);
- var specs = runner.specs();
- var specCount = 0;
- for (var i = 0; i < specs.length; i++) {
- if (this.specFilter(specs[i])) {
- specCount++;
- }
- }
- var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
- message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
- this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
-
- this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
-};
-
-jasmine.AtomReporter.prototype.reportSuiteResults = function(suite) {
- var results = suite.results();
- var status = results.passed() ? 'passed' : 'failed';
- if (results.totalCount === 0) { // todo: change this to check results.skipped
- status = 'skipped';
- }
- this.suiteDivs[suite.id].className += " " + status;
-};
-
-jasmine.AtomReporter.prototype.reportSpecStarting = function(spec) {
- if (this.logRunningSpecs) {
- this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
- }
-};
-
-jasmine.AtomReporter.prototype.reportSpecResults = function(spec) {
- var results = spec.results();
+jasmine.AtomReporterHelpers.getSpecStatus = function(child) {
+ var results = child.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.skipped) {
status = 'skipped';
}
- var specDiv = this.createDom('div', { className: 'spec ' + status },
- this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
+
+ return status;
+};
+
+jasmine.AtomReporterHelpers.appendToSummary = function(child, childElement) {
+ var parentDiv = this.dom.summary;
+ var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
+ var parent = child[parentSuite];
+
+ if (parent) {
+ if (typeof this.views.suites[parent.id] == 'undefined') {
+ this.views.suites[parent.id] = new jasmine.AtomReporter.SuiteView(parent, this.dom, this.views);
+ }
+ parentDiv = this.views.suites[parent.id].element;
+ }
+
+ parentDiv.appendChild(childElement);
+};
+
+
+jasmine.AtomReporterHelpers.addHelpers = function(ctor) {
+ for(var fn in jasmine.AtomReporterHelpers) {
+ ctor.prototype[fn] = jasmine.AtomReporterHelpers[fn];
+ }
+};
+
+jasmine.AtomReporter = function(_doc) {
+ var self = this;
+ var doc = _doc || window.document;
+
+ var reporterView;
+
+ var dom = {};
+
+ // Jasmine Reporter Public Interface
+ self.logRunningSpecs = false;
+
+ self.reportRunnerStarting = function(runner) {
+ var specs = runner.specs() || [];
+
+ if (specs.length == 0) {
+ return;
+ }
+
+ createReporterDom();
+ doc.body.appendChild(dom.reporter);
+
+ reporterView = new jasmine.AtomReporter.ReporterView(dom);
+ reporterView.addSpecs(specs, self.specFilter);
+ };
+
+ self.reportRunnerResults = function(runner) {
+ reporterView && reporterView.complete();
+ };
+
+ self.reportSuiteResults = function(suite) {
+ reporterView.suiteComplete(suite);
+ };
+
+ self.reportSpecStarting = function(spec) {
+ if (self.logRunningSpecs) {
+ self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
+ }
+
+ reporterView.specStarted(spec);
+ };
+
+ self.reportSpecResults = function(spec) {
+ reporterView.specComplete(spec);
+ };
+
+ self.log = function() {
+ var console = jasmine.getGlobal().console;
+ if (console && console.log) {
+ if (console.log.apply) {
+ console.log.apply(console, arguments);
+ } else {
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
+ }
+ }
+ };
+
+ self.specFilter = function(spec) {
+ return self.fSpecFilter(spec);
+ };
+
+ return self;
+
+ function createReporterDom() {
+ dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
+ dom.banner = self.createDom('div', { className: 'banner' },
+ self.createDom('span', { className: 'title' }, "Atom "),
+ self.createDom('span', { className: 'version' }, "0.0.0")),
+
+ dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
+ dom.alert = self.createDom('div', {className: 'alert'}),
+ dom.results = self.createDom('div', {className: 'results'},
+ dom.summary = self.createDom('div', { className: 'summary' }),
+ dom.details = self.createDom('div', { id: 'details' }))
+ );
+ }
+
+ function searchWithCatch() {
+ var params = jasmine.AtomReporter.parameters(window.document);
+ var removed = false;
+ var i = 0;
+
+ while (!removed && i < params.length) {
+ if (params[i].match(/catch=/)) {
+ params.splice(i, 1);
+ removed = true;
+ }
+ i++;
+ }
+ if (jasmine.CATCH_EXCEPTIONS) {
+ params.push("catch=false");
+ }
+
+ return params.join("&");
+ }
+};
+jasmine.AtomReporter.parameters = function(doc) {
+ var paramStr = doc.location.search.substring(1);
+ var params = [];
+
+ if (paramStr.length > 0) {
+ params = paramStr.split('&');
+ }
+ return params;
+}
+jasmine.AtomReporter.sectionLink = function(sectionName) {
+ var link = '?';
+ var params = [];
+
+ if (sectionName) {
+ params.push('spec=' + encodeURIComponent(sectionName));
+ }
+ if (!jasmine.CATCH_EXCEPTIONS) {
+ params.push("catch=false");
+ }
+ if (params.length > 0) {
+ link += params.join("&");
+ }
+
+ return link;
+};
+jasmine.AtomReporterHelpers.addHelpers(jasmine.AtomReporter);
+jasmine.AtomReporter.ReporterView = function(dom) {
+ this.startedAt = new Date();
+ this.runningSpecCount = 0;
+ this.completeSpecCount = 0;
+ this.passedCount = 0;
+ this.failedCount = 0;
+ this.skippedCount = 0;
+
+ this.createResultsMenu = function() {
+ this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
+ this.summaryMenuItem = this.createDom('span', {className: 'summaryMenuItem'}, '0 specs'),
+ ' | ',
+ this.detailsMenuItem = this.createDom('span', {className: 'detailsMenuItem'}, '0 failing'),
+ this.currentSpecMenuItem = this.createDom('div', {className: 'currentSpecMenuItem'}, '')
+ );
+
+ };
+
+ this.addSpecs = function(specs, specFilter) {
+ this.totalSpecCount = specs.length;
+
+ this.views = {
+ specs: {},
+ suites: {}
+ };
+
+ for (var i = 0; i < specs.length; i++) {
+ var spec = specs[i];
+ this.views.specs[spec.id] = new jasmine.AtomReporter.SpecView(spec, dom, this.views);
+ if (specFilter(spec)) {
+ this.runningSpecCount++;
+ }
+ }
+ };
+
+ this.specStarted = function(spec) {
+ if (this.currentSpecMenuItem) {
+ this.currentSpecMenuItem.innerHTML = spec.getFullName()
+ }
+ }
+
+ this.specComplete = function(spec) {
+ this.completeSpecCount++;
+
+ if (isUndefined(this.views.specs[spec.id])) {
+ this.views.specs[spec.id] = new jasmine.AtomReporter.SpecView(spec, dom);
+ }
+
+ var specView = this.views.specs[spec.id];
+
+ switch (specView.status()) {
+ case 'passed':
+ this.passedCount++;
+ break;
+
+ case 'failed':
+ this.failedCount++;
+ break;
+
+ case 'skipped':
+ this.skippedCount++;
+ break;
+ }
+
+ specView.refresh(spec);
+ this.refresh();
+ };
+
+ this.suiteComplete = function(suite) {
+ var suiteView = this.views.suites[suite.id];
+ if (isUndefined(suiteView)) {
+ return;
+ }
+ suiteView.refresh();
+ };
+
+ this.refresh = function() {
+ if (isUndefined(this.resultsMenu)) {
+ this.createResultsMenu();
+ dom.alert.appendChild(this.resultsMenu);
+ }
+
+ // summary info
+ this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
+ this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
+ };
+
+ this.complete = function() {
+ dom.alert.removeChild(this.resultsMenu);
+ var skippedSpecs = this.skippedCount == 0 ? "" : " (" + this.skippedCount + " specs skipped)"
+
+ if (this.failedCount === 0) {
+ dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, this.passedCount + "/" + specPluralizedFor(this.totalSpecCount - this.skippedCount) + " passed" + skippedSpecs));
+ } else {
+ dom.alert.appendChild(this.createDom('span', {className: 'failingAlert bar'}, specPluralizedFor(this.failedCount) + " failed" + skippedSpecs));
+ showDetails();
+ }
+
+ dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
+ };
+
+ return this;
+
+ function showDetails() {
+ if (dom.reporter.className.search(/showDetails/) === -1) {
+ dom.reporter.className += " showDetails";
+ }
+ }
+
+ function isUndefined(obj) {
+ return typeof obj === 'undefined';
+ }
+
+ function isDefined(obj) {
+ return !isUndefined(obj);
+ }
+
+ function specPluralizedFor(count) {
+ var str = count + " spec";
+ if (count > 1) {
+ str += "s"
+ }
+ return str;
+ }
+
+};
+
+jasmine.AtomReporterHelpers.addHelpers(jasmine.AtomReporter.ReporterView);
+
+
+jasmine.AtomReporter.SpecView = function(spec, dom, views) {
+ this.spec = spec;
+ this.dom = dom;
+ this.views = views;
+
+ this.symbol = this.createDom('li', { className: 'pending' });
+ this.dom.symbolSummary.appendChild(this.symbol);
+
+ this.summary = this.createDom('div', { className: 'specSummary' },
+ this.createDom('a', {
+ className: 'description',
+ href: jasmine.AtomReporter.sectionLink(this.spec.getFullName()),
+ title: this.spec.getFullName()
+ }, this.spec.description)
+ );
+
+ this.detail = this.createDom('div', { className: 'specDetail' },
this.createDom('a', {
className: 'description',
- href: '?spec=' + encodeURIComponent(spec.getFullName()),
- title: spec.getFullName()
- }, spec.description));
+ href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
+ title: this.spec.getFullName()
+ }, this.spec.getFullName())
+ );
+};
+jasmine.AtomReporter.SpecView.prototype.status = function() {
+ return this.getSpecStatus(this.spec);
+};
- var resultItems = results.getItems();
+jasmine.AtomReporter.SpecView.prototype.refresh = function() {
+ this.symbol.className = this.status();
+
+ switch (this.status()) {
+ case 'skipped':
+ case 'passed':
+ break;
+
+ case 'failed':
+ this.appendSummaryToSuiteDiv();
+ this.appendFailureDetail();
+ break;
+ }
+};
+
+jasmine.AtomReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
+ this.summary.className += ' ' + this.status();
+ this.appendToSummary(this.spec, this.summary);
+};
+
+jasmine.AtomReporter.SpecView.prototype.appendFailureDetail = function() {
+ this.detail.className += ' ' + this.status();
+
+ var resultItems = this.spec.results().getItems();
var messagesDiv = this.createDom('div', { className: 'messages' });
+
for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i];
@@ -154,37 +379,29 @@ jasmine.AtomReporter.prototype.reportSpecResults = function(spec) {
}
if (messagesDiv.childNodes.length > 0) {
- specDiv.appendChild(messagesDiv);
- }
-
- this.suiteDivs[spec.suite.id].appendChild(specDiv);
-};
-
-jasmine.AtomReporter.prototype.log = function() {
- var console = jasmine.getGlobal().console;
- if (console && console.log) {
- if (console.log.apply) {
- console.log.apply(console, arguments);
- } else {
- console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
- }
+ this.detail.appendChild(messagesDiv);
+ this.dom.details.appendChild(this.detail);
}
};
-jasmine.AtomReporter.prototype.getLocation = function() {
- return this.document.location;
+jasmine.AtomReporterHelpers.addHelpers(jasmine.AtomReporter.SpecView);jasmine.AtomReporter.SuiteView = function(suite, dom, views) {
+ this.suite = suite;
+ this.dom = dom;
+ this.views = views;
+
+ this.element = this.createDom('div', { className: 'suite' },
+ this.createDom('a', { className: 'description', href: jasmine.AtomReporter.sectionLink(this.suite.getFullName()) }, this.suite.description)
+ );
+
+ this.appendToSummary(this.suite, this.element);
};
-jasmine.AtomReporter.prototype.specFilter = function(spec) {
- var paramMap = {};
- var params = this.getLocation().search.substring(1).split('&');
- for (var i = 0; i < params.length; i++) {
- var p = params[i].split('=');
- paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
- }
-
- if (!paramMap.spec) {
- return true;
- }
- return spec.getFullName().indexOf(paramMap.spec) === 0;
+jasmine.AtomReporter.SuiteView.prototype.status = function() {
+ return this.getSpecStatus(this.suite);
};
+
+jasmine.AtomReporter.SuiteView.prototype.refresh = function() {
+ this.element.className += " " + this.status();
+};
+
+jasmine.AtomReporterHelpers.addHelpers(jasmine.AtomReporter.SuiteView);
\ No newline at end of file
diff --git a/vendor/jasmine-console-reporter.js b/vendor/jasmine-console-reporter.js
index fc6eb75d7..46fa75a29 100644
--- a/vendor/jasmine-console-reporter.js
+++ b/vendor/jasmine-console-reporter.js
@@ -31,7 +31,9 @@ jasmine.ConsoleReporter.prototype.reportSpecResults = function(spec) {
for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i];
if (this.logErrors && result.type == 'expect' && result.passed && !result.passed()) {
- console.log("ERROR: " + spec.getFullName())
+ message = spec.getFullName()
+ console.log("\n\n" + message)
+ console.log((new Array(message.length + 1)).join('-'))
if (result.trace.stack) {
console.log(result.trace.stack)
}
@@ -43,9 +45,5 @@ jasmine.ConsoleReporter.prototype.reportSpecResults = function(spec) {
};
jasmine.ConsoleReporter.prototype.specFilter = function(spec) {
- if (!jasmine.getEnv().focusPriority) {
- return true;
- }
-
- return fSpecFilter(spec);
+ return true;
};
diff --git a/vendor/jasmine-focused.js b/vendor/jasmine-focused.js
index c10b1b976..6ffb8b940 100644
--- a/vendor/jasmine-focused.js
+++ b/vendor/jasmine-focused.js
@@ -36,28 +36,12 @@ var fffit = function(description, specDefinitions) {
fit(description, specDefinitions, 3);
};
-var fSpecFilter = function(specOrSuite) {
+jasmine.AtomReporter.prototype.fSpecFilter = function(specOrSuite) {
globalFocusPriority = jasmine.getEnv().focusPriority;
if (!globalFocusPriority) return true;
if (specOrSuite.focusPriority >= globalFocusPriority) return true;
var parent = specOrSuite.parentSuite || specOrSuite.suite;
if (!parent) return false;
- return fSpecFilter(parent);
-}
-
-jasmine.AtomReporter.prototype.specFilter = function(spec) {
- var paramMap = {};
- var params = this.getLocation().search.substring(1).split('&');
- for (var i = 0; i < params.length; i++) {
- var p = params[i].split('=');
- paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
- }
-
- if (!paramMap.spec && !jasmine.getEnv().focusPriority) {
- return true;
- }
-
- return (spec.getFullName().indexOf(paramMap.spec) === 0) || fSpecFilter(spec);
-};
-
+ return this.fSpecFilter(parent);
+};
\ No newline at end of file
diff --git a/vendor/jasmine-helper.coffee b/vendor/jasmine-helper.coffee
index 0defd1990..d20f96573 100644
--- a/vendor/jasmine-helper.coffee
+++ b/vendor/jasmine-helper.coffee
@@ -8,9 +8,6 @@ module.exports.runSpecSuite = (specSuite, logErrors=true) ->
$ = require 'jquery'
TimeReporter = require 'time-reporter'
- $('body').append $$ ->
- @div id: 'jasmine-content'
-
reporter = if atom.exitWhenDone
new jasmine.ConsoleReporter(document, logErrors)
else
@@ -22,4 +19,8 @@ module.exports.runSpecSuite = (specSuite, logErrors=true) ->
jasmineEnv.addReporter(new TimeReporter())
jasmineEnv.specFilter = (spec) -> reporter.specFilter(spec)
+
+ $('body').append $$ ->
+ @div id: 'jasmine-content'
+
jasmineEnv.execute()
diff --git a/vendor/jasmine.js b/vendor/jasmine.js
index 2a5b5ad58..0da28abfa 100644
--- a/vendor/jasmine.js
+++ b/vendor/jasmine.js
@@ -1,8 +1,10 @@
-// Modified line 1769
-// - if (self.blocks[self.index].abort) {
-// + if (self.blocks[self.index] && self.blocks[self.index].abort) {
+// Modified line
+// - var isCommonJS = typeof window == "undefined" && typeof exports == "object";
+// +
+//
+// Modified method jasmine.WaitsForBlock.prototype.execute
-var isCommonJS = typeof window == "undefined";
+var isCommonJS = typeof window == "undefined" && typeof exports == "object";
/**
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
@@ -38,11 +40,23 @@ jasmine.VERBOSE = false;
*/
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
+/**
+ * Maximum levels of nesting that will be included when an object is pretty-printed
+ */
+jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
+
/**
* Default timeout interval in milliseconds for waitsFor() blocks.
*/
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
+/**
+ * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite.
+ * Set to false to let the exception bubble up in the browser.
+ *
+ */
+jasmine.CATCH_EXCEPTIONS = true;
+
jasmine.getGlobal = function() {
function getGlobal() {
return window;
@@ -200,6 +214,21 @@ jasmine.any = function(clazz) {
return new jasmine.Matchers.Any(clazz);
};
+/**
+ * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
+ * attributes on the object.
+ *
+ * @example
+ * // don't care about any other attributes than foo.
+ * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
+ *
+ * @param sample {Object} sample
+ * @returns matchable object for the sample
+ */
+jasmine.objectContaining = function (sample) {
+ return new jasmine.Matchers.ObjectContaining(sample);
+};
+
/**
* Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
*
@@ -452,7 +481,7 @@ jasmine.log = function() {
* @see jasmine.createSpy
* @param obj
* @param methodName
- * @returns a Jasmine spy that can be chained with all spy methods
+ * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
*/
var spyOn = function(obj, methodName) {
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
@@ -497,6 +526,7 @@ if (isCommonJS) exports.xit = xit;
* jasmine.Matchers functions.
*
* @param {Object} actual Actual value to test against and expected value
+ * @return {jasmine.Matchers}
*/
var expect = function(actual) {
return jasmine.getEnv().currentSpec.expect(actual);
@@ -856,6 +886,25 @@ jasmine.Env.prototype.xit = function(desc, func) {
};
};
+jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
+ if (a.source != b.source)
+ mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
+
+ if (a.ignoreCase != b.ignoreCase)
+ mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier");
+
+ if (a.global != b.global)
+ mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier");
+
+ if (a.multiline != b.multiline)
+ mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier");
+
+ if (a.sticky != b.sticky)
+ mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier");
+
+ return (mismatchValues.length === 0);
+};
+
jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
return true;
@@ -918,11 +967,19 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
return a.getTime() == b.getTime();
}
- if (a instanceof jasmine.Matchers.Any) {
+ if (a.jasmineMatches) {
+ return a.jasmineMatches(b);
+ }
+
+ if (b.jasmineMatches) {
+ return b.jasmineMatches(a);
+ }
+
+ if (a instanceof jasmine.Matchers.ObjectContaining) {
return a.matches(b);
}
- if (b instanceof jasmine.Matchers.Any) {
+ if (b instanceof jasmine.Matchers.ObjectContaining) {
return b.matches(a);
}
@@ -934,6 +991,10 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
return (a == b);
}
+ if (a instanceof RegExp && b instanceof RegExp) {
+ return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
+ }
+
if (typeof a === "object" && typeof b === "object") {
return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
}
@@ -1001,10 +1062,15 @@ jasmine.Block = function(env, func, spec) {
};
jasmine.Block.prototype.execute = function(onComplete) {
- try {
+ if (!jasmine.CATCH_EXCEPTIONS) {
this.func.apply(this.spec);
- } catch (e) {
- this.spec.fail(e);
+ }
+ else {
+ try {
+ this.func.apply(this.spec);
+ } catch (e) {
+ this.spec.fail(e);
+ }
}
onComplete();
};
@@ -1216,7 +1282,7 @@ jasmine.Matchers.prototype.toEqual = function(expected) {
/**
* toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
* @param expected
- * @deprecated as of 1.0. Use not.toNotEqual() instead.
+ * @deprecated as of 1.0. Use not.toEqual() instead.
*/
jasmine.Matchers.prototype.toNotEqual = function(expected) {
return !this.env.equals_(this.actual, expected);
@@ -1262,6 +1328,17 @@ jasmine.Matchers.prototype.toBeNull = function() {
return (this.actual === null);
};
+/**
+ * Matcher that compares the actual to NaN.
+ */
+jasmine.Matchers.prototype.toBeNaN = function() {
+ this.message = function() {
+ return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
+ };
+
+ return (this.actual !== this.actual);
+};
+
/**
* Matcher that boolean not-nots the actual.
*/
@@ -1339,18 +1416,14 @@ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
+ var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
+ var positiveMessage = "";
if (this.actual.callCount === 0) {
- // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
- return [
- "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
- "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
- ];
+ positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
} else {
- return [
- "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
- "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
- ];
+ positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '')
}
+ return [positiveMessage, invertedMessage];
};
return this.env.contains_(this.actual.argsForCall, expectedArgs);
@@ -1389,7 +1462,7 @@ jasmine.Matchers.prototype.toContain = function(expected) {
* Matcher that checks that the expected item is NOT an element in the actual Array.
*
* @param {Object} expected
- * @deprecated as of 1.0. Use not.toNotContain() instead.
+ * @deprecated as of 1.0. Use not.toContain() instead.
*/
jasmine.Matchers.prototype.toNotContain = function(expected) {
return !this.env.contains_(this.actual, expected);
@@ -1408,22 +1481,19 @@ jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
* up to a given level of decimal precision (default 2).
*
* @param {Number} expected
- * @param {Number} precision
+ * @param {Number} precision, as number of decimal places
*/
jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
if (!(precision === 0)) {
precision = precision || 2;
}
- var multiplier = Math.pow(10, precision);
- var actual = Math.round(this.actual * multiplier);
- expected = Math.round(expected * multiplier);
- return expected == actual;
+ return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2);
};
/**
* Matcher that checks that the expected exception was thrown by the actual.
*
- * @param {String} expected
+ * @param {String} [expected]
*/
jasmine.Matchers.prototype.toThrow = function(expected) {
var result = false;
@@ -1457,7 +1527,7 @@ jasmine.Matchers.Any = function(expectedClass) {
this.expectedClass = expectedClass;
};
-jasmine.Matchers.Any.prototype.matches = function(other) {
+jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
if (this.expectedClass == String) {
return typeof other == 'string' || other instanceof String;
}
@@ -1477,10 +1547,222 @@ jasmine.Matchers.Any.prototype.matches = function(other) {
return other instanceof this.expectedClass;
};
-jasmine.Matchers.Any.prototype.toString = function() {
+jasmine.Matchers.Any.prototype.jasmineToString = function() {
return '';
};
+jasmine.Matchers.ObjectContaining = function (sample) {
+ this.sample = sample;
+};
+
+jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
+ mismatchKeys = mismatchKeys || [];
+ mismatchValues = mismatchValues || [];
+
+ var env = jasmine.getEnv();
+
+ var hasKey = function(obj, keyName) {
+ return obj != null && obj[keyName] !== jasmine.undefined;
+ };
+
+ for (var property in this.sample) {
+ if (!hasKey(other, property) && hasKey(this.sample, property)) {
+ mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
+ }
+ else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
+ mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual.");
+ }
+ }
+
+ return (mismatchKeys.length === 0 && mismatchValues.length === 0);
+};
+
+jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
+ return "";
+};
+// Mock setTimeout, clearTimeout
+// Contributed by Pivotal Computer Systems, www.pivotalsf.com
+
+jasmine.FakeTimer = function() {
+ this.reset();
+
+ var self = this;
+ self.setTimeout = function(funcToCall, millis) {
+ self.timeoutsMade++;
+ self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
+ return self.timeoutsMade;
+ };
+
+ self.setInterval = function(funcToCall, millis) {
+ self.timeoutsMade++;
+ self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
+ return self.timeoutsMade;
+ };
+
+ self.clearTimeout = function(timeoutKey) {
+ self.scheduledFunctions[timeoutKey] = jasmine.undefined;
+ };
+
+ self.clearInterval = function(timeoutKey) {
+ self.scheduledFunctions[timeoutKey] = jasmine.undefined;
+ };
+
+};
+
+jasmine.FakeTimer.prototype.reset = function() {
+ this.timeoutsMade = 0;
+ this.scheduledFunctions = {};
+ this.nowMillis = 0;
+};
+
+jasmine.FakeTimer.prototype.tick = function(millis) {
+ var oldMillis = this.nowMillis;
+ var newMillis = oldMillis + millis;
+ this.runFunctionsWithinRange(oldMillis, newMillis);
+ this.nowMillis = newMillis;
+};
+
+jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
+ var scheduledFunc;
+ var funcsToRun = [];
+ for (var timeoutKey in this.scheduledFunctions) {
+ scheduledFunc = this.scheduledFunctions[timeoutKey];
+ if (scheduledFunc != jasmine.undefined &&
+ scheduledFunc.runAtMillis >= oldMillis &&
+ scheduledFunc.runAtMillis <= nowMillis) {
+ funcsToRun.push(scheduledFunc);
+ this.scheduledFunctions[timeoutKey] = jasmine.undefined;
+ }
+ }
+
+ if (funcsToRun.length > 0) {
+ funcsToRun.sort(function(a, b) {
+ return a.runAtMillis - b.runAtMillis;
+ });
+ for (var i = 0; i < funcsToRun.length; ++i) {
+ try {
+ var funcToRun = funcsToRun[i];
+ this.nowMillis = funcToRun.runAtMillis;
+ funcToRun.funcToCall();
+ if (funcToRun.recurring) {
+ this.scheduleFunction(funcToRun.timeoutKey,
+ funcToRun.funcToCall,
+ funcToRun.millis,
+ true);
+ }
+ } catch(e) {
+ }
+ }
+ this.runFunctionsWithinRange(oldMillis, nowMillis);
+ }
+};
+
+jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
+ this.scheduledFunctions[timeoutKey] = {
+ runAtMillis: this.nowMillis + millis,
+ funcToCall: funcToCall,
+ recurring: recurring,
+ timeoutKey: timeoutKey,
+ millis: millis
+ };
+};
+
+/**
+ * @namespace
+ */
+jasmine.Clock = {
+ defaultFakeTimer: new jasmine.FakeTimer(),
+
+ reset: function() {
+ jasmine.Clock.assertInstalled();
+ jasmine.Clock.defaultFakeTimer.reset();
+ },
+
+ tick: function(millis) {
+ jasmine.Clock.assertInstalled();
+ jasmine.Clock.defaultFakeTimer.tick(millis);
+ },
+
+ runFunctionsWithinRange: function(oldMillis, nowMillis) {
+ jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
+ },
+
+ scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
+ jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
+ },
+
+ useMock: function() {
+ if (!jasmine.Clock.isInstalled()) {
+ var spec = jasmine.getEnv().currentSpec;
+ spec.after(jasmine.Clock.uninstallMock);
+
+ jasmine.Clock.installMock();
+ }
+ },
+
+ installMock: function() {
+ jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
+ },
+
+ uninstallMock: function() {
+ jasmine.Clock.assertInstalled();
+ jasmine.Clock.installed = jasmine.Clock.real;
+ },
+
+ real: {
+ setTimeout: jasmine.getGlobal().setTimeout,
+ clearTimeout: jasmine.getGlobal().clearTimeout,
+ setInterval: jasmine.getGlobal().setInterval,
+ clearInterval: jasmine.getGlobal().clearInterval
+ },
+
+ assertInstalled: function() {
+ if (!jasmine.Clock.isInstalled()) {
+ throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
+ }
+ },
+
+ isInstalled: function() {
+ return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
+ },
+
+ installed: null
+};
+jasmine.Clock.installed = jasmine.Clock.real;
+
+//else for IE support
+jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
+ if (jasmine.Clock.installed.setTimeout.apply) {
+ return jasmine.Clock.installed.setTimeout.apply(this, arguments);
+ } else {
+ return jasmine.Clock.installed.setTimeout(funcToCall, millis);
+ }
+};
+
+jasmine.getGlobal().setInterval = function(funcToCall, millis) {
+ if (jasmine.Clock.installed.setInterval.apply) {
+ return jasmine.Clock.installed.setInterval.apply(this, arguments);
+ } else {
+ return jasmine.Clock.installed.setInterval(funcToCall, millis);
+ }
+};
+
+jasmine.getGlobal().clearTimeout = function(timeoutKey) {
+ if (jasmine.Clock.installed.clearTimeout.apply) {
+ return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
+ } else {
+ return jasmine.Clock.installed.clearTimeout(timeoutKey);
+ }
+};
+
+jasmine.getGlobal().clearInterval = function(timeoutKey) {
+ if (jasmine.Clock.installed.clearTimeout.apply) {
+ return jasmine.Clock.installed.clearInterval.apply(this, arguments);
+ } else {
+ return jasmine.Clock.installed.clearInterval(timeoutKey);
+ }
+};
+
/**
* @constructor
*/
@@ -1609,10 +1891,6 @@ jasmine.PrettyPrinter = function() {
* @param value
*/
jasmine.PrettyPrinter.prototype.format = function(value) {
- if (this.ppNestLevel_ > 40) {
- throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
- }
-
this.ppNestLevel_++;
try {
if (value === jasmine.undefined) {
@@ -1621,8 +1899,8 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
this.emitScalar('null');
} else if (value === jasmine.getGlobal()) {
this.emitScalar('');
- } else if (value instanceof jasmine.Matchers.Any) {
- this.emitScalar(value.toString());
+ } else if (value.jasmineToString) {
+ this.emitScalar(value.jasmineToString());
} else if (typeof value === 'string') {
this.emitString(value);
} else if (jasmine.isSpy(value)) {
@@ -1655,6 +1933,7 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
+ if (!obj.hasOwnProperty(property)) continue;
if (property == '__Jasmine_been_here_before__') continue;
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
obj.__lookupGetter__(property) !== null) : false);
@@ -1682,6 +1961,11 @@ jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
};
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
+ if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
+ this.append("Array");
+ return;
+ }
+
this.append('[ ');
for (var i = 0; i < array.length; i++) {
if (i > 0) {
@@ -1693,6 +1977,11 @@ jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
};
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
+ if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
+ this.append("Object");
+ return;
+ }
+
var self = this;
this.append('{ ');
var first = true;
@@ -1721,6 +2010,10 @@ jasmine.StringPrettyPrinter.prototype.append = function(value) {
};
jasmine.Queue = function(env) {
this.env = env;
+
+ // parallel to blocks. each true value in this array means the block will
+ // get executed even if we abort
+ this.ensured = [];
this.blocks = [];
this.running = false;
this.index = 0;
@@ -1728,15 +2021,30 @@ jasmine.Queue = function(env) {
this.abort = false;
};
-jasmine.Queue.prototype.addBefore = function(block) {
+jasmine.Queue.prototype.addBefore = function(block, ensure) {
+ if (ensure === jasmine.undefined) {
+ ensure = false;
+ }
+
this.blocks.unshift(block);
+ this.ensured.unshift(ensure);
};
-jasmine.Queue.prototype.add = function(block) {
+jasmine.Queue.prototype.add = function(block, ensure) {
+ if (ensure === jasmine.undefined) {
+ ensure = false;
+ }
+
this.blocks.push(block);
+ this.ensured.push(ensure);
};
-jasmine.Queue.prototype.insertNext = function(block) {
+jasmine.Queue.prototype.insertNext = function(block, ensure) {
+ if (ensure === jasmine.undefined) {
+ ensure = false;
+ }
+
+ this.ensured.splice((this.index + this.offset + 1), 0, ensure);
this.blocks.splice((this.index + this.offset + 1), 0, block);
this.offset++;
};
@@ -1760,7 +2068,7 @@ jasmine.Queue.prototype.next_ = function() {
while (goAgain) {
goAgain = false;
- if (self.index < self.blocks.length && !this.abort) {
+ if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
var calledSynchronously = true;
var completedSynchronously = false;
@@ -2051,7 +2359,7 @@ jasmine.Spec.prototype.finish = function(onComplete) {
jasmine.Spec.prototype.after = function(doAfter) {
if (this.queue.isRunning()) {
- this.queue.add(new jasmine.Block(this.env, doAfter, this));
+ this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
} else {
this.afterCallbacks.unshift(doAfter);
}
@@ -2089,15 +2397,15 @@ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
}
for (i = 0; i < this.afterCallbacks.length; i++) {
- this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
+ this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
}
for (suite = this.suite; suite; suite = suite.parentSuite) {
for (i = 0; i < suite.after_.length; i++) {
- this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
+ this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
}
}
for (i = 0; i < runner.after_.length; i++) {
- this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
+ this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
}
};
@@ -2351,192 +2659,9 @@ jasmine.WaitsForBlock.MultiCompletion.prototype.buildCompletionFunction = functi
};
};
-// Mock setTimeout, clearTimeout
-// Contributed by Pivotal Computer Systems, www.pivotalsf.com
-
-jasmine.FakeTimer = function() {
- this.reset();
-
- var self = this;
- self.setTimeout = function(funcToCall, millis) {
- self.timeoutsMade++;
- self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
- return self.timeoutsMade;
- };
-
- self.setInterval = function(funcToCall, millis) {
- self.timeoutsMade++;
- self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
- return self.timeoutsMade;
- };
-
- self.clearTimeout = function(timeoutKey) {
- self.scheduledFunctions[timeoutKey] = jasmine.undefined;
- };
-
- self.clearInterval = function(timeoutKey) {
- self.scheduledFunctions[timeoutKey] = jasmine.undefined;
- };
-
-};
-
-jasmine.FakeTimer.prototype.reset = function() {
- this.timeoutsMade = 0;
- this.scheduledFunctions = {};
- this.nowMillis = 0;
-};
-
-jasmine.FakeTimer.prototype.tick = function(millis) {
- var oldMillis = this.nowMillis;
- var newMillis = oldMillis + millis;
- this.runFunctionsWithinRange(oldMillis, newMillis);
- this.nowMillis = newMillis;
-};
-
-jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
- var scheduledFunc;
- var funcsToRun = [];
- for (var timeoutKey in this.scheduledFunctions) {
- scheduledFunc = this.scheduledFunctions[timeoutKey];
- if (scheduledFunc != jasmine.undefined &&
- scheduledFunc.runAtMillis >= oldMillis &&
- scheduledFunc.runAtMillis <= nowMillis) {
- funcsToRun.push(scheduledFunc);
- this.scheduledFunctions[timeoutKey] = jasmine.undefined;
- }
- }
-
- if (funcsToRun.length > 0) {
- funcsToRun.sort(function(a, b) {
- return a.runAtMillis - b.runAtMillis;
- });
- for (var i = 0; i < funcsToRun.length; ++i) {
- try {
- var funcToRun = funcsToRun[i];
- this.nowMillis = funcToRun.runAtMillis;
- funcToRun.funcToCall();
- if (funcToRun.recurring) {
- this.scheduleFunction(funcToRun.timeoutKey,
- funcToRun.funcToCall,
- funcToRun.millis,
- true);
- }
- } catch(e) {
- }
- }
- this.runFunctionsWithinRange(oldMillis, nowMillis);
- }
-};
-
-jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
- this.scheduledFunctions[timeoutKey] = {
- runAtMillis: this.nowMillis + millis,
- funcToCall: funcToCall,
- recurring: recurring,
- timeoutKey: timeoutKey,
- millis: millis
- };
-};
-
-/**
- * @namespace
- */
-jasmine.Clock = {
- defaultFakeTimer: new jasmine.FakeTimer(),
-
- reset: function() {
- jasmine.Clock.assertInstalled();
- jasmine.Clock.defaultFakeTimer.reset();
- },
-
- tick: function(millis) {
- jasmine.Clock.assertInstalled();
- jasmine.Clock.defaultFakeTimer.tick(millis);
- },
-
- runFunctionsWithinRange: function(oldMillis, nowMillis) {
- jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
- },
-
- scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
- jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
- },
-
- useMock: function() {
- if (!jasmine.Clock.isInstalled()) {
- var spec = jasmine.getEnv().currentSpec;
- spec.after(jasmine.Clock.uninstallMock);
-
- jasmine.Clock.installMock();
- }
- },
-
- installMock: function() {
- jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
- },
-
- uninstallMock: function() {
- jasmine.Clock.assertInstalled();
- jasmine.Clock.installed = jasmine.Clock.real;
- },
-
- real: {
- setTimeout: jasmine.getGlobal().setTimeout,
- clearTimeout: jasmine.getGlobal().clearTimeout,
- setInterval: jasmine.getGlobal().setInterval,
- clearInterval: jasmine.getGlobal().clearInterval
- },
-
- assertInstalled: function() {
- if (!jasmine.Clock.isInstalled()) {
- throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
- }
- },
-
- isInstalled: function() {
- return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
- },
-
- installed: null
-};
-jasmine.Clock.installed = jasmine.Clock.real;
-
-//else for IE support
-jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
- if (jasmine.Clock.installed.setTimeout.apply) {
- return jasmine.Clock.installed.setTimeout.apply(this, arguments);
- } else {
- return jasmine.Clock.installed.setTimeout(funcToCall, millis);
- }
-};
-
-jasmine.getGlobal().setInterval = function(funcToCall, millis) {
- if (jasmine.Clock.installed.setInterval.apply) {
- return jasmine.Clock.installed.setInterval.apply(this, arguments);
- } else {
- return jasmine.Clock.installed.setInterval(funcToCall, millis);
- }
-};
-
-jasmine.getGlobal().clearTimeout = function(timeoutKey) {
- if (jasmine.Clock.installed.clearTimeout.apply) {
- return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
- } else {
- return jasmine.Clock.installed.clearTimeout(timeoutKey);
- }
-};
-
-jasmine.getGlobal().clearInterval = function(timeoutKey) {
- if (jasmine.Clock.installed.clearTimeout.apply) {
- return jasmine.Clock.installed.clearInterval.apply(this, arguments);
- } else {
- return jasmine.Clock.installed.clearInterval(timeoutKey);
- }
-};
-
jasmine.version_= {
"major": 1,
- "minor": 1,
- "build": 0,
- "revision": 1315677058
+ "minor": 3,
+ "build": 1,
+ "revision": 1354556913
};