tty 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/.rspec +2 -1
  2. data/.travis.yml +3 -6
  3. data/README.md +232 -134
  4. data/lib/tty/plugins/plugin.rb +56 -0
  5. data/lib/tty/plugins.rb +75 -0
  6. data/lib/tty/shell/suggestion.rb +102 -0
  7. data/lib/tty/shell.rb +41 -14
  8. data/lib/tty/system/editor.rb +111 -0
  9. data/lib/tty/system/which.rb +13 -1
  10. data/lib/tty/system.rb +44 -28
  11. data/lib/tty/table/border/null.rb +0 -9
  12. data/lib/tty/table/border/row_line.rb +21 -0
  13. data/lib/tty/table/border.rb +63 -32
  14. data/lib/tty/table/border_dsl.rb +1 -1
  15. data/lib/tty/table/column_set.rb +16 -17
  16. data/lib/tty/table/field.rb +27 -7
  17. data/lib/tty/table/header.rb +18 -9
  18. data/lib/tty/table/operation/alignment_set.rb +20 -25
  19. data/lib/tty/table/operation/escape.rb +30 -0
  20. data/lib/tty/table/operation/filter.rb +36 -0
  21. data/lib/tty/table/operation/truncation.rb +22 -11
  22. data/lib/tty/table/operation/wrapped.rb +21 -10
  23. data/lib/tty/table/operations.rb +10 -8
  24. data/lib/tty/table/orientation/horizontal.rb +1 -1
  25. data/lib/tty/table/renderer/ascii.rb +3 -3
  26. data/lib/tty/table/renderer/basic.rb +135 -65
  27. data/lib/tty/table/renderer/color.rb +1 -4
  28. data/lib/tty/table/renderer/unicode.rb +3 -3
  29. data/lib/tty/table/renderer.rb +48 -61
  30. data/lib/tty/table/row.rb +30 -3
  31. data/lib/tty/table/transformation.rb +38 -0
  32. data/lib/tty/table/validatable.rb +7 -5
  33. data/lib/tty/table.rb +78 -99
  34. data/lib/tty/terminal/color.rb +2 -2
  35. data/lib/tty/terminal/echo.rb +1 -1
  36. data/lib/tty/terminal/pager/basic.rb +52 -0
  37. data/lib/tty/terminal/pager/system.rb +39 -0
  38. data/lib/tty/terminal/pager.rb +95 -0
  39. data/lib/tty/terminal.rb +30 -1
  40. data/lib/tty/version.rb +1 -1
  41. data/lib/tty.rb +41 -1
  42. data/spec/spec_helper.rb +20 -0
  43. data/spec/tty/plugins/find_spec.rb +28 -0
  44. data/spec/tty/plugins/load_spec.rb +20 -0
  45. data/spec/tty/plugins/plugin/load_spec.rb +30 -0
  46. data/spec/tty/plugins/plugin/new_spec.rb +18 -0
  47. data/spec/tty/shell/suggest_spec.rb +50 -0
  48. data/spec/tty/support/conversion_spec.rb +3 -3
  49. data/spec/tty/support/delegatable_spec.rb +1 -1
  50. data/spec/tty/support/equatable_spec.rb +6 -9
  51. data/spec/tty/system/editor/available_spec.rb +40 -0
  52. data/spec/tty/system/editor/build_spec.rb +40 -0
  53. data/spec/tty/system/editor/command_spec.rb +16 -0
  54. data/spec/tty/system/editor/executables_spec.rb +13 -0
  55. data/spec/tty/system/editor/invoke_spec.rb +38 -0
  56. data/spec/tty/system/editor/open_spec.rb +27 -0
  57. data/spec/tty/system/platform_spec.rb +4 -6
  58. data/spec/tty/system/which/which_spec.rb +48 -0
  59. data/spec/tty/system/which_spec.rb +8 -34
  60. data/spec/tty/table/border/ascii/rendering_spec.rb +19 -5
  61. data/spec/tty/table/border/new_spec.rb +1 -1
  62. data/spec/tty/table/border/null/rendering_spec.rb +24 -8
  63. data/spec/tty/table/border/unicode/rendering_spec.rb +19 -5
  64. data/spec/tty/table/column_set/extract_widths_spec.rb +4 -15
  65. data/spec/tty/table/column_set/total_width_spec.rb +15 -0
  66. data/spec/tty/table/data_spec.rb +14 -0
  67. data/spec/tty/table/each_spec.rb +17 -4
  68. data/spec/tty/table/each_with_index_spec.rb +34 -6
  69. data/spec/tty/table/field/length_spec.rb +21 -0
  70. data/spec/tty/table/field/lines_spec.rb +21 -0
  71. data/spec/tty/table/filter_spec.rb +23 -0
  72. data/spec/tty/table/header/call_spec.rb +1 -1
  73. data/spec/tty/table/header/height_spec.rb +27 -0
  74. data/spec/tty/table/initialize_spec.rb +6 -6
  75. data/spec/tty/table/operation/alignment_set/call_spec.rb +39 -0
  76. data/spec/tty/table/operation/escape/call_spec.rb +16 -0
  77. data/spec/tty/table/operation/filter/call_spec.rb +17 -0
  78. data/spec/tty/table/operation/truncation/call_spec.rb +15 -10
  79. data/spec/tty/table/operation/truncation/truncate_spec.rb +1 -1
  80. data/spec/tty/table/operation/wrapped/call_spec.rb +15 -10
  81. data/spec/tty/table/operation/wrapped/wrap_spec.rb +1 -1
  82. data/spec/tty/table/operations/new_spec.rb +4 -4
  83. data/spec/tty/table/options_spec.rb +0 -28
  84. data/spec/tty/table/orientation_spec.rb +5 -6
  85. data/spec/tty/table/properties_spec.rb +1 -4
  86. data/spec/tty/table/render_spec.rb +57 -0
  87. data/spec/tty/table/{renders_with_spec.rb → render_with_spec.rb} +29 -10
  88. data/spec/tty/table/renderer/ascii/render_spec.rb +68 -0
  89. data/spec/tty/table/renderer/ascii/separator_spec.rb +28 -0
  90. data/spec/tty/table/renderer/basic/alignment_spec.rb +18 -16
  91. data/spec/tty/table/renderer/basic/extract_column_widths_spec.rb +17 -12
  92. data/spec/tty/table/renderer/basic/filter_spec.rb +53 -0
  93. data/spec/tty/table/renderer/basic/multiline_content_spec.rb +135 -0
  94. data/spec/tty/table/renderer/basic/new_spec.rb +13 -2
  95. data/spec/tty/table/renderer/basic/options_spec.rb +48 -0
  96. data/spec/tty/table/renderer/basic/render_spec.rb +19 -121
  97. data/spec/tty/table/renderer/basic/separator_spec.rb +14 -48
  98. data/spec/tty/table/renderer/basic/truncation_spec.rb +35 -0
  99. data/spec/tty/table/renderer/basic/wrapping_spec.rb +40 -0
  100. data/spec/tty/table/{border_spec.rb → renderer/border_spec.rb} +17 -20
  101. data/spec/tty/table/renderer/select_spec.rb +22 -0
  102. data/spec/tty/table/{border → renderer}/style_spec.rb +13 -14
  103. data/spec/tty/table/renderer/unicode/render_spec.rb +68 -0
  104. data/spec/tty/table/renderer/unicode/separator_spec.rb +26 -0
  105. data/spec/tty/table/rotate_spec.rb +2 -3
  106. data/spec/tty/table/row/call_spec.rb +1 -1
  107. data/spec/tty/table/row/each_spec.rb +31 -0
  108. data/spec/tty/table/row/height_spec.rb +27 -0
  109. data/spec/tty/table/to_s_spec.rb +3 -3
  110. data/spec/tty/table/transformation/extract_tuples_spec.rb +35 -0
  111. data/spec/tty/table/validatable/validate_options_spec.rb +1 -2
  112. data/spec/tty/terminal/home_spec.rb +3 -3
  113. data/spec/tty/terminal/page_spec.rb +13 -0
  114. data/spec/tty/terminal/pager/available_spec.rb +40 -0
  115. data/spec/tty/terminal/pager/basic/page_spec.rb +54 -0
  116. data/spec/tty/terminal/pager/command_spec.rb +16 -0
  117. data/spec/tty/terminal/pager/executables_spec.rb +13 -0
  118. data/spec/tty/terminal/pager/page_spec.rb +47 -0
  119. data/spec/tty/terminal/pager/system/page_spec.rb +29 -0
  120. data/spec/tty/text/distance/distance_spec.rb +12 -0
  121. data/tty.gemspec +7 -3
  122. metadata +160 -27
  123. data/spec/tty/table/operation/alignment_set/align_rows_spec.rb +0 -53
  124. data/spec/tty/table/renderer/pick_renderer_spec.rb +0 -25
  125. data/spec/tty/table/renderer_spec.rb +0 -49
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --color
2
- -f s
2
+ --format progress
3
+ --order random
data/.travis.yml CHANGED
@@ -2,18 +2,15 @@ language: ruby
2
2
  before_install:
3
3
  - gem install bundler
4
4
  rvm:
5
- - 1.8.7
6
- - 1.9.2
7
5
  - 1.9.3
6
+ - 2.0.0
8
7
  - ruby-head
9
- - jruby-18mode
10
8
  - jruby-19mode
11
- - rbx-18mode
12
9
  - rbx-19mode
13
- - ree
14
10
  - jruby-head
11
+ - rbx-head
15
12
  matrix:
16
13
  allow_failures:
17
14
  - rvm: ruby-head
18
15
  - rvm: jruby-head
19
- - rvm: rbx-19mode
16
+ - rvm: rbx-head
data/README.md CHANGED
@@ -2,10 +2,12 @@
2
2
  [![Gem Version](https://badge.fury.io/rb/tty.png)][gem]
3
3
  [![Build Status](https://secure.travis-ci.org/peter-murach/tty.png?branch=master)][travis]
4
4
  [![Code Climate](https://codeclimate.com/github/peter-murach/tty.png)][codeclimate]
5
+ [![Coverage Status](https://coveralls.io/repos/peter-murach/tty/badge.png?branch=master)][coveralls]
5
6
 
6
7
  [gem]: http://badge.fury.io/rb/tty
7
8
  [travis]: http://travis-ci.org/peter-murach/tty
8
9
  [codeclimate]: https://codeclimate.com/github/peter-murach/tty
10
+ [coveralls]: https://coveralls.io/r/peter-murach/tty
9
11
 
10
12
  Toolbox for developing CLI clients in Ruby. This library provides a fluid interface for working with terminals.
11
13
 
@@ -13,9 +15,9 @@ Toolbox for developing CLI clients in Ruby. This library provides a fluid interf
13
15
 
14
16
  Jump-start development of your command line app:
15
17
 
16
- * Table rendering with an easy-to-use API [status: In Progress]
17
- * Terminal output colorization. [status: ✔ ]
18
- * Terminal & System detection utilities. [status: In Progress]
18
+ * Table rendering with an easy-to-use API. [status: In Progress]
19
+ * Terminal output colorization, paging. [status: ✔ ]
20
+ * System & command detection utilities. [status: In Progress]
19
21
  * Text manipulation(wrapping/truncation) [status: In Progress]
20
22
  * Shell user interface. [status: In Progress]
21
23
  * File diffs. [status: TODO]
@@ -47,75 +49,112 @@ Or install it yourself as:
47
49
  To instantiate table pass 2-dimensional array:
48
50
 
49
51
  ```ruby
50
- table = TTY::Table[['a1', 'a2'], ['b1', 'b2']]
51
- table = TTY::Table.new [['a1', 'a2'], ['b1', 'b2']]
52
- table = TTY::Table.new rows: [['a1', 'a2'], ['b1', 'b2']]
53
- table = TTY::Table.new ['h1', 'h2'], [['a1', 'a2'], ['b1', 'b2']]
54
- table = TTY::Table.new header: ['h1', 'h2'], rows: [['a1', 'a2'], ['b1', 'b2']]
52
+ table = TTY::Table[['a1', 'a2'], ['b1', 'b2']]
53
+ table = TTY::Table.new [['a1', 'a2'], ['b1', 'b2']]
54
+ table = TTY::Table.new rows: [['a1', 'a2'], ['b1', 'b2']]
55
+ table = TTY::Table.new ['h1', 'h2'], [['a1', 'a2'], ['b1', 'b2']]
56
+ table = TTY::Table.new header: ['h1', 'h2'], rows: [['a1', 'a2'], ['b1', 'b2']]
55
57
  ```
56
58
 
57
59
  or cross header with rows inside a hash like so
58
60
 
59
61
  ```ruby
60
- table = TTY::Table.new [{'h1' => ['a1', 'a2'], 'h2' => ['b1', 'b2']}]
62
+ table = TTY::Table.new [{'h1' => ['a1', 'a2'], 'h2' => ['b1', 'b2']}]
61
63
  ```
62
64
 
63
- Apart from `rows` and `header`, you can provide other customization options such as
65
+ Table behaves like an Array so `<<`, `each` and familiar methods can be used
64
66
 
65
67
  ```ruby
66
- column_widths # array of maximum columns widths
67
- column_aligns # array of cell alignments out of :left, :center and :right
68
- renderer # enforce display type out of :basic, :color, :unicode, :ascii
69
- orientation # either :horizontal or :vertical
70
- border # hash of border properties out of :characters, :style, :separator keys
71
- width # constrain the table total width, otherwise dynamically calculated based on content and terminal size
68
+ table << ['a1', 'a2', 'a3']
69
+ table << ['b1', 'b2', 'b3']
70
+ table << ['a1', 'a2'] << ['b1', 'b2'] # chain rows assignment
71
+
72
+ table.each { |row| ... } # iterate over rows
73
+ table.each_with_index # iterate over each element with row and column index
74
+ table[i, j] # return element at row(i) and column(j)
75
+ table.row(i) { ... } # return array for row(i)
76
+ table.column(j) { ... } # return array for column(j)
77
+ table.column(name) # return array for column(name), name of header
78
+ table.row_size # return row size
79
+ table.column_size # return column size
80
+ table.size # return an array of [row_size, column_size]
81
+ table.border # specify border properties
72
82
  ```
73
83
 
74
- Table behaves like an Array so `<<`, `each` and familiar methods can be used
84
+ or pass your rows in a block
75
85
 
76
86
  ```ruby
77
- table << ['a1', 'a2', 'a3']
78
- table << ['b1', 'b2', 'b3']
79
- table << ['a1', 'a2'] << ['b1', 'b2'] # chain rows assignment
80
-
81
- table.each { |row| ... } # iterate over rows
82
- table.each_with_index # iterate over each element with row and column index
83
- table[i, j] # return element at row(i) and column(j)
84
- table.row(i) { ... } # return array for row(i)
85
- table.column(j) { ... } # return array for column(j)
86
- table.column(name) # return array for column(name), name of header
87
- table.row_size # return row size
88
- table.column_size # return column size
89
- table.size # return an array of [row_size, column_size]
90
- table.border # specify border properties
87
+ table = TTY::Table.new do |t|
88
+ t << ['a1', 'a2', 'a3']
89
+ t << ['b1', 'b2', 'b3']
90
+ end
91
91
  ```
92
92
 
93
- or pass your rows in a block
93
+ #### Rendering
94
+
95
+ Once you have an instance of `TTY::Table` you can print it out to the stdout by doing:
94
96
 
95
97
  ```ruby
96
- table = TTY::Table.new do |t|
97
- t << ['a1', 'a2', 'a3']
98
- t << ['b1', 'b2', 'b3']
99
- end
98
+ table.to_s
99
+
100
+ a1 a2 a3
101
+ b1 b2 b3
100
102
  ```
101
103
 
102
- And then to print do
104
+ This will use so called `basic` renderer with default options.
105
+
106
+ However, you can include other customization options such as
103
107
 
104
108
  ```ruby
105
- table.to_s
109
+ column_widths # array of maximum columns widths
110
+ column_aligns # array of cell alignments out of :left, :center and :right, default :left
111
+ width # constrain the table total width, otherwise dynamically calculated based on content and terminal size
112
+ renderer # enforce display type out of :basic, :color, :unicode, :ascii
113
+ border # hash of border properties out of :characters, :style, :separator keys
114
+ border_class # a type of border to use
115
+ multiline # if true will wrap text at new line or column width, when false will escape special characters
116
+ filter # a proc object that is applied to every field in a row
117
+ orientation # either :horizontal or :vertical
118
+ ```
119
+
120
+ #### Multiline
121
+
122
+ Renderer options may include `multiline` parameter. The `true` value will cause the table fields wrap at their natural line breaks or in case when the column widths are set the content will wrap.
106
123
 
107
- a1 a2 a3
108
- b1 b2 b3
124
+ ```
125
+ table = TTY::Table.new [ ["First", '1'], ["Multi\nLine\nContent", '2'], ["Third", '3']]
126
+ table.render :ascii, multiline: true
127
+ # =>
128
+ +-------+-+
129
+ |First |1|
130
+ |Multi |2|
131
+ |Line | |
132
+ |Content| |
133
+ |Third |3|
134
+ +-------+-+
135
+ ```
136
+
137
+ When the `false` option is specified all the special characters will be escaped and if the column widths are set the content will be truncated like so
138
+
139
+ ```ruby
140
+ table = TTY::Table.new [ ["First", '1'], ["Multiline\nContent", '2'], ["Third", '3']]
141
+ table.render :ascii, multiline: false
142
+ # =>
143
+ +------------------+-+
144
+ |First |1|
145
+ |Multiline\nContent|2|
146
+ |Third |3|
147
+ +------------------+-+
109
148
  ```
110
149
 
111
150
  #### Border
112
151
 
113
152
  To print border around data table you need to specify `renderer` type out of `basic`, `ascii`, `unicode`. By default `basic` is used. For instance, to output unicode border:
114
153
 
115
- ```
116
- table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2'], renderer: 'unicode'
117
- table.to_s
118
-
154
+ ```ruby
155
+ table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
156
+ table.render :unicode
157
+ # =>
119
158
  ┌───────┬───────┐
120
159
  │header1│header2│
121
160
  ├───────┼───────┤
@@ -127,25 +166,24 @@ To print border around data table you need to specify `renderer` type out of `ba
127
166
  You can also create your own custom border by subclassing `TTY::Table::Border` and implementing the `def_border` method using internal DSL methods like so:
128
167
 
129
168
  ```ruby
130
- class MyBorder < TTY::Table::Border
131
- def_border do
132
- left '$'
133
- center '$'
134
- right '$'
135
- bottom ' '
136
- bottom_mid '*'
137
- bottom_left '*'
138
- bottom_right '*'
139
- end
169
+ class MyBorder < TTY::Table::Border
170
+ def_border do
171
+ left '$'
172
+ center '$'
173
+ right '$'
174
+ bottom ' '
175
+ bottom_mid '*'
176
+ bottom_left '*'
177
+ bottom_right '*'
140
178
  end
179
+ end
141
180
  ```
142
181
 
143
- Next pass the border class to your instantiated table
182
+ Next pass the border class to your table instance `render_with` method
144
183
 
145
184
  ```ruby
146
- table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
147
- table.renders_with MyBorder
148
- table.to_s
185
+ table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
186
+ table.render_with MyBorder
149
187
 
150
188
  $header1$header2$
151
189
  $a1 $a2 $
@@ -155,13 +193,13 @@ Next pass the border class to your instantiated table
155
193
  Finally, if you want to introduce slight modifications to the predefined border types, you can use table `border` helper like so
156
194
 
157
195
  ```ruby
158
- table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
159
- table.border do
196
+ table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
197
+ table.render do |renderer|
198
+ renderer.border do
160
199
  mid '='
161
200
  mid_mid ' '
162
201
  end
163
-
164
- table.to_s
202
+ end
165
203
 
166
204
  header1 header2
167
205
  ======= =======
@@ -172,9 +210,10 @@ Finally, if you want to introduce slight modifications to the predefined border
172
210
  In addition to specifying border characters you can force table to render separator line on each row like:
173
211
 
174
212
  ```ruby
175
- table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']]
176
- table.border.separator = :each_row
177
- table.to_s
213
+ table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']]
214
+ table.render do |renderer|
215
+ renderer.border.separator = :each_row
216
+ end
178
217
 
179
218
  +-------+-------+
180
219
  |header1|header2|
@@ -188,7 +227,9 @@ In addition to specifying border characters you can force table to render separa
188
227
  Also to change the display color of your border do:
189
228
 
190
229
  ```ruby
191
- table.border.style = :red
230
+ table.render do |renderer|
231
+ renderer.border.style = :red
232
+ end
192
233
  ```
193
234
 
194
235
  #### Alignment
@@ -196,24 +237,25 @@ Also to change the display color of your border do:
196
237
  All columns are left aligned by default. You can enforce per column alignment by passing `column_aligns` option like so
197
238
 
198
239
  ```ruby
199
- rows = [['a1', 'a2'], ['b1', 'b2']
200
- table = TTY::Table.new rows: rows, column_aligns: [:center, :right]
240
+ rows = [['a1', 'a2'], ['b1', 'b2']
241
+ table = TTY::Table.new rows: rows
242
+ table.render column_aligns: [:center, :right]
201
243
  ```
202
244
 
203
245
  To align a single column do
204
246
 
205
247
  ```ruby
206
- table.align_column(1, :right)
248
+ table.align_column(1, :right)
207
249
  ```
208
250
 
209
251
  If you require a more granular alignment you can align individual fields in a row by passing `align` option
210
252
 
211
253
  ```ruby
212
- table = TTY::Table.new do |t|
213
- t << ['a1', 'a2', 'a3']
214
- t << ['b1', {:value => 'b2', :align => :right}, 'b3']
215
- t << ['c1', 'c2', {:value => 'c3', :align => :center}]
216
- end
254
+ table = TTY::Table.new do |t|
255
+ t << ['a1', 'a2', 'a3']
256
+ t << ['b1', {:value => 'b2', :align => :right}, 'b3']
257
+ t << ['c1', 'c2', {:value => 'c3', :align => :center}]
258
+ end
217
259
  ```
218
260
 
219
261
  #### Style
@@ -221,7 +263,8 @@ If you require a more granular alignment you can align individual fields in a ro
221
263
  To format individual fields/cells do
222
264
 
223
265
  ```ruby
224
- table = TTY::Table.new rows: rows, width: 40
266
+ table = TTY::Table.new rows: rows
267
+ table.render width: 40
225
268
  ```
226
269
 
227
270
  #### Filter
@@ -229,13 +272,16 @@ To format individual fields/cells do
229
272
  You can define filters that will modify individual table fields value before they are rendered. A filter can be a callable such as proc. Here's an example that formats
230
273
 
231
274
  ```ruby
232
- table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
233
- table.filter = Proc.new do |val, row_index, col_index|
275
+ table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']
276
+ table.render do |renderer|
277
+ renderer.filter = Proc.new do |val, row_index, col_index|
234
278
  if col_index == 1 and !(row_index == 0)
235
279
  val.capitalize
280
+ else
281
+ val
236
282
  end
237
283
  end
238
- table.to_s
284
+ end
239
285
 
240
286
  +-------+-------+
241
287
  |header1|header2|
@@ -244,12 +290,17 @@ You can define filters that will modify individual table fields value before the
244
290
  +-------+-------+
245
291
  |b1 |B2 |
246
292
  +-------+-------+
247
-
248
293
  ```
249
294
 
250
295
  To add background color to even fields do
251
296
 
252
297
  ```ruby
298
+ table.render do |renderer|
299
+ renderer.filter = Proc.new do |val, row_index, col_index|
300
+ if col_index % 2 == 1
301
+ TTY.color.set val, :red, :on_green
302
+ end
303
+ end
253
304
  ```
254
305
 
255
306
  ### Terminal
@@ -257,19 +308,41 @@ To add background color to even fields do
257
308
  To read general terminal properties you can use on of the helpers
258
309
 
259
310
  ```ruby
260
- term = TTY::Terminal.new
261
- term.width # => 140
262
- term.height # => 60
263
- term.color? # => true or false
264
- term.echo(false) { } # switch off echo for the block
311
+ term = TTY::Terminal.new
312
+ term.width # => 140
313
+ term.height # => 60
314
+ term.color? # => true or false
315
+ term.echo(false) { } # switch off echo for the block
316
+ term.page # page terminal output, on non unix systems falls back to ruby implementation
265
317
  ```
266
318
 
267
319
  To colorize your output do
268
320
 
269
321
  ```ruby
270
- term.color.set 'text...', :bold, :red, :on_green # => red bold text on green background
271
- term.color.remove 'text...' # strips off ansi escape sequences
272
- term.color.code :red # ansi escape code for the supplied color
322
+ term.color.set 'text...', :bold, :red, :on_green # => red bold text on green background
323
+ term.color.remove 'text...' # strips off ansi escape sequences
324
+ term.color.code :red # ansi escape code for the supplied color
325
+ ```
326
+
327
+ Available colors are:
328
+
329
+ ```ruby
330
+ black
331
+ red
332
+ green
333
+ yellow
334
+ blue
335
+ magenta
336
+ cyan
337
+ white
338
+ ```
339
+
340
+ To supply background color simply prefix it with `on_`. For example a green background would be `on_green`.
341
+
342
+ To page your output do
343
+
344
+ ```ruby
345
+ term.page 'long text...'
273
346
  ```
274
347
 
275
348
  ### Shell
@@ -279,88 +352,113 @@ Main responsibility is to interact with the prompt and provide convenience metho
279
352
  Available methods are
280
353
 
281
354
  ```ruby
282
- shell = TTY::Shell.new
283
- shell.ask # print question
284
- shell.read # read from stdin
285
- shell.say # print message to stdout
286
- shell.confirm # print message(s) in green
287
- shell.warn # print message(s) in yellow
288
- shell.error # print message(s) in red
289
- shell.print_table # print table to stdout
355
+ shell = TTY::Shell.new
356
+ shell.ask # print question
357
+ shell.read # read from stdin
358
+ shell.say # print message to stdout
359
+ shell.confirm # print message(s) in green
360
+ shell.warn # print message(s) in yellow
361
+ shell.error # print message(s) in red
362
+ shell.suggest # print suggestion message based on possible matches
363
+ shell.print_table # print table to stdout
290
364
  ```
291
365
 
292
366
  In order to ask question and parse answers:
293
367
 
294
368
  ```ruby
295
- shell = TTY::Shell.new
296
- answer = shell.ask("What is your name?").read_string
369
+ shell = TTY::Shell.new
370
+ answer = shell.ask("What is your name?").read_string
297
371
  ```
298
372
 
299
373
  The library provides small DSL to help with parsing and asking precise questions
300
374
 
301
375
  ```ruby
302
- argument # :required or :optional
303
- character # turn character based input, otherwise line (default: false)
304
- clean # reset question
305
- default # default value used if none is provided
306
- echo # turn echo on and off (default: true)
307
- mask # mask characters i.e '****' (default: false)
308
- modify # apply answer modification :upcase, :downcase, :trim, :chomp etc..
309
- range # specify range '0-9', '0..9', '0...9' or negative '-1..-9'
310
- validate # regex against which stdin input is checked
311
- valid # a list of expected valid options
376
+ argument # :required or :optional
377
+ character # turn character based input, otherwise line (default: false)
378
+ clean # reset question
379
+ default # default value used if none is provided
380
+ echo # turn echo on and off (default: true)
381
+ mask # mask characters i.e '****' (default: false)
382
+ modify # apply answer modification :upcase, :downcase, :trim, :chomp etc..
383
+ range # specify range '0-9', '0..9', '0...9' or negative '-1..-9'
384
+ validate # regex against which stdin input is checked
385
+ valid # a list of expected valid options
312
386
  ```
313
387
 
314
388
  You can chain question methods or configure them inside a block
315
389
 
316
390
  ```ruby
317
- shell.ask("What is your name?").argument(:required).default('Piotr').validate(/\w+\s\w+/).read_string
318
-
319
- shell.ask "What is your name?" do
320
- argument :required
321
- default 'Piotr'
322
- validate /\w+\s\w+/
323
- valid ['Piotr', 'Piotrek']
324
- modify :capitalize
325
- end.read_string
391
+ shell.ask("What is your name?").argument(:required).default('Piotr').validate(/\w+\s\w+/).read_string
392
+
393
+ shell.ask "What is your name?" do
394
+ argument :required
395
+ default 'Piotr'
396
+ validate /\w+\s\w+/
397
+ valid ['Piotr', 'Piotrek']
398
+ modify :capitalize
399
+ end.read_string
326
400
  ```
327
401
 
328
402
  Reading answers and converting them into required types can be done with custom readers
329
403
 
330
404
  ```ruby
331
- read_bool # return true or false for strings such as "Yes", "No"
332
- read_date # return date type
333
- read_datetime # return datetime type
334
- read_email # validate answer against email regex
335
- read_float # return decimal or error if cannot convert
336
- read_int # return integer or error if cannot convert
337
- read_multiple # return multiple line string
338
- read_password # return string with echo turned off
339
- read_range # return range type
340
- read_string # return string
405
+ read_bool # return true or false for strings such as "Yes", "No"
406
+ read_date # return date type
407
+ read_datetime # return datetime type
408
+ read_email # validate answer against email regex
409
+ read_float # return decimal or error if cannot convert
410
+ read_int # return integer or error if cannot convert
411
+ read_multiple # return multiple line string
412
+ read_password # return string with echo turned off
413
+ read_range # return range type
414
+ read_string # return string
341
415
  ```
342
416
 
343
417
  For example, if we wanted to ask a user for a single digit in given range
344
418
 
345
419
  ```ruby
346
- ask("Provide number in range: 0-9") do
347
- range '0-9'
348
- on_error :retry
349
- end.read_int
420
+ ask("Provide number in range: 0-9") do
421
+ range '0-9'
422
+ on_error :retry
423
+ end.read_int
350
424
  ```
351
425
 
352
426
  on the other hand, if we are interested in range answer then
353
427
 
354
428
  ```ruby
355
- ask("Provide range of numbers?").read_range
429
+ ask("Provide range of numbers?").read_range
430
+ ```
431
+
432
+ To suggest possible matches for the user input use `suggest` method like so
433
+
434
+ ```ruby
435
+ shell.suggest('sta', ['stage', 'stash', 'commit', 'branch'])
436
+ # =>
437
+ Did you mean one of these?
438
+ stage
439
+ stash
356
440
  ```
357
441
 
358
442
  ### System
359
443
 
360
444
  ```ruby
361
- TTY::System.unix? # => true
362
- TTY::System.windows? # => false
363
- TTY::System.which(cmd) # full path to executable if found, nil otherwise
445
+ TTY::System.unix? # check if unix platform
446
+ TTY::System.windows? # check if windows platform
447
+ TTY::System.which(cmd) # full path to executable if found, nil otherwise
448
+ TTY::System.exists?(cmd) # check if command is available
449
+ TTY::System.editor # provides access to system editor
450
+ ```
451
+
452
+ To set preferred editor you can either use shell environment variables such as `EDITOR` and `VISUAL` or set the command(s) manually like so
453
+
454
+ ```ruby
455
+ TTY::System.editor.command('vim')
456
+ ```
457
+
458
+ To open a file in your editor of choice do
459
+
460
+ ```ruby
461
+ TTY::System.editor.open('file path...')
364
462
  ```
365
463
 
366
464
  ## Contributing
@@ -0,0 +1,56 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module TTY
4
+
5
+ # A class responsible for plugin loading
6
+ class Plugin
7
+
8
+ attr_reader :name
9
+
10
+ attr_reader :gem
11
+
12
+ attr_reader :gem_name
13
+
14
+ attr_accessor :enabled
15
+
16
+ # Initialize a Plugin
17
+ #
18
+ # @param [String] name
19
+ # the plugin name
20
+ #
21
+ # @param [Gem::Specification] gem
22
+ # the rubygems gem
23
+ #
24
+ # @api public
25
+ def initialize(name, gem)
26
+ @name = name
27
+ @gem = gem
28
+ @gem_name = "tty-#{name}"
29
+ @enabled = false
30
+ end
31
+
32
+ # Check if this plugin has been enabled
33
+ #
34
+ # @return [Boolean]
35
+ #
36
+ # @api public
37
+ def enabled?
38
+ !!enabled
39
+ end
40
+
41
+ # Load the plugin (require the gem)
42
+ #
43
+ # @api public
44
+ def load!
45
+ begin
46
+ require gem_name unless enabled?
47
+ rescue LoadError => error
48
+ TTY.shell.error("Unable to load plugin #{gem_name}.")
49
+ rescue => error
50
+ TTY.shell.error("require '#{gem_name}' failed with #{error}")
51
+ end
52
+ self.enabled = true
53
+ end
54
+
55
+ end # Plugin
56
+ end # TTY