Merge branch 'config'

This commit is contained in:
Nathan Sobo
2012-12-31 12:43:25 -06:00
48 changed files with 1891 additions and 318 deletions

View File

@@ -0,0 +1,17 @@
Package = require 'package'
fs = require 'fs'
module.exports =
class AtomPackage extends Package
constructor: ->
super
@module = require(@path)
@module.name = @name
load: ->
try
rootView.activatePackage(@module)
extensionKeymapPath = require.resolve(fs.join(@name, "src/keymap"), verifyExistence: false)
require extensionKeymapPath if fs.exists(extensionKeymapPath)
catch e
console.error "Failed to load package named '#{name}'", e.stack

11
src/app/atom-theme.coffee Normal file
View File

@@ -0,0 +1,11 @@
fs = require 'fs'
Theme = require 'theme'
module.exports =
class AtomTheme extends Theme
constructor: (@path) ->
super
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)

View File

@@ -1,5 +1,8 @@
TextMateBundle = require("text-mate-bundle")
fs = require 'fs'
_ = require 'underscore'
Package = require 'package'
TextMatePackage = require 'text-mate-package'
messageIdCounter = 1
originalSendMessageToBrowserProcess = atom.sendMessageToBrowserProcess
@@ -9,18 +12,25 @@ _.extend atom,
pendingBrowserProcessCallbacks: {}
getAvailablePackages: ->
allPackageNames = []
for packageDirPath in config.packageDirPaths
packageNames = fs.list(packageDirPath)
.filter((packagePath) -> fs.isDirectory(packagePath))
.map((packagePath) -> fs.base(packagePath))
allPackageNames.push(packageNames...)
_.unique(allPackageNames)
getAvailableTextMateBundles: ->
@getAvailablePackages().filter (packageName) => TextMatePackage.testName(packageName)
loadPackages: (packageNames=@getAvailablePackages()) ->
disabledPackages = config.get("core.disabledPackages") ? []
for packageName in packageNames
@loadPackage(packageName) unless _.contains(disabledPackages, packageName)
loadPackage: (name) ->
try
packagePath = require.resolve(name, verifyExistence: false)
throw new Error("No package found named '#{name}'") unless packagePath
packagePath = fs.directory(packagePath)
extension = require(packagePath)
extension.name = name
rootView.activateExtension(extension)
extensionKeymapPath = require.resolve(fs.join(name, "src/keymap"), verifyExistence: false)
require extensionKeymapPath if fs.exists(extensionKeymapPath)
catch e
console.error "Failed to load package named '#{name}'", e.stack
Package.forName(name).load()
open: (args...) ->
@sendMessageToBrowserProcess('open', args)
@@ -85,4 +95,3 @@ _.extend atom,
if name is 'reply'
[messageId, callbackIndex] = data.shift()
@pendingBrowserProcessCallbacks[messageId]?[callbackIndex]?(data...)

View File

