Class: Cowtech::Lib::Console

Inherits:
Object
  • Object
show all
Defined in:
lib/cowtech-lib/console.rb

Overview

A class which provides some method to operate with files and to format pretty messages.

Author:

  • Shogun

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConsole

Create a new Console.



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/cowtech-lib/console.rb', line 328

def initialize
  @indent_level = 0
  @show_commands = false
  @show_outputs = false
  @skip_commands = false
  @tty_width = -1
  @@indentator= " "        

  @@styles = {
    # Default color
    "default" => "\33[0m",
    # Text style
    "bold" => "\33[1m", "underline" => "\33[4m", "blink" => "\33[5m", "reverse" => "\33[7m", "concealed" => "\33[8m",
    # Foreground colors
    "black" => "\33[30m", "red" => "\33[31m", "green" => "\33[32m", "yellow" => "\33[33m", "blue" => "\33[34m", "magenta" => "\33[35m", "cyan" => "\33[36m", "white" => "\33[37m",
    # Background colors
    "bg_black" => "\33[40m", "bg_red" => "\33[41m", "bg_green" => "\33[42m", "bg_yellow" => "\33[43m", "bg_blue" => "\33[44m", "bg_magenta" => "\33[45m", "bg_cyan" => "\33[46m", "bg_white" => "\33[47m"
  }

  @@statuses = {
    :ok => '<text style="bold blue">[ <text style="bold green">OK</text> ]</text> ',
    :pass => '<text style="bold blue">[<text style="bold cyan">PASS</text>]</text> ',
    :fail => '<text style="bold blue">[<text style="bold red">FAIL</text>]</text> ',
    :warn => '<text style="bold blue">[<text style="bold yellow">WARN</text>]</text> ',
  }
end

Instance Attribute Details

#indent_levelObject

Indentation level



53
54
55
# File 'lib/cowtech-lib/console.rb', line 53

def indent_level
  @indent_level
end

#indentatorObject

Indentation string(s)



68
69
70
# File 'lib/cowtech-lib/console.rb', line 68

def indentator
  @indentator
end

#show_commandsObject

Whether show executed commands



56
57
58
# File 'lib/cowtech-lib/console.rb', line 56

def show_commands
  @show_commands
end

#show_outputsObject

Whether show output of executed commands



59
60
61
# File 'lib/cowtech-lib/console.rb', line 59

def show_outputs
  @show_outputs
end

#skip_commandsObject

Whether simply print commands rather than executing them



62
63
64
# File 'lib/cowtech-lib/console.rb', line 62

def skip_commands
  @skip_commands
end

#statusesObject (readonly)

Exit status for commands



65
66
67
# File 'lib/cowtech-lib/console.rb', line 65

def statuses
  @statuses
end

Instance Method Details

#error(msg, args = nil) ⇒ Object

Prints an error message.



226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/cowtech-lib/console.rb', line 226

def error(msg, args = nil)
  args ||= {}

  if msg.is_a?(Hash) then
    args.merge!(msg)
  else
    args[:msg] = msg
  end

  args[:error] = args[:msg]

  self.write(args)
end

#fatal(msg, args = nil) ⇒ Object

Prints and error message then abort.



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/cowtech-lib/console.rb', line 241

def fatal(msg, args = nil)
  args ||= {}

  if msg.is_a?(Hash) then
    args.merge!(msg)
  else
    args[:msg] = msg
  end

  args[:error] = args[:msg]
  args[:exit_after] = true
  args[:code] ||= 1

  self.write(args)
end

#indent(msg, level = nil) ⇒ Object

Indents a message.

Arguments:

  • msg: The message to indent

  • add_additional: Whether add extra space to align to initial message “*”

Returns: The indentated message



97
98
99
# File 'lib/cowtech-lib/console.rb', line 97

def indent(msg, level = nil)
  (@@indentator * (level || @indent_level)) + msg
end

#indent_region(level, absolute = false) ⇒ Object

Execute codes in an indented block



84
85
86
87
88
89
# File 'lib/cowtech-lib/console.rb', line 84

def indent_region(level, absolute = false)
  old_level = @indent_level
  self.indent_set(level, absolute)
  yield
  @indent_level = old_level      
end

#indent_resetObject

Resets indentation level to 0.



79
80
81
# File 'lib/cowtech-lib/console.rb', line 79

def indent_reset
  @indent_level = 0
end

#indent_set(level, absolute = false) ⇒ Object

Sets indentation level. Arguments:

  • indent: The new indentation level

  • : If the level is absolute or relative to the current level



74
75
76
# File 'lib/cowtech-lib/console.rb', line 74

def indent_set(level, absolute = false)
  @indent_level = [(!absolute ? @indent_level : 0) + level, 0].max
end

#parse_message(node, stack = []) ⇒ Object

Substitute tag with color.

Arguments:

  • node: The node which operate on

  • stack: The stack of old styles. Do not set this by yourself!

Returns: The new text



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
# File 'lib/cowtech-lib/console.rb', line 108

