Class: ArduinoCI::Logger

Inherits:
Object
  • Object
show all
Defined in:
lib/arduino_ci/logger.rb

Overview

Provide all text processing functions to aid readability of the test log

Constant Summary collapse

TAB_WIDTH =
4
INDENT_CHAR =
" ".freeze
FAILED_ASSURANCE_MESSAGE =
"This may indicate a problem with your configuration; halting here".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width = nil) ⇒ Logger

Returns a new instance of Logger.

Parameters:

  • width (int) (defaults to: nil)

    The desired console width



18
19
20
21
22
23
# File 'lib/arduino_ci/logger.rb', line 18

def initialize(width = nil)
  @tab           = 0
  @width         = width.nil? ? 80 : width
  @failure_count = 0
  @passfail      = proc { |result| result ? "" : "" }
end

Instance Attribute Details

#failure_countInteger (readonly)

Returns The number of failures reported through the logging mechanism.

Returns:

  • (Integer)

    The number of failures reported through the logging mechanism



15
16
17
# File 'lib/arduino_ci/logger.rb', line 15

def failure_count
  @failure_count
end

#tabInteger (readonly)

Returns the cardinal number of indents.

Returns:

  • (Integer)

    the cardinal number of indents



12
13
14
# File 'lib/arduino_ci/logger.rb', line 12

def tab
  @tab
end

Class Method Details

.auto_widthObject

create a logger that’s automatically sized to the console, between 80 and 132 characters



26
27
28
29
30
31
32
33
34
# File 'lib/arduino_ci/logger.rb', line 26

def self.auto_width
  width = begin
    [132, [80, IO::console.winsize[1] - 2].max].min
  rescue NoMethodError
    80
  end

  self.new(width)
end

Instance Method Details

#assure(message) { ... } ⇒ Object

Make a nice status (with checkmark) for something that kills the script immediately on failure

Parameters:

  • message

    the message to print

Yields:

  • The action being performed

Yield Returns:

  • (boolean)

    whether the action was successful

Returns:

  • (Object)

    The return value of the block



169
170
171
# File 'lib/arduino_ci/logger.rb', line 169

def assure(message, &block)
  perform_action(message, false, @passfail, FAILED_ASSURANCE_MESSAGE, true, true, &block)
end

#assure_multiline(message) { ... } ⇒ Object

Make a nice multiline status (with checkmark) for something that kills the script immediately on failure

Parameters:

  • message

    the message to print

Yields:

  • The action being performed

Yield Returns:

  • (boolean)

    whether the action was successful

Returns:

  • (Object)

    The return value of the block



179
180
181
# File 'lib/arduino_ci/logger.rb', line 179

def assure_multiline(message, &block)
  perform_action(message, true, @passfail, FAILED_ASSURANCE_MESSAGE, true, true, &block)
end

#attempt(message) { ... } ⇒ Object

Make a nice status (with checkmark) for something that defers any failure code until script exit

Parameters:

  • message

    the message to print

Yields:

  • The action being performed

Yield Returns:

  • (boolean)

    whether the action was successful

Returns:

  • (Object)

    The return value of the block



148
149
150
# File 'lib/arduino_ci/logger.rb', line 148

def attempt(message, &block)
  perform_action(message, false, @passfail, nil, true, false, &block)
end

#attempt_multiline(message) { ... } ⇒ Object

Make a nice multiline status (with checkmark) for something that defers any failure code until script exit

Parameters:

  • message

    the message to print

Yields:

  • The action being performed

Yield Returns:

  • (boolean)

    whether the action was successful

Returns:

  • (Object)

    The return value of the block



158
159
160
# File 'lib/arduino_ci/logger.rb', line 158

def attempt_multiline(message, &block)
  perform_action(message, true, @passfail, nil, true, false, &block)
end

print a nice banner for this project



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/arduino_ci/logger.rb', line 37

def banner
  art = [
    "         .                  __  ___",
    " _, ,_  _| , . * ._   _    /  `  | ",
    "(_| [ `(_] (_| | [ ) (_)   \\__. _|_   v#{ArduinoCI::VERSION}",
  ]

  pad = " " * ((@width - art[2].length) / 2)
  art.each { |l| puts "#{pad}#{l}" }
  puts
end

#fail(message) ⇒ Object

print a failure message (with checkmark) but do not exit

Parameters:

  • message

    the message to print

Returns:

  • (Object)

    The return value of the block



193
194
195
# File 'lib/arduino_ci/logger.rb', line 193

def fail(message)
  attempt(message) { false }
end

#halt(message) ⇒ Object

print a failure message (with checkmark) and exit immediately afterward

Parameters:

  • message

    the message to print

Returns:

  • (Object)

    The return value of the block



200
201
202
# File 'lib/arduino_ci/logger.rb', line 200

def halt(message)
  assure(message) { false }
end

#indent(amount = 1) { ... } ⇒ void

This method returns an undefined value.

increment an indentation level for the duration of a block’s execution

Parameters:

  • amount (Integer) (defaults to: 1)

    the number of tabs to indent

