tty 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  *.swp
2
+ *.swo
2
3
  *.gem
3
4
  *.rbc
4
5
  .bundle
data/README.md CHANGED
@@ -1,11 +1,10 @@
1
1
  # TTY
2
- [![Build Status](https://secure.travis-ci.org/peter-murach/tty.png?branch=master)][travis] [![Dependency Status](https://gemnasium.com/peter-murach/tty.png?travis)][gemnasium] [![Code Climate](https://codeclimate.com/badge.png)][codeclimate]
2
+ [![Build Status](https://secure.travis-ci.org/peter-murach/tty.png?branch=master)][travis] [![Code Climate](https://codeclimate.com/badge.png)][codeclimate]
3
3
 
4
4
  [travis]: http://travis-ci.org/peter-murach/tty
5
- [gemnasium]: https://gemnasium.com/peter-murach/tty
6
5
  [codeclimate]: https://codeclimate.com/github/peter-murach/tty
7
6
 
8
- Toolbox for developing CLI clients.
7
+ Toolbox for developing CLI clients in Ruby.
9
8
 
10
9
  ## Features
11
10
 
@@ -14,9 +13,11 @@ Jump-start development of your command line app:
14
13
  * Fully customizable table rendering with an easy-to-use API.
15
14
  (status: In Progress)
16
15
  * Terminal output colorization. (status: TODO)
17
- * Terminal & System detection utilities. (status: TODO)
16
+ * Terminal & System detection utilities. (status: In Progress)
18
17
  * Text alignment/padding and diffs. (status: TODO)
19
18
  * Shell user interface. (status: TODO)
19
+ * Progress bar. (status: TODO)
20
+ * Fully tested with major ruby interpreters.
20
21
  * No dependencies to allow for easy gem vendoring.
21
22
 
22
23
  ## Installation
@@ -37,14 +38,22 @@ Or install it yourself as:
37
38
 
38
39
  ### Table
39
40
 
40
- Creating tables
41
+ To instantiate table
42
+
43
+ ```ruby
44
+ table = TTY::Table.new :rows => [['a1', 'a2'], ['b1', 'b2']]
45
+ table = TTY::Table[['a1', 'a2'], ['b1', 'b2']]
46
+ ```
47
+
48
+ Table behaves like an array so `<<` and similar methods can be used
41
49
 
42
50
  ```ruby
43
- table = TTY::Table.new ['Header 1', 'Header 2']
44
51
  table << ['a1', 'a2', 'a3']
45
52
  table << ['b1', 'b2', 'b3']
46
53
  ```
47
54
 
55
+ or pass your rows in a block
56
+
48
57
  ```ruby
49
58
  table = TTY::Table.new header: ['Header 1', 'Header 2'] do |t|
50
59
  t << ['a1', 'a2', 'a3']
@@ -52,6 +61,36 @@ Creating tables
52
61
  end
53
62
  ```
54
63
 
64
+ And then to print do
65
+
66
+ ```ruby
67
+ table.to_s # => a1 a2 a3
68
+ # b1 b2 b3
69
+ ```
70
+
71
+ To print `unicode` table
72
+
73
+ ```ruby
74
+ table = TTY::Table.new renderer: 'unicode'
75
+ table.to_s
76
+ ```
77
+
78
+ ### Terminal
79
+
80
+ ```ruby
81
+ term = TTY::Terminal.new
82
+ term.width # => 140
83
+ term.height # => 60
84
+ term.color? # => true or false
85
+ ```
86
+
87
+ ### System
88
+
89
+ ```ruby
90
+ TTY::System.unix? # => true
91
+ TTY::System.windows? # => false
92
+ ```
93
+
55
94
  ## Contributing
56
95
 
57
96
  1. Fork it
data/lib/tty.rb CHANGED
@@ -1,11 +1,32 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  require 'tty/version'
4
- require 'tty/table'
5
- require 'tty/color'
6
4
 
7
5
  require 'tty/support/utils'
6
+ require 'tty/support/delegatable'
7
+ require 'tty/support/conversion'
8
+
9
+ require 'tty/color'
10
+ require 'tty/terminal'
11
+ require 'tty/system'
12
+ require 'tty/table'
8
13
 
9
14
  module TTY
10
15
 
16
+ # Raised when the argument type is different from expected
17
+ class TypeError < ArgumentError; end
18
+
19
+ class << self
20
+
21
+ # Return terminal instance
22
+ #
23
+ # @return [TTY::Terminal]
24
+ #
25
+ # @api public
26
+ def terminal
27
+ @terminal ||= Terminal.new
28
+ end
29
+
30
+ end
31
+
11
32
  end # TTY
data/lib/tty/color.rb CHANGED
@@ -10,9 +10,5 @@ module TTY
10
10
 
11
11
  attr_reader :enabled
12
12
 
13
- def self.color?
14
- %x{tput colors 2>/dev/null}.to_i > 2
15
- end
16
-
17
13
  end # Color
18
14
  end # TTY
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module TTY
4
+ # A mixin to allow instances conversion to different types
5
+ module Conversion
6
+
7
+ # Converts the object into an Array. If copy is set to true
8
+ # a copy of object will be made.
9
+ #
10
+ # @param [Object] object
11
+ #
12
+ # @param [Boolean] copy
13
+ #
14
+ # @return [Array]
15
+ #
16
+ # @api private
17
+ def convert_to_array(object, copy=false)
18
+ case object
19
+ when Array
20
+ copy ? object.dup : object
21
+ when Hash
22
+ Array(object)
23
+ else
24
+ begin
25
+ converted = object.to_ary
26
+ rescue Exception => e
27
+ raise TTY::TypeError, "Cannot convert #{object.class} into an Array (#{e.message})"
28
+ end
29
+ converted
30
+ end
31
+ end
32
+
33
+ end # Conversion
34
+ end # TTY
@@ -0,0 +1,44 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module TTY
4
+ # A mixin to allow delegetable methods to be added
5
+ module Delegatable
6
+
7
+ # Create delegator for each specified method
8
+ #
9
+ # @example
10
+ # delegatable_method :source, :method
11
+ #
12
+ # @param [Symbol] source
13
+ #
14
+ # @param [Array] methods
15
+ #
16
+ # @return [self]
17
+ #
18
+ # @api public
19
+ def delegatable_method(source, *methods)
20
+ methods.each { |method| define_delegatable_method(source, method)}
21
+ self
22
+ end
23
+
24
+ private
25
+
26
+ # Create a delegator method for the method name
27
+ #
28
+ # @param [Symbol] source
29
+ #
30
+ # @param [Symbol] method name
31
+ #
32
+ # @return [undefined]
33
+ #
34
+ # @api private
35
+ def define_delegatable_method(source, method)
36
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
37
+ def #{method}(*args, &block)
38
+ #{source}.#{method}(*args, &block)
39
+ end
40
+ RUBY
41
+ end
42
+
43
+ end # Delegatable
44
+ end # TTY
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+
1
3
  module TTY
2
4
  module Utils
3
5
  extend self
data/lib/tty/system.rb ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'rbconfig'
4
+
5
+ module TTY
6
+ class System
7
+
8
+ class << self
9
+
10
+ # Check if windows platform.
11
+ #
12
+ # @return [Boolean]
13
+ #
14
+ # @api public
15
+ def windows?
16
+ RbConfig::CONFIG['host_os'] =~ /msdos|mswin|djgpp|mingw|windows/
17
+ end
18
+
19
+ # Check if unix platform
20
+ #
21
+ # @return [Boolean]
22
+ #
23
+ # @api public
24
+ def unix?
25
+ RbConfig::CONFIG['host_os'] =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
26
+ end
27
+
28
+ end
29
+
30
+ end # System
31
+ end # TTY
data/lib/tty/table.rb CHANGED
@@ -2,10 +2,13 @@
2
2
 
3
3
  require 'forwardable'
4
4
  require 'tty/table/renderer'
5
+ require 'tty/table/error'
6
+ require 'tty/table/validatable'
5
7
 
6
8
  module TTY
7
9
  class Table
8
- include Comparable, Enumerable, Renderer
10
+ include Comparable, Enumerable, Renderer, Conversion
11
+ include Validatable
9
12
  extend Forwardable
10
13
 
11
14
  # The table header
@@ -34,6 +37,16 @@ module TTY
34
37
  # TODO implement table orientation
35
38
  end
36
39
 
40
+ # Create a new Table where each argument is a row
41
+ #
42
+ # @example
43
+ # table = TTY::Table.new[['a1', 'a2'], ['b1', 'b2']]
44
+ #
45
+ # @api public
46
+ def self.[](*rows)
47
+ self.new(:rows => rows)
48
+ end
49
+
37
50
  # Instantiate a new Table
38
51
  #
39
52
  # @example of direct parameters
@@ -44,6 +57,8 @@ module TTY
44
57
  # rows = [ ['a1', 'a2'], ['b1', 'b2'] ]
45
58
  # table = Table.new :header => ['Header 1', 'Header 2'], :rows => rows
46
59
  #
60
+ # @param [Array[Symbol], Hash] *args
61
+ #
47
62
  # @api public
48
63
  def self.new(*args, &block)
49
64
  options = Utils.extract_options!(args)
@@ -58,28 +73,105 @@ module TTY
58
73
  # Initialize a Table
59
74
  #
60
75
  # @param [Hash] options
76
+ # the options to create the table with
77
+ # @option options [String] :header
78
+ # column names to be displayed
79
+ # @option options [String] :rows
80
+ # Array of Arrays expressin the rows
81
+ # @option options [String] :renderer
82
+ # used to format table output
83
+ #
61
84
  # @return [Table]
62
85
  #
63
86
  # @api private
64
87
  def initialize(options={}, &block)
65
88
  @header = options.fetch :header, []
66
- @rows = options.fetch :rows, []
89
+ @rows = coerce(options.fetch :rows, [])
67
90
  @renderer = pick_renderer options[:renderer]
91
+ assert_row_sizes @rows
68
92
  yield_or_eval &block if block_given?
69
93
  end
70
94
 
71
- # Lookup an attribute value given an attribute name
95
+ # Lookup element of the table given a row(i) and column(j)
72
96
  #
73
- def [](index)
74
- if index >= 0
75
- rows.map { |row| row[0] }.compact
97
+ # @api public
98
+ def [](i, j)
99
+ if i >= 0 && j >= 0
100
+ rows.fetch(i){return nil}[j]
76
101
  else
77
102
  raise IndexError.new("index #{index} not found")
78
103
  end
79
104
  end
105
+ alias element []
106
+ alias component []
107
+
108
+ # Set table value at row(i) and column(j)
109
+ #
110
+ # @api private
111
+ def []=(i, j, val)
112
+ @rows[i][j] = val
113
+ end
114
+ private :[]=
115
+
116
+ # Return a row number at the index of the table as an Array.
117
+ # When a block is given, the elements of that Array are iterated over.
118
+ #
119
+ # @example
120
+ # rows = [ ['a1', 'a2'], ['b1', 'b2'] ]
121
+ # table = TTY::Table.new :rows => rows
122
+ # table.row(1) { |element| ... }
123
+ #
124
+ # @param [Integer] index
125
+ #
126
+ # @yield []
127
+ # optional block to execute in the iteration operation
128
+ #
129
+ # @return [self]
130
+ #
131
+ # @api public
132
+ def row(index, &block)
133
+ if block_given?
134
+ rows.fetch(index){return self}.each(&block)
135
+ self
136
+ else
137
+ rows.fetch(index){return nil}
138
+ end
139
+ end
80
140
 
141
+ # Return a column number at the index of the table as an Array.
142
+ # When a block is given, the elements of that Array are iterated over.
143
+ #
144
+ # @example
145
+ # rows = [ ['a1', 'a2'], ['b1', 'b2'] ]
146
+ # table = TTY::Table.new :rows => rows
147
+ # table.column(1) { |element| ... }
148
+ #
149
+ # @param [Integer] index
150
+ #
151
+ # @yield []
152
+ # optional block to execute in the iteration operation
153
+ #
154
+ # @return [self]
155
+ #
156
+ # @api public
157
+ def column(index)
158
+ if block_given?
159
+ return self if index >= column_size || index < 0
160
+ rows.map { |row| yield row[index].compact }
161
+ else
162
+ return nil if index >= column_size || index < 0
163
+ rows.map { |row| row[index] }.compact
164
+ end
165
+ end
166
+
167
+ # Add row to table
168
+ #
169
+ # @param [Array] row
170
+ #
81
171
  # @api public
82
172
  def <<(row)
173
+ rows_copy = rows.dup
174
+ assert_row_sizes rows_copy << row
83
175
  rows << row
84
176
  end
85
177
 
@@ -87,11 +179,12 @@ module TTY
87
179
  #
88
180
  # @example
89
181
  # table = TTY::Table.new(header, tuples)
90
- # table.each { |tuple| ... }
182
+ # table.each { |row| ... }
91
183
  #
92
- # @yield [tuple]
184
+ # @yield [Array[Array]]
93
185
  #
94
186
  # @return [self]
187
+ #
95
188
  # @api public
96
189
  def each
97
190
  return to_enum unless block_given?
@@ -101,22 +194,62 @@ module TTY
101
194
  self
102
195
  end
103
196
 
197
+ # Return the number of columns
198
+ #
199
+ # @example
200
+ # table.column_size # => 5
201
+ #
202
+ # @return [Integer]
203
+ #
204
+ # @api public
205
+ def column_size
206
+ return rows[0].size if (rows.size > 0)
207
+ return 0
208
+ end
209
+
104
210
  # Return the number of rows
105
211
  #
106
212
  # @example
107
- # table.size # => 5
213
+ # table.row_size # => 5
108
214
  #
109
215
  # @return [Integer]
216
+ #
217
+ # @api public
218
+ def row_size
219
+ rows.size
220
+ end
221
+
222
+ # Return the number of rows and columns
223
+ #
224
+ # @example
225
+ # table.size # => [3,5]
226
+ #
227
+ # @return [Array] row x columns
228
+ #
229
+ # @api public
110
230
  def size
111
- return rows[0].length if (rows.length > 0)
112
- return 0
231
+ [row_size, column_size]
113
232
  end
114
233
 
115
234
  # Check table width
116
235
  #
117
236
  # @return [Integer] width
237
+ #
238
+ # @api public
118
239
  def width
119
-
240
+ extract_column_widths(rows)
241
+ total_width
242
+ end
243
+
244
+ # Compare this table with other table for equality
245
+ #
246
+ # @param [TTY::Table] other
247
+ #
248
+ # @return [Boolean]
249
+ #
250
+ # @api public
251
+ def eql?(other)
252
+ instance_of?(other.class)
120
253
  end
121
254
 
122
255
  # Compare the table with other table for equivalency
@@ -135,23 +268,25 @@ module TTY
135
268
 
136
269
  # Return string representation of table
137
270
  #
271
+ # @return [String]
272
+ #
138
273
  # @api public
139
274
  def to_s
140
- renderer.render(rows)
275
+ render(rows)
141
276
  end
142
277
 
143
278
  # Coerce an Enumerable into a Table
279
+ # This coercion mechanism is used by Table to handle Enumerable types
280
+ # and force them into array type.
144
281
  #
145
282
  # @param [Enumerable] object
146
283
  # the object to coerce
147
284
  #
148
- def self.coerce(object)
149
- if object.kind_of?(TTY::Table)
150
- object
151
- elsif object.kind_of?(Hash)
152
- array = [object.keys]
153
- array << object.values
154
- end
285
+ # @return [Array]
286
+ #
287
+ # @api public
288
+ def coerce(rows)
289
+ convert_to_array(rows)
155
290
  end
156
291
 
157
292
  private