]> git.cworth.org Git - sup/blob - lib/sup/modes/reply-mode.rb
dee7aaa7bc57286d69b4539acc99d87adc87b647
[sup] / lib / sup / modes / reply-mode.rb
1 module Redwood
2
3 class ReplyMode < EditMessageMode
4   REPLY_TYPES = [:sender, :recipient, :list, :all, :user]
5   TYPE_DESCRIPTIONS = {
6     :sender => "Reply to sender",
7     :recipient => "Reply to recipient",
8     :all => "Reply to all",
9     :list => "Reply to mailing list",
10     :user => "Customized reply"
11   }
12
13   register_keymap do |k|
14     k.add :move_cursor_right, "Move cursor to the right", :right
15     k.add :move_cursor_left, "Move cursor to the left", :left
16   end
17
18   def initialize message
19     super 2, :twiddles => false
20     @m = message
21
22     ## it's important to put this early because it forces a read of
23     ## the full headers (most importantly the list-post header, if
24     ## any)
25     @body = reply_body_lines(message)
26
27     from =
28       if @m.recipient_email
29         AccountManager.account_for(@m.recipient_email)
30       else
31         (@m.to + @m.cc).find { |p| AccountManager.is_account? p }
32       end || AccountManager.default_account
33
34     #from_email = @m.recipient_email || from.email
35     from_email = from.email
36
37     ## ignore reply-to for list messages because it's typically set to
38     ## the list address anyways
39     to = @m.is_list_message? ? @m.from : (@m.replyto || @m.from)
40     cc = (@m.to + @m.cc - [from, to]).uniq
41
42     @headers = {}
43     @headers[:sender] = {
44       "From" => "#{from.name} <#{from_email}>",
45       "To" => [to.full_address],
46     } unless AccountManager.is_account? to
47
48     @headers[:recipient] = {
49       "From" => "#{from.name} <#{from_email}>",
50       "To" => cc.map { |p| p.full_address },
51     } unless cc.empty? || @m.is_list_message?
52
53     @headers[:user] = {
54       "From" => "#{from.name} <#{from_email}>",
55     }
56
57     @headers[:all] = {
58       "From" => "#{from.name} <#{from_email}>",
59       "To" => [to.full_address],
60       "Cc" => cc.map { |p| p.full_address },
61     } unless cc.empty?
62
63     @headers[:list] = {
64       "From" => "#{from.name} <#{from_email}>",
65       "To" => [@m.list_address.full_address],
66     } if @m.is_list_message?
67
68     refs = gen_references
69     mid = gen_message_id
70     @headers.each do |k, v|
71       @headers[k] = {
72                "To" => "",
73                "Cc" => "",
74                "Bcc" => "",
75                "In-Reply-To" => "<#{@m.id}>",
76                "Subject" => Message.reify_subj(@m.subj),
77                "Message-Id" => mid,
78                "References" => refs,
79              }.merge v
80     end
81
82     @type_labels = REPLY_TYPES.select { |t| @headers.member?(t) }
83     @selected_type = 
84       if @m.is_list_message?
85         :list
86       elsif @headers.member? :sender
87         :sender
88       else
89         :recipient
90       end
91
92     @body += sig_lines
93     regen_text
94   end
95
96   def lines; @text.length + 2; end
97   def [] i
98     case i
99     when 0
100       lame = []
101       @type_labels.each do |t|
102         lame << [(t == @selected_type ? :none_highlight : :none), 
103           "#{TYPE_DESCRIPTIONS[t]}"]
104         lame << [:none, "  "]
105       end
106       lame + [[:none, ""]]
107     when 1
108       ""
109     else
110       @text[i - 2]
111     end
112   end
113
114 protected
115
116   def body; @body; end
117   def header; @headers[@selected_type]; end
118
119   def reply_body_lines m
120     lines = ["Excerpts from #{@m.from.name}'s message of #{@m.date}:"] + 
121       m.basic_body_lines.map { |l| "> #{l}" }
122     lines.pop while lines.last =~ /^\s*$/
123     lines
124   end
125
126   def handle_new_text new_header, new_body
127     @body = new_body
128
129     if new_header.size != header.size ||
130         header.any? { |k, v| new_header[k] != v }
131       @selected_type = :user
132       @headers[:user] = new_header
133     end
134   end
135
136   def regen_text
137     @text = header_lines(header - NON_EDITABLE_HEADERS) + [""] + body
138   end
139
140   def gen_references
141     (@m.refs + [@m.id]).map { |x| "<#{x}>" }.join(" ")
142   end
143   
144   def move_cursor_left
145     i = @type_labels.index @selected_type
146     @selected_type = @type_labels[(i - 1) % @type_labels.length]
147     update
148   end
149
150   def move_cursor_right
151     i = @type_labels.index @selected_type
152     @selected_type = @type_labels[(i + 1) % @type_labels.length]
153     update
154   end
155 end
156
157 end