@@ -1,11 +1,17 @@
fs = require 'fs'
_ = require 'underscore'
EventEmitter = require 'event-emitter'
{$$} = require 'space-pen'
jQuery = require 'jquery'
Specificity = require 'specificity'
Theme = require 'theme'
configDirPath = fs.absolute("~/.atom")
configJsonPath = fs.join(configDirPath, "config.json")
userInitScriptPath = fs.join(configDirPath, "atom.coffee")
bundledThemesDirPath = fs.join(resourcePath, "themes")
bundledPackagesDirPath = fs.join(resourcePath, "src/packages")
userThemesDirPath = fs.join(configDirPath, "themes")
userPackagesDirPath = fs.join(configDirPath, "packages")
require.paths.unshift userPackagesDirPath
@@ -13,46 +19,31 @@ require.paths.unshift userPackagesDirPath
module.exports =
class Config
configDirPath: configDirPath
themeDirPaths: [userThemesDirPath, bundledThemesDirPath]
packageDirPaths: [userPackagesDirPath, bundledPackagesDirPath]
settings: null
constructor: ->
@settings =
core: _.clone(require('root-view').configDefaults)
editor: _.clone(require('editor').configDefaults)
load: ->
@settings = {}
@loadUserConfig()
@assignDefaults()
@loadPackages()
@requireUserInitScript()
atom.loadPackages()
Theme.load(config.get("core.theme") ? 'IR_Black')
loadUserConfig: ->
if fs.exists(configJsonPath)
userConfig = JSON.parse(fs.read(configJsonPath))
_.extend(@settings, userConfig)
assignDefaults: ->
@settings ?= {}
@setDefaults "core", require('root-view').configDefaults
@setDefaults "editor", require('editor').configDefaults
getAvailablePackages: ->
availablePackages =
fs.list(bundledPackagesDirPath)
.concat(fs.list(userPackagesDirPath)).map (path) -> fs.base(path)
_.unique(availablePackages)
loadPackages: ->
disabledPackages = config.get("core.disabledPackages") ? []
for packageName in @getAvailablePackages()
unless _.contains disabledPackages, packageName
atom.loadPackage(packageName)
get: (keyPath) ->
keys = @keysForKeyPath(keyPath)
value = @settings
for key in keys
break unless value = value[key]
value
_.valueForKeyPath(@settings, keyPath)
set: (keyPath, value) ->
keys = @keysForKeyPath(keyPath)
keys = keyPath.split('.')
hash = @settings
while keys.length > 1
key = keys.shift()
@@ -64,7 +55,7 @@ class Config
value
setDefaults: (keyPath, defaults) ->
keys = @keysForKeyPath(keyPath)
keys = keyPath.split('.')
hash = @settings
for key in keys
hash[key] ?= {}
@@ -73,12 +64,6 @@ class Config
_.defaults hash, defaults
@update()
keysForKeyPath: (keyPath) ->
if typeof keyPath is 'string'
keyPath.split(".")
else
new Array(keyPath...)
observe: (keyPath, callback) ->
value = @get(keyPath)
previousValue = _.clone(value)

View File

@@ -3,7 +3,6 @@ _ = require 'underscore'
fs = require 'fs'
BindingSet = require 'binding-set'
Specificity = require 'specificity'
module.exports =
class Keymap

View File

@@ -67,14 +67,14 @@ class LanguageMode
toggleLineCommentsForBufferRows: (start, end) ->
scopes = @editSession.scopesForBufferPosition([start, 0])
return unless commentStartString = TextMateBundle.lineCommentStartStringForScope(scopes[0])
return unless commentStartString = syntax.getProperty(scopes, "editor.commentStart")
buffer = @editSession.buffer
commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '($1)?')
commentStartRegex = new OnigRegExp("^(\\s*)(#{commentStartRegexString})")
shouldUncomment = commentStartRegex.test(buffer.lineForRow(start))
if commentEndString = TextMateBundle.lineCommentEndStringForScope(scopes[0])
if commentEndString = syntax.getProperty(scopes, "editor.commentEnd")
if shouldUncomment
commentEndRegexString = _.escapeRegExp(commentEndString).replace(/^(\s+)/, '($1)?')
commentEndRegex = new OnigRegExp("(#{commentEndRegexString})(\\s*)$")
@@ -119,7 +119,7 @@ class LanguageMode
continue if @editSession.isBufferRowBlank(row)
indentation = @editSession.indentationForBufferRow(row)
if indentation <= startIndentLevel
includeRowInFold = indentation == startIndentLevel and TextMateBundle.foldEndRegexForScope(@grammar, scopes[0]).search(@editSession.lineForBufferRow(row))
includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes).search(@editSession.lineForBufferRow(row))
foldEndRow = row if includeRowInFold
break
@@ -130,7 +130,7 @@ class LanguageMode
suggestedIndentForBufferRow: (bufferRow) ->
currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
return currentIndentLevel unless increaseIndentPattern = TextMateBundle.indentRegexForScope(scopes[0])
return currentIndentLevel unless increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
currentLine = @buffer.lineForRow(bufferRow)
precedingRow = @buffer.previousNonBlankRow(bufferRow)
@@ -139,10 +139,10 @@ class LanguageMode
precedingLine = @buffer.lineForRow(precedingRow)
desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
desiredIndentLevel += 1 if increaseIndentPattern.test(precedingLine)
desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine)
return desiredIndentLevel unless decreaseIndentPattern = TextMateBundle.outdentRegexForScope(scopes[0])
desiredIndentLevel -= 1 if decreaseIndentPattern.test(currentLine)
return desiredIndentLevel unless decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
desiredIndentLevel -= 1 if decreaseIndentRegex.test(currentLine)
Math.max(desiredIndentLevel, currentIndentLevel)
@@ -159,32 +159,44 @@ class LanguageMode
precedingLine = @editSession.lineForBufferRow(precedingRow)
scopes = @editSession.scopesForBufferPosition([precedingRow, Infinity])
increaseIndentPattern = TextMateBundle.indentRegexForScope(scopes[0])
return unless increaseIndentPattern
increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
return unless increaseIndentRegex
currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
desiredIndentLevel += 1 if increaseIndentPattern.test(precedingLine)
desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine)
if desiredIndentLevel > currentIndentLevel
@editSession.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
autoDecreaseIndentForBufferRow: (bufferRow) ->
scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
increaseIndentPattern = TextMateBundle.indentRegexForScope(scopes[0])
decreaseIndentPattern = TextMateBundle.outdentRegexForScope(scopes[0])
return unless increaseIndentPattern and decreaseIndentPattern
increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
return unless increaseIndentRegex and decreaseIndentRegex
line = @buffer.lineForRow(bufferRow)
return unless decreaseIndentPattern.test(line)
return unless decreaseIndentRegex.test(line)
currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
precedingRow = @buffer.previousNonBlankRow(bufferRow)
precedingLine = @buffer.lineForRow(precedingRow)
desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
desiredIndentLevel -= 1 unless increaseIndentPattern.test(precedingLine)
desiredIndentLevel -= 1 unless increaseIndentRegex.test(precedingLine)
if desiredIndentLevel < currentIndentLevel
@editSession.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
tokenizeLine: (line, stack, firstLine) ->
{tokens, stack} = @grammar.tokenizeLine(line, stack, firstLine)
increaseIndentRegexForScopes: (scopes) ->
if increaseIndentPattern = syntax.getProperty(scopes, 'editor.increaseIndentPattern')
new OnigRegExp(increaseIndentPattern)
decreaseIndentRegexForScopes: (scopes) ->
if decreaseIndentPattern = syntax.getProperty(scopes, 'editor.decreaseIndentPattern')
new OnigRegExp(decreaseIndentPattern)
foldEndRegexForScopes: (scopes) ->
if foldEndPattern = syntax.getProperty(scopes, 'editor.foldEndPattern')
new OnigRegExp(foldEndPattern)

