console-glitter 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/console-glitter.rb +152 -0
- data/lib/console-glitter/ansi.rb +148 -0
- data/lib/console-glitter/version.rb +3 -0
- metadata +47 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: c6dc7f133fc08089409ca94c2faccc434cfadc80
|
|
4
|
+
data.tar.gz: e7ded778c22128e5378af28f24c1463cc8616aed
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: fd4af9e20d868a6159feb8f728df53b9ff45e84524054690df857fc2adbb2c7b0a6392e044ab2fbf41107769a25196779d6f34b9a939f95b132b352857c1ecb2
|
|
7
|
+
data.tar.gz: 29da738fc607e8016e35cc67118957141174407bbfc82dbccf68af8d99a635808ae79ec24ba1b7144a97e4cd0572150b555d1b232aa97d91ae59e95d201438ee
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
require 'console-glitter/version'
|
|
2
|
+
require 'console-glitter/ansi'
|
|
3
|
+
|
|
4
|
+
module ConsoleGlitter
|
|
5
|
+
module UI extend self
|
|
6
|
+
extend ANSI
|
|
7
|
+
# Public: Prompt user for input, allowing for a default answer and a list
|
|
8
|
+
# of valid responses to be provided.
|
|
9
|
+
#
|
|
10
|
+
# question - Query to be presented to the user.
|
|
11
|
+
# options - Hash containing arguments defining acceptable responses.
|
|
12
|
+
# (default: {}):
|
|
13
|
+
# :default_answer - String containing the default answer. If
|
|
14
|
+
# this is nil, a non-empty answer MUST be
|
|
15
|
+
# given.
|
|
16
|
+
# :allow_empty - Whether or not to allow empty responses.
|
|
17
|
+
# Unless explicitly allowed, empty answers
|
|
18
|
+
# will be rejected.
|
|
19
|
+
# :valid_answers - An Array containing all valid responses. If
|
|
20
|
+
# this is empty, any answer will be accepted
|
|
21
|
+
# (except empty answers as specified above).
|
|
22
|
+
#
|
|
23
|
+
# Returns a String containing the answer provided by the user.
|
|
24
|
+
def prompt(question, options = {})
|
|
25
|
+
default = options[:default_answer].to_s
|
|
26
|
+
allow_empty = options[:allow_empty]
|
|
27
|
+
valid = options[:valid_answers] || []
|
|
28
|
+
|
|
29
|
+
default_display = " [#{default.strip}]" unless default.empty?
|
|
30
|
+
question.strip!
|
|
31
|
+
|
|
32
|
+
answer = nil
|
|
33
|
+
while answer.nil?
|
|
34
|
+
print "#{question}#{default_display}> "
|
|
35
|
+
answer = $stdin.readline.strip
|
|
36
|
+
answer = default if answer.empty?
|
|
37
|
+
|
|
38
|
+
if answer.empty?
|
|
39
|
+
answer = nil unless allow_empty
|
|
40
|
+
elsif valid.any?
|
|
41
|
+
answer = nil unless valid.grep(answer).any?
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
answer
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Public: Wrap Console#prompt but accept only a Y/N response.
|
|
49
|
+
#
|
|
50
|
+
# question - String containing the question to present to the user.
|
|
51
|
+
# args - Hash containing arguments to control acceptable responses.
|
|
52
|
+
# (default: {}):
|
|
53
|
+
# :default_answer - String containing the default answer.
|
|
54
|
+
#
|
|
55
|
+
# Returns true or false corresponding to Y or N answer respectively.
|
|
56
|
+
def prompt_yn(question, args = {})
|
|
57
|
+
args[:valid_answers] = []
|
|
58
|
+
answer = nil
|
|
59
|
+
|
|
60
|
+
until answer =~ /^[yn]/i
|
|
61
|
+
answer = prompt(question, args)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
/^n/i.match(answer).nil?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Public: Render a "spinner" on the command line and yield to a block,
|
|
68
|
+
# reporting success if nothing is raised, or else reporting failure.
|
|
69
|
+
#
|
|
70
|
+
# message - Message to be displayed describing the task being evaluated.
|
|
71
|
+
# block - Block to be yielded to determine pass or fail.
|
|
72
|
+
#
|
|
73
|
+
# Returns the result of the yielded block if successful.
|
|
74
|
+
# Raises whatever is raised inside the yielded block.
|
|
75
|
+
def spinner(message, &block)
|
|
76
|
+
success = nil
|
|
77
|
+
result = nil
|
|
78
|
+
|
|
79
|
+
pre = "\r#{bold}#{white} [#{reset}"
|
|
80
|
+
post = "#{bold}#{white}] #{reset}#{message}"
|
|
81
|
+
pre_ok = "\r#{bold}#{white} [#{green} ok "
|
|
82
|
+
pre_fail = "\r#{bold}#{white} [#{red}fail"
|
|
83
|
+
|
|
84
|
+
thread = Thread.new do
|
|
85
|
+
step = 0
|
|
86
|
+
spin = [" ", ". ", ".. ", "... ", "....", " ...", " ..", " ."]
|
|
87
|
+
while success.nil?
|
|
88
|
+
print "#{pre}#{spin[step % 8]}#{post}"
|
|
89
|
+
step += 1
|
|
90
|
+
sleep 0.5
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if success
|
|
94
|
+
print "#{pre_ok}#{post}\n"
|
|
95
|
+
else
|
|
96
|
+
print "#{pre_fail}#{post}\n"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
begin
|
|
101
|
+
result = yield
|
|
102
|
+
success = true
|
|
103
|
+
thread.join
|
|
104
|
+
return result
|
|
105
|
+
rescue
|
|
106
|
+
success = false
|
|
107
|
+
thread.join
|
|
108
|
+
raise
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Public: Generate a formatted, printable table.
|
|
113
|
+
#
|
|
114
|
+
# rows - An Array containing Hashes which contain desired options to
|
|
115
|
+
# display. (e.g. [{"col1" => "a", "col2" => "b"}])
|
|
116
|
+
# labels - Hash containing key-value pairs to label each key in options.
|
|
117
|
+
# (default: nil)
|
|
118
|
+
#
|
|
119
|
+
# Returns a String containing the grid.
|
|
120
|
+
# Raises ArgumentError if anything but an Array is passed as rows.
|
|
121
|
+
def build_grid(rows, labels = nil)
|
|
122
|
+
if labels.nil?
|
|
123
|
+
labels = rows[0].keys.reduce({}) { |c,e| c.merge({e => e}) }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
keys = labels.keys
|
|
127
|
+
|
|
128
|
+
max_width = labels.reduce({}) do |c,e|
|
|
129
|
+
c.merge({e[0]=> ([labels] + rows).map { |r| r[e[0]].length }.max})
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
grid_rule = max_width.reduce('+') do |c,e|
|
|
133
|
+
c + ('-' * (e[1] + 2)) + '+'
|
|
134
|
+
end
|
|
135
|
+
grid_rule << "\n"
|
|
136
|
+
|
|
137
|
+
grid = grid_rule.dup
|
|
138
|
+
grid << keys.reduce('|') do |c,e|
|
|
139
|
+
c + " #{bold}% #{max_width[e]}s#{reset} |" % labels[e]
|
|
140
|
+
end
|
|
141
|
+
grid << "\n"
|
|
142
|
+
|
|
143
|
+
grid << rows.reduce(grid_rule) do |c,e|
|
|
144
|
+
content = keys.reduce('') do |s,k|
|
|
145
|
+
s + " % #{max_width[k]}s |" % e[k]
|
|
146
|
+
end
|
|
147
|
+
c + "|#{content}\n"
|
|
148
|
+
end
|
|
149
|
+
grid << grid_rule
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
module ConsoleGlitter
|
|
2
|
+
module ANSI extend self
|
|
3
|
+
# Public: Return an appropriate escape sequence depending upon the current
|
|
4
|
+
# platform.
|
|
5
|
+
#
|
|
6
|
+
# sequence - Control code(s) to be escaped. Multiple codes may be chained,
|
|
7
|
+
# separated by ';'.
|
|
8
|
+
#
|
|
9
|
+
# Examples
|
|
10
|
+
#
|
|
11
|
+
# ConsoleGlitter::ANSI.escape 0
|
|
12
|
+
# # => "\033[0m"
|
|
13
|
+
#
|
|
14
|
+
# Returns a String.
|
|
15
|
+
def escape(sequence)
|
|
16
|
+
RUBY_PLATFORM =~ /win/i ? '' : "\033[#{sequence}m"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Public: Generate an escape sequence to set the foreground color to an
|
|
20
|
+
# approximation of a 4 or 8 bit per channel hex RGB color a la CSS.
|
|
21
|
+
#
|
|
22
|
+
# color - String containing hex digits describing the color to convert.
|
|
23
|
+
# May be 4 or 8 bits per channel (3 or 6 characters long,
|
|
24
|
+
# respectively).
|
|
25
|
+
#
|
|
26
|
+
# Examples
|
|
27
|
+
#
|
|
28
|
+
# ConsoleGlitter::ANSI.hex_color("00FFFF")
|
|
29
|
+
# # => "\033[38;5;51m"
|
|
30
|
+
# ConsoleGlitter::ANSI.hex_color("F0F")
|
|
31
|
+
# # => "\033[38;5;201m"
|
|
32
|
+
#
|
|
33
|
+
# Returns the appropriate escape code as a Fixnum.
|
|
34
|
+
def hex_color(color)
|
|
35
|
+
escape [38, 5, closest(color)].join(';')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Public: Generate an escape sequence to set the bg color to an
|
|
39
|
+
# approximation of a 4 or 8 bit per channel hex RGB color a la CSS.
|
|
40
|
+
#
|
|
41
|
+
# color - String containing hex digits describing the color to convert.
|
|
42
|
+
# May be 4 or 8 bits per channel (3 or 6 characters long,
|
|
43
|
+
# respectively).
|
|
44
|
+
#
|
|
45
|
+
# Examples
|
|
46
|
+
#
|
|
47
|
+
# ConsoleGlitter::ANSI.bg_hex_color("00FFFF")
|
|
48
|
+
# # => "\033[38;5;51m"
|
|
49
|
+
# ConsoleGlitter::ANSI.bg_hex_color("F0F")
|
|
50
|
+
# # => "\033[38;5;201m"
|
|
51
|
+
#
|
|
52
|
+
# Returns the appropriate escape code as a Fixnum.
|
|
53
|
+
def bg_hex_color(color)
|
|
54
|
+
escape [48, 5, closest(color)].join(';')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
# Internal: Allow on-the-fly definition of ANSI control sequences. Methods
|
|
60
|
+
# are created for convenience which will either wrap the result of a block
|
|
61
|
+
# in the tag specified and a reset tag, or else simply return the code in
|
|
62
|
+
# question.
|
|
63
|
+
#
|
|
64
|
+
# name - String or Symbol containing the name of the constant to be
|
|
65
|
+
# defined.
|
|
66
|
+
# code - ANSI escape code to be saved.
|
|
67
|
+
#
|
|
68
|
+
# Returns nothing.
|
|
69
|
+
#
|
|
70
|
+
# Signature
|
|
71
|
+
#
|
|
72
|
+
# <name>(block)
|
|
73
|
+
#
|
|
74
|
+
# name - Name specified.
|
|
75
|
+
# block - Optional block to be evaluated, the result of which will placed
|
|
76
|
+
# in between the escape code specified.
|
|
77
|
+
def ansi(name, code)
|
|
78
|
+
code = escape(code)
|
|
79
|
+
|
|
80
|
+
define_method(name.to_sym) do |&block|
|
|
81
|
+
if block
|
|
82
|
+
"#{code}#{block.call}#{reset}"
|
|
83
|
+
else
|
|
84
|
+
code
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Internal: Parse a string describing either a 4 or 8 bit-per-channel color
|
|
90
|
+
# (similar to CSS formatting), matching it with the closest approximation
|
|
91
|
+
# for 256 color mode.
|
|
92
|
+
#
|
|
93
|
+
# color - String containing hex digits describing the color to convert.
|
|
94
|
+
# May be 4 or 8 bits per channel (3 or 6 characters long,
|
|
95
|
+
# respectively).
|
|
96
|
+
#
|
|
97
|
+
# Examples
|
|
98
|
+
#
|
|
99
|
+
# ConsoleGlitter::ANSI.closest("00FFFF")
|
|
100
|
+
# # => 51
|
|
101
|
+
# ConsoleGlitter::ANSI.closest("F0F")
|
|
102
|
+
# # => 201
|
|
103
|
+
#
|
|
104
|
+
# Returns the appropriate escape code as a Fixnum.
|
|
105
|
+
def closest(color)
|
|
106
|
+
bpc = 4
|
|
107
|
+
bpc *= 2 if color.length > 3
|
|
108
|
+
color = color.to_i(16)
|
|
109
|
+
|
|
110
|
+
blue = color % (1 << bpc)
|
|
111
|
+
green = ((color - blue) % (1 << (bpc * 2))) >> bpc
|
|
112
|
+
red = (color - (blue + green)) >> (bpc * 2)
|
|
113
|
+
|
|
114
|
+
# 216 (6**3) colors are mapped in 256 color mode (40 colors are otherwise
|
|
115
|
+
# reserved for normal and bold standard colors from 0x00 to 0x0f in
|
|
116
|
+
# addition to a 24 color gradient from black to white from 0xe8 - 0xff.)
|
|
117
|
+
[blue,green,red].each_with_index.map do |c,i|
|
|
118
|
+
(c/(((1 << bpc)-1)/5)) * 6**i
|
|
119
|
+
end.
|
|
120
|
+
reduce(&:+) + 0x10
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Define most common ANSI sequences
|
|
124
|
+
ansi :reset, 0
|
|
125
|
+
ansi :bold, 1
|
|
126
|
+
ansi :faint, 2
|
|
127
|
+
ansi :underline, 4
|
|
128
|
+
ansi :blink, 5
|
|
129
|
+
|
|
130
|
+
ansi :black, 30
|
|
131
|
+
ansi :red, 31
|
|
132
|
+
ansi :green, 32
|
|
133
|
+
ansi :brown, 33
|
|
134
|
+
ansi :blue, 34
|
|
135
|
+
ansi :magenta, 35
|
|
136
|
+
ansi :cyan, 36
|
|
137
|
+
ansi :white, 37
|
|
138
|
+
|
|
139
|
+
ansi :bg_black, 40
|
|
140
|
+
ansi :bg_red, 41
|
|
141
|
+
ansi :bg_green, 42
|
|
142
|
+
ansi :bg_brown, 43
|
|
143
|
+
ansi :bg_blue, 44
|
|
144
|
+
ansi :bg_magenta, 45
|
|
145
|
+
ansi :bg_cyan, 46
|
|
146
|
+
ansi :bg_white, 47
|
|
147
|
+
end
|
|
148
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: console-glitter
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Chris Wuest
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-01-07 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Tools for building nice looking CLI applications
|
|
14
|
+
email: chris@chriswuest.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- lib/console-glitter.rb
|
|
20
|
+
- lib/console-glitter/ansi.rb
|
|
21
|
+
- lib/console-glitter/version.rb
|
|
22
|
+
homepage: http://github.com/cwuest/console-glitter
|
|
23
|
+
licenses:
|
|
24
|
+
- MIT
|
|
25
|
+
metadata: {}
|
|
26
|
+
post_install_message:
|
|
27
|
+
rdoc_options: []
|
|
28
|
+
require_paths:
|
|
29
|
+
- lib
|
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
31
|
+
requirements:
|
|
32
|
+
- - ">="
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: '0'
|
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
requirements: []
|
|
41
|
+
rubyforge_project:
|
|
42
|
+
rubygems_version: 2.0.5
|
|
43
|
+
signing_key:
|
|
44
|
+
specification_version: 4
|
|
45
|
+
summary: Tools for prettier CLI apps
|
|
46
|
+
test_files: []
|
|
47
|
+
has_rdoc:
|