1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
require 'rdoc/markup'
##
# Handle common directives that can occur in a block of text:
#
# : include : filename
#
# RDoc plugin authors can register additional directives to be handled through
# RDoc::Markup::PreProcess::register
class RDoc::Markup::PreProcess
@registered = {}
##
# Registers +directive+ as one handled by RDoc. If a block is given the
# directive will be replaced by the result of the block, otherwise the
# directive will be removed from the processed text.
def self.register directive, &block
@registered[directive] = block
end
##
# Registered directives
def self.registered
@registered
end
##
# Creates a new pre-processor for +input_file_name+ that will look for
# included files in +include_path+
def initialize(input_file_name, include_path)
@input_file_name = input_file_name
@include_path = include_path
end
##
# Look for directives in a chunk of +text+.
#
# Options that we don't handle are yielded. If the block returns false the
# directive is restored to the text. If the block returns nil or no block
# was given the directive is handled according to the registered directives.
# If a String was returned the directive is replaced with the string.
#
# If no matching directive was registered the directive is restored to the
# text.
#
# If +code_object+ is given and the param is set as metadata on the
# +code_object+. See RDoc::CodeObject#metadata
def handle text, code_object = nil
text.gsub!(/^([ \t]*#?[ \t]*):(\w+):([ \t]*)(.+)?\n/) do
next $& if $3.empty? and $4 and $4[0, 1] == ':'
prefix = $1
directive = $2.downcase
param = $4
case directive
when 'include' then
filename = param.split[0]
include_file filename, prefix
else
result = yield directive, param if block_given?
case result
when nil then
code_object.metadata[directive] = param if code_object
if RDoc::Markup::PreProcess.registered.include? directive then
handler = RDoc::Markup::PreProcess.registered[directive]
result = handler.call directive, param if handler
else
result = "#{prefix}:#{directive}: #{param}\n"
end
when false then
result = "#{prefix}:#{directive}: #{param}\n"
end
result
end
end
text
end
##
# Include a file, indenting it correctly.
def include_file(name, indent)
if full_name = find_include_file(name) then
content = if defined?(Encoding) then
File.binread full_name
else
File.read full_name
end
# HACK determine content type and force encoding
content = content.sub(/\A# .*coding[=:].*$/, '').lstrip
# strip leading '#'s, but only if all lines start with them
if content =~ /^[^#]/ then
content.gsub(/^/, indent)
else
content.gsub(/^#?/, indent)
end
else
warn "Couldn't find file to include '#{name}' from #{@input_file_name}"
''
end
end
##
# Look for the given file in the directory containing the current file,
# and then in each of the directories specified in the RDOC_INCLUDE path
def find_include_file(name)
to_search = [File.dirname(@input_file_name)].concat @include_path
to_search.each do |dir|
full_name = File.join(dir, name)
stat = File.stat(full_name) rescue next
return full_name if stat.readable?
end
nil
end
end
|