lib/vedeu/input/dsl.rb
# frozen_string_literal: true
module Vedeu
module Input
# You can define keymaps by name which matches a defined
# interface. When that interface is in focus, keys pressed as part
# of this definition will affect that interface. This allows you
# to form context driven behaviour for your application.
#
# @api private
#
class DSL
include Vedeu::Common
include Vedeu::DSL
# Define actions for keypresses for when specific interfaces are
# in focus. Unless an interface is specified, the key will be
# assumed to be global, meaning its action will happen
# regardless of the interface in focus.
#
# Vedeu.keymap :my_interface do
# key('s') { Vedeu.trigger(:save) }
# key('h', :left) { Vedeu.trigger(:left) }
# key('j', :down) { Vedeu.trigger(:down) }
# key('p') do
# # ... some code
# end
# # ... some code
# end
#
# # or...
#
# Vedeu.keys :my_interface do
# # ... some code
# end
#
# # or...
#
# Vedeu.interface :my_interface do
# keymap do
# # ... some code
# end # or...
#
# keys do
# # ... some code
# end
# end
#
# @note
# If a keymap with this name does not already exist,
# pre-register it, otherwise we have no way of knowing if a
# key defined in the DSL for this keymap has already been
# registered. This protects the client application from
# attempting to define the same key more than once for the
# same keymap.
#
# This is also used when defining the '_global_' keymap.
#
# @macro param_name
# @macro param_block
# @macro raise_requires_block
# @macro raise_missing_required
# @return [Vedeu::Input::Keymap]
def self.keymap(name, &block)
raise Vedeu::Error::MissingRequired unless name
raise Vedeu::Error::RequiresBlock unless block_given?
unless Vedeu.keymaps.registered?(name)
Vedeu::Input::Keymap.new(name: name).store
end
Vedeu::Input::Keymap.build(name: name, &block).store
end
# Define keypress(es) to perform an action.
#
# @param keys [Array<String>|Array<Symbol>|String|Symbol]
# The key(s) pressed. Special keys can be found in
# {Vedeu::Input::Input#specials}. When more than one key is
# defined, then the extras are treated as aliases.
# @macro param_block
# @macro raise_invalid_syntax
# @return [Array] A collection containing the keys minus any
# invalid or nil keys.
def key(*keys, &block)
raise Vedeu::Error::InvalidSyntax,
'No action defined for `key`.' unless block_given?
raise Vedeu::Error::InvalidSyntax,
'No keypresses defined for `key`.' unless present?(keys)
valid_keys(keys).each do |key|
model.add(Vedeu::Input::Key.new(key, &block))
end
end
alias key= key
private
# @param keys [Array<void>]
# @return [Array<String|Symbol>]
def valid_keys(keys)
keys.compact.keep_if do |key|
symbol?(key) || (string?(key) && present?(key))
end
end
end # DSL
end # Input
# @api public
# @!method keymap
# @see Vedeu::Input::DSL.keymap
def_delegators Vedeu::Input::DSL,
:keymap
end # Vedeu