Skip to content

Commit 0fa6793

Browse files
committed
feat(plugin): introduce simple event-based plugin system
1 parent 0e5a763 commit 0fa6793

File tree

5 files changed

+77
-0
lines changed

5 files changed

+77
-0
lines changed

lib/rdoc.rb

+2
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,6 @@ def self.home
208208
autoload :Extend, "#{__dir__}/rdoc/code_object/extend"
209209
autoload :Require, "#{__dir__}/rdoc/code_object/require"
210210

211+
autoload :BasePlugin, "#{__dir__}/rdoc/base_plugin"
212+
autoload :EventRegistry, "#{__dir__}/rdoc/event_registry"
211213
end

lib/rdoc/base_plugin.rb

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module RDoc
2+
class BasePlugin
3+
# Register a literner for the given event
4+
5+
def self.listens_to(event_name, &block)
6+
rdoc.event_registry.register(event_name, block)
7+
end
8+
9+
# Activate the plugin with the given RDoc instance
10+
# Without calling this, plugins won't work
11+
12+
def self.activate_with(rdoc = ::RDoc::RDoc.current)
13+
@@rdoc = rdoc
14+
end
15+
16+
def self.rdoc
17+
@@rdoc
18+
end
19+
end
20+
end

lib/rdoc/event_registry.rb

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module RDoc
2+
class EventRegistry
3+
EVENT_TYPES = %i[
4+
rdoc_start
5+
sample
6+
rdoc_store_complete
7+
]
8+
9+
attr_reader :environment
10+
11+
def initialize
12+
@registry = EVENT_TYPES.map { |event_name| [event_name, []] }.to_h
13+
@environment = {}
14+
end
15+
16+
def register(event_name, handler)
17+
@registry[event_name] << handler
18+
end
19+
20+
def trigger(event_name, *args)
21+
@registry[event_name].each do |handler|
22+
handler.call(@environment, *args)
23+
end
24+
end
25+
end
26+
end

lib/rdoc/options.rb

+19
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ def init_ivars # :nodoc:
395395
@coverage_report = false
396396
@op_dir = nil
397397
@page_dir = nil
398+
@plugins = []
398399
@pipe = false
399400
@output_decoration = true
400401
@rdoc_include = []
@@ -436,6 +437,7 @@ def init_with map # :nodoc:
436437
@main_page = map['main_page']
437438
@markup = map['markup']
438439
@op_dir = map['op_dir']
440+
@plugins = map['plugins']
439441
@show_hash = map['show_hash']
440442
@tab_width = map['tab_width']
441443
@template_dir = map['template_dir']
@@ -503,6 +505,7 @@ def == other # :nodoc:
503505
@main_page == other.main_page and
504506
@markup == other.markup and
505507
@op_dir == other.op_dir and
508+
@plugins == other.plugins and
506509
@rdoc_include == other.rdoc_include and
507510
@show_hash == other.show_hash and
508511
@static_path == other.static_path and
@@ -868,6 +871,12 @@ def parse argv
868871

869872
opt.separator nil
870873

874+
opt.on("--plugins=PLUGINS", "-P", Array, "Use plugins") do |value|
875+
@plugins.concat value
876+
end
877+
878+
opt.separator nil
879+
871880
opt.on("--tab-width=WIDTH", "-w", Integer,
872881
"Set the width of tab characters.") do |value|
873882
raise OptionParser::InvalidArgument,
@@ -1344,6 +1353,16 @@ def visibility= visibility
13441353
end
13451354
end
13461355

1356+
# Load plugins specified with options
1357+
# Currently plugin search logic is very simple, but it's not practical.
1358+
# TODO: We will improve this later.
1359+
1360+
def load_plugins
1361+
@plugins.each do |plugin_name|
1362+
require_relative "./#{plugin_name}.rb"
1363+
end
1364+
end
1365+
13471366
##
13481367
# Displays a warning using Kernel#warn if we're being verbose
13491368

lib/rdoc/rdoc.rb

+10
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ class RDoc::RDoc
7171

7272
attr_accessor :store
7373

74+
##
75+
# Event registry for RDoc plugins
76+
77+
attr_accessor :event_registry
78+
7479
##
7580
# Add +klass+ that can generate output after parsing
7681

@@ -105,6 +110,7 @@ def initialize
105110
@options = nil
106111
@stats = nil
107112
@store = nil
113+
@event_registry = ::RDoc::EventRegistry.new
108114
end
109115

110116
##
@@ -449,6 +455,9 @@ def document options
449455
end
450456
@options.finish
451457

458+
::RDoc::BasePlugin.activate_with(self)
459+
@options.load_plugins
460+
452461
@store = RDoc::Store.new(@options)
453462

454463
if @options.pipe then
@@ -469,6 +478,7 @@ def document options
469478
@options.default_title = "RDoc Documentation"
470479

471480
@store.complete @options.visibility
481+
@event_registry.trigger :rdoc_store_complete, @store
472482

473483
@stats.coverage_level = @options.coverage_report
474484

0 commit comments

Comments
 (0)