Module: Sevgi::Graphics::Module

Defined in:
lib/sevgi/graphics/mixtures/call.rb

Overview

Callable drawing module support. Extend a plain Ruby module with this API to make its public instance methods callable drawing steps.

Examples:

Define and call a drawing module

Widget = Module.new do
  extend Sevgi::Graphics::Module

  def item(id)
    rect(id:)
  end
end

SVG { Call(Widget, "box") }

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.call(mod, receiver, *args, **kwargs) ⇒ Object?

Runs module hooks and callables against a receiver.

Parameters:

  • mod (Module)

    callable module

  • receiver (Sevgi::Graphics::Element)

    receiver element

  • args (Array<Object>)

    callable arguments

  • kwargs (Hash)

    callable keyword arguments

Returns:

  • (Object, nil)

    last callable return value

Raises:

  • (Sevgi::ArgumentError)

    when mod is not a plain module



64
65
66
67
68
69
70
# File 'lib/sevgi/graphics/mixtures/call.rb', line 64

def self.call(mod, receiver, ...)
  mod._befores.each { receiver.Within(receiver, &it) } if mod.respond_to?(:_befores) && mod._befores
  # return last callable return value
  callables(mod).map { it.bind(receiver).call(...) }.last.tap do
    mod._afters.each { receiver.Within(receiver, &it) } if mod.respond_to?(:_afters) && mod._afters
  end
end

.callables(mod) ⇒ Array<UnboundMethod>

Returns the methods that should be executed for a callable module.

Parameters:

  • mod (Module)

    callable module

Returns:

  • (Array<UnboundMethod>)

Raises:

  • (Sevgi::ArgumentError)

    when mod is not a plain module



76
77
78
79
80
81
82
# File 'lib/sevgi/graphics/mixtures/call.rb', line 76

def self.callables(mod)
  ArgumentError.("Must be a module: #{mod}") unless mod.instance_of?(::Module)

  callable_names(mod).uniq.filter_map do |name|
    mod.instance_method(name) if mod.public_method_defined?(name)
  end
end

.extended(base) ⇒ void

This method returns an undefined value.

Initializes callable module state.

Parameters:

  • base (Module)

    extended module



42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/sevgi/graphics/mixtures/call.rb', line 42

def self.extended(base)
  base.instance_exec do
    @_callables = []
    @_befores = []
    @_afters = []

    class << self
      attr_reader :_callables, :_befores, :_afters
    end

    extend(DSL)
  end
end

Instance Method Details

#method_added(method) ⇒ Array<Symbol>?

Tracks newly defined methods as callable drawing candidates. Invocation runs unique methods that are still public, preserving tracked definition order.

Parameters:

  • method (Symbol)

    method name Ruby reports as added

Returns:

  • (Array<Symbol>, nil)


22
23
24
25
26
# File 'lib/sevgi/graphics/mixtures/call.rb', line 22

def method_added(method)
  super

  _callables << method if public_method_defined?(method)
end