21
src/app/package.coffee Normal file
View File

@@ -0,0 +1,21 @@
fs = require 'fs'
module.exports =
class Package
@forName: (name) ->
AtomPackage = require 'atom-package'
TextMatePackage = require 'text-mate-package'
if TextMatePackage.testName(name)
new TextMatePackage(name)
else
new AtomPackage(name)
constructor: (@name) ->
@path = require.resolve(@name, verifyExistence: false)
throw new Error("No package found named '#{@name}'") unless @path
@path = fs.directory(@path) unless fs.isDirectory(@path)
load: ->
for { selector, properties } in @getScopedProperties()
syntax.addProperties(selector, properties)

View File

@@ -10,7 +10,6 @@ Project = require 'project'
Pane = require 'pane'
PaneColumn = require 'pane-column'
PaneRow = require 'pane-row'
TextMateTheme = require 'text-mate-theme'
module.exports =
class RootView extends View
@@ -24,25 +23,23 @@ class RootView extends View
@div id: 'vertical', outlet: 'vertical', =>
@div id: 'panes', outlet: 'panes'
@deserialize: ({ projectPath, panesViewState, extensionStates }) ->
rootView = new RootView(projectPath, extensionStates: extensionStates, suppressOpen: true)
@deserialize: ({ projectPath, panesViewState, packageStates }) ->
rootView = new RootView(projectPath, packageStates: packageStates, suppressOpen: true)
rootView.setRootPane(rootView.deserializeView(panesViewState)) if panesViewState
rootView
extensions: null
extensionStates: null
packageModules: null
packageStates: null
title: null
initialize: (pathToOpen, { @extensionStates, suppressOpen } = {}) ->
initialize: (pathToOpen, { @packageStates, suppressOpen } = {}) ->
window.rootView = this
@extensionStates ?= {}
@extensions = {}
@packageStates ?= {}
@packageModules = {}
@project = new Project(pathToOpen)
config.load()
TextMateTheme.activate(config.get("core.theme") ? 'IR_Black')
@handleEvents()
if pathToOpen
@@ -53,7 +50,7 @@ class RootView extends View
serialize: ->
projectPath: @project?.getPath()
panesViewState: @panes.children().view()?.serialize()
extensionStates: @serializeExtensions()
packageStates: @serializePackages()
handleFocus: (e) ->
if @getActiveEditor()
@@ -99,14 +96,14 @@ class RootView extends View
afterAttach: (onDom) ->
@focus() if onDom
serializeExtensions: ->
extensionStates = {}
for name, extension of @extensions
serializePackages: ->
packageStates = {}
for name, packageModule of @packageModules
try
extensionStates[name] = extension.serialize?()
packageStates[name] = packageModule.serialize?()
catch e
console?.error("Exception serializing '#{name}' extension\n", e.stack)
extensionStates
console?.error("Exception serializing '#{name}' package's module\n", e.stack)
packageStates
deserializeView: (viewState) ->
switch viewState.viewClass
@@ -115,18 +112,18 @@ class RootView extends View
when 'PaneColumn' then PaneColumn.deserialize(viewState, this)
when 'Editor' then Editor.deserialize(viewState, this)
activateExtension: (extension, config) ->
throw new Error("Trying to activate an extension with no name attribute") unless extension.name?
@extensions[extension.name] = extension
extension.activate(this, @extensionStates[extension.name], config)
activatePackage: (packageModule) ->
throw new Error("Trying to activate a package module with no name attribute") unless packageModule.name?
@packageModules[packageModule.name] = packageModule
packageModule.activate(this, @packageStates[packageModule.name])
deactivateExtension: (extension) ->
extension.deactivate?()
delete @extensions[extension.name]
deactivatePackage: (packageModule) ->
packageModule.deactivate?()
delete @packageModules[packageModule.name]
deactivate: ->
atom.setRootViewStateForPath(@project.getPath(), @serialize())
@deactivateExtension(extension) for name, extension of @extensions
@deactivatePackage(packageModule) for name, packageModule of @packageModules
@remove()
open: (path, options = {}) ->