def parse_message(node, stack = [])
  rv = ""
  styles = (node.name == "text" and node.attributes["style"]) ? node.attributes["style"].split(" ") : nil

  # Add style of current tag
  if styles then
    styles.each do |style|
      rv += @@styles[style] || ""
    end

    stack.push(styles)
  end

  # Now parse subnodes
  node.children.each do |child|
    if child.node_type == :text then
      rv += child.to_s
    elsif child.name == "text" then
      rv += self.parse_message(child, stack)
    end
  end

  # Remove style of current tag
  if styles then 
    stack.pop()

    # Restore previous style
    (stack.pop || ["default"]).each do |style|
      rv += @@styles[style]
    end
  end

  rv
end

#read(args) ⇒ Object

Read input from the user.

Arguments:

  • msg: The prompt to show

  • valids: A list of regexp to validate the input

  • case_sensitive: Wheter the validation is case_sensitive

Returns: The read input



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'lib/cowtech-lib/console.rb', line 282

def read(args)
  # Adjust prompt
  msg = args[:msg] + ((msg !~ /([:?](\s*))$/) ? ":" : "")
  msg += " " unless msg =~ / ^/

  # Turn choices into regular expressions
  regexps = (args[:valids] || []).force_array.collect do |valid|
    unless valid.is_a?(Regexp) then
      valid = Regexp.new((valid !~ /^\^/ ? "^" : "") + valid + (valid !~ /\$$/ ? "$" : ""), Regexp::EXTENDED + (args[:case_sensitive] ? Regexp::IGNORECASE : 0), "U")
    else
      valid
    end
  end

  rv = nil

  # Read input
  while true do
    # Show message
    print(msg)

    # Get reply
    bufs = gets.chop()

    # If we don't have any regexp
    if regexps.length == 0 then
      rv = bufs
      break
    end

    # Validate inputs
    regexps.each do |re|
      if bufs =~ re then
        rv = bufs
        break
      end
    end

    break if rv
    self.write(:warn => "Sorry, your reply was not understood. Please try again")
  end

  rv
end

#status(status, args = nil) ⇒ Object

Prints an error status



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/cowtech-lib/console.rb', line 258

def status(status, args = nil)
  args ||= {}

  if status.is_a?(Hash) then
    args.merge!(status)
  else
    args[:status] = status
  end

  status = status.is_a?(Hash) ? status[:status] : status
  args[:end] = @@statuses[status] || @@statuses[:ok]
  args[:dots] = false
  args[:up] = true if args[:up] == nil
  self.write(args)
end

#warn(msg, args = nil) ⇒ Object

Syntatic sugar Prints a warning message.



211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/cowtech-lib/console.rb', line 211

def warn(msg, args = nil)
  args ||= {}
  
  if msg.is_a?(Hash) then
    args.merge!(msg)
  else
    args[:msg] = msg
  end
  
  args[:warn] = args[:msg]

  self.write(args)
end

#write(args) ⇒ Object

Prints a message. Arguments:

  • msg: The message to print

  • dots: Whether add “…” to the message

  • newline: Whether add a newline to the message

  • plain: Whether ignore tags

  • must_indent: Whether indent the message

  • internal: If the method is called by another method. Do not set this by yourself!



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
# File 'lib/cowtech-lib/console.rb', line 151

def write(args)
  msg = args[:msg]

  # Check some alternative syntax
  [:begin, :warn, :error, :debug, :info, :right, :end].each do |t|
    if args[t] then
      msg = args[t]
      args[:type] = t
      args[t] = nil
    end
  end
  args[:fatal] = true if args[:status] == :fail

  # Check for specific msg type
  if [:begin, :warn, :error, :debug, :info].include?(args[:type]) then
    mc = {:begin => "bold green", :warn => "bold yellow", :error => "bold red", :debug => "magenta", :info => "bold cyan"}
    color = args[:color] || mc[args[:type]]
    msg = !args[:full_color] ? "<text style=\"#{color}\">*</text> #{self.indent(msg)}" : "<text style=\"#{color}\">* #{self.indent(msg)}</text>"
  end

  # Add dots and indentation if needed
  msg = self.indent(msg + (args.fetch(:dots, true) ? "..." : ""), args[:indent] ? args[:indent] : @indent_level)
  
  # Parse the message
  unless args[:plain] then
    begin
      xml = "<text>#{msg}</text>"
      msg = self.parse_message(REXML::Document.new(xml).root)
    rescue Exception => e
      print "[ERROR] Invalid message tagging, check XML syntax (or color requested) of the following message:\n\n\t#{xml}\n\n"
      print "\tThe errors was: #{e.message} (#{e.class.to_s})\n\n"
      exit(1)
    end
  end

  # Add newline if needed
  msg += "\n" if args.fetch(:newline, true)

  if args[:internal] then 
    msg 
  else 
    if [:end, :right].include?(args[:type]) then
      # Get screen width
      @tty_width = `tput cols`.to_i if @tty_width < 0

      # Get padding
      pad = @tty_width - msg.inspect.gsub(/(\\e\[[0-9]+m)|(\")|(\\n)/, "").length

      print "\033[A" if args[:up]
      print "\033[0G\033[#{pad}C"
    end

    print(msg)
  end

  exit(args[:code] || 0) if args[:exit_after] || args[:fatal]
end