awesome_print 1.6.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,138 @@
1
+ require_relative "../colorize"
2
+
3
+ module AwesomePrint
4
+ module Formatters
5
+ class BaseFormatter
6
+ include Colorize
7
+
8
+ DEFAULT_LIMIT_SIZE = 7
9
+
10
+ # To support limited output, for example:
11
+ #
12
+ # ap ('a'..'z').to_a, :limit => 3
13
+ # [
14
+ # [ 0] "a",
15
+ # [ 1] .. [24],
16
+ # [25] "z"
17
+ # ]
18
+ #
19
+ # ap (1..100).to_a, :limit => true # Default limit is 7.
20
+ # [
21
+ # [ 0] 1,
22
+ # [ 1] 2,
23
+ # [ 2] 3,
24
+ # [ 3] .. [96],
25
+ # [97] 98,
26
+ # [98] 99,
27
+ # [99] 100
28
+ # ]
29
+ #------------------------------------------------------------------------------
30
+ def should_be_limited?
31
+ options[:limit] or (options[:limit].is_a?(Fixnum) and options[:limit] > 0)
32
+ end
33
+
34
+ def get_limit_size
35
+ case options[:limit]
36
+ when true
37
+ DEFAULT_LIMIT_SIZE
38
+ else
39
+ options[:limit]
40
+ end
41
+ end
42
+
43
+ def limited(data, width, is_hash = false)
44
+ limit = get_limit_size
45
+ if data.length <= limit
46
+ data
47
+ else
48
+ # Calculate how many elements to be displayed above and below the separator.
49
+ head = limit / 2
50
+ tail = head - (limit - 1) % 2
51
+
52
+ # Add the proper elements to the temp array and format the separator.
53
+ temp = data[0, head] + [ nil ] + data[-tail, tail]
54
+
55
+ if is_hash
56
+ temp[head] = "#{indent}#{data[head].strip} .. #{data[data.length - tail - 1].strip}"
57
+ else
58
+ temp[head] = "#{indent}[#{head.to_s.rjust(width)}] .. [#{data.length - tail - 1}]"
59
+ end
60
+
61
+ temp
62
+ end
63
+ end
64
+
65
+
66
+ def method_tuple(method)
67
+ if method.respond_to?(:parameters) # Ruby 1.9.2+
68
+ # See http://ruby.runpaint.org/methods#method-objects-parameters
69
+ args = method.parameters.inject([]) do |arr, (type, name)|
70
+ name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
71
+ arr << case type
72
+ when :req then name.to_s
73
+ when :opt, :rest then "*#{name}"
74
+ when :block then "&#{name}"
75
+ else '?'
76
+ end
77
+ end
78
+ else # See http://ruby-doc.org/core/classes/Method.html#M001902
79
+ args = (1..method.arity.abs).map { |i| "arg#{i}" }
80
+ args[-1] = "*#{args[-1]}" if method.arity < 0
81
+ end
82
+
83
+ # method.to_s formats to handle:
84
+ #
85
+ # #<Method: Fixnum#zero?>
86
+ # #<Method: Fixnum(Integer)#years>
87
+ # #<Method: User(#<Module:0x00000103207c00>)#_username>
88
+ # #<Method: User(id: integer, username: string).table_name>
89
+ # #<Method: User(id: integer, username: string)(ActiveRecord::Base).current>
90
+ # #<UnboundMethod: Hello#world>
91
+ #
92
+ if method.to_s =~ /(Unbound)*Method: (.*)[#\.]/
93
+ unbound, klass = $1 && '(unbound)', $2
94
+ if klass && klass =~ /(\(\w+:\s.*?\))/ # Is this ActiveRecord-style class?
95
+ klass.sub!($1, '') # Yes, strip the fields leaving class name only.
96
+ end
97
+ owner = "#{klass}#{unbound}".gsub('(', ' (')
98
+ end
99
+
100
+ [ method.name.to_s, "(#{args.join(', ')})", owner.to_s ]
101
+ end
102
+
103
+ #
104
+ # Indentation related methods
105
+ #-----------------------------------------
106
+ def indentation
107
+ inspector.current_indentation
108
+ end
109
+
110
+ def indented
111
+ inspector.increase_indentation(&Proc.new)
112
+ end
113
+
114
+ def indent
115
+ ' ' * indentation
116
+ end
117
+
118
+ def outdent
119
+ ' ' * (indentation - options[:indent].abs)
120
+ end
121
+
122
+ def align(value, width)
123
+ if options[:multiline]
124
+ if options[:indent] > 0
125
+ value.rjust(width)
126
+ elsif options[:indent] == 0
127
+ indent + value.ljust(width)
128
+ else
129
+ indent[0, indentation + options[:indent]] + value.ljust(width)
130
+ end
131
+ else
132
+ value
133
+ end
134
+ end
135
+
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'base_formatter'
2
+
3
+ module AwesomePrint
4
+ module Formatters
5
+ class ClassFormatter < BaseFormatter
6
+
7
+ attr_reader :klass, :inspector, :options
8
+
9
+ def initialize(klass, inspector)
10
+ @klass = klass
11
+ @inspector = inspector
12
+ @options = inspector.options
13
+ end
14
+
15
+ def format
16
+ if superclass = klass.superclass # <-- Assign and test if nil.
17
+ colorize("#{klass.inspect} < #{superclass}", :class)
18
+ else
19
+ colorize(klass.inspect, :class)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'base_formatter'
2
+ require "shellwords"
3
+
4
+ module AwesomePrint
5
+ module Formatters
6
+ class DirFormatter < BaseFormatter
7
+
8
+ attr_reader :dir, :inspector, :options
9
+
10
+ def initialize(dir, inspector)
11
+ @dir = dir
12
+ @inspector = inspector
13
+ @options = inspector.options
14
+ end
15
+
16
+ def format
17
+ ls = `ls -alF #{dir.path.shellescape}`
18
+ colorize(ls.empty? ? dir.inspect : "#{dir.inspect}\n#{ls.chop}", :dir)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'base_formatter'
2
+ require "shellwords"
3
+
4
+ module AwesomePrint
5
+ module Formatters
6
+ class FileFormatter < BaseFormatter
7
+
8
+ attr_reader :file, :inspector, :options
9
+
10
+ def initialize(file, inspector)
11
+ @file = file
12
+ @inspector = inspector
13
+ @options = inspector.options
14
+ end
15
+
16
+ def format
17
+ ls = File.directory?(file) ? `ls -adlF #{file.path.shellescape}` : `ls -alF #{file.path.shellescape}`
18
+ colorize(ls.empty? ? file.inspect : "#{file.inspect}\n#{ls.chop}", :file)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'base_formatter'
2
+
3
+ module AwesomePrint
4
+ module Formatters
5
+ class HashFormatter < BaseFormatter
6
+
7
+ attr_reader :hash, :inspector, :options
8
+
9
+ def initialize(hash, inspector)
10
+ @hash = hash
11
+ @inspector = inspector
12
+ @options = inspector.options
13
+ end
14
+
15
+ def format
16
+ return "{}" if hash == {}
17
+
18
+ keys = hash.keys
19
+ keys = keys.sort { |a, b| a.to_s <=> b.to_s } if options[:sort_keys]
20
+ data = keys.map do |key|
21
+ plain_single_line do
22
+ [ inspector.awesome(key), hash[key] ]
23
+ end
24
+ end
25
+
26
+ width = data.map { |key, | key.size }.max || 0
27
+ width += indentation if options[:indent] > 0
28
+
29
+ data = data.map do |key, value|
30
+ indented do
31
+ align(key, width) << colorize(" => ", :hash) << inspector.awesome(value)
32
+ end
33
+ end
34
+
35
+ data = limited(data, width, :hash => true) if should_be_limited?
36
+ if options[:multiline]
37
+ "{\n" << data.join(",\n") << "\n#{outdent}}"
38
+ else
39
+ "{ #{data.join(', ')} }"
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def plain_single_line
46
+ plain, multiline = options[:plain], options[:multiline]
47
+ options[:plain], options[:multiline] = true, false
48
+ yield
49
+ ensure
50
+ options[:plain], options[:multiline] = plain, multiline
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'base_formatter'
2
+
3
+ module AwesomePrint
4
+ module Formatters
5
+ class MethodFormatter < BaseFormatter
6
+
7
+ attr_reader :method, :inspector, :options
8
+
9
+ def initialize(method, inspector)
10
+ @method = method
11
+ @inspector = inspector
12
+ @options = inspector.options
13
+ end
14
+
15
+ def format
16
+ name, args, owner = method_tuple(method)
17
+
18
+ "#{colorize(owner, :class)}##{colorize(name, :method)}#{colorize(args, :args)}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,80 @@
1
+ require_relative 'base_formatter'
2
+
3
+ module AwesomePrint
4
+ module Formatters
5
+ class ObjectFormatter < BaseFormatter
6
+
7
+ attr_reader :object, :variables, :inspector, :options
8
+
9
+ def initialize(object, variables, inspector)
10
+ @object = object
11
+ @variables = variables
12
+ @inspector = inspector
13
+ @options = inspector.options
14
+ end
15
+
16
+ def format
17
+ vars = variables.map do |var|
18
+ property = var.to_s[1..-1].to_sym # to_s because of some monkey patching done by Puppet.
19
+ accessor = if object.respond_to?(:"#{property}=")
20
+ object.respond_to?(property) ? :accessor : :writer
21
+ else
22
+ object.respond_to?(property) ? :reader : nil
23
+ end
24
+ if accessor
25
+ [ "attr_#{accessor} :#{property}", var ]
26
+ else
27
+ [ var.to_s, var ]
28
+ end
29
+ end
30
+
31
+ data = vars.sort.map do |declaration, var|
32
+ key = left_aligned do
33
+ align(declaration, declaration.size)
34
+ end
35
+
36
+ unless options[:plain]
37
+ if key =~ /(@\w+)/
38
+ key.sub!($1, colorize($1, :variable))
39
+ else
40
+ key.sub!(/(attr_\w+)\s(\:\w+)/, "#{colorize('\\1', :keyword)} #{colorize('\\2', :method)}")
41
+ end
42
+ end
43
+
44
+ indented do
45
+ var_contents = if valid_instance_var?(var)
46
+ object.instance_variable_get(var)
47
+ else
48
+ object.send(var) # Enables handling of Struct attributes
49
+ end
50
+
51
+ key << colorize(" = ", :hash) + inspector.awesome(var_contents)
52
+ end
53
+ end
54
+
55
+ if options[:multiline]
56
+ "#<#{awesome_instance}\n#{data.join(%Q/,\n/)}\n#{outdent}>"
57
+ else
58
+ "#<#{awesome_instance} #{data.join(', ')}>"
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def valid_instance_var?(variable_name)
65
+ variable_name.to_s.start_with?('@')
66
+ end
67
+
68
+ def awesome_instance
69
+ "#{object.class}:0x%08x" % (object.__id__ * 2)
70
+ end
71
+
72
+ def left_aligned
73
+ current, options[:indent] = options[:indent], 0
74
+ yield
75
+ ensure
76
+ options[:indent] = current
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'base_formatter'
2
+
3
+ module AwesomePrint
4
+ module Formatters
5
+ class SimpleFormatter < BaseFormatter
6
+
7
+ attr_reader :string, :type, :inspector, :options
8
+
9
+ def initialize(string, type, inspector)
10
+ @string = string
11
+ @type = type
12
+ @inspector = inspector
13
+ @options = inspector.options
14
+ end
15
+
16
+ def format
17
+ colorize(string, type)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ module AwesomePrint
2
+ class Indentator
3
+
4
+ attr_reader :shift_width, :indentation
5
+
6
+ def initialize(indentation)
7
+ @indentation = indentation
8
+ @shift_width = indentation.freeze
9
+ end
10
+
11
+ def indent
12
+ @indentation += shift_width
13
+ yield
14
+ ensure
15
+ @indentation -= shift_width
16
+ end
17
+ end
18
+ end
@@ -3,6 +3,8 @@
3
3
  # Awesome Print is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
5
  #------------------------------------------------------------------------------
6
+ require_relative "indentator"
7
+
6
8
  module AwesomePrint
7
9
 
8
10
  class << self # Class accessors for custom defaults.
@@ -48,7 +50,7 @@ module AwesomePrint
48
50
  end
49
51
 
50
52
  class Inspector
51
- attr_accessor :options
53
+ attr_accessor :options, :indentator
52
54
 
53
55
  AP = :__awesome_print__
54
56
 
@@ -90,8 +92,17 @@ module AwesomePrint
90
92
  merge_options!(options)
91
93
 
92
94
  @formatter = AwesomePrint::Formatter.new(self)
95
+ @indentator = AwesomePrint::Indentator.new(@options[:indent].abs)
93
96
  Thread.current[AP] ||= []
94
97
  end
98
+
99
+ def current_indentation
100
+ indentator.indentation
101
+ end
102
+
103
+ def increase_indentation
104
+ indentator.indent(&Proc.new)
105
+ end
95
106
 
96
107
  # Dispatcher that detects data nesting and invokes object-aware formatter.
97
108
  #------------------------------------------------------------------------------