mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
merge dev, fix conflicts from package rewrite
This commit is contained in:
@@ -1,42 +1,88 @@
|
||||
Package = require 'package'
|
||||
fs = require 'fs'
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class AtomPackage extends Package
|
||||
metadata: null
|
||||
keymapsDirPath: null
|
||||
autoloadStylesheets: true
|
||||
packageMain: null
|
||||
|
||||
constructor: (@name) ->
|
||||
super
|
||||
@keymapsDirPath = fs.join(@path, 'keymaps')
|
||||
|
||||
load: ->
|
||||
load: ({activateImmediately}={}) ->
|
||||
try
|
||||
@loadMetadata()
|
||||
@loadKeymaps()
|
||||
@loadStylesheets() if @autoloadStylesheets
|
||||
rootView?.activatePackage(@name, this) unless @isDirectory
|
||||
@loadStylesheets()
|
||||
if @metadata.activationEvents and not activateImmediately
|
||||
@subscribeToActivationEvents()
|
||||
else
|
||||
@activatePackageMain()
|
||||
catch e
|
||||
console.warn "Failed to load package named '#{@name}'", e.stack
|
||||
this
|
||||
|
||||
disableEventHandlersOnBubblePath: (event) ->
|
||||
bubblePathEventHandlers = []
|
||||
disabledHandler = ->
|
||||
element = $(event.target)
|
||||
while element.length
|
||||
if eventHandlers = element.data('events')?[event.type]
|
||||
for eventHandler in eventHandlers
|
||||
eventHandler.disabledHandler = eventHandler.handler
|
||||
eventHandler.handler = disabledHandler
|
||||
bubblePathEventHandlers.push(eventHandler)
|
||||
element = element.parent()
|
||||
bubblePathEventHandlers
|
||||
|
||||
restoreEventHandlersOnBubblePath: (eventHandlers) ->
|
||||
for eventHandler in eventHandlers
|
||||
eventHandler.handler = eventHandler.disabledHandler
|
||||
delete eventHandler.disabledHandler
|
||||
|
||||
unsubscribeFromActivationEvents: (activateHandler) ->
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
rootView.off(event, activateHandler) for event in @metadata.activationEvents
|
||||
else
|
||||
rootView.off(event, selector, activateHandler) for event, selector of @metadata.activationEvents
|
||||
|
||||
subscribeToActivationEvents: () ->
|
||||
activateHandler = (event) =>
|
||||
bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event)
|
||||
@activatePackageMain()
|
||||
$(event.target).trigger(event)
|
||||
@restoreEventHandlersOnBubblePath(bubblePathEventHandlers)
|
||||
@unsubscribeFromActivationEvents(activateHandler)
|
||||
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
rootView.command(event, activateHandler) for event in @metadata.activationEvents
|
||||
else
|
||||
rootView.command(event, selector, activateHandler) for event, selector of @metadata.activationEvents
|
||||
|
||||
activatePackageMain: ->
|
||||
mainPath = @path
|
||||
mainPath = fs.join(mainPath, @metadata.main) if @metadata.main
|
||||
mainPath = require.resolve(mainPath)
|
||||
if fs.isFile(mainPath)
|
||||
@packageMain = require(mainPath)
|
||||
config.setDefaults(@name, @packageMain.configDefaults)
|
||||
atom.activateAtomPackage(this)
|
||||
|
||||
loadMetadata: ->
|
||||
if metadataPath = fs.resolveExtension(fs.join(@path, "package"), ['cson', 'json'])
|
||||
if metadataPath = fs.resolveExtension(fs.join(@path, 'package'), ['cson', 'json'])
|
||||
@metadata = fs.readObject(metadataPath)
|
||||
@metadata ?= {}
|
||||
|
||||
loadKeymaps: ->
|
||||
if keymaps = @metadata?.keymaps
|
||||
keymaps = keymaps.map (relativePath) =>
|
||||
fs.resolve(@keymapsDirPath, relativePath, ['cson', 'json', ''])
|
||||
keymap.load(keymapPath) for keymapPath in keymaps
|
||||
keymapsDirPath = fs.join(@path, 'keymaps')
|
||||
|
||||
if @metadata.keymaps
|
||||
for path in @metadata.keymaps
|
||||
keymapPath = fs.resolve(keymapsDirPath, path, ['cson', 'json', ''])
|
||||
keymap.load(keymapPath)
|
||||
else
|
||||
keymap.loadDirectory(@keymapsDirPath)
|
||||
keymap.loadDirectory(keymapsDirPath)
|
||||
|
||||
loadStylesheets: ->
|
||||
for stylesheetPath in @getStylesheetPaths()
|
||||
requireStylesheet(stylesheetPath)
|
||||
|
||||
getStylesheetPaths: ->
|
||||
stylesheetDirPath = fs.join(@path, 'stylesheets')
|
||||
fs.list(stylesheetDirPath)
|
||||
for stylesheetPath in fs.list(stylesheetDirPath)
|
||||
requireStylesheet(stylesheetPath)
|
||||
@@ -12,42 +12,58 @@ _.extend atom,
|
||||
exitWhenDone: window.location.params.exitWhenDone
|
||||
loadedThemes: []
|
||||
pendingBrowserProcessCallbacks: {}
|
||||
loadedPackages: []
|
||||
activatedAtomPackages: []
|
||||
atomPackageStates: {}
|
||||
|
||||
activateAtomPackage: (pack) ->
|
||||
@activatedAtomPackages.push(pack)
|
||||
pack.packageMain.activate(@atomPackageStates[pack.name])
|
||||
|
||||
deactivateAtomPackages: ->
|
||||
pack.packageMain.deactivate?() for pack in @activatedAtomPackages
|
||||
@activatedAtomPackages = []
|
||||
|
||||
serializeAtomPackages: ->
|
||||
packageStates = {}
|
||||
for pack in @activatedAtomPackages
|
||||
try
|
||||
packageStates[pack.name] = pack.packageMain.serialize?()
|
||||
catch e
|
||||
console?.error("Exception serializing '#{pack.name}' package's module\n", e.stack)
|
||||
packageStates
|
||||
|
||||
loadPackage: (name, options) ->
|
||||
packagePath = _.find @getPackagePaths(), (packagePath) -> fs.base(packagePath) == name
|
||||
pack = Package.build(packagePath)
|
||||
pack?.load(options)
|
||||
|
||||
loadPackages: ->
|
||||
{packages, asyncTextMatePackages} = _.groupBy @getPackages(), (pack) ->
|
||||
if pack instanceof TextMatePackage and pack.name isnt 'text.tmbundle'
|
||||
'asyncTextMatePackages'
|
||||
textMatePackages = []
|
||||
for path in @getPackagePaths()
|
||||
pack = Package.build(path)
|
||||
@loadedPackages.push(pack)
|
||||
if pack instanceof TextMatePackage and fs.base(pack.path) isnt 'text.tmbundle'
|
||||
textMatePackages.push(pack)
|
||||
else
|
||||
'packages'
|
||||
pack.load()
|
||||
|
||||
pack.load() for pack in packages
|
||||
if asyncTextMatePackages.length
|
||||
new LoadTextMatePackagesTask(asyncTextMatePackages).start()
|
||||
new LoadTextMatePackagesTask(textMatePackages).start() if textMatePackages.length > 0
|
||||
|
||||
getPackages: ->
|
||||
@packages ?= @getPackageNames().map((name) -> Package.build(name))
|
||||
.filter((pack) -> pack?)
|
||||
new Array(@packages...)
|
||||
getLoadedPackages: ->
|
||||
_.clone(@loadedPackages)
|
||||
|
||||
loadTextMatePackages: ->
|
||||
pack.load() for pack in @getTextMatePackages()
|
||||
|
||||
getTextMatePackages: ->
|
||||
@getPackages().filter (pack) -> pack instanceof TextMatePackage
|
||||
|
||||
loadPackage: (name) ->
|
||||
Package.build(name)?.load()
|
||||
|
||||
getPackageNames: ->
|
||||
getPackagePaths: ->
|
||||
disabledPackages = config.get("core.disabledPackages") ? []
|
||||
allPackageNames = []
|
||||
packagePaths = []
|
||||
for packageDirPath in config.packageDirPaths
|
||||
packageNames = fs.list(packageDirPath)
|
||||
.filter((packagePath) -> fs.isDirectory(packagePath))
|
||||
.map((packagePath) -> fs.base(packagePath))
|
||||
allPackageNames.push(packageNames...)
|
||||
_.unique(allPackageNames)
|
||||
.filter (name) -> not _.contains(disabledPackages, name)
|
||||
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
|
||||
|
||||
loadThemes: ->
|
||||
themeNames = config.get("core.themes") ? ['atom-dark-ui', 'atom-dark-syntax']
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
AtomPackage = require 'atom-package'
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class DeferredAtomPackage extends AtomPackage
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
@autoloadStylesheets = false
|
||||
|
||||
activate: (@rootView, @state) ->
|
||||
@instance = null
|
||||
onLoadEvent = (e) => @onLoadEvent(e, @getInstance())
|
||||
if _.isArray(@loadEvents)
|
||||
for event in @loadEvents
|
||||
@rootView.command(event, onLoadEvent)
|
||||
else
|
||||
for event, selector of @loadEvents
|
||||
@rootView.command(event, selector, onLoadEvent)
|
||||
this
|
||||
|
||||
deactivate: -> @instance?.deactivate?()
|
||||
|
||||
serialize: ->
|
||||
if @instance
|
||||
@instance.serialize?()
|
||||
else
|
||||
@state
|
||||
|
||||
getInstance: ->
|
||||
unless @instance
|
||||
@loadStylesheets()
|
||||
InstanceClass = require @instanceClass
|
||||
@instance = InstanceClass.activate(@rootView, @state)
|
||||
@instance
|
||||
@@ -8,78 +8,10 @@ class LanguageMode
|
||||
buffer = null
|
||||
grammar = null
|
||||
editSession = null
|
||||
pairedCharacters:
|
||||
'(': ')'
|
||||
'[': ']'
|
||||
'{': '}'
|
||||
'"': '"'
|
||||
"'": "'"
|
||||
|
||||
constructor: (@editSession) ->
|
||||
@buffer = @editSession.buffer
|
||||
@reloadGrammar()
|
||||
@bracketMarkers = []
|
||||
|
||||
_.adviseBefore @editSession, 'insertText', (text) =>
|
||||
return true if @editSession.hasMultipleCursors()
|
||||
|
||||
cursorBufferPosition = @editSession.getCursorBufferPosition()
|
||||
previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
|
||||
nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])
|
||||
|
||||
if @isOpeningBracket(text) and not @editSession.getSelection().isEmpty()
|
||||
@wrapSelectionInBrackets(text)
|
||||
return false
|
||||
|
||||
hasWordAfterCursor = /\w/.test(nextCharacter)
|
||||
hasWordBeforeCursor = /\w/.test(previousCharacter)
|
||||
|
||||
autoCompleteOpeningBracket = @isOpeningBracket(text) and not hasWordAfterCursor and not (@isQuote(text) and hasWordBeforeCursor)
|
||||
skipOverExistingClosingBracket = false
|
||||
if @isClosingBracket(text) and nextCharacter == text
|
||||
if bracketMarker = _.find(@bracketMarkers, (marker) => @editSession.getMarkerBufferRange(marker)?.end.isEqual(cursorBufferPosition))
|
||||
skipOverExistingClosingBracket = true
|
||||
|
||||
if skipOverExistingClosingBracket
|
||||
@editSession.destroyMarker(bracketMarker)
|
||||
_.remove(@bracketMarkers, bracketMarker)
|
||||
@editSession.moveCursorRight()
|
||||
false
|
||||
else if autoCompleteOpeningBracket
|
||||
@editSession.insertText(text + @pairedCharacters[text])
|
||||
@editSession.moveCursorLeft()
|
||||
range = [cursorBufferPosition, cursorBufferPosition.add([0, text.length])]
|
||||
@bracketMarkers.push @editSession.markBufferRange(range)
|
||||
false
|
||||
|
||||
_.adviseBefore @editSession, 'backspace', =>
|
||||
return if @editSession.hasMultipleCursors()
|
||||
return unless @editSession.getSelection().isEmpty()
|
||||
|
||||
cursorBufferPosition = @editSession.getCursorBufferPosition()
|
||||
previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition])
|
||||
nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])])
|
||||
if @pairedCharacters[previousCharacter] is nextCharacter
|
||||
@editSession.transact =>
|
||||
@editSession.moveCursorLeft()
|
||||
@editSession.delete()
|
||||
@editSession.delete()
|
||||
false
|
||||
|
||||
wrapSelectionInBrackets: (bracket) ->
|
||||
pair = @pairedCharacters[bracket]
|
||||
@editSession.mutateSelectedText (selection) =>
|
||||
return if selection.isEmpty()
|
||||
|
||||
range = selection.getBufferRange()
|
||||
options = reverse: selection.isReversed()
|
||||
selection.insertText("#{bracket}#{selection.getText()}#{pair}")
|
||||
selectionStart = range.start.add([0, 1])
|
||||
if range.start.row is range.end.row
|
||||
selectionEnd = range.end.add([0, 1])
|
||||
else
|
||||
selectionEnd = range.end
|
||||
selection.setBufferRange([selectionStart, selectionEnd], options)
|
||||
|
||||
reloadGrammar: ->
|
||||
path = @buffer.getPath()
|
||||
@@ -92,23 +24,6 @@ class LanguageMode
|
||||
throw new Error("No grammar found for path: #{path}") unless @grammar
|
||||
previousGrammar isnt @grammar
|
||||
|
||||
isQuote: (string) ->
|
||||
/'|"/.test(string)
|
||||
|
||||
isOpeningBracket: (string) ->
|
||||
@pairedCharacters[string]?
|
||||
|
||||
isClosingBracket: (string) ->
|
||||
@getInvertedPairedCharacters()[string]?
|
||||
|
||||
getInvertedPairedCharacters: ->
|
||||
return @invertedPairedCharacters if @invertedPairedCharacters
|
||||
|
||||
@invertedPairedCharacters = {}
|
||||
for open, close of @pairedCharacters
|
||||
@invertedPairedCharacters[close] = open
|
||||
@invertedPairedCharacters
|
||||
|
||||
toggleLineCommentsForBufferRows: (start, end) ->
|
||||
scopes = @editSession.scopesForBufferPosition([start, 0])
|
||||
return unless commentStartString = syntax.getProperty(scopes, "editor.commentStart")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
|
||||
module.exports =
|
||||
loadPackage: (name) ->
|
||||
callTaskMethod('packageLoaded', new TextMatePackage(name).readGrammars())
|
||||
loadPackage: (path) ->
|
||||
callTaskMethod('packageLoaded', new TextMatePackage(path).readGrammars())
|
||||
|
||||
@@ -16,10 +16,10 @@ class LoadTextMatePackagesTask extends Task
|
||||
return
|
||||
|
||||
@package = @packages.shift()
|
||||
@loadPackage(@package.name)
|
||||
@loadPackage(@package.path)
|
||||
|
||||
loadPackage: (name) ->
|
||||
@callWorkerMethod('loadPackage', name)
|
||||
loadPackage: (path) ->
|
||||
@callWorkerMethod('loadPackage', path)
|
||||
|
||||
packageLoaded: (grammars) ->
|
||||
@package.loadGrammars(grammars)
|
||||
|
||||
@@ -2,34 +2,17 @@ fs = require 'fs'
|
||||
|
||||
module.exports =
|
||||
class Package
|
||||
@resolve: (name) ->
|
||||
path = require.resolve(name, verifyExistence: false)
|
||||
return path if path
|
||||
throw new Error("No package found named '#{name}'")
|
||||
|
||||
@build: (name) ->
|
||||
@build: (path) ->
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
AtomPackage = require 'atom-package'
|
||||
if TextMatePackage.testName(name)
|
||||
new TextMatePackage(name)
|
||||
|
||||
if TextMatePackage.testName(path)
|
||||
new TextMatePackage(path)
|
||||
else
|
||||
if fs.isDirectory(@resolve(name))
|
||||
new AtomPackage(name)
|
||||
else
|
||||
try
|
||||
PackageClass = require name
|
||||
new PackageClass(name) if typeof PackageClass is 'function'
|
||||
catch e
|
||||
console.warn "Failed to load package named '#{name}'", e.stack
|
||||
new AtomPackage(path)
|
||||
|
||||
name: null
|
||||
path: null
|
||||
isDirectory: false
|
||||
module: null
|
||||
|
||||
constructor: (@name) ->
|
||||
@path = Package.resolve(@name)
|
||||
@isDirectory = fs.isDirectory(@path)
|
||||
@path = fs.directory(@path) unless @isDirectory
|
||||
|
||||
activate: (rootView) ->
|
||||
constructor: (@path) ->
|
||||
@name = fs.base(@path)
|
||||
|
||||
@@ -118,6 +118,10 @@ class Project
|
||||
getEditSessions: ->
|
||||
new Array(@editSessions...)
|
||||
|
||||
eachEditSession: (callback) ->
|
||||
callback(editSession) for editSession in @getEditSessions()
|
||||
@on 'edit-session-created', (editSession) -> callback(editSession)
|
||||
|
||||
removeEditSession: (editSession) ->
|
||||
_.remove(@editSessions, editSession)
|
||||
|
||||
@@ -125,9 +129,12 @@ class Project
|
||||
buffers = []
|
||||
for editSession in @editSessions when not _.include(buffers, editSession.buffer)
|
||||
buffers.push editSession.buffer
|
||||
|
||||
buffers
|
||||
|
||||
eachBuffer: (callback) ->
|
||||
callback(buffer) for buffer in @getBuffers()
|
||||
@on 'buffer-created', (buffer) -> callback(buffer)
|
||||
|
||||
bufferForPath: (filePath) ->
|
||||
if filePath?
|
||||
filePath = @resolve(filePath)
|
||||
|
||||
@@ -29,19 +29,19 @@ class RootView extends View
|
||||
else
|
||||
projectOrPathToOpen = projectPath # This will migrate people over to the new project serialization scheme. It should be removed eventually.
|
||||
|
||||
rootView = new RootView(projectOrPathToOpen , packageStates: packageStates, suppressOpen: true)
|
||||
atom.atomPackageStates = packageStates ? {}
|
||||
|
||||
rootView = new RootView(projectOrPathToOpen , suppressOpen: true)
|
||||
rootView.setRootPane(rootView.deserializeView(panesViewState)) if panesViewState
|
||||
rootView
|
||||
|
||||
packageModules: null
|
||||
packageStates: null
|
||||
packages: null
|
||||
title: null
|
||||
pathToOpenIsFile: false
|
||||
|
||||
initialize: (projectOrPathToOpen, { @packageStates, suppressOpen } = {}) ->
|
||||
initialize: (projectOrPathToOpen, { suppressOpen } = {}) ->
|
||||
window.rootView = this
|
||||
@packageStates ?= {}
|
||||
@packageModules = {}
|
||||
@packages = []
|
||||
@viewClasses = {
|
||||
"Pane": Pane,
|
||||
"PaneRow": PaneRow,
|
||||
@@ -68,7 +68,7 @@ class RootView extends View
|
||||
serialize: ->
|
||||
projectState: @project?.serialize()
|
||||
panesViewState: @panes.children().view()?.serialize()
|
||||
packageStates: @serializePackages()
|
||||
packageStates: atom.serializeAtomPackages()
|
||||
|
||||
handleFocus: (e) ->
|
||||
if @getActiveEditor()
|
||||
@@ -118,33 +118,15 @@ class RootView extends View
|
||||
afterAttach: (onDom) ->
|
||||
@focus() if onDom
|
||||
|
||||
serializePackages: ->
|
||||
packageStates = {}
|
||||
for name, packageModule of @packageModules
|
||||
try
|
||||
packageStates[name] = packageModule.serialize?()
|
||||
catch e
|
||||
console?.error("Exception serializing '#{name}' package's module\n", e.stack)
|
||||
packageStates
|
||||
|
||||
registerViewClass: (viewClass) ->
|
||||
@viewClasses[viewClass.name] = viewClass
|
||||
|
||||
deserializeView: (viewState) ->
|
||||
@viewClasses[viewState.viewClass]?.deserialize(viewState, this)
|
||||
|
||||
activatePackage: (name, packageModule) ->
|
||||
config.setDefaults(name, packageModule.configDefaults) if packageModule.configDefaults?
|
||||
@packageModules[name] = packageModule
|
||||
packageModule.activate(this, @packageStates[name])
|
||||
|
||||
deactivatePackage: (name) ->
|
||||
@packageModules[name].deactivate?()
|
||||
delete @packageModules[name]
|
||||
|
||||
deactivate: ->
|
||||
atom.setRootViewStateForPath(@project.getPath(), @serialize())
|
||||
@deactivatePackage(name) for name of @packageModules
|
||||
atom.deactivateAtomPackages()
|
||||
@remove()
|
||||
|
||||
open: (path, options = {}) ->
|
||||
@@ -274,9 +256,11 @@ class RootView extends View
|
||||
callback(editor) for editor in @getEditors()
|
||||
@on 'editor:attached', (e, editor) -> callback(editor)
|
||||
|
||||
eachEditSession: (callback) ->
|
||||
@project.eachEditSession(callback)
|
||||
|
||||
eachBuffer: (callback) ->
|
||||
callback(buffer) for buffer in @project.getBuffers()
|
||||
@project.on 'buffer-created', (buffer) -> callback(buffer)
|
||||
@project.eachBuffer(callback)
|
||||
|
||||
indexOfPane: (pane) ->
|
||||
index = -1
|
||||
|
||||
@@ -9,9 +9,12 @@ module.exports =
|
||||
class TextMateGrammar
|
||||
@readFromPath: (path) ->
|
||||
grammarContent = null
|
||||
plist.parseString fs.read(path), (e, data) ->
|
||||
throw new Error(e) if e
|
||||
grammarContent = data[0]
|
||||
if fs.extension(path) is '.cson'
|
||||
grammarContent = fs.readObject(path)
|
||||
else
|
||||
plist.parseString fs.read(path), (e, data) ->
|
||||
throw new Error(e) if e
|
||||
grammarContent = data[0]
|
||||
throw new Error("Failed to load grammar at path `#{path}`") unless grammarContent
|
||||
grammarContent
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class TextMatePackage extends Package
|
||||
try
|
||||
@loadGrammars()
|
||||
catch e
|
||||
console.warn "Failed to load package named '#{@name}'", e.stack
|
||||
console.warn "Failed to load package at '#{@path}'", e.stack
|
||||
this
|
||||
|
||||
getGrammars: -> @grammars
|
||||
|
||||
@@ -37,8 +37,8 @@ windowAdditions =
|
||||
# Note: RootView assigns itself on window on initialization so that
|
||||
# window.rootView is available when loading user configuration
|
||||
attachRootView: (pathToOpen) ->
|
||||
if rootViewState = atom.getRootViewStateForPath(pathToOpen)
|
||||
RootView.deserialize(rootViewState)
|
||||
if pathState = atom.getRootViewStateForPath(pathToOpen)
|
||||
RootView.deserialize(pathState)
|
||||
else
|
||||
new RootView(pathToOpen)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user