]> git.cworth.org Git - sup/blob - lib/sup/modes/reply-mode.rb
added "reply to recipient"
[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
36     ## ignore reply-to for list messages because it's typically set to
37     ## the list address anyways
38     to = @m.is_list_message? ? @m.from : (@m.replyto || @m.from)
39     cc = (@m.to + @m.cc - [from, to]).uniq
40
41     @headers = {}
42     @headers[:sender] = {
43       "From" => "#{from.name} <#{from_email}>",
44       "To" => [to.full_address],
45     } unless AccountManager.is_account? to
46
47     @headers[:recipient] = {
48       "From" => "#{from.name} <#{from_email}>",
49       "To" => cc.map { |p| p.full_address },
50     } unless cc.empty?
51
52     @headers[:user] = {
53       "From" => "#{from.name} <#{from_email}>",
54     }
55
56     @headers[:all] = {
57       "From" => "#{from.name} <#{from_email}>",
58       "To" => [to.full_address],
59       "Cc" => cc.map { |p| p.full_address },
60     } unless cc.empty?
61
62     @headers[:list] = {
63       "From" => "#{from.name} <#{from_email}>",
64       "To" => [@m.list_address.full_address],
65     } if @m.is_list_message?
66
67     refs = gen_references
68     mid = gen_message_id
69     @headers.each do |k, v|
70       @headers[k] = {
71                "To" => "",
72                "Cc" => "",
73                "Bcc" => "",
74                "In-Reply-To" => "<#{@m.id}>",
75                "Subject" => Message.reify_subj(@m.subj),
76                "Message-Id" => mid,
77                "References" => refs,
78              }.merge v
79     end
80
81     @type_labels = REPLY_TYPES.select { |t| @headers.member?(t) }
82     @selected_type = 
83       if @m.is_list_message?
84         :list
85       elsif @headers.member? :sender
86         :sender
87       else
88         :recipient
89       end
90
91     regen_text
92   end
93
94   def lines; @text.length + 2; end
95   def [] i
96     case i
97     when 0
98       lame = []
99       @type_labels.each do |t|
100         lame << [(t == @selected_type ? :none_highlight : :none), 
101           "#{TYPE_DESCRIPTIONS[t]}"]
102         lame << [:none, "  "]
103       end
104       lame + [[:none, ""]]
105     when 1
106       ""
107     else
108       @text[i - 2]
109     end
110   end
111
112 protected
113
114   def body; @body + sig_lines; end
115   def header; @headers[@selected_type]; end
116
117   def reply_body_lines m
118     lines = ["Excerpts from #{@m.from.name}'s message of #{@m.date}:"] + 
119       m.basic_body_lines.map { |l| "> #{l}" }
120     lines.pop while lines.last !~ /[:alpha:]/
121     lines
122   end
123
124   def handle_new_text new_header, new_body
125     @body = new_body
126
127     if new_header.size != header.size ||
128         header.any? { |k, v| new_header[k] != v }
129       #raise "nhs: #{new_header.size} hs: #{header.size} new: #{new_header.inspect} old: #{header.inspect}"
130       @selected_type = :user
131       @headers[:user] = new_header
132     end
133   end
134
135   def regen_text
136     @text = header_lines(header - NON_EDITABLE_HEADERS) + [""] + body
137   end
138
139   def gen_references
140     (@m.refs + [@m.id]).map { |x| "<#{x}>" }.join(" ")
141   end
142   
143   def move_cursor_left
144     i = @type_labels.index @selected_type
145     @selected_type = @type_labels[(i - 1) % @type_labels.length]
146     update
147   end
148
149   def move_cursor_right
150     i = @type_labels.index @selected_type
151     @selected_type = @type_labels[(i + 1) % @type_labels.length]
152     update
153   end
154 end
155
156 end