rbcurse 1.1.5 → 1.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. data/CHANGELOG +45 -0
  2. data/Makefile +1 -1
  3. data/Manifest.txt +91 -0
  4. data/NOTES +349 -2
  5. data/README.markdown +12 -0
  6. data/VERSION +1 -1
  7. data/examples/abasiclist.rb +25 -0
  8. data/examples/alpmenu.rb +42 -0
  9. data/examples/app.rb +883 -0
  10. data/examples/appcombo.rb +17 -0
  11. data/examples/appdirtree.rb +73 -0
  12. data/examples/appemail.rb +164 -0
  13. data/examples/appemaillb.rb +308 -0
  14. data/examples/appgcompose.rb +303 -0
  15. data/examples/appgmail.rb +951 -0
  16. data/examples/atree.rb +56 -0
  17. data/examples/dirtree.rb +78 -0
  18. data/examples/focusmanager.rb +31 -0
  19. data/examples/imap.rb +48 -0
  20. data/examples/menu1.rb +79 -0
  21. data/examples/multispl.rb +86 -0
  22. data/examples/rfe.rb +3 -4
  23. data/examples/rmail.rb +188 -0
  24. data/examples/s.rb +10 -0
  25. data/examples/scrollbar.rb +104 -0
  26. data/examples/splitp.rb +56 -0
  27. data/examples/table1.rb +30 -0
  28. data/examples/term.rb +48 -0
  29. data/examples/term2.rb +54 -0
  30. data/examples/test1.rb +4 -2
  31. data/examples/test2.rb +9 -9
  32. data/examples/testapp.rb +44 -0
  33. data/examples/testapp2.rb +51 -0
  34. data/examples/testcombo.rb +2 -2
  35. data/examples/testgmail.rb +46 -0
  36. data/examples/testlistbox.rb +0 -1
  37. data/examples/testmultispl.rb +199 -0
  38. data/examples/testree.rb +127 -0
  39. data/examples/testscroller.rb +0 -1
  40. data/examples/testscrolllb.rb +1 -1
  41. data/examples/testscrollp.rb +2 -1
  42. data/examples/testscrollta.rb +1 -1
  43. data/examples/testscrolltable.rb +1 -2
  44. data/examples/testsplit.rb +1 -1
  45. data/examples/testsplit2.rb +1 -1
  46. data/examples/testsplit3.rb +1 -1
  47. data/examples/testsplit3_1.rb +1 -1
  48. data/examples/testsplit3a.rb +1 -1
  49. data/examples/testsplit3b.rb +1 -1
  50. data/examples/testsplitta.rb +1 -1
  51. data/examples/testsplittv.rb +1 -1
  52. data/examples/testsplittvv.rb +1 -1
  53. data/examples/testtodo.rb +491 -488
  54. data/examples/testvimsplit.rb +111 -0
  55. data/examples/todo.db +0 -0
  56. data/examples/todocsv.csv +28 -0
  57. data/examples/viewtodo.rb +408 -403
  58. data/lib/rbcurse/action.rb +1 -0
  59. data/lib/rbcurse/app.rb +1294 -0
  60. data/lib/rbcurse/applicationheader.rb +7 -2
  61. data/lib/rbcurse/checkboxcellrenderer.rb +0 -12
  62. data/lib/rbcurse/colormap.rb +34 -8
  63. data/lib/rbcurse/comboboxcellrenderer.rb +0 -11
  64. data/lib/rbcurse/defaultlistselectionmodel.rb +23 -7
  65. data/lib/rbcurse/extras/bottomline.rb +1681 -0
  66. data/lib/rbcurse/extras/directorylist.rb +445 -0
  67. data/lib/rbcurse/extras/directorytree.rb +69 -0
  68. data/lib/rbcurse/extras/divider.rb +310 -0
  69. data/lib/rbcurse/extras/focusmanager.rb +31 -0
  70. data/lib/rbcurse/extras/listselectable.rb +222 -0
  71. data/lib/rbcurse/extras/masterdetail.rb +164 -0
  72. data/lib/rbcurse/extras/menutree.rb +63 -0
  73. data/lib/rbcurse/extras/rlink.rb +27 -0
  74. data/lib/rbcurse/extras/rmenulink.rb +21 -0
  75. data/lib/rbcurse/extras/scrollbar.rb +134 -0
  76. data/lib/rbcurse/extras/stdscrwindow.rb +247 -0
  77. data/lib/rbcurse/extras/tabular.rb +258 -0
  78. data/lib/rbcurse/extras/tabularwidget.rb +1070 -0
  79. data/lib/rbcurse/extras/viewer.rb +106 -0
  80. data/lib/rbcurse/io.rb +137 -80
  81. data/lib/rbcurse/keylabelprinter.rb +4 -0
  82. data/lib/rbcurse/listcellrenderer.rb +91 -59
  83. data/lib/rbcurse/listscrollable.rb +93 -95
  84. data/lib/rbcurse/listselectable.rb +60 -7
  85. data/lib/rbcurse/ractionevent.rb +67 -0
  86. data/lib/rbcurse/rbasiclistbox.rb +688 -0
  87. data/lib/rbcurse/rcombo.rb +5 -5
  88. data/lib/rbcurse/rcommandwindow.rb +555 -0
  89. data/lib/rbcurse/rinputdataevent.rb +12 -0
  90. data/lib/rbcurse/rlistbox.rb +305 -124
  91. data/lib/rbcurse/rmenu.rb +99 -46
  92. data/lib/rbcurse/rmessagebox.rb +13 -6
  93. data/lib/rbcurse/rmulticontainer.rb +54 -93
  94. data/lib/rbcurse/rmultisplit.rb +731 -0
  95. data/lib/rbcurse/rmultitextview.rb +3 -2
  96. data/lib/rbcurse/rpopupmenu.rb +0 -1
  97. data/lib/rbcurse/rprogress.rb +117 -0
  98. data/lib/rbcurse/rscrollpane.rb +2 -1
  99. data/lib/rbcurse/rsplitpane.rb +94 -20
  100. data/lib/rbcurse/rsplitpane2.rb +1009 -0
  101. data/lib/rbcurse/rtabbedpane.rb +3 -2
  102. data/lib/rbcurse/rtabbedwindow.rb +0 -1
  103. data/lib/rbcurse/rtable.rb +92 -64
  104. data/lib/rbcurse/rtextarea.rb +91 -57
  105. data/lib/rbcurse/rtextview.rb +223 -70
  106. data/lib/rbcurse/rtree.rb +723 -0
  107. data/lib/rbcurse/rviewport.rb +2 -1
  108. data/lib/rbcurse/rvimsplit.rb +768 -0
  109. data/lib/rbcurse/rwidget.rb +524 -325
  110. data/lib/rbcurse/table/tablecellrenderer.rb +1 -1
  111. data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -1
  112. data/lib/rbcurse/tree/treecellrenderer.rb +137 -0
  113. data/lib/rbcurse/tree/treemodel.rb +428 -0
  114. data/lib/rbcurse/vieditable.rb +14 -13
  115. data/lib/ver/ncurses.rb +6 -0
  116. data/lib/ver/window.rb +67 -32
  117. metadata +99 -23
  118. data/bin/rbcurse +0 -0
  119. data/examples/rvimsplit.rb +0 -376
  120. data/examples/todo.rb +0 -1
  121. data/lib/rbcurse/rform.rb +0 -845
  122. data/lib/rbcurse/selectable.rb +0 -94
  123. data/rbcurse.gemspec +0 -188
