Class: Megatest::PrettyPrint::Printer
- Inherits:
-
PrettyPrint
- Object
- PrettyPrint
- Megatest::PrettyPrint::Printer
- Defined in:
- lib/megatest/pretty_print.rb
Overview
This class is largely a copy of the ‘pp` gem but rewritten to not rely on monkey patches and with some small rendering modifications notably around multiline strings.
Constant Summary collapse
- INSTANCE_VARIABLES =
Object.instance_method(:instance_variables)
- CLASS =
Kernel.instance_method(:class)
- METHOD =
Object.instance_method(:method)
- OBJECT_INSPECT =
Object.instance_method(:inspect)
Class Method Summary collapse
Instance Method Summary collapse
-
#check_inspect_key?(id) ⇒ Boolean
Check whether the object_id
idis in the current buffer of objects to be pretty printed. -
#comma_breakable ⇒ Object
A convenience method which is same as follows:.
-
#guard_inspect_key ⇒ Object
Yields to a block and preserves the previous set of objects being printed.
- #inspect_object(obj) ⇒ Object
-
#object_address_group(obj, &block) ⇒ Object
A convenience method, like object_group, but also reformats the Object’s object_id.
-
#object_group(obj, &block) ⇒ Object
A convenience method which is same as follows:.
-
#pop_inspect_key(id) ⇒ Object
Removes an object from the set of objects being pretty printed.
-
#pp(obj) ⇒ Object
Adds
objto the pretty printing buffer using Object#pretty_print or Object#pretty_print_cycle. -
#pp_hash(obj) ⇒ Object
A pretty print for a Hash.
-
#pp_object(obj) ⇒ Object
A present standard failsafe for pretty printing any given Object.
- #pretty_print(obj) ⇒ Object
- #pretty_print_cycle(obj) ⇒ Object
- #pretty_print_instance_variables(obj) ⇒ Object
-
#push_inspect_key(id) ⇒ Object
Adds the object_id
idto the set of objects being pretty printed, so as to not repeat objects. -
#seplist(list, sep = nil, iter_method = :each) ⇒ Object
Adds a separated list.
- #special_inspect?(obj) ⇒ Boolean
Class Method Details
.pp(obj, out = +"",, width = 79) ⇒ Object
15 16 17 18 19 20 |
# File 'lib/megatest/pretty_print.rb', line 15 def pp(obj, out = +"", width = 79) q = new(out, width) q.guard_inspect_key { q.pp obj } q.flush out end |
Instance Method Details
#check_inspect_key?(id) ⇒ Boolean
Check whether the object_id id is in the current buffer of objects to be pretty printed. Used to break cycles in chains of objects to be pretty printed.
41 42 43 |
# File 'lib/megatest/pretty_print.rb', line 41 def check_inspect_key?(id) @recursive_key&.include?(id) end |
#comma_breakable ⇒ Object
A convenience method which is same as follows:
text ','
breakable
100 101 102 103 |
# File 'lib/megatest/pretty_print.rb', line 100 def comma_breakable text "," breakable end |
#guard_inspect_key ⇒ Object
Yields to a block and preserves the previous set of objects being printed.
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/megatest/pretty_print.rb', line 25 def guard_inspect_key @recursive_key = {}.compare_by_identity save = @recursive_key begin @recursive_key = {}.compare_by_identity yield ensure @recursive_key = save end end |
#inspect_object(obj) ⇒ Object
278 279 280 281 282 |
# File 'lib/megatest/pretty_print.rb', line 278 def inspect_object(obj) obj.inspect rescue NoMethodError # Basic Object etc. OBJECT_INSPECT.bind_call(obj) end |
#object_address_group(obj, &block) ⇒ Object
A convenience method, like object_group, but also reformats the Object’s object_id.
90 91 92 93 94 |
# File 'lib/megatest/pretty_print.rb', line 90 def object_address_group(obj, &block) str = Kernel.instance_method(:to_s).bind_call(obj) str.chomp!(">") group(1, str, ">", &block) end |
#object_group(obj, &block) ⇒ Object
A convenience method which is same as follows:
group(1, '#<' + obj.class.name, '>') { ... }
82 83 84 |
# File 'lib/megatest/pretty_print.rb', line 82 def object_group(obj, &block) group(1, "#<#{obj.class.name}>", &block) end |
#pop_inspect_key(id) ⇒ Object
Removes an object from the set of objects being pretty printed.
52 53 54 |
# File 'lib/megatest/pretty_print.rb', line 52 def pop_inspect_key(id) @recursive_key.delete id end |
#pp(obj) ⇒ Object
Adds obj to the pretty printing buffer using Object#pretty_print or Object#pretty_print_cycle.
Object#pretty_print_cycle is used when obj is already printed, a.k.a the object reference chain has a cycle.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/megatest/pretty_print.rb', line 61 def pp(obj) # If obj is a Delegator then use the object being delegated to for cycle # detection obj = obj.__getobj__ if defined?(::Delegator) && ::Delegator === obj if check_inspect_key?(obj) group { pretty_print_cycle(obj) } return end begin push_inspect_key(obj) group { pretty_print(obj) } ensure pop_inspect_key(obj) end end |
#pp_hash(obj) ⇒ Object
A pretty print for a Hash
164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/megatest/pretty_print.rb', line 164 def pp_hash(obj) group(1, "{", "}") do seplist(obj, nil, :each_pair) do |k, v| group do pp k text "=>" group(1) do breakable "" pp v end end end end end |
#pp_object(obj) ⇒ Object
A present standard failsafe for pretty printing any given Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/megatest/pretty_print.rb', line 143 def pp_object(obj) object_address_group(obj) do seplist(pretty_print_instance_variables(obj), -> { text "," }) do |v| breakable v = v.to_s if Symbol === v text v text "=" group(1) do breakable "" pp(obj.instance_eval(v)) end end end end |
#pretty_print(obj) ⇒ Object
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 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/megatest/pretty_print.rb', line 183 def pretty_print(obj) case obj when String if obj.size > 30 && obj.byterindex("\n", -1) text obj.inspect.gsub('\n', "\\n\n").sub(/\\n\n"\z/, '\n"') else text obj.inspect end when Array group(1, "[", "]") do seplist(obj) do |v| pp v end end when Hash pp_hash(obj) when Range pp obj.begin breakable "" text(obj.exclude_end? ? "..." : "..") breakable "" pp obj.end if obj.end when MatchData nc = [] obj.regexp.named_captures.each do |name, indexes| indexes.each { |i| nc[i] = name } end object_group(obj) do breakable seplist(0...obj.size, -> { breakable }) do |i| if i != 0 if nc[i] text nc[i] else pp i end text ":" pp obj[i] end pp obj[i] end end when Regexp, Symbol, Numeric, Module, true, false, nil text(obj.inspect) when Struct group(1, format("#<struct %s", CLASS.bind_call(obj)), ">") do seplist(Struct.instance_method(:members).bind_call(obj), -> { text "," }) do |member| breakable text member.to_s text "=" group(1) do breakable "" pp obj[member] end end end else if ENV.equal?(obj) pp_hash(ENV.sort.to_h) elsif special_inspect?(obj) text(obj.inspect) else pp_object(obj) end end end |
#pretty_print_cycle(obj) ⇒ Object
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/megatest/pretty_print.rb', line 251 def pretty_print_cycle(obj) case obj when Array text(obj.empty? ? "[]" : "[...]") when Hash text(obj.empty? ? "{}" : "{...}") when Struct text format("#<struct %s:...>", CLASS.bind_call(obj)) when Numeric, Symbol, FalseClass, TrueClass, NilClass, Module text obj.inspect else object_address_group(obj) do breakable text "..." end end end |
#pretty_print_instance_variables(obj) ⇒ Object
159 160 161 |
# File 'lib/megatest/pretty_print.rb', line 159 def pretty_print_instance_variables(obj) INSTANCE_VARIABLES.bind_call(obj).sort end |
#push_inspect_key(id) ⇒ Object
Adds the object_id id to the set of objects being pretty printed, so as to not repeat objects.
47 48 49 |
# File 'lib/megatest/pretty_print.rb', line 47 def push_inspect_key(id) @recursive_key[id] = true end |
#seplist(list, sep = nil, iter_method = :each) ⇒ Object
Adds a separated list. The list is separated by comma with breakable space, by default.
#seplist iterates the list using iter_method. It yields each object to the block given for #seplist. The procedure separator_proc is called between each yields.
If the iteration is zero times, separator_proc is not called at all.
If separator_proc is nil or not given, lambda { comma_breakable } is used. If iter_method is not given, :each is used.
For example, following 3 code fragments has similar effect.
q.seplist([1,2,3]) {|v| xxx v }
q.seplist([1,2,3], lambda { q.comma_breakable }, :each) {|v| xxx v }
xxx 1
q.comma_breakable
xxx 2
q.comma_breakable
xxx 3
129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/megatest/pretty_print.rb', line 129 def seplist(list, sep = nil, iter_method = :each) sep ||= -> { comma_breakable } first = true list.__send__(iter_method) do |*v| if first first = false else sep.call end yield(*v) end end |
#special_inspect?(obj) ⇒ Boolean
270 271 272 273 274 |
# File 'lib/megatest/pretty_print.rb', line 270 def special_inspect?(obj) METHOD.bind_call(obj, :inspect).owner != Kernel rescue NoMethodError false end |