mirror of
https://github.com/atom/atom.git
synced 2026-01-25 14:59:03 -05:00
Merge branch 'master' into structural-folding
This commit is contained in:
@@ -190,18 +190,6 @@ describe "Keymap", ->
|
||||
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
|
||||
describe ".bindKey(selector, pattern, eventName)", ->
|
||||
it "binds a single key", ->
|
||||
keymap.bindKey '.child-node', 'z', 'foo'
|
||||
|
||||
fooHandler = jasmine.createSpy('fooHandler')
|
||||
fragment.on 'foo', fooHandler
|
||||
|
||||
target = fragment.find('.child-node')[0]
|
||||
keymap.handleKeyEvent(keydownEvent('z', target: target))
|
||||
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
|
||||
describe ".keystrokeStringForEvent(event)", ->
|
||||
describe "when no modifiers are pressed", ->
|
||||
it "returns a string that identifies the key pressed", ->
|
||||
@@ -224,3 +212,24 @@ describe "Keymap", ->
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('{', shiftKey: true))).toBe '{'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('left', shiftKey: true))).toBe 'shift-left'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('Left', shiftKey: true))).toBe 'shift-left'
|
||||
|
||||
|
||||
describe ".bindingsForElement(element)", ->
|
||||
it "returns the matching bindings for the element", ->
|
||||
keymap.bindKeys '.command-mode', 'c': 'c'
|
||||
keymap.bindKeys '.grandchild-node', 'g': 'g'
|
||||
|
||||
bindings = keymap.bindingsForElement(fragment.find('.grandchild-node'))
|
||||
expect(Object.keys(bindings).length).toBe 2
|
||||
expect(bindings['c']).toEqual "c"
|
||||
expect(bindings['g']).toEqual "g"
|
||||
|
||||
describe "when multiple bindings match a keystroke", ->
|
||||
it "only returns bindings that match the most specific selector", ->
|
||||
keymap.bindKeys '.command-mode', 'g': 'command-mode'
|
||||
keymap.bindKeys '.command-mode .grandchild-node', 'g': 'command-and-grandchild-node'
|
||||
keymap.bindKeys '.grandchild-node', 'g': 'grandchild-node'
|
||||
|
||||
bindings = keymap.bindingsForElement(fragment.find('.grandchild-node'))
|
||||
expect(Object.keys(bindings).length).toBe 1
|
||||
expect(bindings['g']).toEqual "command-and-grandchild-node"
|
||||
|
||||
@@ -356,6 +356,32 @@ describe "RootView", ->
|
||||
rootView.trigger(event)
|
||||
expect(commandHandler).toHaveBeenCalled()
|
||||
|
||||
describe ".activeKeybindings()", ->
|
||||
originalKeymap = null
|
||||
keymap = null
|
||||
editor = null
|
||||
|
||||
beforeEach ->
|
||||
rootView.attachToDom()
|
||||
editor = rootView.activeEditor()
|
||||
keymap = new (require 'keymap')
|
||||
originalKeymap = window.keymap
|
||||
window.keymap = keymap
|
||||
|
||||
afterEach ->
|
||||
window.keymap = originalKeymap
|
||||
|
||||
it "returns all keybindings available for focused element", ->
|
||||
editor.on 'test-event-a', => # nothing
|
||||
|
||||
keymap.bindKeys ".editor",
|
||||
"meta-a": "test-event-a"
|
||||
"meta-b": "test-event-b"
|
||||
|
||||
keybindings = rootView.activeKeybindings()
|
||||
expect(Object.keys(keybindings).length).toBe 2
|
||||
expect(keybindings["meta-a"]).toEqual "test-event-a"
|
||||
|
||||
describe "when the path of the focused editor's buffer changes", ->
|
||||
it "changes the document.title and emits an active-editor-path-change event", ->
|
||||
pathChangeHandler = jasmine.createSpy 'pathChangeHandler'
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
Specificity = require 'specificity'
|
||||
fs = require 'fs'
|
||||
|
||||
Specificity = require 'specificity'
|
||||
PEG = require 'pegjs'
|
||||
|
||||
module.exports =
|
||||
class BindingSet
|
||||
selector: null
|
||||
keystrokeMap: null
|
||||
commandForEvent: null
|
||||
keystrokePatternParser: null
|
||||
parser: null
|
||||
|
||||
constructor: (@selector, mapOrFunction) ->
|
||||
@parser = PEG.buildParser(fs.read(require.resolve 'keystroke-pattern.pegjs'))
|
||||
@specificity = Specificity(@selector)
|
||||
@commandForEvent = @buildEventHandler(mapOrFunction)
|
||||
@keystrokeMap = {}
|
||||
|
||||
buildEventHandler: (mapOrFunction) ->
|
||||
if _.isFunction(mapOrFunction)
|
||||
mapOrFunction
|
||||
@commandForEvent = mapOrFunction
|
||||
else
|
||||
mapOrFunction = @normalizeKeystrokePatterns(mapOrFunction)
|
||||
(event) =>
|
||||
for pattern, command of mapOrFunction
|
||||
return command if event.keystroke == pattern
|
||||
@keystrokeMap = @normalizeKeystrokeMap(mapOrFunction)
|
||||
@commandForEvent = (event) =>
|
||||
for keystroke, command of @keystrokeMap
|
||||
return command if event.keystroke == keystroke
|
||||
null
|
||||
|
||||
normalizeKeystrokePatterns: (map) ->
|
||||
normalizedMap = {}
|
||||
for pattern, event of map
|
||||
normalizedMap[@normalizeKeystrokePattern(pattern)] = event
|
||||
normalizedMap
|
||||
normalizeKeystrokeMap: (keystrokeMap) ->
|
||||
normalizeKeystrokeMap = {}
|
||||
for keystroke, command of keystrokeMap
|
||||
normalizeKeystrokeMap[@normalizeKeystroke(keystroke)] = command
|
||||
|
||||
normalizeKeystrokePattern: (pattern) ->
|
||||
keys = @parser.parse(pattern)
|
||||
normalizeKeystrokeMap
|
||||
|
||||
normalizeKeystroke: (keystroke) ->
|
||||
keys = @parser.parse(keystroke)
|
||||
modifiers = keys[0...-1]
|
||||
modifiers.sort()
|
||||
[modifiers..., _.last(keys)].join('-')
|
||||
|
||||
|
||||
@@ -454,7 +454,7 @@ class Editor extends View
|
||||
|
||||
return if oldScreenRange.start.row > @lastRenderedScreenRow
|
||||
|
||||
maxEndRow = Math.max(@getLastVisibleScreenRow() + @lineOverdraw, @lastRenderedScreenRow)
|
||||
maxEndRow = Math.max(@getFirstVisibleScreenRow() + @lineOverdraw, @lastRenderedScreenRow)
|
||||
@gutter.renderLineNumbers(@firstRenderedScreenRow, maxEndRow) if e.lineNumbersChanged
|
||||
|
||||
newScreenRange = newScreenRange.copy()
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
fs = require 'fs'
|
||||
|
||||
BindingSet = require 'binding-set'
|
||||
Specificity = require 'specificity'
|
||||
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class Keymap
|
||||
bindingSetsBySelector: null
|
||||
bindingSets: null
|
||||
|
||||
constructor: ->
|
||||
@bindingSets = []
|
||||
@@ -26,10 +27,17 @@ class Keymap
|
||||
bindKeys: (selector, bindings) ->
|
||||
@bindingSets.unshift(new BindingSet(selector, bindings))
|
||||
|
||||
bindKey: (selector, pattern, eventName) ->
|
||||
bindings = {}
|
||||
bindings[pattern] = eventName
|
||||
@bindKeys(selector, bindings)
|
||||
bindingsForElement: (element) ->
|
||||
keystrokeMap = {}
|
||||
currentNode = $(element)
|
||||
|
||||
while currentNode.length
|
||||
bindingSets = @bindingSets.filter (set) -> currentNode.is(set.selector)
|
||||
bindingSets.sort (a, b) -> b.specificity - a.specificity
|
||||
_.defaults(keystrokeMap, set.keystrokeMap) for set in bindingSets
|
||||
currentNode = currentNode.parent()
|
||||
|
||||
keystrokeMap
|
||||
|
||||
handleKeyEvent: (event) ->
|
||||
event.keystroke = @keystrokeStringForEvent(event)
|
||||
@@ -47,9 +55,6 @@ class Keymap
|
||||
currentNode = currentNode.parent()
|
||||
true
|
||||
|
||||
reset: ->
|
||||
@bindingSets = []
|
||||
|
||||
triggerCommandEvent: (keyEvent, commandName) ->
|
||||
commandEvent = $.Event(commandName)
|
||||
commandEvent.keyEvent = keyEvent
|
||||
|
||||
7
src/app/keymaps/atom.coffee
Normal file
7
src/app/keymaps/atom.coffee
Normal file
@@ -0,0 +1,7 @@
|
||||
window.keymap.bindKeys '*'
|
||||
'meta-w': 'close'
|
||||
'alt-meta-i': 'show-console'
|
||||
right: 'move-right'
|
||||
left: 'move-left'
|
||||
down: 'move-down'
|
||||
up: 'move-up'
|
||||
@@ -1,15 +1,3 @@
|
||||
window.keymap.bindKeys '*'
|
||||
'meta-s': 'save'
|
||||
'meta-w': 'close'
|
||||
'alt-meta-i': 'show-console'
|
||||
'meta-+': 'increase-font-size'
|
||||
'meta--': 'decrease-font-size'
|
||||
|
||||
right: 'move-right'
|
||||
left: 'move-left'
|
||||
down: 'move-down'
|
||||
up: 'move-up'
|
||||
|
||||
window.keymap.bindKeys '.editor',
|
||||
'meta-s': 'save'
|
||||
'shift-right': 'select-right'
|
||||
@@ -39,3 +27,5 @@ window.keymap.bindKeys '.editor',
|
||||
'meta-]': 'indent-selected-rows'
|
||||
'meta-{': 'show-previous-buffer'
|
||||
'meta-}': 'show-next-buffer'
|
||||
'meta-+': 'increase-font-size'
|
||||
'meta--': 'decrease-font-size'
|
||||
|
||||
5
src/app/keymaps/keybindings-view.coffee
Normal file
5
src/app/keymaps/keybindings-view.coffee
Normal file
@@ -0,0 +1,5 @@
|
||||
window.keymap.bindKeys '*',
|
||||
'ctrl-?': 'keybindings-view:attach'
|
||||
|
||||
window.keymap.bindKeys ".keybindings-view",
|
||||
'escape': 'keybindings-view:detach'
|
||||
@@ -114,6 +114,9 @@ class RootView extends View
|
||||
if not previousActiveEditor or editor.buffer.path != previousActiveEditor.buffer.path
|
||||
@trigger 'active-editor-path-change', editor.buffer.path
|
||||
|
||||
activeKeybindings: ->
|
||||
keymap.bindingsForElement(document.activeElement)
|
||||
|
||||
setTitle: (title='untitled') ->
|
||||
document.title = title
|
||||
|
||||
|
||||
1
src/extensions/keybindings-view/index.coffee
Normal file
1
src/extensions/keybindings-view/index.coffee
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require 'keybindings-view/keybindings-view'
|
||||
31
src/extensions/keybindings-view/keybindings-view.coffee
Normal file
31
src/extensions/keybindings-view/keybindings-view.coffee
Normal file
@@ -0,0 +1,31 @@
|
||||
{View, $$} = require 'space-pen'
|
||||
|
||||
module.exports =
|
||||
class KeybindingsView extends View
|
||||
@activate: (rootView, state) ->
|
||||
requireStylesheet 'keybinding-view.css'
|
||||
@instance = new this(rootView)
|
||||
|
||||
@content: (rootView) ->
|
||||
@div class: 'keybindings-view', tabindex: -1, =>
|
||||
@ul outlet: 'keybindingList'
|
||||
|
||||
initialize: (@rootView) ->
|
||||
@rootView.on 'keybindings-view:attach', => @attach()
|
||||
@on 'keybindings-view:detach', => @detach()
|
||||
|
||||
attach: ->
|
||||
@keybindingList.empty()
|
||||
@keybindingList.append $$ ->
|
||||
for keystroke, command of rootView.activeKeybindings()
|
||||
@li =>
|
||||
@span class: 'keystroke', "#{keystroke}"
|
||||
@span ":"
|
||||
@span "#{command}"
|
||||
|
||||
@rootView.append(this)
|
||||
@focus()
|
||||
|
||||
detach: ->
|
||||
super()
|
||||
@rootView.focus()
|
||||
@@ -61,4 +61,3 @@ body {
|
||||
background: #991212;
|
||||
-webkit-transition: background 200ms ease-out;
|
||||
}
|
||||
|
||||
|
||||
18
static/keybinding-view.css
Normal file
18
static/keybinding-view.css
Normal file
@@ -0,0 +1,18 @@
|
||||
.keybindings-view {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
background-color: white;
|
||||
overflow: scroll;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.keybindings-view li .keystroke {
|
||||
font-weight: bold;
|
||||
float: left;
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
width: 200px;
|
||||
}
|
||||
Reference in New Issue
Block a user