Class: Redwood::Thread

Inherits:
Object show all
Includes:
Enumerable
Defined in:
lib/sup/thread.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeThread

Returns a new instance of Thread.



33
34
35
36
37
38
# File 'lib/sup/thread.rb', line 33

def initialize
  ## ah, the joys of a multithreaded application with a class called
  ## "Thread". i keep instantiating the wrong one...
  raise "wrong Thread class, buddy!" if block_given?
  @containers = []
end

Instance Attribute Details

#containersObject (readonly)

Returns the value of attribute containers.



32
33
34
# File 'lib/sup/thread.rb', line 32

def containers
  @containers
end

Instance Method Details

#<<(c) ⇒ Object



40
41
42
# File 'lib/sup/thread.rb', line 40

def << c
  @containers << c
end

#apply_label(t) ⇒ Object



98
# File 'lib/sup/thread.rb', line 98

def apply_label t; each { |m, *o| m && m.add_label(t) }; end

#authorsObject



96
# File 'lib/sup/thread.rb', line 96

def authors; map { |m, *o| m.from if m }.compact.uniq; end

#dateObject



87
# File 'lib/sup/thread.rb', line 87

def date; map { |m, *o| m.date if m }.compact.max; end

#direct_participantsObject



116
117
118
# File 'lib/sup/thread.rb', line 116

def direct_participants
  map { |m, *o| [m.from] + m.to if m }.flatten.compact.uniq
end

#dirty?Boolean

Returns:

  • (Boolean)


86
# File 'lib/sup/thread.rb', line 86

def dirty?; any? { |m, *o| m && m.dirty? }; end

#drop(c) ⇒ Object



46
# File 'lib/sup/thread.rb', line 46

def drop c; @containers.delete(c) or raise "bad drop"; end

#dump(f = $stdout) ⇒ Object

unused



49
50
51
52
53
# File 'lib/sup/thread.rb', line 49

def dump f=$stdout
  f.puts "=== start thread #{self} with #{@containers.length} trees ==="
  @containers.each { |c| c.dump_recursive f }
  f.puts "=== end thread ==="
end

#each(fake_root = false) ⇒ Object

yields each message, its depth, and its parent. the message yield parameter can be a Message object, or :fake_root, or nil (no message found but the presence of one deduced from other messages).



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/sup/thread.rb', line 59

def each fake_root=false
  adj = 0
  root = @containers.find_all { |c| !Message.subj_is_reply?(c) }.argmin { |c| c.date || 0 }

  if root
    adj = 1
    root.first_useful_descendant.each_with_stuff do |c, d, par|
      yield c.message, d, (par ? par.message : nil)
    end
  elsif @containers.length > 1 && fake_root
    adj = 1
    yield :fake_root, 0, nil
  end

  @containers.each do |cont|
    next if cont == root
    fud = cont.first_useful_descendant
    fud.each_with_stuff do |c, d, par|
      ## special case here: if we're an empty root that's already
      ## been joined by a fake root, don't emit
      yield c.message, d + adj, (par ? par.message : nil) unless
        fake_root && c.message.nil? && root.nil? && c == fud 
    end
  end
end

#empty!Object



45
# File 'lib/sup/thread.rb', line 45

def empty!; @containers.clear; end

#empty?Boolean

Returns:

  • (Boolean)


44
# File 'lib/sup/thread.rb', line 44

def empty?; @containers.empty?; end

#firstObject



85
# File 'lib/sup/thread.rb', line 85

def first; each { |m, *o| return m if m }; nil; end

#has_label?(t) ⇒ Boolean

Returns:

  • (Boolean)


113
# File 'lib/sup/thread.rb', line 113

def has_label? t; any? { |m, *o| m && m.has_label?(t) }; end

#labelsObject



126
127
128
# File 'lib/sup/thread.rb', line 126

def labels
    map { |m, *o| m && m.labels }.flatten.compact.uniq.sort_by { |t| t.to_s }
end

#labels=(l) ⇒ Object



129
130
131
# File 'lib/sup/thread.rb', line 129

def labels= l
  each { |m, *o| m && m.labels = l.clone }
end

#latest_messageObject



133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/sup/thread.rb', line 133

def latest_message
  inject(nil) do |a, b| 
    b = b.first
    if a.nil?
      b
    elsif b.nil?
      a
    else
      b.date > a.date ? b : a
    end
  end
end

#participantsObject



120
121
122
# File 'lib/sup/thread.rb', line 120

def participants
  map { |m, *o| [m.from] + m.to + m.cc + m.bcc if m }.flatten.compact.uniq
end

#remove_label(t) ⇒ Object



99
# File 'lib/sup/thread.rb', line 99

def remove_label t; each { |m, *o| m && m.remove_label(t) }; end

#save(index) ⇒ Object



114
# File 'lib/sup/thread.rb', line 114

def save index; each { |m, *o| m && m.save(index) }; end

#set_labels(l) ⇒ Object



111
# File 'lib/sup/thread.rb', line 111

def set_labels l; each { |m, *o| m && m.labels = l }; end

#sizeObject



124
# File 'lib/sup/thread.rb', line 124

def size; map { |m, *o| m ? 1 : 0 }.sum; end

#snippetObject



88
89
90
91
92
93
94
95
# File 'lib/sup/thread.rb', line 88

def snippet
  with_snippets = select { |m, *o| m && m.snippet && !m.snippet.empty? }
  first_unread, * = with_snippets.select { |m, *o| m.has_label?(:unread) }.sort_by { |m, *o| m.date }.first
  return first_unread.snippet if first_unread
  last_read, * = with_snippets.sort_by { |m, *o| m.date }.last
  return last_read.snippet if last_read
  ""
end

#subjObject



125
# File 'lib/sup/thread.rb', line 125

def subj; argfind { |m, *o| m && m.subj }; end

#to_sObject



146
147
148
# File 'lib/sup/thread.rb', line 146

def to_s
  "<thread containing: #{@containers.join ', '}>"
end

#toggle_label(label) ⇒ Object



101
102
103
104
105
106
107
108
109
# File 'lib/sup/thread.rb', line 101

def toggle_label label
  if has_label? label
    remove_label label
    return false
  else
    apply_label label
    return true
  end
end