tty 0.1.0 → 0.1.1

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -3
  3. data/CHANGELOG.md +8 -0
  4. data/README.md +74 -42
  5. data/lib/tty.rb +7 -9
  6. data/lib/tty/conversion.rb +16 -0
  7. data/lib/tty/conversion/converter/array.rb +35 -0
  8. data/lib/tty/{coercer → conversion/converter}/boolean.rb +20 -7
  9. data/lib/tty/conversion/converter/float.rb +28 -0
  10. data/lib/tty/conversion/converter/integer.rb +28 -0
  11. data/lib/tty/{coercer → conversion/converter}/range.rb +16 -7
  12. data/lib/tty/logger.rb +1 -1
  13. data/lib/tty/shell/question.rb +2 -1
  14. data/lib/tty/shell/response.rb +9 -4
  15. data/lib/tty/shell/statement.rb +3 -2
  16. data/lib/tty/table.rb +3 -3
  17. data/lib/tty/table/border.rb +8 -5
  18. data/lib/tty/table/border/row_line.rb +2 -2
  19. data/lib/tty/table/operation/alignment_set.rb +2 -1
  20. data/lib/tty/table/padder.rb +1 -1
  21. data/lib/tty/table/renderer/basic.rb +1 -1
  22. data/lib/tty/terminal.rb +1 -118
  23. data/lib/tty/text/truncation.rb +4 -1
  24. data/lib/tty/text/wrapping.rb +4 -1
  25. data/lib/tty/vector.rb +4 -3
  26. data/lib/tty/version.rb +2 -2
  27. data/spec/tty/{support/conversion_spec.rb → conversion/converter/array/convert_spec.rb} +4 -5
  28. data/spec/tty/{coercer/boolean/coerce_spec.rb → conversion/converter/boolean/convert_spec.rb} +5 -4
  29. data/spec/tty/{coercer/float/coerce_spec.rb → conversion/converter/float/convert_spec.rb} +3 -2
  30. data/spec/tty/{coercer/integer/coerce_spec.rb → conversion/converter/integer/convert_spec.rb} +4 -2
  31. data/spec/tty/{coercer/range/coerce_spec.rb → conversion/converter/range/convert_spec.rb} +3 -2
  32. data/spec/tty/shell/error_spec.rb +4 -1
  33. data/spec/tty/shell/response/read_bool_spec.rb +1 -1
  34. data/spec/tty/shell/say_spec.rb +3 -0
  35. data/spec/tty/shell/statement/initialize_spec.rb +2 -2
  36. data/spec/tty/shell/warn_spec.rb +3 -0
  37. data/spec/tty/table/field/equality_spec.rb +1 -1
  38. data/spec/tty/table/render_spec.rb +3 -0
  39. data/spec/tty/table/render_with_spec.rb +8 -5
  40. data/spec/tty/table/renderer/basic/coloring_spec.rb +10 -9
  41. data/spec/tty/table/renderer/style_spec.rb +3 -0
  42. data/spec/tty/terminal/color_spec.rb +6 -3
  43. data/tasks/console.rake +1 -1
  44. data/tty.gemspec +7 -1
  45. metadata +88 -30
  46. data/lib/tty/coercer.rb +0 -13
  47. data/lib/tty/coercer/float.rb +0 -20
  48. data/lib/tty/coercer/integer.rb +0 -20
  49. data/lib/tty/support/conversion.rb +0 -35
  50. data/lib/tty/support/equatable.rb +0 -152
  51. data/lib/tty/terminal/color.rb +0 -157
  52. data/spec/tty/support/equatable_spec.rb +0 -201
  53. data/spec/tty/terminal/color/code_spec.rb +0 -19
  54. data/spec/tty/terminal/color/remove_spec.rb +0 -44
  55. data/spec/tty/terminal/color/set_spec.rb +0 -29
  56. data/spec/tty/terminal/size_spec.rb +0 -97