Yields:

  • The code to execute while indented



82
83
84
85
86
87
# File 'lib/arduino_ci/logger.rb', line 82

def indent(amount = 1, &block)
  @tab += amount
  block.call
ensure
  @tab -= amount
end

#indentationString

Returns the current line indentation.

Returns:

  • (String)

    the current line indentation



50
51
52
# File 'lib/arduino_ci/logger.rb', line 50

def indentation
  (INDENT_CHAR * TAB_WIDTH * @tab)
end

#inform(message) { ... } ⇒ Object

Print a value as a status line “message… retval”

Parameters:

  • message

    the message to print

Yields:

  • The action being performed

Yield Returns:

  • (String)

    The value to print at the end of the line

Returns:

  • (Object)

    The return value of the block



210
211
212
# File 'lib/arduino_ci/logger.rb', line 210

def inform(message, &block)
  perform_action(message, false, proc { |x| x }, nil, false, false, &block)
end

#inform_multiline(message) { ... } ⇒ Object

Print section beginning and end

Parameters:

  • message

    the message to print

Yields:

  • The action being performed

Returns:

  • (Object)

    The return value of the block



219
220
221
# File 'lib/arduino_ci/logger.rb', line 219

def inform_multiline(message, &block)
  perform_action(message, true, nil, nil, false, false, &block)
end

#iprint(str) ⇒ void

This method returns an undefined value.

print an indented string

Parameters:

  • str (String)

    the string to print



72
73
74
75
# File 'lib/arduino_ci/logger.rb', line 72

def iprint(str)
  print(indentation)
  print(str)
end

#iputs(str = "") ⇒ void

This method returns an undefined value.

put an indented string

Parameters:

  • str (String) (defaults to: "")

    the string to puts



58
59
60
61
62
63
64
65
66
# File 'lib/arduino_ci/logger.rb', line 58

def iputs(str = "")
  print(indentation)

  # split the lines and interleave with a newline character, then render
  stream_lines = str.to_s.split("\n")
  marked_stream_lines = stream_lines.flat_map { |s| [s, :nl] }.tap(&:pop)
  marked_stream_lines.each { |l| print(l == :nl ? "\n#{indentation}" : l) }
  puts
end

#perform_action(message, multiline, mark_fn, on_fail_msg, tally_on_fail, abort_on_fail) { ... } ⇒ Object

make a nice status line for an action and react to the action

TODO / note to self: inform_multiline is tougher to write

without altering the signature because it only leaves space
for the checkmark _after_ the multiline, it doesn't know how
to make that conditionally the body

Parameters:

  • message

    String the text of the progress indicator

  • multiline

    boolean whether multiline output is expected

  • mark_fn

    block (string) -> string that says how to describe the result

  • on_fail_msg

    String custom message for failure

  • tally_on_fail

    boolean whether to increment @failure_count

  • abort_on_fail

    boolean whether to abort immediately on failure (i.e. if this is a fatal error)

Yields:

  • The action being performed

Yield Returns:

  • (Object)

    whether the action was successful, can be any type but it is evaluated as a boolean

Returns:

  • (Object)

    The return value of the block



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
# File 'lib/arduino_ci/logger.rb', line 105

def perform_action(message, multiline, mark_fn, on_fail_msg, tally_on_fail, abort_on_fail)
  line = "#{indentation}#{message}... "
  endline = "#{indentation}...#{message} "
  if multiline
    puts line
    @tab += 1
  else
    print line
  end
  $stdout.flush

  # handle the block and any errors it raises
  caught_error = nil
  begin
    result = yield
  rescue StandardError => e
    caught_error = e
    result = false
  ensure
    @tab -= 1 if multiline
  end

  # put the trailing mark
  mark = mark_fn.nil? ? "" : mark_fn.call(result)
  # if multiline, put checkmark at full width
  print endline if multiline
  puts mark.to_s.rjust(@width - line.length, " ")
  unless result
    iputs on_fail_msg unless on_fail_msg.nil?
    raise caught_error unless caught_error.nil?

    @failure_count += 1 if tally_on_fail
    terminate if abort_on_fail
  end
  result
end

#phase(name) ⇒ void

This method returns an undefined value.

Print a section heading to the console to break up the text output

Parameters:

  • name (String)

    the section name



234
235
236
237
238
239
# File 'lib/arduino_ci/logger.rb', line 234

def phase(name)
  puts
  rule("=")
  puts("|  #{name}")
  puts("====")
end

#rule(char) ⇒ void

This method returns an undefined value.

Print a horizontal rule across the console

Parameters:

  • char (String)

    the character to use



226
227
228
# File 'lib/arduino_ci/logger.rb', line 226

def rule(char)
  puts char[0] * @width
end

#warn(message) ⇒ Object

print a failure message (with checkmark) but do not tally a failure

Parameters:

  • message

    the message to print

Returns:

  • (Object)

    The return value of the block



186
187
188
# File 'lib/arduino_ci/logger.rb', line 186

def warn(message)
  inform("WARNING") { message }
end