data/examples/atree.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'rbcurse/app'
2
+
3
+ App.new do
4
+ header = app_header "rbcurse 1.2.0", :text_center => "Tree Demo", :text_right =>"New Improved!", :color => :black, :bgcolor => :white, :attr => :bold
5
+ message "Press Enter to expand/collapse"
6
+
7
+ stack :margin_top => 2, :margin => 5, :width => 30 do
8
+ tree :height => 10, :title => "ruby way" do
9
+ root "root" do
10
+ branch "hello" do
11
+ leaf "ruby"
12
+ end
13
+ branch "goodbye" do
14
+ leaf "java"
15
+ leaf "verbosity"
16
+ end
17
+ end
18
+ end
19
+
20
+
21
+ # using a Hash
22
+ model = { :ruby => [ "jruby", {:mri => %W[ 1.8.6 1.8.7]}, {:yarv => %W[1.9.1 1.9.2]}, "rubinius", "macruby" ], :python => %W[ cpython jython laden-swallow ] }
23
+ tree :data => model, :title => "Hash"
24
+
25
+ end # stack
26
+ stack :margin_top => 2, :margin => 40, :width => 30 do
27
+
28
+ # using an Array
29
+ tree :data => %W[ ruby cobol jruby smalltalk fortran piethon purrl lithp ], :title=> "Array"
30
+
31
+ # long way ISO 9001 certifed, SEI CMM 5 compliant
32
+ #
33
+ root = TreeNode.new "ROOT"
34
+ subroot = TreeNode.new "subroot"
35
+ leaf1 = TreeNode.new "leaf 1"
36
+ leaf2 = TreeNode.new "leaf 2"
37
+ model = DefaultTreeModel.new root
38
+ #model.insert_node_into(subroot, root, 0) # BLEAH JAVA !!
39
+
40
+ # slightly better, since we return self in ruby
41
+ root << subroot
42
+ subroot << leaf1 << leaf2
43
+ leaf1 << "leaf11"
44
+ leaf1 << "leaf12"
45
+
46
+ # more rubyish way
47
+ root.add "blocky", true do
48
+ add "block2"
49
+ add "block3" do
50
+ add "block31"
51
+ end
52
+ end
53
+
54
+ tree :data => model, :title => "legacy way"
55
+ end
56
+ end # app
@@ -0,0 +1,78 @@
1
+ require 'rbcurse/app'
2
+ require 'fileutils'
3
+ require 'rbcurse/tree/treemodel'
4
+
5
+ def _directories wd
6
+ $log.debug " directories got XXX: #{wd} "
7
+ d = Dir.new(wd)
8
+ ent = d.entries.reject{|e| !File.directory? File.join(wd,e)}
9
+ $log.debug " directories got XXX: #{ent} "
10
+ ent.delete(".");ent.delete("..")
11
+ return ent
12
+ end
13
+ App.new do
14
+ header = app_header "rbcurse 1.2.0", :text_center => "Yet Another File Manager", :text_right =>"Directory Lister", :color => :black, :bgcolor => :white#, :attr => Ncurses::A_BLINK
15
+ message "Press Enter to expand/collapse"
16
+
17
+ pwd = Dir.getwd
18
+ #d = Dir.new(pwd)
19
+ #entries = d.entries.reject{|e| !File.directory? e}
20
+ #entries.delete(".");entries.delete("..")
21
+ entries = _directories pwd
22
+ patharray = pwd.split("/")
23
+ # we have an array of path, to add recursively, one below the other`
24
+ nodes = []
25
+ nodes << TreeNode.new(patharray.shift)
26
+ patharray.each do |e|
27
+ nodes << nodes.last.add(e)
28
+ end
29
+ last = nodes.last
30
+ nodes.last.add entries
31
+ model = DefaultTreeModel.new nodes.first
32
+
33
+
34
+
35
+ ht = 24
36
+ borderattrib = :reverse
37
+ stack :margin_top => 1, :margin => 0, :width => 30 do
38
+ @t = tree :data => model, :height => ht, :border_attrib => borderattrib
39
+ @t.bind :TREE_WILL_EXPAND_EVENT do |node|
40
+ path = File.join(*node.user_object_path)
41
+ dirs = _directories path
42
+ ch = node.children
43
+ ch.each do |e|
44
+ o = e.user_object
45
+ if dirs.include? o
46
+ dirs.delete o
47
+ else
48
+ # delete this child since its no longer present TODO
49
+ end
50
+ end
51
+ message " #{node} will expand: #{path}, #{dirs} "
52
+ node.add dirs
53
+ end
54
+ @t.bind :TREE_SELECTION_EVENT do |ev|
55
+ if ev.state == :SELECTED
56
+ node = ev.node
57
+ path = File.join(*node.user_object_path)
58
+ files = Dir.new(path).entries
59
+ files.delete(".")
60
+ @l.list files
61
+ #TODO show all details in filelist
62
+ @current_path = path
63
+ $log.debug " XXX selected afterseeting lb: #{@l} "
64
+ end
65
+ end # select
66
+ @t.expand_node last #
67
+ @t.mark_parents_expanded last # make parents visible
68
+ end
69
+ stack :margin_top => 1, :margin => 30, :width => 50 do
70
+ @l = list_box :height => ht, :border_attrib => borderattrib
71
+ @l.bind :LIST_SELECTION_EVENT do |ev|
72
+ $log.debug " XXX GOT A LIST EVENT #{ev} "
73
+ message ev.source.selected_value
74
+ #TODO when selects drill down
75
+ #TODO when selecting, sync tree with this
76
+ end
77
+ end
78
+ end # app
@@ -0,0 +1,31 @@
1
+ # Allow some objects to take focus when a certain key is pressed.
2
+ # This is for objects like scrollbars and dividers. We don't want these always
3
+ # getting focus, only sometimes when we want to resize panes.
4
+ # This will not only be included by Form but by containers such as Vimsplit
5
+ # or MasterDetail.
6
+ # Usage: the idea is that when you create dividers, you would add them to the FocusManager
7
+ # Thus they would remain non-focusable on creation. When hte user presses (say F3) then
8
+ # make_focusable is called, or toggle_focusable. Now user can press TAB and access
9
+ # these bars. When he is done he can toggle again.
10
+ # TODO: we might add a Circular class here so user can traverse only these objects
11
+ module RubyCurses
12
+ module FocusManager
13
+ extend self
14
+ attr_reader :focusables
15
+ # add a component to this list so it can be made focusable later
16
+ def add component
17
+ @focusables ||= []
18
+ @focusables << component
19
+ self
20
+ end
21
+ def make_focusable bool=true
22
+ @focusing = bool
23
+ @focusables.each { |e| e.focusable(bool) }
24
+ end
25
+ def toggle_focusable
26
+ return unless @focusables
27
+ alert "FocusManager Making #{@focusable.length} objects #{!@focusing} "
28
+ make_focusable !@focusing
29
+ end
30
+ end
31
+ end
data/examples/imap.rb ADDED
@@ -0,0 +1,48 @@
1
+ require 'net/imap'
2
+ require 'net/http'
3
+
4
+ def labels conn
5
+ (conn.list("", "%")+conn.list("[Gmail]/", "%")).inject([]) do |labels,label|
6
+ label[:name].each_line {|l| labels << l }
7
+ labels
8
+ end
9
+ end
10
+ def label_counts _labels
11
+ _labels.each { |e|
12
+ puts e
13
+ next if e == "[Gmail]"
14
+ imap.select e rescue next
15
+ u = imap.search('UNSEEN').count
16
+ s = imap.search('SEEN').count
17
+ puts " #{e} : #{u} #{s} "
18
+ }
19
+ end
20
+ @config={}
21
+ @config['server'] = 'imap.gmail.com'
22
+ @config['port'] = 993
23
+ @config['username'] = "rahul2012@gmail.com"
24
+ @config['password'] = "rahulku234"
25
+ imap = Net::IMAP.new(@config['server'],@config['port'],true)
26
+ imap.login(@config['username'], @config['password'])
27
+ puts "connceted -------"
28
+ _labels = labels(imap)
29
+ puts _labels
30
+ puts "-------"
31
+ imap.select('INBOX')
32
+ ctr = 0
33
+ imap.search(["SEEN"]).each do |message_id|
34
+ ctr += 1
35
+ puts message_id
36
+ x = imap.fetch(message_id, "RFC822")[0].attr["RFC822"]
37
+ puts x.class
38
+ msg = x.split("\n")
39
+ puts msg.grep /^Subject:/
40
+ puts msg.grep /^From:/
41
+ puts msg.grep /^Date:/
42
+
43
+ #break if ctr >= 5
44
+ #MailFetcher.receive(imap.fetch(message_id, "RFC822")[0].attr["RFC822"])
45
+ #imap.store(message_id, "+FLAGS", [:Deleted])
46
+ end
47
+ imap.logout()
48
+ imap.disconnect()
data/examples/menu1.rb ADDED
@@ -0,0 +1,79 @@
1
+ require 'rbcurse/app'
2
+
3
+ #if $0 == __FILE__
4
+ App.new do
5
+ #title "Demo of Menu - rbcurse"
6
+ #subtitle "Hit F1 to quit, F2 for menubar toggle"
7
+ header = app_header "rbcurse 1.2.0", :text_center => "Menubar Demo", :text_right =>"enabled"
8
+
9
+ # TODO accelerators and
10
+ # getting a handle for later use
11
+ mb = menubar do
12
+ #@toggle_key=KEY_F2
13
+ menu "File" do
14
+ item "Open", "O" do
15
+ command do
16
+ alert "HA!! you wanted to open a file?"
17
+ end
18
+ end
19
+ item "New", "N"
20
+ separator
21
+ item "Close", "C"
22
+
23
+ end # menu
24
+ menu "Window" do
25
+ item "Tile", "T"
26
+ menu "Find" do
27
+ item "More", "M"
28
+ $x = item "Less", "L" do
29
+ #accelerator "Ctrl-X"
30
+ command do
31
+ alert "You clickses on Less"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end # menubar
37
+ mb.toggle_key = KEY_F2
38
+ @form.set_menu_bar mb
39
+ stack :margin_top => 10, :margin => 5 do
40
+ field "a field", :attr => 'reverse', :block_event => :CHANGE do |e|
41
+ message e.to_s
42
+
43
+ case e.text
44
+ when "d"
45
+ #alert("Me gots #{e.text} disabling menu item Window:Find: ")
46
+ #$x.enabled = false
47
+ when "e"
48
+ # TODO this alert shows data wrapped but overlaps border
49
+ #alert("Me gots #{e.text} enabling menu item Window:Find: Adding accel ")
50
+ #$x.enabled = true
51
+ $x.accelerator = "Ctrl-X"
52
+ end
53
+ end
54
+ @adock = nil
55
+ keyarray = [
56
+ ["F1" , "Exit"], nil,
57
+ ["F2", "Menu"], nil,
58
+ ["M-e", "Disable"], ["M-x", "XXXX"],
59
+ ["C-?", "Help"], nil
60
+ ]
61
+ @adock = dock keyarray
62
+ lbltext = "Click this to enable or disable menu option Window:Find:Less"
63
+ blank 1
64
+ hline :width => lbltext.length
65
+ label :text => lbltext
66
+ toggle :offvalue => " Enable ", :onvalue => " Disable ", :mnemonic => 'E', :value => true do |e|
67
+ $x.enabled = e.item.value
68
+ header.text_right = e.item.value ? "enabled" : "disabled"
69
+ if e.item.value
70
+ @adock.update_application_key_label "M-e", "M-e", "Disable"
71
+ else
72
+ @adock.update_application_key_label "M-e", "M-e", "Enable"
73
+ end
74
+ #@form.handle_key mb.toggle_key
75
+ end
76
+ link "a linkie"
77
+ end # stack
78
+ end # app
79
+ #end
@@ -0,0 +1,86 @@
1
+ require 'rbcurse/app'
2
+
3
+ App.new do
4
+ header = app_header "rbcurse 1.2.0", :text_center => "MultiSplit Demo", :text_right =>"ColumnBrowse pattern"
5
+ message_row(27)
6
+ message "<TAB> and <BTAB> "
7
+ oo = :HORIZONTAL_SPLIT
8
+ oo = :VERTICAL_SPLIT
9
+
10
+ stack :margin_top => 5, :margin => 15, :width => 79 do
11
+ splp = multisplit "outer", :height => 16, :split_count => 2, :orientation => oo do |s|
12
+ #s.suppress_borders = false
13
+ lb = list_box "Classes",:list => `ri -f bs`.split("\n")
14
+ s.add lb
15
+
16
+ lb2 = list_box "Methods", :list => ["highline", "sqlite3-ruby", "thor", "ncurses"], :choose => ["thor"]
17
+ #lb2.suppress_borders true
18
+ s.add lb2
19
+ #sc = textarea "Edit"
20
+ #s.add sc
21
+ end # splp
22
+ c1 = splp[0]
23
+ c2 = splp[1]
24
+ #c1.bind_key(KEY_RETURN){
25
+ # listbox now traps key ENTER and fires PRESS event
26
+ c1.bind(:PRESS){
27
+ #m = Object::const_get(c1.text).public_instance_methods
28
+ lines = `ri -f bs #{c1.text} | tr -d ''`.split("\n")
29
+ i = lines.index "= CCllaassss mmeetthhooddss::"
30
+ m = nil
31
+ if i
32
+ lines[i] = "Class Methods:"
33
+ m = lines.slice(i..-1)
34
+ i = m.index "= IInnssttaannccee mmeetthhooddss::"
35
+ m[i] = "Instance Methods:" if i
36
+ else
37
+ i = lines.index "= IInnssttaannccee mmeetthhooddss::"
38
+ if i
39
+ lines[i] = "Instance Methods:"
40
+ m = lines.slice(i..-1)
41
+ end
42
+ end
43
+ if m
44
+ c2.remove_all
45
+ c2.insert 0, *m
46
+ c2.clear_selection # since we had put default value using choose
47
+ end
48
+ }
49
+
50
+
51
+ blank
52
+ flow do
53
+ #toggle :onvalue => "Vertical", :offvalue => "Horizontal", :value => true do |e|
54
+ #message "pressed #{e.state}"
55
+ #case e.state
56
+ #when :DESELECTED
57
+ #$log.debug " about to call orientation with V"
58
+ #splp.orientation :VERTICAL_SPLIT
59
+ ##ret = splp.reset_to_preferred_sizes
60
+ #else
61
+ #$log.debug " about to call orientation with H"
62
+ #splp.orientation :HORIZONTAL_SPLIT
63
+ ##ret = splp.reset_to_preferred_sizes
64
+ #end
65
+ #end
66
+ fc = splp
67
+ # increase split size
68
+ button "+" do
69
+ #splp.set_divider_location(splp.divider_location+1)
70
+ #fc.set_divider_location(splp.divider_location+1)
71
+ fc.increase
72
+ end
73
+ # decrease split size
74
+ button "-" do
75
+ #fc.set_divider_location(splp.divider_location-1)
76
+ fc.decrease
77
+ end
78
+ # equalize split size
79
+ button "=" do
80
+ #splp.set_resize_weight(0.50)
81
+ fc.same
82
+ end
83
+ end
84
+
85
+ end # stack
86
+ end # app
data/examples/rfe.rb CHANGED
@@ -7,14 +7,13 @@
7
7
  # Copyright rkumar 2009, 2010 under Ruby License.