70
src/app/syntax.coffee Normal file
View File

@@ -0,0 +1,70 @@
_ = require 'underscore'
jQuery = require 'jquery'
Specificity = require 'specificity'
{$$} = require 'space-pen'
module.exports =
class Syntax
constructor: ->
@globalProperties = {}
@scopedPropertiesIndex = 0
@scopedProperties = []
@propertiesBySelector = {}
addProperties: (args...) ->
selector = args.shift() if args.length > 1
properties = args.shift()
if selector
@scopedProperties.unshift(
selector: selector,
properties: properties,
specificity: Specificity(selector),
index: @scopedPropertiesIndex++
)
else
_.extend(@globalProperties, properties)
getProperty: (scope, keyPath) ->
for object in @propertiesForScope(scope, keyPath)
value = _.valueForKeyPath(object, keyPath)
return value if value?
undefined
propertiesForScope: (scope, keyPath) ->
matchingProperties = []
candidates = @scopedProperties.filter ({properties}) -> _.valueForKeyPath(properties, keyPath)?
if candidates.length
element = @buildScopeElement(scope)
while element
matchingProperties.push(@matchingPropertiesForElement(element, candidates)...)
element = element.parentNode
matchingProperties.concat([@globalProperties])
matchingPropertiesForElement: (element, candidates) ->
matchingScopedProperties = candidates.filter ({selector}) ->
jQuery.find.matchesSelector(element, selector)
matchingScopedProperties.sort (a, b) ->
if a.specificity == b.specificity
b.index - a.index
else
b.specificity - a.specificity
_.pluck matchingScopedProperties, 'properties'
buildScopeElement: (scope) ->
scope = new Array(scope...)
element = $$ ->
elementsForRemainingScopes = =>
classString = scope.shift()
classes = classString.replace(/^\./, '').replace(/\./g, ' ')
if scope.length
@div class: classes, elementsForRemainingScopes
else
@div class: classes
elementsForRemainingScopes()
deepestChild = element.find(":not(:has(*))")
if deepestChild.length
deepestChild[0]
else
element[0]

View File