@@ -1,13 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- module TTY
4
-
5
- # Abstract class for type coercions
6
- #
7
- # @abstract
8
- class Coercer
9
- include TTY::Equatable
10
-
11
- end # Coercer
12
-
13
- end # TTY
@@ -1,20 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module TTY
4
- class Coercer
5
- # Coerce values into float number
6
- #
7
- # @api public
8
- class Float
9
- def self.coerce(value, strict = true)
10
- Kernel.send(:Float, value.to_s)
11
- rescue
12
- if strict
13
- raise InvalidArgument, "#{value} could not be coerced into Float"
14
- else
15
- value.to_f
16
- end
17
- end
18
- end # Float
19
- end # Coercer
20
- end # TTY
@@ -1,20 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module TTY
4
- class Coercer
5
- # Coerce value into integer number
6
- #
7
- # @api public
8
- class Integer
9
- def self.coerce(value, strict = true)
10
- Kernel.send(:Integer, value.to_s)
11
- rescue
12
- if strict
13
- raise InvalidArgument, "#{value} could not be coerced into Integer"
14
- else
15
- value.to_i
16
- end
17
- end
18
- end # Integer
19
- end # Coercer
20
- end # TTY
@@ -1,35 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module TTY
4
- # A mixin to allow instances conversion to array type
5
- #
6
- # @api public
7
- module Conversion
8
- # Converts the object into an Array. If copy is set to true
9
- # a copy of object will be made.
10
- #
11
- # @param [Object] object
12
- #
13
- # @param [Boolean] copy
14
- #
15
- # @return [Array]
16
- #
17
- # @api private
18
- def convert_to_array(object, copy = false)
19
- case object
20
- when Array
21
- copy ? object.dup : object
22
- when Hash
23
- Array(object)
24
- else
25
- begin
26
- converted = object.to_ary
27
- rescue Exception => e
28
- raise TTY::TypeError,
29
- "Cannot convert #{object.class} into an Array (#{e.message})"
30
- end
31
- converted
32
- end
33
- end
34
- end # Conversion
35
- end # TTY
@@ -1,152 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- module TTY
4
-
5
- # Make it easy to define equality and hash methods.
6
- module Equatable
7
-
8
- # Hook into module inclusion.
9
- #
10
- # @param [Module] base
11
- # the module or class including Equatable
12
- #
13
- # @return [self]
14
- #
15
- # @api private
16
- def self.included(base)
17
- super
18
- base.extend(self)
19
- base.class_eval do
20
- define_comparison_attrs
21
- include Methods
22
- define_methods
23
- end
24
- self
25
- end
26
-
27
- # Holds all attributes used for comparison.
28
- #
29
- # @return [Array<Symbol>]
30
- #
31
- # @api private
32
- attr_reader :comparison_attrs
33
-
34
- # Objects that include this module are assumed to be value objects.
35
- # It is also assumed that the only values that affect the results of
36
- # equality comparison are the values of the object's attributes.
37
- #
38
- # @param [Array<Symbol>] *args
39
- #
40
- # @return [undefined]
41
- #
42
- # @api public
43
- def attr_reader(*args)
44
- super
45
- @comparison_attrs.concat(args)
46
- end
47
-
48
- # Copy the comparison_attrs into the subclass.
49
- #
50
- # @param [Class] subclass
51
- #
52
- # @api private
53
- def inherited(subclass)
54
- super
55
- subclass.instance_variable_set(:@comparison_attrs, comparison_attrs.dup)
56
- end
57
-
58
- private
59
-
60
- # Define class instance #comparison_attrs as an empty array.
61
- #
62
- # @return [undefined]
63
- #
64
- # @api private
65
- def define_comparison_attrs
66
- instance_variable_set('@comparison_attrs', [])
67
- end
68
-
69
- # Define all methods needed for ensuring object's equality.
70
- #
71
- # @return [undefined]
72
- #
73
- # @api private
74
- def define_methods
75
- define_compare
76
- define_hash
77
- define_inspect
78
- end
79
-
80
- # Define a #compare? method to check if the receiver is the same
81
- # as the other object.
82
- #
83
- # @return [undefined]
84
- #
85
- # @api private
86
- def define_compare
87
- define_method(:compare?) do |comparator, other|
88
- klass = self.class
89
- attrs = klass.comparison_attrs || []
90
- attrs.all? { |attr| send(attr).send(comparator, other.send(attr)) }
91
- end
92
- end
93
-
94
- # Define a hash method that ensures that the hash value is the same for
95
- # the same instance attributes and their corresponding values.
96
- #
97
- # @api private
98
- def define_hash
99
- define_method(:hash) do
100
- klass = self.class
101
- attrs = klass.comparison_attrs || []
102
- ([klass] + attrs.map { |attr| send(attr)}).hash
103
- end
104
- end
105
-
106
- # Define an inspect method that shows the class name and the values for the
107
- # instance's attributes.
108
- #
109
- # @return [undefined]
110
- #
111
- # @api private
112
- def define_inspect
113
- define_method(:inspect) do
114
- klass = self.class
115
- name = klass.name || klass.inspect
116
- attrs = klass.comparison_attrs || []
117
- "#<#{name}#{attrs.map { |attr| " #{attr}=#{send(attr).inspect}" }.join}>"
118
- end
119
- end
120
-
121
- module Methods
122
-
123
- # Compare two objects for equality based on their value
124
- # and being an instance of the given class.
125
- #
126
- # @param [Object] other
127
- # the other object in comparison
128
- #
129
- # @return [Boolean]
130
- #
131
- # @api public
132
- def eql?(other)
133
- instance_of?(other.class) && compare?(__method__, other)
134
- end
135
-
136
- # Compare two objects for equality based on their value
137
- # and being a subclass of the given class.
138
- #
139
- # @param [Object] other
140
- # the other object in comparison
141
- #
142
- # @return [Boolean]
143
- #
144
- # @api public
145
- def ==(other)
146
- kind_of?(other.class) && compare?(__method__, other)
147
- end
148
-
149
- end # Methods
150
-
151
- end # Equatable
152
- end # TTY
@@ -1,157 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module TTY
4
- class Terminal
5
- # A class responsible for coloring strings.
6
- class Color
7
- # Embed in a String to clear all previous ANSI sequences.
8
- CLEAR = "\e[0m"
9
- # The start of an ANSI bold sequence.
10
- BOLD = "\e[1m"
11
- # The start of an ANSI underlined sequence.
12
- UNDERLINE = "\e[4m"
13
-
14
- STYLES = %w( BOLD CLEAR UNDERLINE ).freeze
15
-
16
- # Escape codes for text color.
17
- BLACK = "\e[30m"
18
- RED = "\e[31m"
19
- GREEN = "\e[32m"
20
- YELLOW = "\e[33m"
21
- BLUE = "\e[34m"
22
- MAGENTA = "\e[35m"
23
- CYAN = "\e[36m"
24
- WHITE = "\e[37m"
25
-
26
- LIGHT_BLACK = "\e[90m"
27
- LIGHT_RED = "\e[91m"
28
- LIGHT_GREEN = "\e[92m"
29
- LIGHT_YELLOW = "\e[93m"
30
- LIGHT_BLUE = "\e[94m"
31
- LIGHT_MAGENTA = "\e[95m"
32
- LIGHT_CYAN = "\e[96m"
33
-
34
- TEXT_COLORS = (constants.grep(/^[^ON_]*/) - STYLES).freeze
35
-
36
- # Escape codes for background color.
37
- ON_BLACK = "\e[40m"
38
- ON_RED = "\e[41m"
39
- ON_GREEN = "\e[42m"
40
- ON_YELLOW = "\e[43m"
41
- ON_BLUE = "\e[44m"
42
- ON_MAGENTA = "\e[45m"
43
- ON_CYAN = "\e[46m"
44
- ON_WHITE = "\e[47m"
45
-
46
- ON_LIGHT_BLACK = "\e[100m"
47
- ON_LIGHT_RED = "\e[101m"
48
- ON_LIGHT_GREEN = "\e[102m"
49
- ON_LIGHT_YELLOW = "\e[103m"
50
- ON_LIGHT_BLUE = "\e[104m"
51
- ON_LIGHT_MAGENTA = "\e[105m"
52
- ON_LIGHT_CYAN = "\e[106m"
53
-
54
- BACKGROUND_COLORS = constants.grep(/^ON_*/).freeze
55
-
56
- attr_reader :enabled
57
-
58
- # Initialize a Terminal Color
59
- #
60
- # @api public
61
- def initialize(enabled = false)
62
- @enabled = enabled
63
- end
64
-
65
- # Disable coloring of this terminal session
66
- #
67
- # @api public
68
- def disable!
69
- @enabled = false
70
- end
71
-
72
- # Check if coloring is on
73
- #
74
- # @return [Boolean]
75
- #
76
- # @api public
77
- def enabled?
78
- @enabled
79
- end
80
-
81
- # Apply ANSI color to the given string.
82
- #
83
- # @param [String] string
84
- # text to add ANSI strings
85
- #
86
- # @param [Array[Symbol]] colors
87
- #
88
- # @example
89
- # apply "text", :yellow, :on_green, :underline
90
- #
91
- # @return [String]
92
- #
93
- # @api public
94
- def set(string, *colors)
95
- validate(*colors)
96
- ansi_colors = colors.map { |color| lookup(color) }
97
- "#{ansi_colors.join}#{string}#{CLEAR}"
98
- end
99
-
100
- # Same as instance method.
101
- #
102
- # @return [undefined]
103
- #
104
- # @api public
105
- def self.set(string, *colors)
106
- new.set(string, *colors)
107
- end
108
-
109
- # Remove color codes from a string.
110
- #
111
- # @param [String] string
112
- #
113
- # @return [String]
114
- #
115
- # @api public
116
- def remove(string)
117
- string.to_s.gsub(/(\[)?\033(\[)?[;?\d]*[\dA-Za-z](\])?/, '')
118
- end
119
-
120
- # Return raw color code without embeding it into a string.
121
- #
122
- # @return [Array[String]]
123
- # ANSI escape codes
124
- #
125
- # @api public
126
- def code(*colors)
127
- validate(*colors)
128
- colors.map { |color| lookup(color) }
129
- end
130
-
131
- # All ANSI color names as strings.
132
- #
133
- # @return [Array[String]]
134
- #
135
- # @api public
136
- def names
137
- (STYLES + BACKGROUND_COLORS + TEXT_COLORS).map { |col| col.to_s.downcase }
138
- end
139
-
140
- protected
141
-
142
- # Find color representation.
143
- #
144
- # @api private
145
- def lookup(color)
146
- self.class.const_get(color.to_s.upcase)
147
- end
148
-
149
- # @api private
150
- def validate(*colors)
151
- return if colors.all? { |color| names.include?(color.to_s) }
152
- raise ArgumentError, 'Bad color or unintialized constant, ' \
153
- " valid colors are: #{names.join(', ')}."
154
- end
155
- end # Color
156
- end # Terminal
157
- end # TTY
@@ -1,201 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- describe TTY::Equatable do
6
- let(:name) { 'Value' }
7
-
8
- context 'without attributes' do
9
- let(:klass) { ::Class.new }
10
-
11
- subject { klass.new }
12
-
13
- before {
14
- allow(klass).to receive(:name).and_return('Value')
15
- klass.send :include, described_class
16
- }
17
-
18
- it { is_expected.to respond_to :compare? }
19
-
20
- it { is_expected.to be_instance_of klass }
21
-
22
- describe '#eql?' do
23
- context 'when objects are similar' do
24
- let(:other) { subject.dup }
25
-
26
- it { expect(subject.eql?(other)).to eq(true) }
27
- end
28
-
29
- context 'when objects are different' do
30
- let(:other) { double('other') }
31
-
32
- it { expect(subject.eql?(other)).to eq(false) }
33
- end
34
- end
35
-
36
- describe '#==' do
37
- context 'when objects are similar' do
38
- let(:other) { subject.dup }
39
-
40
- it { expect(subject == other).to eq(true) }
41
- end
42
-
43
- context 'when objects are different' do
44
- let(:other) { double('other') }
45
-
46
- it { expect(subject == other).to eq(false) }
47
- end
48
- end
49
-
50
- describe '#inspect' do
51
- it { expect(subject.inspect).to eql('#<Value>') }
52
- end
53
-
54
- describe '#hash' do
55
- it { expect(subject.hash).to eql([klass].hash) }
56
- end
57
- end
58
-
59
- context 'with attributes' do
60
- let(:value) { 11 }
61
- let(:klass) {
62
- ::Class.new do
63
- include TTY::Equatable
64
-
65
- attr_reader :value
66
-
67
- def initialize(value)
68
- @value = value
69
- end
70
- end
71
- }
72
-
73
- before {
74
- allow(klass).to receive(:name).and_return name
75
- }
76
-
77
- subject { klass.new(value) }
78
-
79
- it 'dynamically defines #hash method' do
80
- expect(klass.method_defined?(:hash)).to eq(true)
81
- end
82
-
83
- it 'dynamically defines #inspect method' do
84
- expect(klass.method_defined?(:inspect)).to eq(true)
85
- end
86
-
87
- it { is_expected.to respond_to :compare? }
88
-
89
- it { is_expected.to respond_to :eql? }
90
-
91
- describe '#eql?' do
92
- context 'when objects are similar' do
93
- let(:other) { subject.dup }
94
-
95
- it { expect(subject.eql?(other)).to eq(true) }
96
- end
97
-
98
- context 'when objects are different' do
99
- let(:other) { double('other') }
100
-
101
- it { expect(subject.eql?(other)).to eq(false) }
102
- end
103
- end
104
-
105
- describe '#==' do
106
- context 'when objects are similar' do
107
- let(:other) { subject.dup }
108
-
109
- it { expect(subject == other).to eq(true) }
110
- end
111
-
112
- context 'when objects are different' do
113
- let(:other) { double('other') }
114
-
115
- it { expect(subject == other).to eq(false) }
116
- end
117
- end
118
-
119
- describe '#inspect' do
120
- it { expect(subject.inspect).to eql('#<Value value=11>') }
121
- end
122
-
123
- describe '#hash' do
124
- it { expect(subject.hash).to eql( ([klass] + [value]).hash) }
125
- end
126
-
127
- context 'equivalence relation' do
128
- let(:other) { subject.dup }
129
-
130
- it 'is not equal to nil reference' do
131
- expect(subject.eql?(nil)).to eq(false)
132
- end
133
-
134
- it 'is reflexive' do
135
- expect(subject.eql?(subject)).to eq(true)
136
- end
137
-
138
- it 'is symmetric' do
139
- expect(subject.eql?(other)).to eql( other.eql?(subject) )
140
- end
141
- end
142
- end
143
-
144
- context 'subclass' do
145
- let(:value) { 11 }
146
- let(:klass) {
147
- ::Class.new do
148
- include TTY::Equatable
149
-
150
- attr_reader :value
151
-
152
- def initialize(value)
153
- @value = value
154
- end
155
- end
156
- }
157
- let(:subclass) { ::Class.new(klass) }
158
-
159
- before {
160
- allow(klass).to receive(:name).and_return name
161
- }
162
-
163
- subject { subclass.new(value) }
164
-
165
- it { expect(subclass.superclass).to eq(klass) }
166
-
167
- it { is_expected.to respond_to :value }
168
-
169
- describe '#inspect' do
170
- it { expect(subject.inspect).to eql('#<Value value=11>') }
171
- end
172
-
173
- describe '#eql?' do
174
- context 'when objects are similar' do
175
- let(:other) { subject.dup }
176
-
177
- it { expect(subject.eql?(other)).to eq(true) }
178
- end
179
-
180
- context 'when objects are different' do
181
- let(:other) { double('other') }
182
-
183
- it { expect(subject.eql?(other)).to eq(false) }
184
- end
185
- end
186
-
187
- describe '#==' do
188
- context 'when objects are similar' do
189
- let(:other) { subject.dup }
190
-
191
- it { expect(subject == other).to eq(true) }
192
- end
193
-
194
- context 'when objects are different' do
195
- let(:other) { double('other') }
196
-
197
- it { expect(subject == other).to eq(false) }
198
- end
199
- end
200
- end
201
- end