Class: SOF::Cycle::Registry
- Inherits:
-
Object
- Object
- SOF::Cycle::Registry
- Defined in:
- lib/sof/cycle/registry.rb
Overview
The set of classes that handle cycle kinds.
Registration is explicit — a class joins by declaring what it handles (see Cycle.handles), not by subclassing. Inheriting from Cycle for any other reason, such as a test double or an abstract intermediate, then carries no hidden side effect.
The registry is also what the parser reads to recognise notations, so an application can add a kind of its own and have its notation parse without reopening this gem.
Class Method Summary collapse
Instance Method Summary collapse
- #cycle_classes ⇒ Object
-
#for_notation_id(notation_id) ⇒ Object
The class declaring
notation_id— the letter(s) that open a cycle's notation, such as "L" or "LE". -
#handling(kind) ⇒ Object
The class declaring
kind. -
#initialize ⇒ Registry
constructor
A new instance of Registry.
-
#notation_ids ⇒ Object
Registered notation ids, longest first.
-
#notation_pattern ⇒ Object
The alternation the parser splices into its pattern.
-
#register(cycle_class) ⇒ Object
Add a handler, displacing any already handling the same kind or notation id.
-
#unregister(cycle_class) ⇒ Object
Drop a handler.
Constructor Details
#initialize ⇒ Registry
Returns a new instance of Registry.
18 19 20 21 |
# File 'lib/sof/cycle/registry.rb', line 18 def initialize @cycle_classes = [] @notation_pattern = nil end |
Class Method Details
.instance ⇒ Object
16 |
# File 'lib/sof/cycle/registry.rb', line 16 def self.instance = @instance ||= new |
Instance Method Details
#cycle_classes ⇒ Object
47 |
# File 'lib/sof/cycle/registry.rb', line 47 def cycle_classes = @cycle_classes.dup |
#for_notation_id(notation_id) ⇒ Object
The class declaring notation_id — the letter(s) that open a cycle's
notation, such as "L" or "LE".
57 58 59 60 |
# File 'lib/sof/cycle/registry.rb', line 57 def for_notation_id(notation_id) @cycle_classes.find { |klass| klass.notation_id == notation_id } || raise(InvalidKind, "'#{notation_id}' is not a valid kind of Cycle") end |
#handling(kind) ⇒ Object
The class declaring kind.
50 51 52 53 |
# File 'lib/sof/cycle/registry.rb', line 50 def handling(kind) @cycle_classes.find { |klass| klass.handles?(kind) } || raise(InvalidKind, "':#{kind}' is not a valid kind of Cycle") end |
#notation_ids ⇒ Object
Registered notation ids, longest first. A volume-only cycle has none, so it contributes nothing to parse.
64 65 66 |
# File 'lib/sof/cycle/registry.rb', line 64 def notation_ids @cycle_classes.filter_map(&:notation_id).uniq.sort_by { |id| [-id.length, id] } end |
#notation_pattern ⇒ Object
The alternation the parser splices into its pattern. Rebuilt whenever a class registers, so a kind added at runtime is recognised from then on.
70 71 72 |
# File 'lib/sof/cycle/registry.rb', line 70 def notation_pattern @notation_pattern ||= notation_ids.map { Regexp.escape(it) }.join("|") end |
#register(cycle_class) ⇒ Object
Add a handler, displacing any already handling the same kind or notation id. That is what lets an application override a built-in kind — declare a class handling :lookback and it takes over "L" — as well as add one of its own. Re-registering the same class is a no-op, so a reloaded file accumulates no duplicates.
Returns the class, so a declaration can use the result.
30 31 32 33 34 35 36 37 |
# File 'lib/sof/cycle/registry.rb', line 30 def register(cycle_class) displaced = @cycle_classes.reject { |klass| klass.equal?(cycle_class) } .select { |klass| conflicts?(klass, cycle_class) } @cycle_classes -= displaced @cycle_classes << cycle_class unless @cycle_classes.include?(cycle_class) @notation_pattern = nil cycle_class end |
#unregister(cycle_class) ⇒ Object
Drop a handler. Mainly for an application undoing an override, and for tests that register a throwaway kind.
41 42 43 44 45 |
# File 'lib/sof/cycle/registry.rb', line 41 def unregister(cycle_class) @cycle_classes.delete(cycle_class) @notation_pattern = nil cycle_class end |