8
8
  #
9
9
  ####################################################
10
- require 'rubygems'
11
- require 'ncurses'
12
- require 'logger'
10
+ #require 'rubygems'
11
+ #require 'ncurses'
12
+ #require 'logger'
13
13
  require 'rbcurse'
14
14
  require 'rbcurse/rcombo'
15
15
  require 'rbcurse/rlistbox'
16
16
  require './rfe_renderer'
17
- #require 'lib/rbcurse/table/tablecellrenderer'
18
17
  require 'rbcurse/keylabelprinter'
19
18
  require 'rbcurse/applicationheader'
20
19
  require 'rbcurse/action'
data/examples/rmail.rb ADDED
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env ruby -w
2
+ #
3
+ # this will only work in 1.8.7, since mailread.rb is not present after that
4
+ # supply the path of any mbox file such as ~/mbox or ~/mail/read-mail
5
+ # and see a listing of mails, then give a msg number and see body
6
+ # You may run this with -EASCII-8BIT if it crashes with a UTF8 error.
7
+ require 'mailread'
8
+ require 'date'
9
+
10
+ #BOLD = "\e[1m"
11
+ #CLEAR = "\e[0m"
12
+ # a sample mail formatter class
13
+ # Does formatting just like alpine
14
+ # Each message is passed in the format method, thus this is reused
15
+ class MailFormatter
16
+ attr_reader :message
17
+ attr_reader :header
18
+ def initialize #message
19
+ #@message = message
20
+ #@header = message.header
21
+ end
22
+
23
+ def date
24
+ raise StandardError, "pass message first using format()" unless @header
25
+ m = @header
26
+ date = Date.parse(m['Date'])
27
+ date = date.strftime("%b %d")
28
+ end
29
+
30
+ def from
31
+ raise StandardError, "pass message first using format()" unless @header
32
+ m = @header
33
+ match = m['From'].to_s.match(/\((.*)\)/)
34
+ from = m['From']
35
+ if match
36
+ from = match[1]
37
+ else
38
+ match = m['From'].to_s.match(/(.*)</)
39
+ from = match[1] if match
40
+ end
41
+ from
42
+ end
43
+ def body
44
+ raise StandardError, "pass message first using format()" unless @message
45
+ @message.body
46
+ end
47
+
48
+ def subject
49
+ raise StandardError, "pass message first using format()" unless @header
50
+ m = @header
51
+ m['Subject']
52
+ end
53
+ def status
54
+ raise StandardError, "pass message first using format()" unless @header
55
+ m = @header
56
+ m['Status']
57
+ end
58
+
59
+ def format message, count
60
+ @header = message.header
61
+ #@message = message
62
+ m = message.header
63
+ "%2s %2d %s %-25s %-s\n" % [ status, count, date, from, subject ]
64
+ end
65
+
66
+ def create_array message, count
67
+ @header = message.header
68
+ #@message = message
69
+ m = message.header
70
+ #printf("#{attr}%2s %2d %s |%-25s| %-s#{attre}\n", m['Status'], count, date, from, msg.header['Subject'])
71
+ row = [ status, count, date, from, m['Subject'] ]
72
+ end
73
+ end # class
74
+ # opens and maintains an mbox mailbox
75
+ class Mbox
76
+ include Enumerable
77
+ attr_reader :folder
78
+ attr_reader :mails
79
+ attr_reader :unread_count
80
+ attr_reader :read_count
81
+
82
+ # takes a mailbox name, e,g., mbox
83
+ # Does not update, since this is just a demo
84
+ def initialize folder
85
+ raise ArgumentError, "#{folder} not a valid file" if !File.exists? folder
86
+ @folder = folder
87
+ @unread_count = 0
88
+ @read_count = 0
89
+ @mboxh = {}
90
+ @mbox_counts = {}
91
+ @mails = nil
92
+ parse
93
+ end
94
+ def parse &block # :yields: Mail
95
+ mbox = File.open(@folder)
96
+ count = lines = 0
97
+ unread_count = 0
98
+ read_count = 0
99
+ # array of mails
100
+ mails = []
101
+
102
+ # read up the warning message, we don't want it in our array
103
+ msg = Mail.new(mbox)
104
+
105
+ while !mbox.eof?
106
+ msg = Mail.new(mbox)
107
+ count += 1
108
+ s = msg.header['Status']
109
+ if s == "O"
110
+ unread_count += 1
111
+ else
112
+ read_count += 1
113
+ end
114
+ mails << msg
115
+ yield msg if block_given?
116
+ end
117
+ @mails = mails
118
+ #@mbox_counts[@folder] = [unread_count, read_count]
119
+ @unread_count, @read_count = unread_count, read_count
120
+ mbox.close
121
+ end
122
+ def each # :yields: message
123
+ parse unless @mails
124
+ @mails.each { |e| yield e }
125
+ end
126
+ def formatted_each &block
127
+ fmt = @formatter || MailFormatter.new
128
+ each_with_index do |msg, index|
129
+ yield fmt.format msg, index + 1
130
+ end
131
+ end
132
+ # returns an array for each entry which can be used with tabularwidget
133
+ def array_each &block
134
+ fmt = @formatter || MailFormatter.new
135
+ each_with_index do |msg, index|
136
+ yield fmt.create_array msg, index + 1
137
+ end
138
+ end
139
+ # set a formatter object, if you wish to override default one
140
+ def formatter fmt
141
+ @formatter = fmt
142
+ end
143
+ end
144
+ # opens and maintains a hash of mboxes
145
+ # does not see to add any value other than being just a hash !
146
+ class MboxManager
147
+ def initialize
148
+ @boxes = {}
149
+ @current_name = nil
150
+ end
151
+ def use folder
152
+ if !@boxes.has_key? folder
153
+ @mails = Mbox.new folder
154
+ @boxes[folder] = @mails
155
+ else
156
+ @mails = @boxes[folder]
157
+ end
158
+ @current_name = folder
159
+ @mails
160
+ end
161
+ def mails folder=@current_name
162
+ use folder
163
+ @mails
164
+ end
165
+ end
166
+ #puts mails.size
167
+ if __FILE__ == $PROGRAM_NAME
168
+ MAILBOX = ARGV[0] || "mbox"
169
+ mx = Mbox.new "mbox"
170
+ mx.formatted_each do |str|
171
+ puts str
172
+ end
173
+ mails = mx.mails
174
+
175
+ # ask user for a number and print body for that
176
+ while true
177
+ print "Enter a mail number [1 to #{mails.size}]:"
178
+ n = STDIN.gets.chomp
179
+ break if n.nil? || n.empty?
180
+ msg = mails[n.to_i-1]
181
+ body = msg.body
182
+ puts
183
+ string= "#{msg.header['Subject']}"
184
+ puts "#{BOLD}#{string}#{CLEAR}"
185
+ puts "-" * string.length
186
+ puts body
187
+ end
188
+ end