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 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
@@ -0,0 +1,3 @@
1
+ module ConsoleGlitter
2
+ VERSION = '0.1.0'
3
+ 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: