canis 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +45 -0
  3. data/CHANGES +52 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +24 -0
  7. data/Rakefile +2 -0
  8. data/canis.gemspec +25 -0
  9. data/examples/alpmenu.rb +46 -0
  10. data/examples/app.sample +19 -0
  11. data/examples/appemail.rb +191 -0
  12. data/examples/atree.rb +105 -0
  13. data/examples/bline.rb +181 -0
  14. data/examples/common/devel.rb +319 -0
  15. data/examples/common/file.rb +93 -0
  16. data/examples/data/README.markdown +9 -0
  17. data/examples/data/brew.txt +38 -0
  18. data/examples/data/color.2 +37 -0
  19. data/examples/data/gemlist.txt +59 -0
  20. data/examples/data/lotr.txt +12 -0
  21. data/examples/data/ports.txt +136 -0
  22. data/examples/data/table.txt +37 -0
  23. data/examples/data/tasks.csv +88 -0
  24. data/examples/data/tasks.txt +27 -0
  25. data/examples/data/todo.txt +16 -0
  26. data/examples/data/todocsv.csv +28 -0
  27. data/examples/data/unix1.txt +21 -0
  28. data/examples/data/unix2.txt +11 -0
  29. data/examples/dbdemo.rb +506 -0
  30. data/examples/dirtree.rb +177 -0
  31. data/examples/newtabbedwindow.rb +100 -0
  32. data/examples/newtesttabp.rb +92 -0
  33. data/examples/tabular.rb +212 -0
  34. data/examples/tasks.rb +179 -0
  35. data/examples/term2.rb +88 -0
  36. data/examples/testbuttons.rb +307 -0
  37. data/examples/testcombo.rb +102 -0
  38. data/examples/testdb.rb +182 -0
  39. data/examples/testfields.rb +208 -0
  40. data/examples/testflowlayout.rb +43 -0
  41. data/examples/testkeypress.rb +98 -0
  42. data/examples/testlistbox.rb +187 -0
  43. data/examples/testlistbox1.rb +199 -0
  44. data/examples/testmessagebox.rb +144 -0
  45. data/examples/testprogress.rb +116 -0
  46. data/examples/testree.rb +107 -0
  47. data/examples/testsplitlayout.rb +53 -0
  48. data/examples/testsplitlayout1.rb +49 -0
  49. data/examples/teststacklayout.rb +48 -0
  50. data/examples/testwsshortcuts.rb +68 -0
  51. data/examples/testwsshortcuts2.rb +129 -0
  52. data/lib/canis.rb +16 -0
  53. data/lib/canis/core/docs/index.txt +104 -0
  54. data/lib/canis/core/docs/list.txt +16 -0
  55. data/lib/canis/core/docs/style_help.yml +34 -0
  56. data/lib/canis/core/docs/tabbedpane.txt +15 -0
  57. data/lib/canis/core/docs/table.txt +31 -0
  58. data/lib/canis/core/docs/textpad.txt +48 -0
  59. data/lib/canis/core/docs/tree.txt +23 -0
  60. data/lib/canis/core/include/.DS_Store +0 -0
  61. data/lib/canis/core/include/action.rb +83 -0
  62. data/lib/canis/core/include/actionmanager.rb +49 -0
  63. data/lib/canis/core/include/appmethods.rb +179 -0
  64. data/lib/canis/core/include/bordertitle.rb +49 -0
  65. data/lib/canis/core/include/canisparser.rb +100 -0
  66. data/lib/canis/core/include/colorparser.rb +437 -0
  67. data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
  68. data/lib/canis/core/include/io.rb +320 -0
  69. data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
  70. data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
  71. data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
  72. data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
  73. data/lib/canis/core/include/listbindings.rb +89 -0
  74. data/lib/canis/core/include/listeditable.rb +319 -0
  75. data/lib/canis/core/include/listoperations.rb +61 -0
  76. data/lib/canis/core/include/listselectionmodel.rb +388 -0
  77. data/lib/canis/core/include/multibuffer.rb +173 -0
  78. data/lib/canis/core/include/ractionevent.rb +73 -0
  79. data/lib/canis/core/include/rchangeevent.rb +27 -0
  80. data/lib/canis/core/include/rhistory.rb +95 -0
  81. data/lib/canis/core/include/rinputdataevent.rb +47 -0
  82. data/lib/canis/core/include/textdocument.rb +111 -0
  83. data/lib/canis/core/include/vieditable.rb +175 -0
  84. data/lib/canis/core/include/widgetmenu.rb +66 -0
  85. data/lib/canis/core/system/colormap.rb +165 -0
  86. data/lib/canis/core/system/keydefs.rb +32 -0
  87. data/lib/canis/core/system/ncurses.rb +237 -0
  88. data/lib/canis/core/system/panel.rb +129 -0
  89. data/lib/canis/core/system/window.rb +1081 -0
  90. data/lib/canis/core/util/ansiparser.rb +119 -0
  91. data/lib/canis/core/util/app.rb +696 -0
  92. data/lib/canis/core/util/basestack.rb +412 -0
  93. data/lib/canis/core/util/defaultcolorparser.rb +84 -0
  94. data/lib/canis/core/util/extras/README +5 -0
  95. data/lib/canis/core/util/extras/bottomline.rb +1815 -0
  96. data/lib/canis/core/util/extras/padreader.rb +192 -0
  97. data/lib/canis/core/util/focusmanager.rb +31 -0
  98. data/lib/canis/core/util/helpmanager.rb +160 -0
  99. data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
  100. data/lib/canis/core/util/promptmenu.rb +235 -0
  101. data/lib/canis/core/util/rcommandwindow.rb +933 -0
  102. data/lib/canis/core/util/rdialogs.rb +520 -0
  103. data/lib/canis/core/util/textutils.rb +74 -0
  104. data/lib/canis/core/util/viewer.rb +238 -0
  105. data/lib/canis/core/util/widgetshortcuts.rb +508 -0
  106. data/lib/canis/core/widgets/applicationheader.rb +103 -0
  107. data/lib/canis/core/widgets/box.rb +58 -0
  108. data/lib/canis/core/widgets/divider.rb +310 -0
  109. data/lib/canis/core/widgets/extras/README.md +12 -0
  110. data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
  111. data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
  112. data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
  113. data/lib/canis/core/widgets/listbox.rb +326 -0
  114. data/lib/canis/core/widgets/listfooter.rb +86 -0
  115. data/lib/canis/core/widgets/rcombo.rb +210 -0
  116. data/lib/canis/core/widgets/rcontainer.rb +415 -0
  117. data/lib/canis/core/widgets/rlink.rb +30 -0
  118. data/lib/canis/core/widgets/rmenu.rb +970 -0
  119. data/lib/canis/core/widgets/rmenulink.rb +30 -0
  120. data/lib/canis/core/widgets/rmessagebox.rb +400 -0
  121. data/lib/canis/core/widgets/rprogress.rb +118 -0
  122. data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
  123. data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
  124. data/lib/canis/core/widgets/rwidget.rb +3634 -0
  125. data/lib/canis/core/widgets/scrollbar.rb +147 -0
  126. data/lib/canis/core/widgets/statusline.rb +113 -0
  127. data/lib/canis/core/widgets/table.rb +1072 -0
  128. data/lib/canis/core/widgets/tabular.rb +264 -0
  129. data/lib/canis/core/widgets/textpad.rb +1674 -0
  130. data/lib/canis/core/widgets/tree.rb +690 -0
  131. data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
  132. data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
  133. data/lib/canis/version.rb +3 -0
  134. metadata +229 -0
