textify 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Joseph Weissman
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,33 @@
1
+ = Textify
2
+
3
+ Some basic, non-curses-based functions to aid user
4
+ interaction in text-only ruby scripts. Included are
5
+ functions for
6
+
7
+ * Justifying strings
8
+ * List selection, confirmation, data entry
9
+ * Displaying arrays and hashes as tables
10
+
11
+ == Usage
12
+ require "textify"
13
+ class MyClass
14
+ textify
15
+ def foo
16
+ [[1,2,3],[4,5,6],[7,8,9]].table({:headings => %w[ one two three ]})
17
+ end
18
+ end
19
+
20
+ o = MyClass.new
21
+ o.foo
22
+
23
+
24
+ The snippet above outputs:
25
+
26
+
27
+ ****************************************
28
+ * one * two * three *
29
+ ****************************************
30
+ * 1 * 2 * 3 *
31
+ * 4 * 5 * 6 *
32
+ * 7 * 8 * 9 *
33
+ ****************************************
@@ -0,0 +1,33 @@
1
+ = Textify
2
+
3
+ Some basic, non-curses-based functions to aid user
4
+ interaction in text-only ruby scripts. Included are
5
+ functions for
6
+
7
+ * Justifying strings
8
+ * List selection, confirmation, data entry
9
+ * Displaying arrays and hashes as tables
10
+
11
+ == Usage
12
+ require "textify"
13
+ class MyClass
14
+ textify
15
+ def foo
16
+ [[1,2,3],[4,5,6],[7,8,9]].table({:headings => %w[ one two three ]})
17
+ end
18
+ end
19
+
20
+ o = MyClass.new
21
+ o.foo
22
+
23
+
24
+ The snippet above outputs:
25
+
26
+
27
+ ****************************************
28
+ * one * two * three *
29
+ ****************************************
30
+ * 1 * 2 * 3 *
31
+ * 4 * 5 * 6 *
32
+ * 7 * 8 * 9 *
33
+ ****************************************
@@ -0,0 +1,21 @@
1
+ require "textify"
2
+ class MyClass
3
+ textify
4
+ def foo
5
+ # @val = ask "Enter a value: "
6
+ [[1,2,3],[4,5,6],[7,8,9]].table({:headings => %w[ one two three ]})
7
+ end
8
+ end
9
+
10
+ o = MyClass.new
11
+ o.foo
12
+
13
+ =begin
14
+ ****************************************
15
+ * one * two * three *
16
+ ****************************************
17
+ * 1 * 2 * 3 *
18
+ * 4 * 5 * 6 *
19
+ * 7 * 8 * 9 *
20
+ ****************************************
21
+ =end
@@ -0,0 +1,348 @@
1
+ module Textify
2
+ =begin
3
+
4
+ = Textify
5
+
6
+ Some basic, non-curses-based functions to aid user
7
+ interaction in text-only ruby scripts. Included are
8
+ functions for
9
+
10
+ * Justifying strings
11
+ * List selection, confirmation, data entry
12
+ * Displaying arrays and hashes as tables
13
+
14
+ == Usage
15
+ require "textify"
16
+ class MyClass
17
+ textify
18
+ def foo
19
+ [[1,2,3],[4,5,6],[7,8,9]].table({:headings => %w[ one two three ]})
20
+ end
21
+ end
22
+
23
+ o = MyClass.new
24
+ o.foo
25
+
26
+
27
+ The snippet above outputs:
28
+
29
+
30
+ ****************************************
31
+ * one * two * three *
32
+ ****************************************
33
+ * 1 * 2 * 3 *
34
+ * 4 * 5 * 6 *
35
+ * 7 * 8 * 9 *
36
+ ****************************************
37
+
38
+ =end
39
+
40
+ DefaultScreenWidth = 40
41
+
42
+ # minor utility fns
43
+ def br n=1; puts until (n-=1)<0; end
44
+ def cls; br 50; end
45
+
46
+
47
+ =begin
48
+
49
+ Textual.justify (direction, text, options={})
50
+
51
+ Justifies text within the default screen width. Accepts in the options hash:
52
+
53
+ :width set a new default width for this justification
54
+ :character fill with another characer (default is ' ')
55
+
56
+ =end
57
+
58
+ def justify(direction, text, options={})
59
+ # puts "Entering justify..."
60
+ width = options[:width] || DefaultScreenWidth
61
+ if text.length >= width
62
+ # puts "Returning, text '#{text}' (#{text.size}) too big for width #{width}."
63
+ return text
64
+ end
65
+
66
+ orig_text = text
67
+ char = options[:character] || ' '
68
+
69
+ usable_space = width-text.length
70
+ offset = char*usable_space
71
+ left_offset = char * (usable_space.to_f/2).ceil
72
+ right_offset = char * (usable_space - left_offset.size)
73
+
74
+ #half_offset = offset.slice(0..(offset.size/2).floor)
75
+ # puts "Usable space: #{usable_space}. Left: #{left_offset.size}. Right: #{right_offset.size}."
76
+
77
+ text = case direction #.downcase.to_sym
78
+ when :left then "#{text}#{offset}"
79
+ when :right then "#{offset}#{text}"
80
+ when :center then "#{left_offset}#{text}#{right_offset}"
81
+ else text
82
+ end
83
+
84
+ # puts "- Justifying (#{direction.to_s}) to width (#{width}): '#{orig_text}' => \t'#{text}'"
85
+
86
+ text
87
+ end
88
+
89
+
90
+ def test_justify
91
+ title " Testing justify command "
92
+ text = justify :left, "Left Justifed"
93
+ puts text
94
+ puts justify(:right, "Right Justifed")
95
+ puts justify(:center, "Center Justifed")
96
+ puts "Unjustified"
97
+ true
98
+ end
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+ def title name, options={}
107
+ br options[:offset] || 2
108
+ print "#{justify :center, name, {:character => options[:character] || '='}}"
109
+ br options[:offset] || 2
110
+ end
111
+
112
+ def test_title
113
+ title " Sample Title 1 "
114
+ title " Sample Title 2 ", {:character => '@', :offset => 3 }
115
+ title " Sample Title 3 ", {:character => "&", :offset => 2 }
116
+ true
117
+ end
118
+
119
+
120
+
121
+ def display_selection items, prompt
122
+ title prompt # print "\n"*3
123
+ items.each_with_index { |item, n| puts " [#{n+1}] #{item.gsub('_',' ').capitalize} \n" }
124
+ print "\n > "
125
+ @input = gets.to_i;
126
+ end
127
+
128
+ def select(items, prompt=" Please select one of the following options: ", options={})
129
+ #title prompt # print "\n"*3
130
+ #items.each_with_index { |item, n| puts " [#{n+1}] #{item.gsub('_',' ').capitalize} \n" }
131
+ #print "\n > "
132
+ #input = gets.to_i;
133
+ # display_selection;
134
+ @input=0; display_selection(items, prompt) until (@input >= 1 and @input <= items.size)
135
+ #title prompt # print "\n"*3
136
+ #items.each_with_index { |item, n| puts " [#{n+1}] #{item.gsub('_',' ').capitalize} \n" }
137
+ #print "\n > "
138
+ #input = gets.to_i
139
+ #end
140
+
141
+ puts "Selected #{@input} (#{items[@input-1]}).. " #{ }"#{options[input-1]}."
142
+ return items[@input-1]
143
+ end
144
+
145
+ def test_select
146
+ title " Selection Test "
147
+ choices = %w[ apples strawberries bananas mandarin_oranges tangerines oranges cherries watermelons raspberries ]
148
+ option = select choices
149
+ title "Thanks for choosing #{option}!"
150
+ true
151
+ end
152
+
153
+
154
+
155
+
156
+ def confirm(prompt = "Please confirm. ", options = {})
157
+ choices = options[:choices] || %w[ Yes No]
158
+ input = select choices, prompt
159
+ return true if input == choices[0]
160
+ return false
161
+ end
162
+
163
+ def test_confirm
164
+ puts "Must be nice..." if confirm "Are you human?"
165
+ true
166
+ end
167
+
168
+
169
+
170
+ def ask(prompt="\n >",options={})
171
+ prompt = prompt.to_s + "? " if prompt.class == Symbol
172
+ print prompt.capitalize
173
+
174
+ if options[:validate]
175
+ input = gets.chomp
176
+ if options[:validate].downcase == 'numeric'
177
+ end
178
+ else
179
+ return gets.chomp
180
+ end
181
+ end
182
+
183
+ def test_ask
184
+ title " Test Input Gathering "
185
+ name = ask "What's your name? "
186
+ puts "Thanks for answering, #{name}!"
187
+ age = ask "How old are you? "
188
+ puts "Great! It must be nice to be #{age} years old."
189
+ true
190
+ end
191
+
192
+
193
+
194
+
195
+
196
+
197
+ def tabulate(data, options={}); data.table options if %w[ Hash Array ].include? data.class.name; end
198
+
199
+ def test_table
200
+ title " Testing tables "
201
+
202
+ tabulate({:one => "1", :two => "2", :three => "3", :four => "4", :five => "512351234123"}); br 2
203
+ tabulate([[1,2,3,4],[4,5,6,7],[7,8,9,0]], {:headings => %w[ alpha beta gamma delta ], :width => 100} ); br 3
204
+ tabulate([[1,2,3,4],[4,5,6,7],[7,8,9,0]], {:headings => %w[ alpha beta gamma delta ], :width => 50} ); br 3
205
+
206
+ true
207
+ end
208
+
209
+
210
+
211
+
212
+ def unit_test
213
+
214
+ title " Textual Unit Test "
215
+
216
+ results = {}
217
+
218
+ %w[ title ask select confirm justify table ].each {
219
+ |operation| results[operation.to_sym] = send("test_"+operation)
220
+ }
221
+ =begin
222
+ results << {:title, test_title}
223
+ results << {:ask, test_ask}
224
+ results << {:select, test_select}
225
+ results << {:confirm, test_confirm}
226
+ results << {:justify, test_justify}
227
+ results << {:table, test_table}
228
+ =end
229
+ title " Internal Unit Test Results "
230
+ results.each_pair {|k,v| puts " #{k} => #{v==true ? 'pass' : 'fail'}" }
231
+
232
+ assertions = results.size
233
+ passed = results.select { |k,v| v=true }.size
234
+ failed = results.select { |k,v| v=false }.size
235
+
236
+ title " #{assertions} assertions, #{failed} failed, #{passed} passed "
237
+
238
+ return false if failed > 0
239
+ true
240
+ end
241
+ end
242
+
243
+ def textify; include Textify; end
244
+
245
+
246
+ #################################
247
+ # Extensions to Hash
248
+ ########
249
+
250
+ class Hash
251
+ textify
252
+ # include Textual
253
+ def self_analyze
254
+ @minimal_element, @maximal_element = nil,nil
255
+ @min_elem_sz, @max_elem_sz = 0, 0
256
+ each_pair do |k,v|
257
+ [k,v].each do |element|
258
+ if element.to_s.size > @max_elem_sz
259
+ @maximal_element = element; @max_elem_sz = element.to_s.size
260
+ elsif element.to_s.size < @min_elem_sz
261
+ @minimal_element = element; @min_elem_sz = element.to_s.size
262
+ end
263
+ end
264
+ end
265
+ # puts "[Hash.self_analyze] Maximal element => '#{@maximal_element}' (#{@max_elem_sz}), minimal element => '#{@minimal_element}'"
266
+ end
267
+
268
+ def table options={}
269
+ self_analyze
270
+ width = options[:width] || DefaultScreenWidth
271
+ min_column_width = @maximal_element.to_s.size + 2
272
+ column_width = [min_column_width, (width-3).to_f/2].max.to_i
273
+ width = column_width*2 + 3
274
+ hb = "*"*width+"\n"
275
+ result = hb
276
+ each_pair{|k,v| result += "*#{justify :center, k.to_s, :width => (column_width)}*#{justify :center, v, :width=>(column_width)}*\n"}
277
+ result += hb
278
+ puts result
279
+ end
280
+ end
281
+
282
+
283
+ ####################
284
+ # Extensions to Array
285
+ #####
286
+
287
+ class Array
288
+ # include Textual
289
+ textify
290
+
291
+ def self_analyze
292
+ @minimal_element, @maximal_element = nil,nil
293
+ @min_elem_sz, @max_elem_sz = 0, 0
294
+ each do |row|
295
+ if row.is_a? Array
296
+ row.each do |element|
297
+ if element.to_s.size > @max_elem_sz
298
+ @maximal_element = element; @max_elem_sz = element.to_s.size
299
+ elsif element.to_s.size < @min_elem_sz
300
+ @minimal_element = element; @min_elem_sz = element.to_s.size
301
+ end
302
+ end
303
+ end
304
+ end
305
+ # puts "[Array.self_analyze] Maximal element => '#{@maximal_element}' (#{@max_elem_sz}), minimal element => '#{@minimal_element}'"
306
+ end
307
+
308
+ def table options = {}
309
+ width = options[:width] || DefaultScreenWidth
310
+ self_analyze
311
+
312
+ columns = self[0].size
313
+
314
+ min_column_width = @maximal_element.to_s.size + 2
315
+ column_width = [min_column_width, ((width.to_i-columns).to_f/columns)].max.to_i
316
+ width = (column_width*columns) + columns + 1
317
+
318
+ hb = ("*"*(width))+"\n"
319
+ result = hb
320
+
321
+ # puts "[Array.table] Columns = #{columns}. Total width = #{width}. Column width = #{column_width}."
322
+
323
+ if options[:headings] then
324
+ options[:headings].each{ |th| result += "*#{justify :center, th.to_s, :width => column_width}"}
325
+ result += "*\n"
326
+ result += hb
327
+ end
328
+ each do |row|
329
+ row.each do |item|
330
+ result += "*#{justify :center, item.to_s, :width => column_width}"
331
+ end
332
+ result += "*\n"
333
+ end
334
+ result += hb
335
+
336
+ puts result
337
+ end
338
+ end
339
+
340
+
341
+ #### sample interface unit test ##############
342
+
343
+
344
+ if __FILE__ == $0
345
+ class SampleUI; textify; def test_textify; unit_test; end; end
346
+ sample_user_interface = SampleUI.new
347
+ sample_user_interface.test_textify
348
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'textify'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,13 @@
1
+ require 'helper'
2
+ require 'textify'
3
+
4
+ class TestTextify < Test::Unit::TestCase
5
+ should "pass internal unit test" do
6
+ class SampleUI; textify; def test_textify; unit_test; end; end
7
+ sample_user_interface = SampleUI.new
8
+ passed_unit_test = sample_user_interface.test_textify
9
+
10
+ assert passed_unit_test
11
+ flunk "failed internal unit test!" if not passed_unit_test
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: textify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Joseph Weissman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-08 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A collection of simple, non-curses-based functions to assist building user interaction into text-only ruby scripts
17
+ email: jweissman1986@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README
25
+ - README.rdoc
26
+ files:
27
+ - lib/sample.rb
28
+ - lib/textify.rb
29
+ - LICENSE
30
+ - README
31
+ - README.rdoc
32
+ has_rdoc: true
33
+ homepage: http://github.com/jweissman1986/Textify
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --charset=UTF-8
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project:
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: non-curses text-based library to aid user interaction
60
+ test_files:
61
+ - test/helper.rb
62
+ - test/test_textify.rb