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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
#
# notifier.rb - output methods used by irb
# $Release Version: 0.9.6$
# $Revision: 47112 $
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
# --
#
#
#
require "e2mmap"
require "irb/output-method"
module IRB
# An output formatter used internally by the lexer.
module Notifier
extend Exception2MessageMapper
def_exception :ErrUndefinedNotifier,
"undefined notifier level: %d is specified"
def_exception :ErrUnrecognizedLevel,
"unrecognized notifier level: %s is specified"
# Define a new Notifier output source, returning a new CompositeNotifier
# with the given +prefix+ and +output_method+.
#
# The optional +prefix+ will be appended to all objects being inspected
# during output, using the given +output_method+ as the output source. If
# no +output_method+ is given, StdioOutputMethod will be used, and all
# expressions will be sent directly to STDOUT without any additional
# formatting.
def def_notifier(prefix = "", output_method = StdioOutputMethod.new)
CompositeNotifier.new(prefix, output_method)
end
module_function :def_notifier
# An abstract class, or superclass, for CompositeNotifier and
# LeveledNotifier to inherit. It provides several wrapper methods for the
# OutputMethod object used by the Notifier.
class AbstractNotifier
# Creates a new Notifier object
def initialize(prefix, base_notifier)
@prefix = prefix
@base_notifier = base_notifier
end
# The +prefix+ for this Notifier, which is appended to all objects being
# inspected during output.
attr_reader :prefix
# A wrapper method used to determine whether notifications are enabled.
#
# Defaults to +true+.
def notify?
true
end
# See OutputMethod#print for more detail.
def print(*opts)
@base_notifier.print prefix, *opts if notify?
end
# See OutputMethod#printn for more detail.
def printn(*opts)
@base_notifier.printn prefix, *opts if notify?
end
# See OutputMethod#printf for more detail.
def printf(format, *opts)
@base_notifier.printf(prefix + format, *opts) if notify?
end
# See OutputMethod#puts for more detail.
def puts(*objs)
if notify?
@base_notifier.puts(*objs.collect{|obj| prefix + obj.to_s})
end
end
# Same as #ppx, except it uses the #prefix given during object
# initialization.
# See OutputMethod#ppx for more detail.
def pp(*objs)
if notify?
@base_notifier.ppx @prefix, *objs
end
end
# Same as #pp, except it concatenates the given +prefix+ with the #prefix
# given during object initialization.
#
# See OutputMethod#ppx for more detail.
def ppx(prefix, *objs)
if notify?
@base_notifier.ppx @prefix+prefix, *objs
end
end
# Execute the given block if notifications are enabled.
def exec_if
yield(@base_notifier) if notify?
end
end
# A class that can be used to create a group of notifier objects with the
# intent of representing a leveled notification system for irb.
#
# This class will allow you to generate other notifiers, and assign them
# the appropriate level for output.
#
# The Notifier class provides a class-method Notifier.def_notifier to
# create a new composite notifier. Using the first composite notifier
# object you create, sibling notifiers can be initialized with
# #def_notifier.
class CompositeNotifier<AbstractNotifier
# Create a new composite notifier object with the given +prefix+, and
# +base_notifier+ to use for output.
def initialize(prefix, base_notifier)
super
@notifiers = [D_NOMSG]
@level_notifier = D_NOMSG
end
# List of notifiers in the group
attr_reader :notifiers
# Creates a new LeveledNotifier in the composite #notifiers group.
#
# The given +prefix+ will be assigned to the notifier, and +level+ will
# be used as the index of the #notifiers Array.
#
# This method returns the newly created instance.
def def_notifier(level, prefix = "")
notifier = LeveledNotifier.new(self, level, prefix)
@notifiers[level] = notifier
notifier
end
# Returns the leveled notifier for this object
attr_reader :level_notifier
alias level level_notifier
# Sets the leveled notifier for this object.
#
# When the given +value+ is an instance of AbstractNotifier,
# #level_notifier is set to the given object.
#
# When an Integer is given, #level_notifier is set to the notifier at the
# index +value+ in the #notifiers Array.
#
# If no notifier exists at the index +value+ in the #notifiers Array, an
# ErrUndefinedNotifier exception is raised.
#
# An ErrUnrecognizedLevel exception is raised if the given +value+ is not
# found in the existing #notifiers Array, or an instance of
# AbstractNotifier
def level_notifier=(value)
case value
when AbstractNotifier
@level_notifier = value
when Integer
l = @notifiers[value]
Notifier.Raise ErrUndefinedNotifier, value unless l
@level_notifier = l
else
Notifier.Raise ErrUnrecognizedLevel, value unless l
end
end
alias level= level_notifier=
end
# A leveled notifier is comparable to the composite group from
# CompositeNotifier#notifiers.
class LeveledNotifier<AbstractNotifier
include Comparable
# Create a new leveled notifier with the given +base+, and +prefix+ to
# send to AbstractNotifier.new
#
# The given +level+ is used to compare other leveled notifiers in the
# CompositeNotifier group to determine whether or not to output
# notifications.
def initialize(base, level, prefix)
super(prefix, base)
@level = level
end
# The current level of this notifier object
attr_reader :level
# Compares the level of this notifier object with the given +other+
# notifier.
#
# See the Comparable module for more information.
def <=>(other)
@level <=> other.level
end
# Whether to output messages to the output method, depending on the level
# of this notifier object.
def notify?
@base_notifier.level >= self
end
end
# NoMsgNotifier is a LeveledNotifier that's used as the default notifier
# when creating a new CompositeNotifier.
#
# This notifier is used as the +zero+ index, or level +0+, for
# CompositeNotifier#notifiers, and will not output messages of any sort.
class NoMsgNotifier<LeveledNotifier
# Creates a new notifier that should not be used to output messages.
def initialize
@base_notifier = nil
@level = 0
@prefix = ""
end
# Ensures notifications are ignored, see AbstractNotifier#notify? for
# more information.
def notify?
false
end
end
D_NOMSG = NoMsgNotifier.new # :nodoc:
end
end
|