@@ -0,0 +1,412 @@
1
+ # Common stack flow functionality
2
+ # * Name: basestack.rb
3
+ # * Description: Classes that allow user to stack and flow components
4
+ # This is currently used only by experimental. +core+ does not use this
5
+ # for stack and flow. it uses wsshortcuts which does not maintain objects.
6
+ # This maintains objects.
7
+ #
8
+ # * Date: 30.10.11 - 12:57
9
+ # * Last update: 2014-05-02 20:15
10
+ #
11
+ module RubyCurses
12
+ module ModStack
13
+ #
14
+ # Base class for stacks and flows.
15
+ # Will manage determining row col and width height of objects
16
+ # Stacks place objects one below another. Flows place objects to the
17
+ # right of the previous. Orientation can be reversed.
18
+ #
19
+ class BaseStack
20
+ attr_accessor :components
21
+ attr_reader :config
22
+ attr_accessor :form
23
+ def initialize config={}, components=[]
24
+ @config = config
25
+ config.each do |k, v|
26
+ instance_variable_set "@#{k}", v
27
+ end
28
+ @components = components
29
+ @calc_needed = true
30
+ end
31
+ # XXX if user sets later, we won't be checking the config
32
+ # We check the actual variables which config sets in init
33
+ %w[ parent_component width height weight row col orientation margin_top margin_bottom margin_left margin_right].each { |e|
34
+ eval(
35
+ "def #{e}
36
+ @config[:#{e}]
37
+ end
38
+ def #{e}=(val)
39
+ @config[:#{e}]=val
40
+ instance_variable_set \"@#{e}\", val
41
+ @calc_needed = true
42
+ end"
43
+ )
44
+ }
45
+ alias :parent :parent_component
46
+ #alias :parent= :parent_component
47
+ def repaint # stack
48
+ $log.debug "XXX: stack repaint recalc #{@calc_needed} "
49
+ @components.each { |e| e.form = @form unless e.form } #unless @calc_needed
50
+ recalc if @calc_needed
51
+ @components.each { |e| e.repaint }
52
+ end
53
+ def repaint_all x
54
+ @calc_needed = true
55
+ end
56
+ def override_graphic gr
57
+ @graphic = gr
58
+ end
59
+ def focusable; false; end
60
+ # Calculates row col and width height
61
+ # for each subc-omponent based on coords of Container
62
+ # This is to be called only when the container has got its coordinates (i.e
63
+ # Containers repaint). This should be in this objects repaint.
64
+ def recalc
65
+ @calc_needed = false
66
+ comp = self
67
+ if comp.is_a? BaseStack
68
+ check_coords comp
69
+ @margin_left ||= 0
70
+ @margin_right ||= 0
71
+ @margin_top ||= 0
72
+ @margin_bottom ||= 0
73
+ if comp.is_a? Stack
74
+ r = row + @margin_top
75
+ rem = 0
76
+ ht = height - (@margin_top + @margin_bottom)
77
+ if @orientation == :bottom
78
+ mult = -1
79
+ comps = @components.reverse
80
+ r = row + height - @margin_bottom
81
+
82
+ else
83
+ mult = 1
84
+ comps = @components
85
+
86
+ end
87
+ comps.each { |e|
88
+ # should only happen if expandable FIXME
89
+ e.margin_top ||= 0
90
+ e.margin_bottom ||= 0
91
+ e.height = 0.01 * e.weight * (ht - (e.margin_top + e.margin_bottom))
92
+ hround = e.height.floor
93
+ rem += e.height - hround
94
+ e.height = hround #- (@margin_top + @margin_bottom)
95
+ # rounding creates a problem, since 0.5 gets rounded up and we can exceed bound
96
+ # So i floor, and maintain the lost space, and add it back when it exceeds 1
97
+ # This way the last components gets stretched to meet the end, which is required
98
+ # when the height of the stack is odd and there's a left-over row
99
+ if rem >= 1
100
+ e.height += 1
101
+ rem = 0
102
+ end
103
+ # Item level margins have not been accounted for when calculating weightages, and
104
+ # should not be used on the weightage axis
105
+ r += e.margin_top
106
+ if @orientation == :bottom
107
+ r += e.height * mult
108
+ e.row = r
109
+ else
110
+ e.row = r
111
+ r += e.height + 0
112
+ end
113
+ e.margin_left ||= 0
114
+ e.margin_right ||= 0
115
+ e.width = width - (@margin_left + @margin_right + e.margin_left + e.margin_right)
116
+ e.col = col + @margin_left + e.margin_left # ??? XXX
117
+ #$log.debug "XXX: recalc stack #{e.widget.class} r:#{e.row} c:#{e.col} h:#{e.height} = we:#{e.weight} * h:#{height} "
118
+ #e.col_offset = col_offset # ??? XXX
119
+ check_coords e
120
+ e.repaint_all(true)
121
+ e.recalc if e.is_a? BaseStack
122
+ }
123
+ elsif comp.is_a? Flow
124
+ c = col + @margin_left #+ col_offset
125
+ rem = 0
126
+ wd = width - (@margin_left + @margin_right)
127
+ # right_to_left orientation
128
+ if @orientation == :right
129
+ mult = -1
130
+ comps = @components.reverse
131
+ c = col + width - @margin_right
132
+ $log.debug "XXX: ORIENT1f recalc #{@orientation} "
133
+ else
134
+ mult = 1
135
+ comps = @components
136
+ $log.debug "XXX: ORIENT2f recalc #{@orientation} "
137
+ end
138
+ comps.each { |e|
139
+ e.width = e.weight * wd * 0.01
140
+ wround = e.width.floor
141
+ rem += e.width - wround
142
+ e.width = wround
143
+ # see comment in prev block regarding remaininder
144
+ if rem >= 1
145
+ e.width += 1
146
+ rem = 0
147
+ end
148
+ e.height = height - (@margin_top + @margin_bottom) #* weight * 0.01
149
+ #e.height = e.height.round
150
+ if @orientation == :right
151
+ c += e.width * mult # mult 1 or -1
152
+ e.col = c
153
+ else
154
+ e.col = c
155
+ c += e.width * mult # mult 1 or -1
156
+ end
157
+ e.row = row + @margin_top
158
+ check_coords e
159
+ $log.debug "XXX: recalc flow #{e.widget.class} r:#{e.row} c:#{e.col} h:#{e.height} = we:#{e.weight} * w:#{width} "
160
+ e.repaint_all(true) # why not happening when we change row, hieght etc
161
+ e.recalc if e.is_a? BaseStack
162
+ }
163
+ end
164
+ else
165
+ alert "in else recalc DOES NOT COME HERE "
166
+ comp.col = comp.parent.col
167
+ comp.row = comp.parent.row
168
+ comp.height = comp.parent.height
169
+ comp.width = comp.parent.width
170
+ $log.debug "XXX: recalc else #{comp.class} r #{comp.row} c #{comp.col} . h #{comp} height w #{comp.width} "
171
+ end
172
+ end
173
+ # Traverses the comopnent tree and calculates weightages for all components
174
+ # based on what has been specified by user
175
+ def check_coords e # stack
176
+ r = e.row
177
+ c = e.col
178
+ if r >= row + height
179
+ $log.warn "XXX: WARN e.class is out of bounds row #{r} "
180
+ e.visible = false
181
+ end
182
+ if c >= col + width
183
+ $log.warn "XXX: WARN e.class is out of bounds col #{c} "
184
+ e.visible = false
185
+ end
186
+ end
187
+ def increase c=@current_component
188
+ p = self #c.parent_component
189
+ ci = p.components.index(c)
190
+ ni = ci + 1
191
+ if p.components[ni].nil?
192
+ ni = nil
193
+ end
194
+ case p
195
+ when Flow
196
+ # increase width of current and reduce from neighbor
197
+ if ni
198
+ n = p.components[ni]
199
+ $log.debug "XXX: INC fl current #{ci}, total#{p.components.count}, next #{n} "
200
+
201
+ c.width += 1
202
+ n.width -= 1
203
+ n.col += 1
204
+ end
205
+
206
+ when Stack
207
+ if ni
208
+ n = p.components[ni]
209
+ $log.debug "XXX: INC fl current #{ci}, total#{p.components.count}, next #{n} "
210
+
211
+ c.height += 1
212
+ n.height -= 1
213
+ n.row += 1
214
+ end
215
+ $log.debug "XXX: INC st current #{ci}, total#{p.components.count} "
216
+ end
217
+
218
+ end
219
+ def decrease c=@current_component
220
+ p = self #c.parent_component
221
+ ci = p.components.index(c)
222
+ ni = ci + 1
223
+ if p.components[ni].nil?
224
+ ni = nil
225
+ end
226
+ case p
227
+ when Flow
228
+ # increase width of current and reduce from neighbor
229
+ if ni
230
+ n = p.components[ni]
231
+ $log.debug "XXX: INC fl current #{ci}, total#{p.components.count}, next #{n} "
232
+
233
+ c.width -= 1
234
+ n.width += 1
235
+ n.col -= 1
236
+ end
237
+
238
+ when Stack
239
+ if ni
240
+ n = p.components[ni]
241
+ $log.debug "XXX: INC fl current #{ci}, total#{p.components.count}, next #{n} "
242
+
243
+ c.height -= 1
244
+ n.height += 1
245
+ n.row -= 1
246
+ end
247
+ $log.debug "XXX: INC st current #{ci}, total#{p.components.count} "
248
+ end
249
+
250
+ end
251
+ def to_s
252
+ @components
253
+ end
254
+ end # class Base
255
+ # A stack positions objects one below the other
256
+ class Stack < BaseStack; end
257
+ # A flow positions objects in a left to right
258
+ class Flow < BaseStack; end
259
+ #
260
+ # A wrapper over widget mostly because it adds weight and margins
261
+ #
262
+ class Item
263
+ attr_reader :config, :widget
264
+ attr_reader :margin_top, :margin_left, :margin_bottom, :margin_right
265
+ def initialize config={}, widget
266
+ @config = config
267
+ config.each do |k, v|
268
+ instance_variable_set "@#{k}", v
269
+ end
270
+ @margin_left ||= 0
271
+ @margin_right ||= 0
272
+ @margin_top ||= 0
273
+ @margin_bottom ||= 0
274
+ @widget = widget
275
+ end
276
+ def weight; @config[:weight]||100; end
277
+ def weight=(val); @config[:weight]=val; end
278
+ def repaint; @widget.repaint; end
279
+ %w[ form parent parent_component width height row col row_offset col_offset focusable].each { |e|
280
+ eval(
281
+ "def #{e}
282
+ @widget.#{e}
283
+ end
284
+ def #{e}=(val)
285
+ @widget.#{e}=val
286
+ end"
287
+ )
288
+ }
289
+ def method_missing(sym, *args, &block)
290
+ @widget.send sym, *args, &block
291
+ end
292
+ end # class Item
293
+
294
+ # --------------------- module level ------------------------------#
295
+ # General routin to traverse components and their components
296
+ def traverse c, &block
297
+ if c.is_a? BaseStack
298
+ yield c
299
+ c.components.each { |e|
300
+ yield e
301
+ }
302
+ c.components.each { |e| traverse(e, &block) }
303
+ @ctr -= 1
304
+ else
305
+ end
306
+ end
307
+
308
+ # traverse the components and their children
309
+ #
310
+ def each &block
311
+ @components.each { |e| traverse e, &block }
312
+ end
313
+ # module level
314
+ private
315
+ def _stack type, config={}, &block
316
+ case type
317
+ when :stack
318
+ s = Stack.new(config)
319
+ when :flow
320
+ s = Flow.new(config)
321
+ end
322
+ _add s
323
+ @active << s
324
+ yield_or_eval &block if block_given?
325
+ @active.pop
326
+ # if active is empty then this is where we could calculate
327
+ # percentatges and do recalc, thus making it independent
328
+ end
329
+ # module level
330
+ private
331
+ def _add s
332
+ if @active.empty?
333
+ $log.debug "XXX: ADDING TO components #{s} "
334
+ unless s.is_a? BaseStack
335
+ raise "No stack or flow to add to. Results may not be what you want"
336
+ end
337
+ @components << s
338
+ else
339
+ @active.last.components << s
340
+ end
341
+ __add s
342
+ end
343
+
344
+ # module level
345
+ public
346
+ def stack config={}, &block
347
+ _stack :stack, config, &block
348
+ end
349
+ def flow config={}, &block
350
+ _stack :flow, config, &block
351
+ end
352
+ # module level
353
+ private
354
+ def add w, config={}
355
+ i = Item.new config, w
356
+ _add i
357
+ end
358
+ alias :add_widget :add
359
+ # module level
360
+ private
361
+ def calc_weightages2 components, parent
362
+ #puts " #{@ctr} --> #{c.type}, wt: #{c.config[:weight]} "
363
+ @ctr += 1
364
+ wt = 0
365
+ cnt = 0
366
+ sz = components.count
367
+ $log.debug "XXX: calc COMP COUNT #{sz} "
368
+ # calculate how much weightage has been given by user
369
+ # so we can allocate average to other components
370
+ components.each { |e|
371
+ if e.config[:weight]
372
+ wt += e.config[:weight]
373
+ cnt += 1
374
+ end
375
+ $log.debug "XXX: INC setting parent #{parent} to #{e} "
376
+ e.config[:parent] = parent
377
+ e.config[:level] = @ctr
378
+ }
379
+ used = sz - cnt
380
+ $log.debug "XXX: ADDING calc COMP COUNT #{sz} - #{cnt} "
381
+ if used > 0
382
+ avg = (100-wt)/used
383
+ # Allocate average to other components
384
+ components.each { |e| e.config[:weight] = avg unless e.config[:weight] }
385
+ end
386
+ components.each { |e| calc_weightages2(e.components, e) if e.respond_to? :components }
387
+ @ctr -= 1
388
+ end
389
+ # module level
390
+ #private
391
+ public
392
+ # given an widget, return the item, so we can change weight or some other config
393
+ def item_for widget
394
+ each do |e|
395
+ if e.is_a? Item
396
+ if e.widget == widget
397
+ return e
398
+ end
399
+ end
400
+ end
401
+ return nil
402
+ end
403
+ # module level
404
+ # returns the parent (flow or stack) for a given widget
405
+ # allowing user to change configuration such as weight
406
+ def parent_of widget
407
+ f = item_for widget
408
+ return f.config[:parent] if f
409
+ return nil
410
+ end
411
+ end # mod modstack
412
+ end # mod
@@ -0,0 +1,84 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: colorparser.rb
3
+ # Description: Default parse for our tmux format
4
+ # The aim is to be able to specify parsers so different kinds
5
+ # of formatting or documents can be used, such as ANSI formatted
6
+ # manpages.
7
+ # Author: jkepler http://github.com/mare-imbrium/canis/
8
+ # Date: 07.11.11 - 13:17
9
+ # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
+ # Last update: 2014-05-19 12:56
11
+ # ----------------------------------------------------------------------------- #
12
+ # == TODO
13
+ # - perhaps we can compile the regexp once and reuse
14
+ # == CHANGES
15
+ # - adding style 2014-05-19 - 12:52
16
+ #
17
+
18
+ module Canis
19
+ class DefaultColorParser
20
+
21
+ # NOTE: Experimental and minimal
22
+ # parses the formatted string and yields either an array of color, bgcolor and attrib
23
+ # or the text. This will be called by convert_to_chunk.
24
+ #
25
+ # Currently, assumes colors and attributes are correct. No error checking or fancy stuff.
26
+ # s="#[fg=green]hello there#[fg=yellow, bg=black, dim]"
27
+ # @since 1.4.1 2011-11-3 experimental, can change
28
+ # @return [nil] knows nothign about output format.
29
+
30
+ # 187compat 2013-03-20 - 19:33 not working in 187 so added ,1 in some cases for string
31
+ def parse_format s # yields attribs or text
32
+ ## set default colors
33
+ color = :white
34
+ bgcolor = :black
35
+ attrib = FFI::NCurses::A_NORMAL
36
+ text = ""
37
+
38
+ ## split #[...]
39
+ a = s.split /(#\[[^\]]*\])/
40
+ a.each { |e|
41
+ ## process color or attrib portion
42
+ if e[0,2] == "#[" && e[-1,1] == "]"
43
+ # now resetting 1:20 PM November 3, 2011 , earlier we were carrying over
44
+ color, bgcolor, attrib = nil, nil, nil
45
+ style = nil
46
+ catch(:done) do
47
+ e = e[2..-2]
48
+ # TODO we could atthis point check against a hash to see if this string exists, and take
49
+ # the array from there and pass back so we don't keep splitting and parsing.
50
+ ## first split on commas to separate fg, bg and attr
51
+ atts = e.split /\s*,\s*/
52
+ atts.each { |att|
53
+ ## next split on =
54
+ part = att.split /\s*=\s*/
55
+ case part[0]
56
+ when "fg"
57
+ color = part[1]
58
+ when "bg"
59
+ bgcolor = part[1]
60
+ when "style"
61
+ style = part[1]
62
+ when "/end", "end"
63
+ yield :endcolor if block_given?
64
+ #next
65
+ throw :done
66
+ else
67
+ # attrib
68
+ attrib = part[0]
69
+ end
70
+ }
71
+ # 2013-03-25 - 13:31 if numeric color specified
72
+ color = color.to_i if color =~ /^[0-9]+$/
73
+ bgcolor = bgcolor.to_i if bgcolor =~ /^[0-9]+$/
74
+ yield [color,bgcolor,attrib,style] if block_given?
75
+ end # catch
76
+ else
77
+ text = e
78
+ yield text if block_given?
79
+ end
80
+ }
81
+ end
82
+
83
+ end
84
+ end