Document CommandRegistry

This commit is contained in:
Nathan Sobo
2014-09-16 10:08:17 -06:00
parent a069f34ad6
commit 1f95d8069a
2 changed files with 76 additions and 0 deletions

View File

@@ -113,6 +113,9 @@ class Atom extends Model
# Public: A {KeymapManager} instance
keymaps: null
# Public: A {CommandRegistry} instance
commands: null
# Public: A {MenuManager} instance
menu: null

View File

@@ -7,6 +7,41 @@ SequenceCount = 0
SpecificityCache = {}
module.exports =
# Experimental: Associates listener functions with commands in a
# context-sensitive way using CSS selectors. You can access a global instance of
# this class via `atom.commands`, and commands registered there will be
# presented in the command palette.
#
# The global command registry facilitates a style of event handling known as
# *event delegation* that was popularized by jQuery. Atom commands are expressed
# as custom DOM events that can be invoked on the currently focused element via
# a key binding or manually via the command palette. Rather than binding
# listeners for command events directly to DOM nodes, you instead register
# command event listeners globally on `atom.commands` and constrain them to
# specific kinds of elements with CSS selectors.
#
# As the event bubbles upward through the DOM, all registered event listeners
# with matching selectors are invoked in order of specificity. In the event of a
# specificity tie, the most recently registered listener is invoked first. This
# mirrors the "cascade" semantics of CSS. Event listeners are invoked in the
# context of the current DOM node, meaning `this` always points at
# `event.currentTarget`. As is normally the case with DOM events,
# `stopPropagation` and `stopImmediatePropagation` can be used to terminate the
# bubbling process and prevent invocation of additional listeners.
#
# ## Example
#
# Here is a command that inserts the current date in an editor:
#
# ```coffee
# atom.commands.add '.editor',
# 'user:insert-date': (event) ->
# editor = $(this).view().getModel()
# # soon the above above line will be:
# # editor = @getModel()
# editor.insertText(new Date().toLocaleString())
# ```
class CommandRegistry
constructor: (@rootNode) ->
@listenersByCommandName = {}
@@ -19,6 +54,31 @@ class CommandRegistry
oldRootNode?.removeEventListener(commandName, @dispatchCommand, true)
newRootNode?.addEventListener(commandName, @dispatchCommand, true)
# Public: Add one or more command listeners associated with a selector.
#
# ## Arguments: Registering One Command
#
# * `selector` A {String} containing a CSS selector matching elements on which
# you want to handle the commands. The `,` combinator is not currently
# supported.
# * `commandName` A {String} containing the name of a command you want to
# handle such as `user:insert-date`.
# * `callback` A {Function} to call when the given command is invoked on an
# element matching the selector. It will be called with `this` referencing
# the matching DOM node.
# * `event` A standard DOM event instance. Call `stopPropagation` or
# `stopImmediatePropagation` to terminate bubbling early.
#
# ## Arguments: Registering Multiple Commands
#
# * `selector` A {String} containing a CSS selector matching elements on which
# you want to handle the commands. The `,` combinator is not currently
# supported.
# * `commands` An {Object} mapping command names like `user:insert-date` to
# listener {Function}s.
#
# Returns a {Disposable} on which `.dispose()` can be called to remove the
# added command handler(s).
add: (selector, commandName, callback) ->
if typeof commandName is 'object'
commands = commandName
@@ -69,6 +129,17 @@ class CommandRegistry
break if currentTarget is @rootNode
currentTarget = currentTarget.parentNode
# Public: Find all registered commands matching a query.
#
# * `params` An {Object} containing one or more of the following keys:
# * `target` A DOM node that is the hypothetical target of a given command.
#
# Returns an {Array} of {Object}s containing the following keys:
# * `name` The name of the command. For example, `user:insert-date`.
# * `displayName` The display name of the command. For example,
# `User: Insert Date`.
# * `jQuery` Present if the command was registered with the legacy
# `$::command` method.
findCommands: ({target}) ->
commands = []
target = @rootNode unless @rootNode.contains(target)
@@ -97,6 +168,8 @@ class CommandRegistry
class CommandListener
constructor: (@selector, @callback) ->
console.log "calc specificity", @selector
@specificity = (SpecificityCache[@selector] ?= specificity(@selector))
@sequenceNumber = SequenceCount++