tty 0.0.9 → 0.0.10

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 (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