Class: Chef::Formatters::NyanCat

Inherits:
Formatters::Minimal
  • Object
show all
Defined in:
lib/nyan-cat-chef-formatter.rb

Constant Summary collapse

ESC =
"\e["
NND =
"#{ESC}0m"
PASS =
'='
PASS_ARY =
['-', '_']
FAIL =
'*'
ERROR =
'!'
UPDATED =
'+'

Instance Method Summary collapse

Constructor Details

#initialize(out, err) ⇒ NyanCat

attr_reader :current, :example_results, :color_index, :pending_count,

:failure_count, :example_count


20
21
22
23
24
# File 'lib/nyan-cat-chef-formatter.rb', line 20

def initialize(out, err)
  super

  @started = @finished = false
end

Instance Method Details

#ascii_cat(o = '^') ⇒ Array

Ascii version of Nyan cat. Two cats in the array allow Nyan to animate running.

Parameters:

  • o (String) (defaults to: '^')

    Nyan’s eye

Returns:

  • (Array)

    Nyan cats



170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/nyan-cat-chef-formatter.rb', line 170

def ascii_cat(o = '^')
  [[ "_,------,   ",
      "_|  /\\_/\\ ",
      "~|_( #{o} .#{o})  ",
      " \"\"  \"\" "
    ],
    [ "_,------,   ",
      "_|   /\\_/\\",
      "^|__( #{o} .#{o}) ",
      "  \"\"  \"\"    "
    ]]
end

#blue(text) ⇒ Object



245
# File 'lib/nyan-cat-chef-formatter.rb', line 245

def blue(text); "\e[34m#{text}\e[0m"; end

#colorsArray

Calculates the colors of the rainbow

Returns:

  • (Array)


196
197
198
199
200
201
202
203
204
205
# File 'lib/nyan-cat-chef-formatter.rb', line 196

def colors
  @colors ||= (0...(6 * 7)).map do |n|
    pi_3 = Math::PI / 3
    n *= 1.0 / 6
    r  = (3 * Math.sin(n           ) + 3).to_i
    g  = (3 * Math.sin(n + 2 * pi_3) + 3).to_i
    b  = (3 * Math.sin(n + 4 * pi_3) + 3).to_i
    36 * r + 6 * g + b + 16
  end
end

#converge_completeObject



41
42
43
44
45
# File 'lib/nyan-cat-chef-formatter.rb', line 41

def converge_complete
  @finished = true
  dump_progress
  super
end

#converge_start(run_context) ⇒ Object

Called before convergence starts



35
36
37
38
39
# File 'lib/nyan-cat-chef-formatter.rb', line 35

def converge_start(run_context)
  @total_count = run_context.resource_collection.all_resources.size # + 150
  @started = true
  puts "Converging #{run_context.resource_collection.all_resources.size} resources"
end

#current_widthFixnum

Calculates the current flight length

Returns:

  • (Fixnum)


125
126
127
128
129
# File 'lib/nyan-cat-chef-formatter.rb', line 125

def current_width
  padding    = @total_count.to_s.length * 2 + 6
  cat_length = nyan_cat.split("\n").group_by(&:size).max.first
  padding    + (@current >= @total_count ? @total_count : @current) + cat_length
end

#dump_progressObject

Displays the current progress in all Nyan Cat glory

Returns:

  • nothing



104
105
106
107
108
109
110
111
# File 'lib/nyan-cat-chef-formatter.rb', line 104

def dump_progress
  padding = @total_count.to_s.length * 2 + 2
  line = nyan_trail.split("\n").each_with_index.inject([]) do |result, (trail, index)|
    value = "#{scoreboard[index]}/#{@total_count}:"
    result << format("%s %s", value, trail)
  end.join("\n")
  output.print line + eol
end

#eolString

Determines how we end the trail line. If complete, return a newline etc.

Returns:

  • (String)


116
117
118
119
120
# File 'lib/nyan-cat-chef-formatter.rb', line 116

def eol
  return "\n" if @finished
  length = (nyan_cat.split("\n").length - 1)
  length > 0 ? format("\e[1A" * length + "\r") : "\r"
end

#failed?Boolean

Returns:

  • (Boolean)


238
239
240
# File 'lib/nyan-cat-chef-formatter.rb', line 238

def failed?
  @failure_count.to_i > 0
end

#finished?Boolean

Returns:

  • (Boolean)


234
235
236
# File 'lib/nyan-cat-chef-formatter.rb', line 234

def finished?
  @finished
end

#format_duration(duration) ⇒ String

Converts a float of seconds into a minutes/seconds string

Returns:

  • (String)


224
225
226
227
228
229
230
231
232
# File 'lib/nyan-cat-chef-formatter.rb', line 224

def format_duration(duration)
  seconds = ((duration % 60) * 100.0).round / 100.0   # 1.8.7 safe .round(2)
  seconds = seconds.to_i if seconds.to_i == seconds   # drop that zero if it's not needed

  message = "#{seconds} second#{seconds == 1 ? "" : "s"}"
  message = "#{(duration / 60).to_i} minute#{(duration / 60).to_i == 1 ? "" : "s"} and " + message if duration >= 60

  message
end

#green(text) ⇒ Object



242
# File 'lib/nyan-cat-chef-formatter.rb', line 242

def green(text); "\e[32m#{text}\e[0m"; end

#highlight(mark = PASS) ⇒ String

Determines how to color the example. If pass, it is rainbowified, otherwise we assign red if failed or yellow if an error occurred.