@@ -10,18 +10,10 @@ class TextMateBundle
@grammarsByFileType: {}
@grammarsByScopeName: {}
@preferencesByScopeSelector: {}
@bundles: []
@grammars: []
@loadAll: ->
localBundlePath = fs.join(config.configDirPath, "bundles")
localBundles = fs.list(localBundlePath) if fs.exists(localBundlePath)
for bundlePath in localBundles ? []
@registerBundle(new TextMateBundle(bundlePath))
@registerBundle: (bundle)->
@bundles.push(bundle)
@load: (name)->
bundle = new TextMateBundle(require.resolve(name))
for scopeSelector, preferences of bundle.getPreferencesByScopeSelector()
if @preferencesByScopeSelector[scopeSelector]?
@@ -35,6 +27,8 @@ class TextMateBundle
@grammarsByFileType[fileType] = grammar
@grammarsByScopeName[grammar.scopeName] = grammar
bundle
@grammarForFilePath: (filePath) ->
return @grammarsByFileType["txt"] unless filePath
@@ -59,34 +53,6 @@ class TextMateBundle
@grammarForScopeName: (scopeName) ->
@grammarsByScopeName[scopeName]
@getPreferenceInScope: (scopeSelector, preferenceName) ->
@preferencesByScopeSelector[scopeSelector]?[preferenceName]
@getPreferenceValueInScope: (scope, preferenceName, valueName) ->
values = @getPreferenceInScope(scope, preferenceName)
(_.find values, ({name}) -> name is valueName)?['value']
@lineCommentStartStringForScope: (scope) ->
@getPreferenceValueInScope(scope, 'shellVariables', 'TM_COMMENT_START')
@lineCommentEndStringForScope: (scope) ->
@getPreferenceValueInScope(scope, 'shellVariables', 'TM_COMMENT_END')
@indentRegexForScope: (scope) ->
if source = @getPreferenceInScope(scope, 'increaseIndentPattern')
new OnigRegExp(source)
@outdentRegexForScope: (scope) ->
if source = @getPreferenceInScope(scope, 'decreaseIndentPattern')
new OnigRegExp(source)
@foldEndRegexForScope: (grammar, scope) ->
marker = @getPreferenceInScope(scope, 'foldingStopMarker')
if marker
new OnigRegExp(marker)
else
new OnigRegExp(grammar.foldingStopMarker)
grammars: null
constructor: (@path) ->

View File

@@ -0,0 +1,74 @@
Package = require 'package'
TextMateBundle = require 'text-mate-bundle'
fs = require 'fs'
plist = require 'plist'
_ = require 'underscore'
module.exports =
class TextMatePackage extends Package
@testName: (packageName) ->
/(\.|_|-)tmbundle$/.test(packageName)
@cssSelectorFromScopeSelector: (scopeSelector) ->
scopeSelector.split(', ').map((commaFragment) ->
commaFragment.split(' ').map((spaceFragment) ->
spaceFragment.split('.').map((dotFragment) ->
'.' + dotFragment.replace(/\+/g, '\\+')
).join('')
).join(' ')
).join(', ')
load: ->
@bundle = TextMateBundle.load(@name)
@grammars = @bundle.grammars
super
constructor: ->
super
@preferencesPath = fs.join(@path, "Preferences")
@syntaxesPath = fs.join(@path, "Syntaxes")
getScopedProperties: ->
scopedProperties = []
for grammar in @grammars
if properties = @propertiesFromTextMateSettings(grammar)
selector = @cssSelectorFromScopeSelector(grammar.scopeName)
scopedProperties.push({selector, properties})
for {scope, settings} in @getTextMatePreferenceObjects()
if properties = @propertiesFromTextMateSettings(settings)
selector = @cssSelectorFromScopeSelector(scope) if scope?
scopedProperties.push({selector, properties})
scopedProperties
getTextMatePreferenceObjects: ->
preferenceObjects = []
if fs.exists(@preferencesPath)
for preferencePath in fs.list(@preferencesPath)
plist.parseString fs.read(preferencePath), (e, data) =>
if e
console.warn "Failed to parse preference at path '#{preferencePath}'", e.stack
else
preferenceObjects.push(data[0])
preferenceObjects
propertiesFromTextMateSettings: (textMateSettings) ->
if textMateSettings.shellVariables
shellVariables = {}
for {name, value} in textMateSettings.shellVariables
shellVariables[name] = value
textMateSettings.shellVariables = shellVariables
editorProperties = _.compactObject(
commentStart: _.valueForKeyPath(textMateSettings, 'shellVariables.TM_COMMENT_START')
commentEnd: _.valueForKeyPath(textMateSettings, 'shellVariables.TM_COMMENT_END')
increaseIndentPattern: textMateSettings.increaseIndentPattern
decreaseIndentPattern: textMateSettings.decreaseIndentPattern
foldEndPattern: textMateSettings.foldingStopMarker
)
{ editor: editorProperties } if _.size(editorProperties) > 0
cssSelectorFromScopeSelector: (scopeSelector) ->
@constructor.cssSelectorFromScopeSelector(scopeSelector)

