Class: Chamomile::Keymap

Inherits:
Object
  • Object
show all
Defined in:
lib/chamomile/keymap.rb

Overview

Declarative keymap with composable guard conditions.

Usage:

@keymap = Keymap.new
.bind("q")               { quit }
.bind(:tab)              { focus_next }
.only(-> { !modal_open? }) do |km|
  km.bind("j")           { scroll_down }
  km.bind("k")           { scroll_up }
end

Then in update:

def update(msg)
return @keymap.handle(msg, self) if msg.is_a?(KeyEvent)
...
end

Defined Under Namespace

Classes: Entry

Instance Method Summary collapse

Constructor Details

#initializeKeymap

Returns a new instance of Keymap.



23
24
25
# File 'lib/chamomile/keymap.rb', line 23

def initialize
  @entries = []
end

Instance Method Details

#bind(key, guard: nil, &action) ⇒ Object

Bind a key to a block. Returns self for chaining.



28
29
30
31
# File 'lib/chamomile/keymap.rb', line 28

def bind(key, guard: nil, &action)
  @entries << Entry.new(key: key, guard: guard, action: action)
  self
end

#handle(msg, model) ⇒ Object

Process a KeyEvent against the keymap. Returns the result of the matching action, or nil if no match.



51
52
53
54
55
56
57
58
59
60
61
# File 'lib/chamomile/keymap.rb', line 51

def handle(msg, model)
  return nil unless msg.is_a?(KeyEvent)

  @entries.each do |entry|
    next unless keys_match?(entry.key, msg)
    next if entry.guard && !entry.guard.call(model)

    return model.instance_exec(&entry.action)
  end
  nil
end

#only(guard, &block) ⇒ Object

Add a group of bindings that only fire when guard returns true. Guard is a Proc that receives the model.



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/chamomile/keymap.rb', line 35

def only(guard, &block)
  sub = self.class.new
  block.call(sub)
  sub.entries.each do |entry|
    combined_guard = if entry.guard
                       ->(m) { guard.call(m) && entry.guard.call(m) }
                     else
                       guard
                     end
    @entries << Entry.new(key: entry.key, guard: combined_guard, action: entry.action)
  end
  self
end