4 constructor: ({ @window, @commands, @modes, @esc }) ->
14 for { name } in @commands
15 @storage.commands[name] = {}
18 @storage.modes[name] = {}
20 enterMode: (mode, args) ->
21 # Note: `args` is an array of arguments to be passed to the mode's `enter` method. We cannot use
22 # `args...`, since that destroys the `this` context for the mode's `enter` method.
24 @modes[mode].enter(this, @storage.modes[mode], args)
27 for name, mode of @modes
28 mode.onEnterNormalMode?(this, @storage.modes[name])
31 handleKeyDown: (event, keyStr) ->
33 if @mode == MODE_NORMAL or keyStr == @esc
36 if command = @findCommand(@keys)
37 command.func(this, @storage.commands[command.name])
38 return command.name != @esc
39 else if @maybeCommand(@keys)
43 else if not (event.ctrlKey or event.metaKey)
44 @modes[@mode].handleKeyDown(this, @storage.modes[@mode], event, keyStr)
50 handleKeyPress: (event) ->
51 return @lastKeyStr != @esc and @suppress
53 handleKeyUp: (event) ->
56 return @lastKeyStr != @esc and suppress
58 findCommand: (keys) ->
59 for i in [0...keys.length]
60 str = keys[i..].join(',')
61 for command in @commands
62 for key in command.keys()
63 if key == str and command.enabled()
66 maybeCommand: (keys) ->
67 for i in [0...keys.length]
68 str = keys[i..].join(',')
69 for command in @commands
70 for key in command.keys()
71 if key.indexOf(str) == 0 and command.enabled()
74 # What is minimally required for a command
76 constructor: (@keyValues, @name) ->
77 keys: -> return @keyValues
78 enabled: -> return true