mirror of
https://github.com/atom/atom.git
synced 2026-02-16 09:35:54 -05:00
Merge master
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
TextMateGrammar = require 'text-mate-grammar'
|
||||
Package = require 'package'
|
||||
fs = require 'fs-utils'
|
||||
fsUtils = require 'fs-utils'
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
CSON = require 'cson'
|
||||
@@ -8,8 +8,13 @@ CSON = require 'cson'
|
||||
module.exports =
|
||||
class AtomPackage extends Package
|
||||
metadata: null
|
||||
keymaps: null
|
||||
stylesheets: null
|
||||
grammars: null
|
||||
scopedProperties: null
|
||||
mainModulePath: null
|
||||
resolvedMainModulePath: false
|
||||
mainModule: null
|
||||
deferActivation: false
|
||||
|
||||
load: ->
|
||||
try
|
||||
@@ -18,7 +23,7 @@ class AtomPackage extends Package
|
||||
@loadStylesheets()
|
||||
@loadGrammars()
|
||||
@loadScopedProperties()
|
||||
if @deferActivation = @metadata.activationEvents?
|
||||
if @metadata.activationEvents?
|
||||
@registerDeferredDeserializers()
|
||||
else
|
||||
@requireMainModule()
|
||||
@@ -26,59 +31,91 @@ class AtomPackage extends Package
|
||||
console.warn "Failed to load package named '#{@name}'", e.stack
|
||||
this
|
||||
|
||||
activate: ({immediate}={}) ->
|
||||
keymap.add(path, map) for [path, map] in @keymaps
|
||||
applyStylesheet(path, content) for [path, content] in @stylesheets
|
||||
syntax.addGrammar(grammar) for grammar in @grammars
|
||||
syntax.addProperties(path, selector, properties) for [path, selector, properties] in @scopedProperties
|
||||
|
||||
if @metadata.activationEvents? and not immediate
|
||||
@subscribeToActivationEvents()
|
||||
else
|
||||
@activateNow()
|
||||
|
||||
activateNow: ->
|
||||
try
|
||||
if @requireMainModule()
|
||||
config.setDefaults(@name, @mainModule.configDefaults)
|
||||
@mainModule.activate(atom.getPackageState(@name) ? {})
|
||||
catch e
|
||||
console.warn "Failed to activate package named '#{@name}'", e.stack
|
||||
|
||||
loadMetadata: ->
|
||||
if metadataPath = fs.resolveExtension(fs.join(@path, 'package'), ['cson', 'json'])
|
||||
if metadataPath = fsUtils.resolveExtension(fsUtils.join(@path, 'package'), ['cson', 'json'])
|
||||
@metadata = CSON.readObject(metadataPath)
|
||||
@metadata ?= {}
|
||||
|
||||
loadKeymaps: ->
|
||||
keymapsDirPath = fs.join(@path, 'keymaps')
|
||||
@keymaps = @getKeymapPaths().map (path) -> [path, CSON.readObject(path)]
|
||||
|
||||
getKeymapPaths: ->
|
||||
keymapsDirPath = fsUtils.join(@path, 'keymaps')
|
||||
if @metadata.keymaps
|
||||
for path in @metadata.keymaps
|
||||
keymapPath = fs.resolve(keymapsDirPath, path, ['cson', 'json', ''])
|
||||
keymap.load(keymapPath)
|
||||
@metadata.keymaps.map (name) -> fsUtils.resolve(keymapsDirPath, name, ['cson', 'json', ''])
|
||||
else
|
||||
keymap.loadDirectory(keymapsDirPath)
|
||||
fsUtils.list(keymapsDirPath, ['cson', 'json']) ? []
|
||||
|
||||
loadStylesheets: ->
|
||||
stylesheetDirPath = fs.join(@path, 'stylesheets')
|
||||
for stylesheetPath in fs.list(stylesheetDirPath) ? []
|
||||
requireStylesheet(stylesheetPath)
|
||||
@stylesheets = @getStylesheetPaths().map (path) -> [path, loadStylesheet(path)]
|
||||
|
||||
getStylesheetPaths: ->
|
||||
stylesheetDirPath = fsUtils.join(@path, 'stylesheets')
|
||||
if @metadata.stylesheets
|
||||
@metadata.stylesheets.map (name) -> fsUtils.resolve(stylesheetDirPath, name, ['css', 'less', ''])
|
||||
else
|
||||
fsUtils.list(stylesheetDirPath, ['css', 'less']) ? []
|
||||
|
||||
loadGrammars: ->
|
||||
grammarsDirPath = fs.join(@path, 'grammars')
|
||||
for grammarPath in fs.list(grammarsDirPath, ['.cson', '.json']) ? []
|
||||
grammarContent = fs.readObject(grammarPath)
|
||||
grammar = new TextMateGrammar(grammarContent)
|
||||
syntax.addGrammar(grammar)
|
||||
@grammars = []
|
||||
grammarsDirPath = fsUtils.join(@path, 'grammars')
|
||||
for grammarPath in fsUtils.list(grammarsDirPath, ['.cson', '.json']) ? []
|
||||
@grammars.push(TextMateGrammar.loadSync(grammarPath))
|
||||
|
||||
loadScopedProperties: ->
|
||||
scopedPropertiessDirPath = fs.join(@path, 'scoped-properties')
|
||||
for scopedPropertiesPath in fs.list(scopedPropertiessDirPath, ['.cson', '.json']) ? []
|
||||
for selector, properties of fs.readObject(scopedPropertiesPath)
|
||||
syntax.addProperties(selector, properties)
|
||||
@scopedProperties = []
|
||||
scopedPropertiessDirPath = fsUtils.join(@path, 'scoped-properties')
|
||||
for scopedPropertiesPath in fsUtils.list(scopedPropertiessDirPath, ['.cson', '.json']) ? []
|
||||
for selector, properties of fsUtils.readObject(scopedPropertiesPath)
|
||||
@scopedProperties.push([scopedPropertiesPath, selector, properties])
|
||||
|
||||
activate: ->
|
||||
if @deferActivation
|
||||
@subscribeToActivationEvents()
|
||||
else
|
||||
try
|
||||
if @requireMainModule()
|
||||
config.setDefaults(@name, @mainModule.configDefaults)
|
||||
atom.activateAtomPackage(this)
|
||||
catch e
|
||||
console.warn "Failed to activate package named '#{@name}'", e.stack
|
||||
serialize: ->
|
||||
try
|
||||
@mainModule?.serialize?()
|
||||
catch e
|
||||
console.error "Error serializing package '#{@name}'", e.stack
|
||||
|
||||
deactivate: ->
|
||||
@unsubscribeFromActivationEvents()
|
||||
syntax.removeGrammar(grammar) for grammar in @grammars
|
||||
syntax.removeProperties(path) for [path] in @scopedProperties
|
||||
keymap.remove(path) for [path] in @keymaps
|
||||
removeStylesheet(path) for [path] in @stylesheets
|
||||
@mainModule?.deactivate?()
|
||||
|
||||
requireMainModule: ->
|
||||
return @mainModule if @mainModule
|
||||
mainPath =
|
||||
mainModulePath = @getMainModulePath()
|
||||
@mainModule = require(mainModulePath) if fsUtils.isFile(mainModulePath)
|
||||
|
||||
getMainModulePath: ->
|
||||
return @mainModulePath if @resolvedMainModulePath
|
||||
@resolvedMainModulePath = true
|
||||
mainModulePath =
|
||||
if @metadata.main
|
||||
fs.join(@path, @metadata.main)
|
||||
fsUtils.join(@path, @metadata.main)
|
||||
else
|
||||
fs.join(@path, 'index')
|
||||
mainPath = fs.resolveExtension(mainPath, ["", _.keys(require.extensions)...])
|
||||
@mainModule = require(mainPath) if fs.isFile(mainPath)
|
||||
fsUtils.join(@path, 'index')
|
||||
@mainModulePath = fsUtils.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...])
|
||||
|
||||
registerDeferredDeserializers: ->
|
||||
for deserializerName in @metadata.deferredDeserializers ? []
|
||||
@@ -86,25 +123,23 @@ class AtomPackage extends Package
|
||||
|
||||
subscribeToActivationEvents: () ->
|
||||
return unless @metadata.activationEvents?
|
||||
|
||||
activateHandler = (event) =>
|
||||
bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event)
|
||||
@deferActivation = false
|
||||
@activate()
|
||||
$(event.target).trigger(event)
|
||||
@restoreEventHandlersOnBubblePath(bubblePathEventHandlers)
|
||||
@unsubscribeFromActivationEvents(activateHandler)
|
||||
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
rootView.command(event, activateHandler) for event in @metadata.activationEvents
|
||||
rootView.command(event, @handleActivationEvent) for event in @metadata.activationEvents
|
||||
else
|
||||
rootView.command(event, selector, activateHandler) for event, selector of @metadata.activationEvents
|
||||
rootView.command(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
|
||||
|
||||
unsubscribeFromActivationEvents: (activateHandler) ->
|
||||
handleActivationEvent: (event) =>
|
||||
bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event)
|
||||
@activateNow()
|
||||
$(event.target).trigger(event)
|
||||
@restoreEventHandlersOnBubblePath(bubblePathEventHandlers)
|
||||
@unsubscribeFromActivationEvents()
|
||||
|
||||
unsubscribeFromActivationEvents: ->
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
rootView.off(event, activateHandler) for event in @metadata.activationEvents
|
||||
rootView.off(event, @handleActivationEvent) for event in @metadata.activationEvents
|
||||
else
|
||||
rootView.off(event, selector, activateHandler) for event, selector of @metadata.activationEvents
|
||||
rootView.off(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
|
||||
|
||||
disableEventHandlersOnBubblePath: (event) ->
|
||||
bubblePathEventHandlers = []
|
||||
|
||||
@@ -13,59 +13,91 @@ _.extend atom,
|
||||
loadedThemes: []
|
||||
pendingBrowserProcessCallbacks: {}
|
||||
loadedPackages: []
|
||||
activatedAtomPackages: []
|
||||
atomPackageStates: {}
|
||||
activePackages: []
|
||||
packageStates: {}
|
||||
presentingModal: false
|
||||
pendingModals: [[]]
|
||||
|
||||
getPathToOpen: ->
|
||||
@getWindowState('pathToOpen') ? window.location.params.pathToOpen
|
||||
|
||||
activateAtomPackage: (pack) ->
|
||||
@activatedAtomPackages.push(pack)
|
||||
pack.mainModule.activate(@atomPackageStates[pack.name] ? {})
|
||||
getPackageState: (name) ->
|
||||
@packageStates[name]
|
||||
|
||||
deactivateAtomPackages: ->
|
||||
pack.mainModule.deactivate?() for pack in @activatedAtomPackages
|
||||
@activatedAtomPackages = []
|
||||
|
||||
serializeAtomPackages: ->
|
||||
packageStates = {}
|
||||
for pack in @loadedPackages
|
||||
if pack in @activatedAtomPackages
|
||||
try
|
||||
packageStates[pack.name] = pack.mainModule.serialize?()
|
||||
catch e
|
||||
console?.error("Exception serializing '#{pack.name}' package's module\n", e.stack)
|
||||
else
|
||||
packageStates[pack.name] = @atomPackageStates[pack.name]
|
||||
packageStates
|
||||
|
||||
loadPackages: ->
|
||||
textMatePackages = []
|
||||
paths = @getPackagePaths().filter (path) -> fs.base(path) isnt 'text.tmbundle'
|
||||
for path in paths
|
||||
pack = Package.build(path)
|
||||
@loadedPackages.push(pack)
|
||||
pack.load()
|
||||
setPackageState: (name, state) ->
|
||||
@packageStates[name] = state
|
||||
|
||||
activatePackages: ->
|
||||
pack.activate() for pack in @loadedPackages
|
||||
@activatePackage(pack.path) for pack in @getLoadedPackages()
|
||||
|
||||
activatePackage: (id, options) ->
|
||||
if pack = @loadPackage(id, options)
|
||||
@activePackages.push(pack)
|
||||
pack.activate(options)
|
||||
pack
|
||||
|
||||
deactivatePackages: ->
|
||||
@deactivatePackage(pack.path) for pack in @getActivePackages()
|
||||
|
||||
deactivatePackage: (id) ->
|
||||
if pack = @getActivePackage(id)
|
||||
@setPackageState(pack.name, state) if state = pack.serialize?()
|
||||
pack.deactivate()
|
||||
_.remove(@activePackages, pack)
|
||||
else
|
||||
throw new Error("No active package for id '#{id}'")
|
||||
|
||||
getActivePackage: (id) ->
|
||||
if path = @resolvePackagePath(id)
|
||||
_.detect @activePackages, (pack) -> pack.path is path
|
||||
|
||||
isPackageActive: (id) ->
|
||||
if path = @resolvePackagePath(id)
|
||||
_.detect @activePackages, (pack) -> pack.path is path
|
||||
|
||||
getActivePackages: ->
|
||||
_.clone(@activePackages)
|
||||
|
||||
loadPackages: ->
|
||||
@loadPackage(path) for path in @getPackagePaths() when not @isPackageDisabled(path)
|
||||
|
||||
loadPackage: (id, options) ->
|
||||
if @isPackageDisabled(id)
|
||||
return console.warn("Tried to load disabled packaged '#{id}'")
|
||||
|
||||
if path = @resolvePackagePath(id)
|
||||
return pack if pack = @getLoadedPackage(id)
|
||||
pack = Package.load(path, options)
|
||||
@loadedPackages.push(pack)
|
||||
pack
|
||||
else
|
||||
throw new Error("Could not resolve '#{id}' to a package path")
|
||||
|
||||
resolvePackagePath: _.memoize (id) ->
|
||||
return id if fs.isDirectory(id)
|
||||
path = fs.resolve(config.packageDirPaths..., id)
|
||||
path if fs.isDirectory(path)
|
||||
|
||||
getLoadedPackage: (id) ->
|
||||
if path = @resolvePackagePath(id)
|
||||
_.detect @loadedPackages, (pack) -> pack.path is path
|
||||
|
||||
isPackageLoaded: (id) ->
|
||||
@getLoadedPackage(id)?
|
||||
|
||||
getLoadedPackages: ->
|
||||
_.clone(@loadedPackages)
|
||||
|
||||
isPackageDisabled: (id) ->
|
||||
if path = @resolvePackagePath(id)
|
||||
_.include(config.get('core.disabledPackages') ? [], fs.base(path))
|
||||
|
||||
getPackagePaths: ->
|
||||
disabledPackages = config.get("core.disabledPackages") ? []
|
||||
packagePaths = []
|
||||
for packageDirPath in config.packageDirPaths
|
||||
for packagePath in fs.list(packageDirPath)
|
||||
continue if not fs.isDirectory(packagePath)
|
||||
continue if fs.base(packagePath) in disabledPackages
|
||||
continue if packagePath in packagePaths
|
||||
packagePaths.push(packagePath)
|
||||
|
||||
packagePaths
|
||||
packagePaths.push(packagePath) if fs.isDirectory(packagePath)
|
||||
_.uniq(packagePaths)
|
||||
|
||||
loadThemes: ->
|
||||
themeNames = config.get("core.themes") ? ['atom-dark-ui', 'atom-dark-syntax']
|
||||
|
||||
@@ -14,8 +14,9 @@ class BindingSet
|
||||
commandsByKeystrokes: null
|
||||
commandForEvent: null
|
||||
parser: null
|
||||
name: null
|
||||
|
||||
constructor: (@selector, commandsByKeystrokes, @index) ->
|
||||
constructor: (@selector, commandsByKeystrokes, @index, @name) ->
|
||||
BindingSet.parser ?= PEG.buildParser(fs.read(require.resolve 'keystroke-pattern.pegjs'))
|
||||
@specificity = Specificity(@selector)
|
||||
@commandsByKeystrokes = @normalizeCommandsByKeystrokes(commandsByKeystrokes)
|
||||
|
||||
@@ -584,9 +584,15 @@ class EditSession
|
||||
cursor = @addCursor(marker)
|
||||
selection = new Selection({editSession: this, marker, cursor})
|
||||
@selections.push(selection)
|
||||
selectionBufferRange = selection.getBufferRange()
|
||||
@mergeIntersectingSelections()
|
||||
@trigger 'selection-added', selection
|
||||
selection
|
||||
if selection.destroyed
|
||||
for selection in @getSelections()
|
||||
if selection.intersectsBufferRange(selectionBufferRange)
|
||||
return selection
|
||||
else
|
||||
@trigger 'selection-added', selection
|
||||
selection
|
||||
|
||||
addSelectionForBufferRange: (bufferRange, options={}) ->
|
||||
options = _.defaults({invalidationStrategy: 'never'}, options)
|
||||
@@ -837,12 +843,18 @@ class EditSession
|
||||
|
||||
getGrammar: -> @languageMode.grammar
|
||||
|
||||
setGrammar: (grammar) ->
|
||||
@languageMode.grammar = grammar
|
||||
@handleGrammarChange()
|
||||
|
||||
reloadGrammar: ->
|
||||
if @languageMode.reloadGrammar()
|
||||
@unfoldAll()
|
||||
@displayBuffer.tokenizedBuffer.resetScreenLines()
|
||||
@trigger 'grammar-changed'
|
||||
true
|
||||
@handleGrammarChange() if @languageMode.reloadGrammar()
|
||||
|
||||
handleGrammarChange: ->
|
||||
@unfoldAll()
|
||||
@displayBuffer.tokenizedBuffer.resetScreenLines()
|
||||
@trigger 'grammar-changed'
|
||||
true
|
||||
|
||||
getDebugSnapshot: ->
|
||||
[
|
||||
|
||||
@@ -150,7 +150,6 @@ class Editor extends View
|
||||
'editor:toggle-line-comments': @toggleLineCommentsInSelection
|
||||
'editor:log-cursor-scope': @logCursorScope
|
||||
'editor:checkout-head-revision': @checkoutHead
|
||||
'editor:select-grammar': @selectGrammar
|
||||
'editor:copy-path': @copyPathToPasteboard
|
||||
'editor:move-line-up': @moveLineUp
|
||||
'editor:move-line-down': @moveLineDown
|
||||
@@ -374,7 +373,7 @@ class Editor extends View
|
||||
else if clickCount == 3
|
||||
@activeEditSession.selectLine() unless e.shiftKey
|
||||
|
||||
@selectOnMousemoveUntilMouseup()
|
||||
@selectOnMousemoveUntilMouseup() unless e.originalEvent.which > 1
|
||||
|
||||
@renderedLines.on 'mousedown', onMouseDown
|
||||
|
||||
@@ -590,6 +589,7 @@ class Editor extends View
|
||||
@setSoftWrapColumn(softWrapColumn) if @attached
|
||||
if @activeEditSession.getSoftWrap()
|
||||
@addClass 'soft-wrap'
|
||||
@scrollView.scrollLeft(0)
|
||||
@_setSoftWrapColumn = => @setSoftWrapColumn()
|
||||
$(window).on "resize.editor-#{@id}", @_setSoftWrapColumn
|
||||
else
|
||||
@@ -659,7 +659,7 @@ class Editor extends View
|
||||
super
|
||||
rootView?.focus()
|
||||
|
||||
afterRemove: ->
|
||||
beforeRemove: ->
|
||||
@removed = true
|
||||
@activeEditSession?.destroy()
|
||||
$(window).off(".editor-#{@id}")
|
||||
@@ -1143,19 +1143,23 @@ class Editor extends View
|
||||
else
|
||||
@highlightedLine = null
|
||||
|
||||
getGrammar: -> @activeEditSession.getGrammar()
|
||||
getGrammar: ->
|
||||
@activeEditSession.getGrammar()
|
||||
|
||||
selectGrammar: ->
|
||||
GrammarView = require 'grammar-view'
|
||||
new GrammarView(this)
|
||||
setGrammar: (grammar) ->
|
||||
throw new Error("Only mini-editors can explicity set their grammar") unless @mini
|
||||
@activeEditSession.setGrammar(grammar)
|
||||
@handleGrammarChange()
|
||||
|
||||
reloadGrammar: ->
|
||||
grammarChanged = @activeEditSession.reloadGrammar()
|
||||
if grammarChanged
|
||||
@clearRenderedLines()
|
||||
@updateDisplay()
|
||||
@handleGrammarChange() if grammarChanged
|
||||
grammarChanged
|
||||
|
||||
handleGrammarChange: ->
|
||||
@clearRenderedLines()
|
||||
@updateDisplay()
|
||||
|
||||
bindToKeyedEvent: (key, event, callback) ->
|
||||
binding = {}
|
||||
binding[key] = event
|
||||
|
||||
@@ -8,6 +8,7 @@ BindingSet = require 'binding-set'
|
||||
module.exports =
|
||||
class Keymap
|
||||
bindingSets: null
|
||||
nextBindingSetIndex: 0
|
||||
bindingSetsByFirstKeystroke: null
|
||||
queuedKeystrokes: null
|
||||
|
||||
@@ -40,20 +41,39 @@ class Keymap
|
||||
@load(filePath) for filePath in fs.list(directoryPath, ['.cson', '.json']) ? []
|
||||
|
||||
load: (path) ->
|
||||
@add(CSON.readObject(path))
|
||||
@add(path, CSON.readObject(path))
|
||||
|
||||
add: (keymap) ->
|
||||
add: (args...) ->
|
||||
name = args.shift() if args.length > 1
|
||||
keymap = args.shift()
|
||||
for selector, bindings of keymap
|
||||
@bindKeys(selector, bindings)
|
||||
@bindKeys(name, selector, bindings)
|
||||
|
||||
bindKeys: (selector, bindings) ->
|
||||
bindingSet = new BindingSet(selector, bindings, @bindingSets.length)
|
||||
remove: (name) ->
|
||||
for bindingSet in @bindingSets.filter((bindingSet) -> bindingSet.name is name)
|
||||
_.remove(@bindingSets, bindingSet)
|
||||
for keystrokes of bindingSet.commandsByKeystrokes
|
||||
keystroke = keystrokes.split(' ')[0]
|
||||
_.remove(@bindingSetsByFirstKeystroke[keystroke], bindingSet)
|
||||
|
||||
bindKeys: (args...) ->
|
||||
name = args.shift() if args.length > 2
|
||||
[selector, bindings] = args
|
||||
bindingSet = new BindingSet(selector, bindings, @nextBindingSetIndex++, name)
|
||||
@bindingSets.unshift(bindingSet)
|
||||
for keystrokes of bindingSet.commandsByKeystrokes
|
||||
keystroke = keystrokes.split(' ')[0] # only index by first keystroke
|
||||
@bindingSetsByFirstKeystroke[keystroke] ?= []
|
||||
@bindingSetsByFirstKeystroke[keystroke].push(bindingSet)
|
||||
|
||||
unbindKeys: (selector, bindings) ->
|
||||
bindingSet = _.detect @bindingSets, (bindingSet) ->
|
||||
bindingSet.selector is selector and bindingSet.bindings is bindings
|
||||
|
||||
if bindingSet
|
||||
console.log "binding set", bindingSet
|
||||
_.remove(@bindingSets, bindingSet)
|
||||
|
||||
bindingsForElement: (element) ->
|
||||
keystrokeMap = {}
|
||||
currentNode = $(element)
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
'meta-U': 'editor:lower-case'
|
||||
'alt-meta-w': 'editor:close-other-edit-sessions'
|
||||
'meta-P': 'editor:close-all-edit-sessions'
|
||||
'meta-L': 'editor:select-grammar'
|
||||
'ctrl-C': 'editor:copy-path'
|
||||
'ctrl-meta-up': 'editor:move-line-up'
|
||||
'ctrl-meta-down': 'editor:move-line-down'
|
||||
|
||||
@@ -11,6 +11,11 @@ class Package
|
||||
else
|
||||
new AtomPackage(path)
|
||||
|
||||
@load: (path, options) ->
|
||||
pack = @build(path)
|
||||
pack.load(options)
|
||||
pack
|
||||
|
||||
name: null
|
||||
path: null
|
||||
|
||||
|
||||
@@ -324,5 +324,5 @@ class Pane extends View
|
||||
container.adjustPaneDimensions()
|
||||
container.trigger 'pane:removed', [this]
|
||||
|
||||
afterRemove: ->
|
||||
beforeRemove: ->
|
||||
item.destroy?() for item in @getItems()
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class Point
|
||||
@fromObject: (object) ->
|
||||
if object instanceof Point
|
||||
object
|
||||
else
|
||||
if object instanceof Array
|
||||
if _.isArray(object)
|
||||
[row, column] = object
|
||||
else
|
||||
{ row, column } = object
|
||||
|
||||
@@ -31,7 +31,7 @@ class Range
|
||||
new Range(@start.copy(), @end.copy())
|
||||
|
||||
isEqual: (other) ->
|
||||
if other instanceof Array and other.length == 2
|
||||
if _.isArray(other) and other.length == 2
|
||||
other = new Range(other...)
|
||||
|
||||
other.start.isEqual(@start) and other.end.isEqual(@end)
|
||||
|
||||
@@ -29,8 +29,7 @@ class RootView extends View
|
||||
@div id: 'vertical', outlet: 'vertical', =>
|
||||
@subview 'panes', panes ? new PaneContainer
|
||||
|
||||
@deserialize: ({ panes, packages, projectPath }) ->
|
||||
atom.atomPackageStates = packages ? {}
|
||||
@deserialize: ({ panes }) ->
|
||||
panes = deserialize(panes) if panes?.deserializer is 'PaneContainer'
|
||||
new RootView({panes})
|
||||
|
||||
@@ -73,7 +72,6 @@ class RootView extends View
|
||||
version: RootView.version
|
||||
deserializer: 'RootView'
|
||||
panes: @panes.serialize()
|
||||
packages: atom.serializeAtomPackages()
|
||||
|
||||
confirmClose: ->
|
||||
@panes.confirmClose()
|
||||
@@ -94,10 +92,6 @@ class RootView extends View
|
||||
afterAttach: (onDom) ->
|
||||
@focus() if onDom
|
||||
|
||||
deactivate: ->
|
||||
atom.deactivateAtomPackages()
|
||||
@remove()
|
||||
|
||||
open: (path, options = {}) ->
|
||||
changeFocus = options.changeFocus ? true
|
||||
path = project.resolve(path) if path?
|
||||
|
||||
@@ -22,7 +22,6 @@ class Syntax
|
||||
@grammarsByFileType = {}
|
||||
@grammarsByScopeName = {}
|
||||
@grammarOverridesByPath = {}
|
||||
@globalProperties = {}
|
||||
@scopedPropertiesIndex = 0
|
||||
@scopedProperties = []
|
||||
@nullGrammar = new NullGrammar
|
||||
@@ -32,9 +31,14 @@ class Syntax
|
||||
|
||||
addGrammar: (grammar) ->
|
||||
@grammars.push(grammar)
|
||||
for fileType in grammar.fileTypes
|
||||
@grammarsByFileType[fileType] = grammar
|
||||
@grammarsByScopeName[grammar.scopeName] = grammar
|
||||
@grammarsByFileType[fileType] = grammar for fileType in grammar.fileTypes
|
||||
@grammarsByScopeName[grammar.scopeName] = grammar
|
||||
|
||||
removeGrammar: (grammar) ->
|
||||
if _.include(@grammars, grammar)
|
||||
_.remove(@grammars, grammar)
|
||||
delete @grammarsByFileType[fileType] for fileType in grammar.fileTypes
|
||||
delete @grammarsByScopeName[grammar.scopeName]
|
||||
|
||||
setGrammarOverrideForPath: (path, scopeName) ->
|
||||
@grammarOverridesByPath[path] = scopeName
|
||||
@@ -46,7 +50,9 @@ class Syntax
|
||||
@grammarOverridesByPath = {}
|
||||
|
||||
selectGrammar: (filePath, fileContents) ->
|
||||
|
||||
return @grammarsByFileType["txt"] ? @nullGrammar unless filePath
|
||||
|
||||
@grammarOverrideForPath(filePath) ?
|
||||
@grammarByFirstLineRegex(filePath, fileContents) ?
|
||||
@grammarByPath(filePath) ?
|
||||
@@ -94,18 +100,24 @@ class Syntax
|
||||
@grammarsByScopeName[scopeName]
|
||||
|
||||
addProperties: (args...) ->
|
||||
selector = args.shift() if args.length > 1
|
||||
properties = args.shift()
|
||||
name = args.shift() if args.length > 2
|
||||
[selector, properties] = args
|
||||
|
||||
if selector
|
||||
@scopedProperties.unshift(
|
||||
selector: selector,
|
||||
properties: properties,
|
||||
specificity: Specificity(selector),
|
||||
index: @scopedPropertiesIndex++
|
||||
)
|
||||
else
|
||||
_.extend(@globalProperties, properties)
|
||||
@scopedProperties.unshift(
|
||||
name: name
|
||||
selector: selector,
|
||||
properties: properties,
|
||||
specificity: Specificity(selector),
|
||||
index: @scopedPropertiesIndex++
|
||||
)
|
||||
|
||||
removeProperties: (name) ->
|
||||
for properties in @scopedProperties.filter((properties) -> properties.name is name)
|
||||
_.remove(@scopedProperties, properties)
|
||||
|
||||
clearProperties: ->
|
||||
@scopedProperties = []
|
||||
@scopedPropertiesIndex = 0
|
||||
|
||||
getProperty: (scope, keyPath) ->
|
||||
for object in @propertiesForScope(scope, keyPath)
|
||||
@@ -121,7 +133,7 @@ class Syntax
|
||||
while element
|
||||
matchingProperties.push(@matchingPropertiesForElement(element, candidates)...)
|
||||
element = element.parentNode
|
||||
matchingProperties.concat([@globalProperties])
|
||||
matchingProperties
|
||||
|
||||
matchingPropertiesForElement: (element, candidates) ->
|
||||
matchingScopedProperties = candidates.filter ({selector}) ->
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
Package = require 'package'
|
||||
fs = require 'fs'
|
||||
fsUtils = require 'fs-utils'
|
||||
plist = require 'plist'
|
||||
_ = require 'underscore'
|
||||
TextMateGrammar = require 'text-mate-grammar'
|
||||
CSON = require 'cson'
|
||||
async = require 'async'
|
||||
|
||||
module.exports =
|
||||
@@ -31,7 +29,16 @@ class TextMatePackage extends Package
|
||||
TextMatePackage.getLoadQueue().push(this)
|
||||
@loadScopedProperties()
|
||||
|
||||
legalGrammarExtensions: ['plist', 'tmLanguage', 'tmlanguage', 'cson', 'json']
|
||||
activate: ->
|
||||
syntax.addGrammar(grammar) for grammar in @grammars
|
||||
for { selector, properties } in @scopedProperties
|
||||
syntax.addProperties(@path, selector, properties)
|
||||
|
||||
deactivate: ->
|
||||
syntax.removeGrammar(grammar) for grammar in @grammars
|
||||
syntax.removeProperties(@path)
|
||||
|
||||
legalGrammarExtensions: ['plist', 'tmLanguage', 'tmlanguage']
|
||||
|
||||
loadGrammars: (done) ->
|
||||
fsUtils.isDirectoryAsync @syntaxesPath, (isDirectory) =>
|
||||
@@ -52,30 +59,22 @@ class TextMatePackage extends Package
|
||||
|
||||
addGrammar: (grammar) ->
|
||||
@grammars.push(grammar)
|
||||
syntax.addGrammar(grammar)
|
||||
|
||||
activate: -> # no-op
|
||||
syntax.addGrammar(grammar) if atom.isPackageActive(@path)
|
||||
|
||||
getGrammars: -> @grammars
|
||||
|
||||
loadScopedProperties: ->
|
||||
for { selector, properties } in @getScopedProperties()
|
||||
syntax.addProperties(selector, properties)
|
||||
|
||||
getScopedProperties: ->
|
||||
scopedProperties = []
|
||||
@scopedProperties = []
|
||||
|
||||
for grammar in @getGrammars()
|
||||
if properties = @propertiesFromTextMateSettings(grammar)
|
||||
selector = syntax.cssSelectorFromScopeSelector(grammar.scopeName)
|
||||
scopedProperties.push({selector, properties})
|
||||
@scopedProperties.push({selector, properties})
|
||||
|
||||
for {scope, settings} in @getTextMatePreferenceObjects()
|
||||
if properties = @propertiesFromTextMateSettings(settings)
|
||||
selector = syntax.cssSelectorFromScopeSelector(scope) if scope?
|
||||
scopedProperties.push({selector, properties})
|
||||
|
||||
scopedProperties
|
||||
@scopedProperties.push({selector, properties})
|
||||
|
||||
getTextMatePreferenceObjects: ->
|
||||
preferenceObjects = []
|
||||
|
||||
@@ -61,10 +61,12 @@ window.shutdown = ->
|
||||
return if not project and not rootView
|
||||
atom.setWindowState('pathToOpen', project.getPath())
|
||||
atom.setWindowState('project', project.serialize())
|
||||
atom.setWindowState('rootView', rootView.serialize())
|
||||
atom.setWindowState('syntax', syntax.serialize())
|
||||
atom.setWindowState('rootView', rootView.serialize())
|
||||
atom.deactivatePackages()
|
||||
atom.setWindowState('packageStates', atom.packageStates)
|
||||
rootView.remove()
|
||||
atom.saveWindowState()
|
||||
rootView.deactivate()
|
||||
project.destroy()
|
||||
git?.destroy()
|
||||
$(window).off('focus blur before')
|
||||
@@ -78,7 +80,7 @@ window.installAtomCommand = (commandPath) ->
|
||||
bundledCommandPath = fs.resolve(window.resourcePath, 'atom.sh')
|
||||
if bundledCommandPath?
|
||||
fs.write(commandPath, fs.read(bundledCommandPath))
|
||||
spawn("chmod u+x '#{commandPath}'")
|
||||
spawn('chmod', ['u+x', commandPath])
|
||||
|
||||
window.handleWindowEvents = ->
|
||||
$(window).command 'window:toggle-full-screen', => atom.toggleFullScreen()
|
||||
@@ -95,6 +97,7 @@ window.deserializeWindowState = ->
|
||||
|
||||
windowState = atom.getWindowState()
|
||||
|
||||
atom.packageStates = windowState.packageStates ? {}
|
||||
window.project = deserialize(windowState.project) ? new Project(pathToOpen)
|
||||
window.rootView = deserialize(windowState.rootView) ? new RootView
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ describe "Autocomplete", ->
|
||||
describe "@activate()", ->
|
||||
it "activates autocomplete on all existing and future editors (but not on autocomplete's own mini editor)", ->
|
||||
spyOn(AutocompleteView.prototype, 'initialize').andCallThrough()
|
||||
autocompletePackage = window.loadPackage("autocomplete")
|
||||
autocompletePackage = atom.activatePackage("autocomplete")
|
||||
expect(AutocompleteView.prototype.initialize).not.toHaveBeenCalled()
|
||||
|
||||
leftEditor = rootView.getActiveView()
|
||||
@@ -41,7 +41,7 @@ describe "AutocompleteView", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
editor = new Editor(editSession: project.buildEditSession('sample.js'))
|
||||
window.loadPackage('autocomplete')
|
||||
atom.activatePackage('autocomplete')
|
||||
autocomplete = new AutocompleteView(editor)
|
||||
miniEditor = autocomplete.miniEditor
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ describe "Autoflow package", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open()
|
||||
window.loadPackage 'autoflow'
|
||||
atom.activatePackage('autoflow')
|
||||
editor = rootView.getActiveView()
|
||||
config.set('editor.preferredLineLength', 30)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ describe "bracket matching", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage('bracket-matcher')
|
||||
atom.activatePackage('bracket-matcher')
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveView()
|
||||
editSession = editor.activeEditSession
|
||||
|
||||
@@ -7,7 +7,7 @@ describe "CommandLogger", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
commandLogger = window.loadPackage('command-logger').mainModule
|
||||
commandLogger = atom.activatePackage('command-logger').mainModule
|
||||
commandLogger.eventLog = {}
|
||||
editor = rootView.getActiveView()
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ class CommandPaletteView extends SelectList
|
||||
|
||||
filterKey: 'eventDescription'
|
||||
|
||||
previouslyFocusedElement: null
|
||||
keyBindings: null
|
||||
|
||||
initialize: ->
|
||||
@@ -30,10 +29,14 @@ class CommandPaletteView extends SelectList
|
||||
attach: ->
|
||||
super
|
||||
|
||||
@keyBindings = _.losslessInvert(keymap.bindingsForElement(@previouslyFocusedElement))
|
||||
if @previouslyFocusedElement[0]
|
||||
@eventElement = @previouslyFocusedElement
|
||||
else
|
||||
@eventElement = rootView
|
||||
@keyBindings = _.losslessInvert(keymap.bindingsForElement(@eventElement))
|
||||
|
||||
events = []
|
||||
for eventName, eventDescription of _.extend($(window).events(), @previouslyFocusedElement.events())
|
||||
for eventName, eventDescription of _.extend($(window).events(), @eventElement.events())
|
||||
events.push({eventName, eventDescription}) if eventDescription
|
||||
|
||||
events = _.sortBy events, (e) -> e.eventDescription
|
||||
@@ -53,4 +56,4 @@ class CommandPaletteView extends SelectList
|
||||
|
||||
confirmed: ({eventName}) ->
|
||||
@cancel()
|
||||
@previouslyFocusedElement.trigger(eventName)
|
||||
@eventElement.trigger(eventName)
|
||||
|
||||
@@ -9,7 +9,7 @@ describe "CommandPalette", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage("command-palette")
|
||||
atom.activatePackage("command-palette")
|
||||
rootView.attachToDom().focus()
|
||||
rootView.trigger 'command-palette:toggle'
|
||||
palette = rootView.find('.command-palette').view()
|
||||
@@ -81,3 +81,20 @@ describe "CommandPalette", ->
|
||||
expect(activeEditor.isFocused).toBeTruthy()
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
expect(palette.hasParent()).toBeFalsy()
|
||||
|
||||
describe "when no element has focus", ->
|
||||
it "uses the root view as the element to display and trigger events for", ->
|
||||
rootView.trigger 'command-palette:toggle'
|
||||
$(':focus').blur()
|
||||
rootView.trigger 'command-palette:toggle'
|
||||
keyBindings = _.losslessInvert(keymap.bindingsForElement(rootView.getActiveView()))
|
||||
for eventName, description of rootView.events()
|
||||
eventLi = palette.list.children("[data-event-name='#{eventName}']")
|
||||
if description
|
||||
expect(eventLi).toExist()
|
||||
expect(eventLi.find('.label')).toHaveText(description)
|
||||
expect(eventLi.find('.label').attr('title')).toBe(eventName)
|
||||
for binding in keyBindings[eventName] ? []
|
||||
expect(eventLi.find(".key-binding:contains(#{binding})")).toExist()
|
||||
else
|
||||
expect(eventLi).not.toExist()
|
||||
|
||||
@@ -11,8 +11,12 @@ class CommandInterpreter
|
||||
@lastRelativeAddress = compositeCommand if compositeCommand.isRelativeAddress()
|
||||
compositeCommand.execute(@project, activeEditSession)
|
||||
|
||||
repeatRelativeAddress: (activeEditSession) ->
|
||||
@lastRelativeAddress?.execute(@project, activeEditSession)
|
||||
repeatRelativeAddress: (activeEditSession, {reverse}={}) ->
|
||||
return unless @lastRelativeAddress
|
||||
reverse ?= false
|
||||
previousSelectionRange = activeEditSession.getSelection().getBufferRange()
|
||||
address = if reverse then @lastRelativeAddress.reverse() else @lastRelativeAddress
|
||||
|
||||
repeatRelativeAddressInReverse: (activeEditSession) ->
|
||||
@lastRelativeAddress?.reverse().execute(@project, activeEditSession)
|
||||
address.execute(@project, activeEditSession).done ->
|
||||
currentSelectionRange = activeEditSession.getSelection().getBufferRange()
|
||||
$native.beep() if previousSelectionRange.isEqual(currentSelectionRange)
|
||||
|
||||
@@ -44,7 +44,7 @@ class CommandPanelView extends View
|
||||
rootView.command 'command-panel:find-in-file', => @attach('/')
|
||||
rootView.command 'command-panel:find-in-project', => @attach('Xx/')
|
||||
rootView.command 'command-panel:repeat-relative-address', => @repeatRelativeAddress()
|
||||
rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddressInReverse()
|
||||
rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddress(reverse: true)
|
||||
rootView.command 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress()
|
||||
|
||||
@on 'click', '.expand', @onExpandAll
|
||||
@@ -65,6 +65,9 @@ class CommandPanelView extends View
|
||||
|
||||
destroy: ->
|
||||
@previewList.destroy()
|
||||
rootView.off "command-panel:toggle-preview command-panel:find-in-file command-panel:find-in-project \
|
||||
command-panel:repeat-relative-address command-panel:repeat-relative-address-in-reverse command-panel:set-selection-as-regex-address"
|
||||
@remove()
|
||||
|
||||
toggle: ->
|
||||
if @miniEditor.isFocused
|
||||
@@ -138,6 +141,7 @@ class CommandPanelView extends View
|
||||
else
|
||||
@detach()
|
||||
catch error
|
||||
@loadingMessage.hide()
|
||||
if error.name is "SyntaxError"
|
||||
@flashError()
|
||||
return
|
||||
@@ -154,11 +158,8 @@ class CommandPanelView extends View
|
||||
@historyIndex++
|
||||
@miniEditor.setText(@history[@historyIndex] or '')
|
||||
|
||||
repeatRelativeAddress: ->
|
||||
@commandInterpreter.repeatRelativeAddress(rootView.getActivePaneItem())
|
||||
|
||||
repeatRelativeAddressInReverse: ->
|
||||
@commandInterpreter.repeatRelativeAddressInReverse(rootView.getActivePaneItem())
|
||||
repeatRelativeAddress: (options) ->
|
||||
@commandInterpreter.repeatRelativeAddress(rootView.getActivePaneItem(), options)
|
||||
|
||||
setSelectionAsLastRelativeAddress: ->
|
||||
selection = rootView.getActiveView().getSelectedText()
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports =
|
||||
class Address extends Command
|
||||
compile: (project, buffer, ranges) ->
|
||||
deferred = $.Deferred()
|
||||
deferred.resolve ranges.map (range) =>
|
||||
operations = ranges.map (range) =>
|
||||
newRange = @getRange(buffer, range)
|
||||
|
||||
new Operation
|
||||
@@ -15,6 +15,7 @@ class Address extends Command
|
||||
bufferRange: newRange
|
||||
errorMessage: @errorMessage
|
||||
|
||||
deferred.resolve(operations)
|
||||
deferred.promise()
|
||||
|
||||
isAddress: -> true
|
||||
|
||||
@@ -11,7 +11,7 @@ describe "CommandPanel", ->
|
||||
rootView.enableKeymap()
|
||||
editSession = rootView.getActivePaneItem()
|
||||
buffer = editSession.buffer
|
||||
commandPanelMain = window.loadPackage('command-panel', activateImmediately: true).mainModule
|
||||
commandPanelMain = atom.activatePackage('command-panel', immediate: true).mainModule
|
||||
commandPanel = commandPanelMain.commandPanelView
|
||||
commandPanel.history = []
|
||||
commandPanel.historyIndex = 0
|
||||
@@ -28,11 +28,8 @@ describe "CommandPanel", ->
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
window.rootView = RootView.deserialize(rootViewState)
|
||||
rootView.attachToDom()
|
||||
window.loadPackage('command-panel')
|
||||
atom.deactivatePackage('command-panel')
|
||||
atom.activatePackage('command-panel')
|
||||
|
||||
expect(rootView.find('.command-panel')).not.toExist()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
@@ -55,13 +52,12 @@ describe "CommandPanel", ->
|
||||
expect(commandPanel.history[2]).toBe('/test3')
|
||||
expect(commandPanel.historyIndex).toBe(3)
|
||||
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
RootView.deserialize(rootViewState).attachToDom()
|
||||
window.loadPackage('command-panel')
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
atom.deactivatePackage('command-panel')
|
||||
atom.activatePackage('command-panel')
|
||||
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
commandPanel = rootView.find('.command-panel').view()
|
||||
|
||||
expect(commandPanel.history.length).toBe(2)
|
||||
expect(commandPanel.history[0]).toBe('/test2')
|
||||
expect(commandPanel.history[1]).toBe('/test3')
|
||||
@@ -216,39 +212,69 @@ describe "CommandPanel", ->
|
||||
expect(commandPanel.miniEditor.hiddenInput).not.toMatchSelector ':focus'
|
||||
|
||||
describe "when command-panel:repeat-relative-address is triggered on the root view", ->
|
||||
it "repeats the last search command if there is one", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
describe "when there is more than one match", ->
|
||||
it "repeats the last search command if there is one", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
|
||||
editSession.setCursorScreenPosition([4, 0])
|
||||
editSession.setCursorScreenPosition([4, 0])
|
||||
|
||||
commandPanel.execute("/current")
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]]
|
||||
commandPanel.execute("/current")
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]]
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]]
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]]
|
||||
|
||||
commandPanel.execute('s/r/R/g')
|
||||
commandPanel.execute('s/r/R/g')
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,34], [6,41]]
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,34], [6,41]]
|
||||
|
||||
commandPanel.execute('0')
|
||||
commandPanel.execute('/sort/ s/r/R/') # this contains a substitution... won't be repeated
|
||||
commandPanel.execute('0')
|
||||
commandPanel.execute('/sort/ s/r/R/') # this contains a substitution... won't be repeated
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[3,31], [3,38]]
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[3,31], [3,38]]
|
||||
|
||||
describe "when there is only one match and it is selected", ->
|
||||
it "maintains the current selection and plays a beep", ->
|
||||
editSession.setCursorScreenPosition([0, 0])
|
||||
waitsForPromise ->
|
||||
commandPanel.execute("/Array")
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]]
|
||||
spyOn($native, 'beep')
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
waitsFor ->
|
||||
$native.beep.callCount > 0
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]]
|
||||
|
||||
describe "when command-panel:repeat-relative-address-in-reverse is triggered on the root view", ->
|
||||
it "it repeats the last relative address in the reverse direction", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
describe "when there is more than one match", ->
|
||||
it "it repeats the last relative address in the reverse direction", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
|
||||
editSession.setCursorScreenPosition([6, 0])
|
||||
editSession.setCursorScreenPosition([6, 0])
|
||||
|
||||
commandPanel.execute("/current")
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]]
|
||||
commandPanel.execute("/current")
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]]
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]]
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]]
|
||||
|
||||
describe "when there is only one match and it is selected", ->
|
||||
it "maintains the current selection and plays a beep", ->
|
||||
editSession.setCursorScreenPosition([0, 0])
|
||||
waitsForPromise ->
|
||||
commandPanel.execute("/Array")
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]]
|
||||
spyOn($native, 'beep')
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
waitsFor ->
|
||||
$native.beep.callCount > 0
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]]
|
||||
|
||||
describe "when command-panel:set-selection-as-regex-address is triggered on the root view", ->
|
||||
it "sets the @lastRelativeAddress to a RegexAddress of the current selection", ->
|
||||
@@ -319,13 +345,15 @@ describe "CommandPanel", ->
|
||||
# there shouldn't be any dangling operations after this
|
||||
|
||||
describe "if the command is malformed", ->
|
||||
it "adds and removes an error class to the command panel and does not close it", ->
|
||||
it "adds and removes an error class to the command panel and does not close it or display a loading message", ->
|
||||
rootView.attachToDom()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
commandPanel.miniEditor.insertText 'garbage-command!!'
|
||||
|
||||
commandPanel.miniEditor.hiddenInput.trigger keydownEvent('enter')
|
||||
expect(commandPanel.parent()).toExist()
|
||||
expect(commandPanel).toHaveClass 'error'
|
||||
expect(commandPanel.loadingMessage).toBeHidden()
|
||||
|
||||
advanceClock 400
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ describe "Preview List", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView()
|
||||
rootView.attachToDom()
|
||||
commandPanelMain = window.loadPackage('command-panel', activateImmediately: true).mainModule
|
||||
commandPanelMain = atom.activatePackage('command-panel', immediate: true).mainModule
|
||||
commandPanelView = commandPanelMain.commandPanelView
|
||||
previewList = commandPanelView.previewList
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
|
||||
@@ -17,7 +17,7 @@ describe "EditorStats", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
editorStats = window.loadPackage('editor-stats').mainModule.stats
|
||||
editorStats = atom.activatePackage('editor-stats').mainModule.stats
|
||||
|
||||
describe "when a keyup event is triggered", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -163,8 +163,10 @@ class FuzzyFinderView extends SelectList
|
||||
@loadPathsTask.start()
|
||||
|
||||
populateOpenBufferPaths: ->
|
||||
editSessions = project.getEditSessions().filter (editSession)->
|
||||
editSessions = project.getEditSessions().filter (editSession) ->
|
||||
editSession.getPath()?
|
||||
editSessions = _.uniq editSessions, (editSession) ->
|
||||
editSession.getPath()
|
||||
|
||||
editSessions = _.sortBy editSessions, (editSession) =>
|
||||
if editSession is rootView.getActivePaneItem()
|
||||
|
||||
@@ -13,7 +13,7 @@ describe 'FuzzyFinder', ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
rootView.enableKeymap()
|
||||
finderView = window.loadPackage("fuzzy-finder").mainModule.createView()
|
||||
finderView = atom.activatePackage("fuzzy-finder").mainModule.createView()
|
||||
|
||||
describe "file-finder behavior", ->
|
||||
describe "toggling", ->
|
||||
@@ -143,8 +143,8 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
rootView.open()
|
||||
|
||||
states = rootView.serialize().packages
|
||||
states = _.map states['fuzzy-finder'], (path, time) -> [ path, time ]
|
||||
atom.deactivatePackage('fuzzy-finder')
|
||||
states = _.map atom.getPackageState('fuzzy-finder'), (path, time) -> [ path, time ]
|
||||
states = _.sortBy states, (path, time) -> -time
|
||||
|
||||
paths = [ 'sample-with-tabs.coffee', 'sample.txt', 'sample.js' ]
|
||||
@@ -166,6 +166,13 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(rootView.find('.fuzzy-finder')).not.toExist()
|
||||
|
||||
describe "when multiple sessions are opened on the same path", ->
|
||||
it "does not display duplicates for that path in the list", ->
|
||||
rootView.open 'sample.js'
|
||||
rootView.getActivePane().splitRight()
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(_.pluck(finderView.list.children('li'), 'outerText')).toEqual ['sample.js']
|
||||
|
||||
describe "when a path selection is confirmed", ->
|
||||
[editor1, editor2] = []
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ describe "GitHub Flavored Markdown grammar", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(syntax, "addGrammar").andCallThrough()
|
||||
window.loadPackage("gfm")
|
||||
atom.activatePackage("gfm")
|
||||
expect(syntax.addGrammar).toHaveBeenCalled()
|
||||
grammar = syntax.addGrammar.argsForCall[0][0]
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class Gists
|
||||
constructor: ->
|
||||
rootView.command 'gist:create', '.editor', => @createGist()
|
||||
|
||||
createGist: (editor) ->
|
||||
createGist: ->
|
||||
editor = rootView.getActiveView()
|
||||
return unless editor?
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ describe "Gists package", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage('gists')
|
||||
atom.activatePackage('gists')
|
||||
editor = rootView.getActiveView()
|
||||
spyOn($, 'ajax')
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
'.editor':
|
||||
'meta-L': 'grammar-selector:show'
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
SelectList = require 'select-list'
|
||||
Editor = require 'editor'
|
||||
{$$} = require 'space-pen'
|
||||
|
||||
module.exports =
|
||||
class GrammarView extends SelectList
|
||||
class GrammarSelector extends SelectList
|
||||
@viewClass: -> "#{super} grammar-selector from-top overlay mini"
|
||||
|
||||
@viewClass: -> "#{super} grammar-view from-top overlay mini"
|
||||
@activate: ->
|
||||
rootView.command 'grammar-selector:show', '.editor', => new GrammarSelector()
|
||||
|
||||
filterKey: 'name'
|
||||
|
||||
initialize: (@editor) ->
|
||||
initialize: ->
|
||||
@editor = rootView.getActiveView()
|
||||
return unless @editor instanceof Editor
|
||||
@currentGrammar = @editor.getGrammar()
|
||||
@path = @editor.getPath()
|
||||
@autoDetect = name: 'Auto Detect'
|
||||
@command 'editor:select-grammar', =>
|
||||
@command 'grammar-selector:show', =>
|
||||
@cancel()
|
||||
false
|
||||
super
|
||||
@@ -55,6 +60,5 @@ class GrammarView extends SelectList
|
||||
|
||||
attach: ->
|
||||
super
|
||||
|
||||
rootView.append(this)
|
||||
@miniEditor.focus()
|
||||
@miniEditor.focus()
|
||||
2
src/packages/grammar-selector/package.cson
Normal file
2
src/packages/grammar-selector/package.cson
Normal file
@@ -0,0 +1,2 @@
|
||||
'main': 'lib/grammar-selector'
|
||||
'activationEvents': ['grammar-selector:show']
|
||||
@@ -0,0 +1,47 @@
|
||||
GrammarSelector = require '../lib/grammar-selector'
|
||||
RootView = require 'root-view'
|
||||
_ = require 'underscore'
|
||||
|
||||
describe "GrammarSelector", ->
|
||||
[editor, textGrammar, jsGrammar] = []
|
||||
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
atom.activatePackage('grammar-selector')
|
||||
atom.activatePackage('text.tmbundle', sync: true)
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
rootView.open('sample.js')
|
||||
editor = rootView.getActiveView()
|
||||
textGrammar = _.find syntax.grammars, (grammar) -> grammar.name is 'Plain Text'
|
||||
expect(textGrammar).toBeTruthy()
|
||||
jsGrammar = _.find syntax.grammars, (grammar) -> grammar.name is 'JavaScript'
|
||||
expect(jsGrammar).toBeTruthy()
|
||||
expect(editor.getGrammar()).toBe jsGrammar
|
||||
|
||||
describe "when grammar-selector:show is triggered", ->
|
||||
it "displays a list of all the available grammars", ->
|
||||
editor.trigger 'grammar-selector:show'
|
||||
grammarView = rootView.find('.grammar-selector').view()
|
||||
expect(grammarView).toExist()
|
||||
grammars = syntax.grammars
|
||||
expect(grammarView.list.children('li').length).toBe grammars.length + 1
|
||||
expect(grammarView.list.children('li:first').text()).toBe 'Auto Detect'
|
||||
|
||||
describe "when a grammar is selected", ->
|
||||
it "sets the new grammar on the editor", ->
|
||||
editor.trigger 'grammar-selector:show'
|
||||
grammarView = rootView.find('.grammar-selector').view()
|
||||
grammarView.confirmed(textGrammar)
|
||||
expect(editor.getGrammar()).toBe textGrammar
|
||||
|
||||
describe "when auto-detect is selected", ->
|
||||
it "restores the auto-detected grammar on the editor", ->
|
||||
editor.trigger 'grammar-selector:show'
|
||||
grammarView = rootView.find('.grammar-selector').view()
|
||||
grammarView.confirmed(textGrammar)
|
||||
expect(editor.getGrammar()).toBe textGrammar
|
||||
|
||||
editor.trigger 'grammar-selector:show'
|
||||
grammarView = rootView.find('.grammar-selector').view()
|
||||
grammarView.confirmed(grammarView.array[0])
|
||||
expect(editor.getGrammar()).toBe jsGrammar
|
||||
@@ -22,4 +22,4 @@ module.exports =
|
||||
nextPane.showItem(new MarkdownPreviewView(editSession.buffer))
|
||||
else
|
||||
activePane.splitRight(new MarkdownPreviewView(editSession.buffer))
|
||||
activePane.focus()
|
||||
activePane.focus()
|
||||
|
||||
@@ -6,7 +6,7 @@ describe "MarkdownPreview package", ->
|
||||
beforeEach ->
|
||||
project.setPath(project.resolve('markdown'))
|
||||
window.rootView = new RootView
|
||||
window.loadPackage("markdown-preview", activateImmediately: true)
|
||||
atom.activatePackage("markdown-preview", immediate: true)
|
||||
spyOn(MarkdownPreviewView.prototype, 'fetchRenderedMarkdown')
|
||||
|
||||
describe "markdown-preview:show", ->
|
||||
|
||||
@@ -7,7 +7,7 @@ describe 'Package Generator', ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage("package-generator")
|
||||
atom.activatePackage("package-generator")
|
||||
|
||||
describe "when package-generator:generate is triggered", ->
|
||||
it "displays a miniEditor", ->
|
||||
|
||||
@@ -10,7 +10,7 @@ fdescribe "__PackageName__View", ->
|
||||
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
__packageName__ = window.loadPackage('__packageName__', activateImmediately: true)
|
||||
__packageName__ = atom.activatePackage('__packageName__', immediate: true)
|
||||
|
||||
describe "when the __package-name__:toggle event is triggered", ->
|
||||
it "attaches and then detaches the view", ->
|
||||
|
||||
@@ -9,16 +9,14 @@ Package = require 'package'
|
||||
describe "Snippets extension", ->
|
||||
[buffer, editor, editSession] = []
|
||||
beforeEach ->
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
|
||||
packageWithSnippets = window.loadPackage("package-with-snippets")
|
||||
spyOn(atom, "getLoadedPackages").andCallFake ->
|
||||
textMatePackages = window.textMatePackages.filter (pack) -> /package-with-a-cson-grammar|test|textmate-package|javascript/.test(pack.name)
|
||||
textMatePackages.concat([packageWithSnippets])
|
||||
packageWithSnippets = atom.loadPackage("package-with-snippets")
|
||||
|
||||
spyOn(require("snippets/lib/snippets"), 'loadAll')
|
||||
window.loadPackage("snippets")
|
||||
atom.activatePackage("snippets")
|
||||
|
||||
editor = rootView.getActiveView()
|
||||
editSession = rootView.getActivePaneItem()
|
||||
@@ -238,6 +236,9 @@ describe "Snippets extension", ->
|
||||
|
||||
describe "snippet loading", ->
|
||||
beforeEach ->
|
||||
atom.loadPackage('package-with-broken-snippets.tmbundle', sync: true)
|
||||
atom.loadPackage('package-with-snippets')
|
||||
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
jasmine.unspy(snippets, 'loadAll')
|
||||
spyOn(snippets, 'loadAtomSnippets').andCallFake (path, done) -> done()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{View} = require 'space-pen'
|
||||
Range = require 'range'
|
||||
CorrectionsView = require './corrections-view'
|
||||
SpellChecker = require 'spellchecker'
|
||||
|
||||
module.exports =
|
||||
class MisspellingView extends View
|
||||
@@ -30,7 +31,7 @@ class MisspellingView extends View
|
||||
|
||||
screenRange = @getScreenRange()
|
||||
misspelling = @editor.getTextInRange(@editor.bufferRangeForScreenRange(screenRange))
|
||||
corrections = $native.getCorrectionsForMisspelling(misspelling)
|
||||
corrections = SpellChecker.getCorrectionsForMisspelling(misspelling)
|
||||
@correctionsView?.remove()
|
||||
@correctionsView = new CorrectionsView(@editor, corrections, screenRange)
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
SpellChecker = require 'spellchecker'
|
||||
|
||||
module.exports =
|
||||
findMisspellings: (text) ->
|
||||
wordRegex = /(?:^|[\s\[\]])([a-zA-Z']+)(?=[\s\.\[\]]|$)/g
|
||||
@@ -6,7 +8,7 @@ module.exports =
|
||||
for line in text.split('\n')
|
||||
while matches = wordRegex.exec(line)
|
||||
word = matches[1]
|
||||
continue unless $native.isMisspelled(word)
|
||||
continue unless SpellChecker.isMisspelled(word)
|
||||
startColumn = matches.index + matches[0].length - word.length
|
||||
endColumn = startColumn + word.length
|
||||
misspellings.push([[row, startColumn], [row, endColumn]])
|
||||
|
||||
@@ -4,10 +4,12 @@ describe "Spell check", ->
|
||||
[editor] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.activatePackage('text.tmbundle', sync: true)
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
config.set('spell-check.grammars', [])
|
||||
window.loadPackage('spell-check', activateImmediately: true)
|
||||
atom.activatePackage('spell-check', immediate: true)
|
||||
syntax.trigger 'grammars-loaded'
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveView()
|
||||
|
||||
@@ -34,7 +34,7 @@ class StatusBarView extends View
|
||||
|
||||
@updateCursorPositionText()
|
||||
@subscribe @editor, 'cursor:moved', => @updateCursorPositionText()
|
||||
@subscribe @grammarName, 'click', => @editor.trigger 'editor:select-grammar'
|
||||
@subscribe @grammarName, 'click', => @editor.trigger 'grammar-selector:show'
|
||||
@subscribe @editor, 'editor:grammar-changed', => @updateGrammarText()
|
||||
if git?
|
||||
@subscribe git, 'status-changed', (path, status) =>
|
||||
|
||||
@@ -32,7 +32,7 @@ describe "StatusBar", ->
|
||||
|
||||
describe "when associated with an unsaved buffer", ->
|
||||
it "displays 'untitled' instead of the buffer's path, but still displays the buffer position", ->
|
||||
rootView.deactivate()
|
||||
rootView.remove()
|
||||
window.rootView = new RootView
|
||||
rootView.open()
|
||||
rootView.simulateDomAttachment()
|
||||
@@ -180,6 +180,11 @@ describe "StatusBar", ->
|
||||
expect(statusBar.gitStatusIcon).toHaveText('+1')
|
||||
|
||||
describe "grammar label", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('text.tmbundle', sync: true)
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
syntax.trigger 'grammars-loaded'
|
||||
|
||||
it "displays the name of the current grammar", ->
|
||||
expect(statusBar.find('.grammar-name').text()).toBe 'JavaScript'
|
||||
|
||||
@@ -200,8 +205,8 @@ describe "StatusBar", ->
|
||||
expect(statusBar.find('.grammar-name').text()).toBe 'Plain Text'
|
||||
|
||||
describe "when clicked", ->
|
||||
it "toggles the editor:select-grammar event", ->
|
||||
it "toggles the grammar-selector:show event", ->
|
||||
eventHandler = jasmine.createSpy('eventHandler')
|
||||
editor.on 'editor:select-grammar', eventHandler
|
||||
editor.on 'grammar-selector:show', eventHandler
|
||||
statusBar.find('.grammar-name').click()
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
@@ -10,7 +10,7 @@ describe "StripTrailingWhitespace", ->
|
||||
window.rootView = new RootView
|
||||
rootView.open(path)
|
||||
|
||||
window.loadPackage('strip-trailing-whitespace')
|
||||
atom.activatePackage('strip-trailing-whitespace')
|
||||
rootView.focus()
|
||||
editor = rootView.getActiveView()
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ describe "SymbolsView", ->
|
||||
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
window.loadPackage("symbols-view")
|
||||
atom.activatePackage("symbols-view")
|
||||
|
||||
rootView.attachToDom()
|
||||
setArraySpy = spyOn(SymbolsView.prototype, 'setArray').andCallThrough()
|
||||
|
||||
@@ -11,7 +11,7 @@ describe "Tabs package main", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage("tabs")
|
||||
atom.activatePackage("tabs")
|
||||
|
||||
describe ".activate()", ->
|
||||
it "appends a tab bar all existing and new panes", ->
|
||||
|
||||
@@ -5,7 +5,7 @@ describe "TOML grammar", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(syntax, "addGrammar")
|
||||
window.loadPackage("toml")
|
||||
atom.activatePackage("toml")
|
||||
expect(syntax.addGrammar).toHaveBeenCalled()
|
||||
grammar = syntax.addGrammar.argsForCall[0][0]
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@ class TreeView extends ScrollView
|
||||
else
|
||||
@selectActiveFile()
|
||||
|
||||
rootView.on 'pane:active-item-changed pane:became-active', => @selectActiveFile()
|
||||
project.on 'path-changed', => @updateRoot()
|
||||
rootView.on 'pane:active-item-changed.tree-view pane:became-active.tree-view', => @selectActiveFile()
|
||||
project.on 'path-changed.tree-view', => @updateRoot()
|
||||
@observeConfig 'core.hideGitIgnoredFiles', => @updateRoot()
|
||||
|
||||
if @root
|
||||
@@ -67,6 +67,9 @@ class TreeView extends ScrollView
|
||||
|
||||
deactivate: ->
|
||||
@root?.unwatchEntries()
|
||||
rootView.off('.tree-view')
|
||||
project.off('.tree-view')
|
||||
@remove()
|
||||
|
||||
toggle: ->
|
||||
if @hasFocus()
|
||||
|
||||
@@ -13,7 +13,7 @@ describe "TreeView", ->
|
||||
project.setPath(project.resolve('tree-view'))
|
||||
window.rootView = new RootView
|
||||
|
||||
window.loadPackage("tree-view")
|
||||
atom.activatePackage("tree-view")
|
||||
rootView.trigger 'tree-view:toggle'
|
||||
treeView = rootView.find(".tree-view").view()
|
||||
treeView.root = treeView.find('ol > li:first').view()
|
||||
@@ -47,10 +47,8 @@ describe "TreeView", ->
|
||||
describe "when the project has no path", ->
|
||||
beforeEach ->
|
||||
project.setPath(undefined)
|
||||
rootView.deactivate()
|
||||
window.rootView = new RootView()
|
||||
rootView.open()
|
||||
treeView = window.loadPackage("tree-view").mainModule.createView()
|
||||
atom.deactivatePackage("tree-view")
|
||||
treeView = atom.activatePackage("tree-view").mainModule.createView()
|
||||
|
||||
it "does not attach to the root view or create a root node when initialized", ->
|
||||
expect(treeView.hasParent()).toBeFalsy()
|
||||
@@ -66,6 +64,7 @@ describe "TreeView", ->
|
||||
|
||||
describe "when the project is assigned a path because a new buffer is saved", ->
|
||||
it "creates a root directory view but does not attach to the root view", ->
|
||||
rootView.open()
|
||||
rootView.getActivePaneItem().saveAs("/tmp/test.txt")
|
||||
expect(treeView.hasParent()).toBeFalsy()
|
||||
expect(treeView.root.getPath()).toBe '/tmp'
|
||||
@@ -73,16 +72,16 @@ describe "TreeView", ->
|
||||
|
||||
describe "when the root view is opened to a file path", ->
|
||||
it "does not attach to the root view but does create a root node when initialized", ->
|
||||
rootView.deactivate()
|
||||
window.rootView = new RootView
|
||||
atom.deactivatePackage("tree-view")
|
||||
atom.packageStates = {}
|
||||
rootView.open('tree-view.js')
|
||||
treeView = window.loadPackage("tree-view").mainModule.createView()
|
||||
treeView = atom.activatePackage("tree-view").mainModule.createView()
|
||||
expect(treeView.hasParent()).toBeFalsy()
|
||||
expect(treeView.root).toExist()
|
||||
|
||||
describe "when the root view is opened to a directory", ->
|
||||
it "attaches to the root view", ->
|
||||
treeView = window.loadPackage("tree-view").mainModule.createView()
|
||||
treeView = atom.activatePackage("tree-view").mainModule.createView()
|
||||
expect(treeView.hasParent()).toBeTruthy()
|
||||
expect(treeView.root).toExist()
|
||||
|
||||
@@ -91,10 +90,8 @@ describe "TreeView", ->
|
||||
treeView.find('.directory:contains(dir1)').click()
|
||||
sampleJs.click()
|
||||
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
window.rootView = RootView.deserialize(rootViewState)
|
||||
window.loadPackage("tree-view")
|
||||
atom.deactivatePackage("tree-view")
|
||||
atom.activatePackage("tree-view")
|
||||
treeView = rootView.find(".tree-view").view()
|
||||
|
||||
expect(treeView).toExist()
|
||||
@@ -105,13 +102,8 @@ describe "TreeView", ->
|
||||
rootView.attachToDom()
|
||||
treeView.focus()
|
||||
expect(treeView.find(".tree-view")).toMatchSelector ':focus'
|
||||
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
window.rootView = RootView.deserialize(rootViewState)
|
||||
|
||||
rootView.attachToDom()
|
||||
window.loadPackage("tree-view")
|
||||
atom.deactivatePackage("tree-view")
|
||||
atom.activatePackage("tree-view")
|
||||
treeView = rootView.find(".tree-view").view()
|
||||
expect(treeView.find(".tree-view")).toMatchSelector ':focus'
|
||||
|
||||
@@ -599,7 +591,7 @@ describe "TreeView", ->
|
||||
[dirView, fileView, rootDirPath, dirPath, filePath] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView.deactivate()
|
||||
atom.deactivatePackage('tree-view')
|
||||
|
||||
rootDirPath = fs.join(fs.absolute("/tmp"), "atom-tests")
|
||||
fs.remove(rootDirPath) if fs.exists(rootDirPath)
|
||||
@@ -611,8 +603,8 @@ describe "TreeView", ->
|
||||
fs.write(filePath, "doesn't matter")
|
||||
|
||||
project.setPath(rootDirPath)
|
||||
window.rootView = new RootView(rootDirPath)
|
||||
window.loadPackage('tree-view')
|
||||
|
||||
atom.activatePackage('tree-view')
|
||||
rootView.trigger 'tree-view:toggle'
|
||||
treeView = rootView.find(".tree-view").view()
|
||||
dirView = treeView.root.entries.find('.directory:contains(test-dir)').view()
|
||||
|
||||
@@ -6,7 +6,7 @@ describe "WrapGuide", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage('wrap-guide')
|
||||
atom.activatePackage('wrap-guide')
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveView()
|
||||
wrapGuide = rootView.find('.wrap-guide').view()
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# This file is loaded within Task's worker thread. It will attempt to invoke
|
||||
# This file is loaded within Task's worker process. It will attempt to invoke
|
||||
# any message with a 'method' and 'args' key on the global `handler` object. The
|
||||
# initial `handler` object contains the `start` method, which is called by the
|
||||
# task itself to relay information from the window thread and bootstrap the
|
||||
# worker's environment. The `start` method then replaces the handler with an
|
||||
# object required from the given `handlerPath`.
|
||||
|
||||
self.window = {}
|
||||
self.attachEvent = ->
|
||||
global.window = {}
|
||||
global.attachEvent = ->
|
||||
console =
|
||||
warn: -> callTaskMethod 'warn', arguments...
|
||||
log: -> callTaskMethod 'log', arguments...
|
||||
error: -> callTaskMethod 'error', arguments...
|
||||
self.__defineGetter__ 'console', -> console
|
||||
global.__defineGetter__ 'console', -> console
|
||||
|
||||
window.document =
|
||||
createElement: ->
|
||||
@@ -24,21 +24,21 @@ window.document =
|
||||
getElementById: -> {}
|
||||
createComment: -> {}
|
||||
createDocumentFragment: -> {}
|
||||
self.document = window.document
|
||||
global.document = window.document
|
||||
|
||||
# `callTaskMethod` can be used to invoke method's on the parent `Task` object
|
||||
# back in the window thread.
|
||||
self.callTaskMethod = (method, args...) ->
|
||||
postMessage(method: method, args: args)
|
||||
global.callTaskMethod = (method, args...) ->
|
||||
process.send(method: method, args: args)
|
||||
|
||||
# The worker's initial handler replaces itself when `start` is invoked
|
||||
self.handler =
|
||||
# The worker's initial handler replaces itglobal when `start` is invoked
|
||||
global.handler =
|
||||
start: ({globals, handlerPath}) ->
|
||||
for key, value of globals
|
||||
self[key] = value
|
||||
global[key] = value
|
||||
window[key] = value
|
||||
self.handler = require(handlerPath)
|
||||
global.handler = require(handlerPath)
|
||||
callTaskMethod 'started'
|
||||
|
||||
self.addEventListener 'message', ({data}) ->
|
||||
process.on 'message', (data) ->
|
||||
handler[data.method]?(data.args...) if data.method
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
_ = require 'underscore'
|
||||
child_process = require 'child_process'
|
||||
EventEmitter = require 'event-emitter'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
@@ -11,9 +12,11 @@ class Task
|
||||
start: ->
|
||||
throw new Error("Task already started") if @worker?
|
||||
|
||||
blob = new Blob(["require('coffee-script'); require('task-shell');"], type: 'text/javascript')
|
||||
@worker = new Worker(URL.createObjectURL(blob))
|
||||
@worker.onmessage = ({data}) =>
|
||||
# Equivalent with node --eval "...".
|
||||
blob = "require('coffee-script'); require('task-shell');"
|
||||
@worker = child_process.fork '--eval', [ blob ], cwd: __dirname
|
||||
|
||||
@worker.on 'message', (data) =>
|
||||
if @aborted
|
||||
@done()
|
||||
return
|
||||
@@ -22,6 +25,7 @@ class Task
|
||||
this[data.method](data.args...)
|
||||
else
|
||||
@onMessage(data)
|
||||
|
||||
@startWorker()
|
||||
|
||||
log: -> console.log(arguments...)
|
||||
@@ -43,14 +47,14 @@ class Task
|
||||
@postMessage({method, args})
|
||||
|
||||
postMessage: (data) ->
|
||||
@worker.postMessage(data)
|
||||
@worker.send(data)
|
||||
|
||||
abort: ->
|
||||
@aborted = true
|
||||
|
||||
done: ->
|
||||
@abort()
|
||||
@worker?.terminate()
|
||||
@worker?.kill()
|
||||
@worker = null
|
||||
@trigger 'task-completed'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user