Returns:

  • (String)


211
212
213
214
215
216
217
218
219
# File 'lib/nyan-cat-chef-formatter.rb', line 211

def highlight(mark = PASS)
  case mark
  when PASS; rainbowify PASS_ARY[@color_index%2]
  when FAIL; "\e[31m#{mark}\e[0m"
  when ERROR; "\e[33m#{mark}\e[0m"
  when UPDATED; "\e[34m#{mark}\e[0m"
  else mark
  end
end

#nyan_catString

Determine which Ascii Nyan Cat to display. If tests are complete, Nyan Cat goes to sleep. If there are failing or pending examples, Nyan Cat is concerned.

Returns:

  • (String)

    Nyan Cat



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/nyan-cat-chef-formatter.rb', line 89

def nyan_cat
  if self.failed? && self.finished?
    ascii_cat('x')[@color_index%2].join("\n") #'~|_(x.x)'
  elsif self.failed?
    ascii_cat('o')[@color_index%2].join("\n") #'~|_(o.o)'
  elsif self.finished?
    ascii_cat('-')[@color_index%2].join("\n") # '~|_(-.-)'
  else
    ascii_cat('^')[@color_index%2].join("\n") # '~|_(^.^)'
  end
end

#nyan_trailString

Creates a rainbow trail

Returns:

  • (String)

    the sprintf format of the Nyan cat



158
159
160
161
162
163
164
# File 'lib/nyan-cat-chef-formatter.rb', line 158

def nyan_trail
  marks = @ticks.map{ |mark| highlight(mark) }
  marks.shift(current_width - terminal_width) if current_width >= terminal_width
  nyan_cat_lines = nyan_cat.split("\n").each_with_index.map do |line, index|
    format("%s#{line}", marks.join)
  end.join("\n")
end

#rainbowify(string) ⇒ String

Colorizes the string with raindow colors of the rainbow

Returns:

  • (String)


187
188
189
190
191
# File 'lib/nyan-cat-chef-formatter.rb', line 187

def rainbowify(string)
  c = colors[@color_index % colors.size]
  @color_index += 1
  "#{ESC}38;5;#{c}m#{string}#{NND}"
end

#red(text) ⇒ Object



243
# File 'lib/nyan-cat-chef-formatter.rb', line 243

def red(text); "\e[31m#{text}\e[0m"; end

#resource_failed(resource, action, exception) ⇒ Object



53
54
55
56
57
# File 'lib/nyan-cat-chef-formatter.rb', line 53

def resource_failed(resource, action, exception)
  return unless @started
  @failure_count += 1
  tick FAIL
end

#resource_failed_retriable(resource, action, retry_count, exception) ⇒ Object



47
48
49
50
51
# File 'lib/nyan-cat-chef-formatter.rb', line 47

def resource_failed_retriable(resource, action, retry_count, exception)
  return unless @started
  @failure_count += 1
  tick FAIL
end

#resource_skipped(resource, action, conditional) ⇒ Object



59
60
61
62
# File 'lib/nyan-cat-chef-formatter.rb', line 59

def resource_skipped(resource, action, conditional)
  return unless @started
  tick PASS
end

#resource_up_to_date(resource, action) ⇒ Object



64
65
66
67
# File 'lib/nyan-cat-chef-formatter.rb', line 64

def resource_up_to_date(resource, action)
  return unless @started
  tick PASS
end

#resource_updated(resource, action) ⇒ Object

Called after a resource has been completely converged.



70
71
72
73
74
75
# File 'lib/nyan-cat-chef-formatter.rb', line 70

def resource_updated(resource, action)
  updated_resources << resource
  return unless @started
  @updated_count += 1
  tick UPDATED
end

#run_start(version) ⇒ Object



26
27
28
29
30
31
32
# File 'lib/nyan-cat-chef-formatter.rb', line 26

def run_start(version)
  super

  @total_count = 0
  @current = @color_index = @failure_count = @updated_count = 0
  @ticks = []
end

#scoreboardArray

Creates a data store of pass, failed, and pending example results We have to pad the results here because sprintf can’t properly pad color

Returns:

  • (Array)


147
148
149
150
151
152
153
# File 'lib/nyan-cat-chef-formatter.rb', line 147

def scoreboard
  padding = @total_count.to_s.length
  [ @current.to_s.rjust(padding),
    green((@current - @updated_count - @failure_count).to_s.rjust(padding)),
    blue(@updated_count.to_s.rjust(padding)),
    red(@failure_count.to_s.rjust(padding)) ]
end

#terminal_widthFixnum

A Unix trick using stty to get the console columns

Returns:

  • (Fixnum)


134
135
136
137
138
139
140
141
# File 'lib/nyan-cat-chef-formatter.rb', line 134

def terminal_width
  if defined? JRUBY_VERSION
    default_width = 80
  else
    default_width = `stty size`.split.map { |x| x.to_i }.reverse.first - 1
  end
  @terminal_width ||= default_width
end

#tick(mark = PASS) ⇒ Object



77
78
79
80
81
82
# File 'lib/nyan-cat-chef-formatter.rb', line 77

def tick(mark = PASS)
  @ticks << mark
  @current += 1
  @total_count = @current if @current > @total_count
  dump_progress
end

#yellow(text) ⇒ Object



244
# File 'lib/nyan-cat-chef-formatter.rb', line 244

def yellow(text); "\e[33m#{text}\e[0m"; end