View File

@@ -1,46 +1,16 @@
_ = require 'underscore'
fs = require 'fs'
plist = require 'plist'
Theme = require 'theme'
module.exports =
class TextMateTheme
@themesByName: {}
@loadAll: ->
for themePath in fs.list(require.resolve("themes"))
@registerTheme(TextMateTheme.load(themePath))
@load: (path) ->
plistString = fs.read(require.resolve(path))
theme = null
plist.parseString plistString, (err, data) ->
throw new Error("Error loading theme at '#{path}': #{err}") if err
theme = new TextMateTheme(data[0])
theme
@registerTheme: (theme) ->
@themesByName[theme.name] = theme
@getNames: ->
_.keys(@themesByName)
@getTheme: (name) ->
@themesByName[name]
@activate: (name) ->
if theme = @getTheme(name)
theme.activate()
else
throw new Error("No theme with name '#{name}'")
constructor: ({@name, settings}) ->
class TextMateTheme extends Theme
constructor: (@path, {settings}) ->
super
@rulesets = []
globalSettings = settings[0]
@buildGlobalSettingsRulesets(settings[0])
@buildScopeSelectorRulesets(settings[1..])
activate: ->
applyStylesheet(@name, @getStylesheet())
@stylesheets[@path] = @getStylesheet()
getStylesheet: ->
lines = []

56
src/app/theme.coffee Normal file
View File

@@ -0,0 +1,56 @@
fs = require("fs")
plist = require 'plist'
_ = require 'underscore'
module.exports =
class Theme
@stylesheets: null
@load: (names) ->
if typeof(names) == "string"
[@loadTheme(names)]
else
names.map (name) => @loadTheme(name)
@loadTheme: (name) ->
if fs.exists(name)
path = name
else
path = fs.resolve(config.themeDirPaths..., name)
path ?= fs.resolve(config.themeDirPaths..., name + ".tmTheme")
if @isTextMateTheme(path)
theme = @loadTextMateTheme(path)
else
theme = @loadAtomTheme(path)
throw new Error("Cannot activate theme named '#{name}' located at '#{path}'") unless theme
theme.activate()
theme
@loadTextMateTheme: (path) ->
TextMateTheme = require("text-mate-theme")
plistString = fs.read(path)
theme = null
plist.parseString plistString, (err, data) ->
throw new Error("Error loading theme at '#{path}': #{err}") if err
theme = new TextMateTheme(path, data[0])
theme
@loadAtomTheme: (path) ->
AtomTheme = require('atom-theme')
new AtomTheme(path)
@isTextMateTheme: (path) ->
/\.(tmTheme|plist)$/.test(path)
constructor: (@path) ->
@stylesheets = {}
activate: ->
for stylesheetPath, stylesheetContent of @stylesheets
applyStylesheet(stylesheetPath, stylesheetContent)
deactivate: ->
for stylesheetPath, stylesheetContent of @stylesheets
window.removeStylesheet(stylesheetPath)

View File

@@ -9,6 +9,7 @@ _ = require 'underscore'
$ = require 'jquery'
{CoffeeScript} = require 'coffee-script'
Config = require 'config'
Syntax = require 'syntax'
RootView = require 'root-view'
Pasteboard = require 'pasteboard'
require 'jquery-extensions'
@@ -25,8 +26,7 @@ windowAdditions =
# in all environments: spec, benchmark, and application
startup: ->
@config = new Config
TextMateBundle.loadAll()
TextMateTheme.loadAll()
@syntax = new Syntax
@setUpKeymap()
@pasteboard = new Pasteboard
@@ -65,9 +65,14 @@ windowAdditions =
requireStylesheet: (path) ->
unless fullPath = require.resolve(path)
throw new Error("requireStylesheet could not find a file at path '#{path}'")
throw new Error("Could not find a file at path '#{path}'")
window.applyStylesheet(fullPath, fs.read(fullPath))
removeStylesheet: (path) ->
unless fullPath = require.resolve(path)
throw new Error("Could not find a file at path '#{path}'")
$("head style[id='#{fullPath}']").remove()
applyStylesheet: (id, text) ->
unless $("head style[id='#{id}']").length
$('head').append "<style id='#{id}'>#{text}</style>"