When loading a package, honor the 'keymaps' manifest in package.json

Also, add a spec to cover the loading of keymaps in `atom-spec` and
reset the `keymap`'s internal data after each spec gets run to prevent
test pollution with keymaps.
This commit is contained in:
Nathan Sobo 2013-01-03 15:10:11 -07:00
parent 6442a4ba9f
commit a9bb4ea163
11 changed files with 104 additions and 16 deletions

View File

@ -1,4 +1,5 @@
RootView = require 'root-view'
{$$} = require 'space-pen'
describe "the `atom` global", ->
describe ".loadPackage(name)", ->
@ -17,6 +18,33 @@ describe "the `atom` global", ->
atom.loadPackage("package-with-module")
expect(rootView.activatePackage).toHaveBeenCalledWith(extension)
describe "keymap loading", ->
describe "when package.json does not contain a 'keymaps' manifest", ->
it "loads all keymaps in the directory", ->
element1 = $$ -> @div class: 'test-1'
element2 = $$ -> @div class: 'test-2'
expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined()
expect(keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined()
atom.loadPackage("package-with-module")
expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1"
expect(keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2"
describe "when package.json contains a 'keymaps' manifest", ->
it "loads only the keymaps specified by the manifest, in the specified order", ->
element1 = $$ -> @div class: 'test-1'
element3 = $$ -> @div class: 'test-3'
expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined()
atom.loadPackage("package-with-keymaps-manifest")
expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe 'keymap-1'
expect(keymap.bindingsForElement(element1)['ctrl-n']).toBe 'keymap-2'
expect(keymap.bindingsForElement(element3)['ctrl-y']).toBeUndefined()
it "loads stylesheets associated with the package", ->
stylesheetPath = require.resolve("fixtures/packages/package-with-module/stylesheets/styles.css")
expect(stylesheetElementForId(stylesheetPath).length).toBe 0

View File

@ -0,0 +1,5 @@
{
".test-1": {
"ctrl-z": "keymap-1"
}
}

View File

@ -0,0 +1,3 @@
".test-1":
"ctrl-z": "keymap-2"
"ctrl-n": "keymap-2"

View File

@ -0,0 +1,2 @@
".test-3":
"ctrl-y": "keymap-3"

View File

@ -0,0 +1 @@
keymaps: ["keymap-2", "keymap-1"]

View File

@ -0,0 +1,2 @@
".test-1":
"ctrl-z": "test-1"

View File

@ -0,0 +1,2 @@
".test-2":
"ctrl-z": "test-2"

View File

@ -12,10 +12,9 @@ Editor = require 'editor'
TokenizedBuffer = require 'tokenized-buffer'
fs = require 'fs'
require 'window'
requireStylesheet "jasmine.css"
require.paths.unshift(require.resolve('fixtures/packages'))
[bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = []
# Load TextMate bundles, which specs rely on (but not other packages)
atom.loadPackages(atom.getAvailableTextMateBundles())
@ -24,7 +23,11 @@ beforeEach ->
window.fixturesProject = new Project(require.resolve('fixtures'))
window.resetTimeouts()
# reset config after each spec; don't load or save from/to `config.json`
# used to reset keymap after each spec
bindingSetsToRestore = _.clone(keymap.bindingSets)
bindingSetsByFirstKeystrokeToRestore = _.clone(keymap.bindingSetsByFirstKeystroke)
# reset config before each spec; don't load or save from/to `config.json`
window.config = new Config()
spyOn(config, 'load')
spyOn(config, 'save')
@ -42,6 +45,8 @@ beforeEach ->
spyOn(TokenizedBuffer.prototype, "tokenizeInBackground").andCallFake -> @tokenizeNextChunk()
afterEach ->
keymap.bindingSets = bindingSetsToRestore
keymap.bindingSetsByFirstKeystrokeToRestore = bindingSetsByFirstKeystrokeToRestore
delete window.rootView if window.rootView
$('#jasmine-content').empty()
window.fixturesProject.destroy()

View File

@ -3,29 +3,42 @@ fs = require 'fs'
module.exports =
class AtomPackage extends Package
metadata: null
keymapsDirPath: null
constructor: (@name) ->
super
@module = require(@path)
@module.name = @name
@keymapsDirPath = fs.join(@path, 'keymaps')
if @requireModule
@module = require(@path)
@module.name = @name
load: ->
try
@loadMetadata()
@loadKeymaps()
@loadStylesheets()
rootView.activatePackage(@module)
rootView.activatePackage(@module) if @module
catch e
console.error "Failed to load package named '#{@name}'", e.stack
loadMetadata: ->
if metadataPath = fs.resolveExtension(fs.join(@path, "package"), ['cson', 'json'])
@metadata = fs.readObject(metadataPath)
loadKeymaps: ->
for keymapPath in @getKeymapPaths()
keymap.load(keymapPath)
getKeymapPaths: ->
keymapsDirPath = fs.join(@path, 'keymaps')
if fs.exists keymapsDirPath
fs.list keymapsDirPath
if keymaps = @metadata?.keymaps
keymaps.map (relativePath) =>
fs.resolve(@keymapsDirPath, relativePath, ['cson', 'json', ''])
else
[]
if fs.exists(@keymapsDirPath)
fs.list(@keymapsDirPath)
else
[]
loadStylesheets: ->
for stylesheetPath in @getStylesheetPaths()

View File

@ -11,10 +11,21 @@ class Package
else
new AtomPackage(name).load()
name: null
path: null
requireModule: null
module: null
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)
if fs.isDirectory(@path)
@requireModule = false
else
@requireModule = true
@path = fs.directory(@path)
load: ->
for grammar in @getGrammars()

View File

@ -124,11 +124,27 @@ module.exports =
md5ForPath: (path) ->
$native.md5ForPath(path)
resolve: (paths...) ->
to = paths.pop()
for from in paths
path = @join(from, to)
return path if @exists(path)
resolve: (args...) ->
extensions = args.pop() if _.isArray(_.last(args))
pathToResolve = args.pop()
loadPaths = args
for loadPath in loadPaths
candidatePath = @join(loadPath, pathToResolve)
if extensions
if resolvedPath = @resolveExtension(candidatePath, extensions)
return resolvedPath
else
return candidatePath if @exists(candidatePath)
undefined
resolveExtension: (path, extensions) ->
for extension in extensions
if extension == ""
return path if @exists(path)
else
pathWithExtension = path + "." + extension
return pathWithExtension if @exists(pathWithExtension)
undefined
isCompressedExtension: (ext) ->