commit b3b672127f31675db4c697c3d657d49f2c4b0eb5
parent bb459f55d260fee63279b3ea9f9247a37548710e
Author: wmorgan <wmorgan@5c8cc53c-5e98-4d25-b20a-d8db53a31250>
Date: Mon, 6 Aug 2007 00:05:54 +0000
to, cc, bcc prompting and editing, with tab completion
git-svn-id: svn://rubyforge.org/var/svn/sup/trunk@516 5c8cc53c-5e98-4d25-b20a-d8db53a31250
Diffstat:
7 files changed, 83 insertions(+), 26 deletions(-)
diff --git a/bin/sup b/bin/sup
@@ -233,9 +233,13 @@ begin
end
when :compose
- mode = ComposeMode.new
+ to = BufferManager.ask_for_contacts(:people, "To: ") or next
+ cc = BufferManager.ask_for_contacts(:people, "Cc: ") or next if $config[:ask_for_cc]
+ bcc = BufferManager.ask_for_contacts(:people, "Bcc: ") or next if $config[:ask_for_bcc]
+
+ mode = ComposeMode.new :to => to, :cc => cc, :bcc => bcc
bm.spawn "New Message", mode
- mode.edit
+ mode.edit_message
when :poll
# bm.raise_to_front PollManager.buffer
reporting_thread { PollManager.poll }
diff --git a/lib/sup.rb b/lib/sup.rb
@@ -193,6 +193,8 @@ else
:editor => ENV["EDITOR"] || "/usr/bin/vim -f -c 'setlocal spell spelllang=en_us' -c 'set filetype=mail'",
:thread_by_subject => false,
:edit_signature => false,
+ :ask_for_cc => true,
+ :ask_for_bcc => false
}
begin
FileUtils.mkdir_p Redwood::BASE_DIR
diff --git a/lib/sup/buffer.rb b/lib/sup/buffer.rb
@@ -39,7 +39,7 @@ module Ncurses
remove_const :KEY_CANCEL
KEY_ENTER = 10
- KEY_CANCEL = ?\a # ctrl-g
+ KEY_CANCEL = 7 # ctrl-g
KEY_TAB = 9
end
@@ -344,7 +344,7 @@ class BufferManager
def ask_many_with_completions domain, question, completions, default=nil, sep=" "
ask domain, question, default do |partial|
prefix, target =
- case partial.gsub(/#{sep}+/, sep)
+ case partial#.gsub(/#{sep}+/, sep)
when /^\s*$/
["", ""]
when /^(.+#{sep})$/
@@ -403,7 +403,7 @@ class BufferManager
applyable_labels = (LabelManager.applyable_labels - forbidden_labels).map { |l| LabelManager.string_for l }.sort_by { |s| s.downcase }
- answer = BufferManager.ask_many_with_completions domain, question, applyable_labels, default
+ answer = ask_many_with_completions domain, question, applyable_labels, default
return unless answer
@@ -417,6 +417,19 @@ class BufferManager
user_labels
end
+ def ask_for_contacts domain, question, default_contacts=[]
+ default = default_contacts.map { |s| s.to_s }.join(" ")
+ default += " " unless default.empty?
+
+ all_contacts = ContactManager.contacts.map { |c| [ContactManager.alias_for(c), c.longname, c.email] }.flatten.uniq.sort
+
+ answer = BufferManager.ask_many_with_completions domain, question, all_contacts, default, /\s*,\s*/
+
+ if answer
+ answer.split_on_commas.map { |x| ContactManager.contact_for(x.downcase) || PersonManager.person_for(x) }
+ end
+ end
+
def ask domain, question, default=nil, &block
raise "impossible!" if @asking
diff --git a/lib/sup/contact.rb b/lib/sup/contact.rb
@@ -35,7 +35,7 @@ class ContactManager
@a2p.delete aalias
end
end
- def person_with aalias; @a2p[aalias]; end
+ def contact_for aalias; @a2p[aalias]; end
def alias_for person; @p2a[person]; end
def is_contact? person; @p2a.member? person; end
def save
diff --git a/lib/sup/index.rb b/lib/sup/index.rb
@@ -362,7 +362,7 @@ protected
def parse_user_query_string str
str2 = str.gsub(/(to|from):(\S+)/) do
field, name = $1, $2
- if(p = ContactManager.person_with(name))
+ if(p = ContactManager.contact_for(name))
[field, p.email]
else
[field, name]
diff --git a/lib/sup/modes/edit-message-mode.rb b/lib/sup/modes/edit-message-mode.rb
@@ -18,7 +18,8 @@ class EditMessageMode < LineCursorMode
register_keymap do |k|
k.add :send_message, "Send message", 'y'
- k.add :edit, "Edit message", 'e', :enter
+ k.add :edit_field, "Edit field", 'e'
+ k.add :edit_message, "Edit message", :enter
k.add :save_as_draft, "Save as draft", 'P'
k.add :attach_file, "Attach a file", 'a'
k.add :delete_attachment, "Delete an attachment", 'd'
@@ -26,10 +27,12 @@ class EditMessageMode < LineCursorMode
def initialize opts={}
@header = opts.delete(:header) || {}
+ @header_lines = []
+
@body = opts.delete(:body) || []
@body += sig_lines if $config[:edit_signature]
+
@attachments = []
- @attachment_lines = {}
@message_id = "<#{Time.now.to_i}-sup-#{rand 10000}@#{Socket.gethostname}>"
@edited = false
@@ -43,9 +46,36 @@ class EditMessageMode < LineCursorMode
## a hook
def handle_new_text header, body; end
- def edit
+ def edit_field
+ if curpos >= @header_lines.length
+ edit_message
+ else
+ case(field = @header_lines[curpos])
+ when "Subject"
+ text = BufferManager.ask :subject, "Subject: ", @header[field]
+ @header[field] = parse_header field, text if text
+ else
+ default =
+ case field
+ when *MULTI_HEADERS
+ @header[field].join(", ")
+ else
+ @header[field]
+ end
+
+ contacts = BufferManager.ask_for_contacts :people, "#{field}: ", default
+ if contacts
+ text = contacts.map { |s| s.longname }.join(", ")
+ @header[field] = parse_header field, text
+ end
+ end
+ update
+ end
+ end
+
+ def edit_message
@file = Tempfile.new "sup.#{self.class.name.gsub(/.*::/, '').camel_to_hyphy}"
- @file.puts header_lines(@header - NON_EDITABLE_HEADERS)
+ @file.puts format_headers(@header - NON_EDITABLE_HEADERS).first
@file.puts
@file.puts @body
@file.close
@@ -90,8 +120,8 @@ protected
end
def regen_text
- top = header_lines(@header - NON_EDITABLE_HEADERS) + [""]
- @text = top + @body
+ header, @header_lines = format_headers(@header - NON_EDITABLE_HEADERS) + [""]
+ @text = header + [""] + @body
@text += sig_lines unless $config[:edit_signature]
unless @attachments.empty?
@@ -107,24 +137,30 @@ protected
body = f.readlines
header.delete_if { |k, v| NON_EDITABLE_HEADERS.member? k }
- header.each do |k, v|
- next unless MULTI_HEADERS.include?(k) && !v.empty?
- header[k] = v.split_on_commas.map do |name|
- (p = ContactManager.person_with(name)) && p.full_address || name
- end
- end
+ header.each { |k, v| header[k] = parse_header k, v }
[header, body]
end
end
- def header_lines header
- force_headers = FORCE_HEADERS.map { |h| make_lines "#{h}:", header[h] }
- other_headers = (header.keys - FORCE_HEADERS).map do |h|
- make_lines "#{h}:", header[h]
+ def parse_header k, v
+ if MULTI_HEADERS.include?(k)
+ v.split_on_commas.map do |name|
+ (p = ContactManager.contact_for(name)) && p.full_address || name
+ end
+ else
+ v
end
+ end
- (force_headers + other_headers).flatten.compact
+ def format_headers header
+ header_lines = []
+ headers = (FORCE_HEADERS + (header.keys - FORCE_HEADERS)).map do |h|
+ lines = make_lines "#{h}:", header[h]
+ lines.length.times { header_lines << h }
+ lines
+ end.flatten.compact
+ [headers, header_lines]
end
def make_lines header, things
diff --git a/lib/sup/textfield.rb b/lib/sup/textfield.rb
@@ -103,10 +103,12 @@ class TextField
Ncurses::Form::REQ_NEXT_CHAR
when Ncurses::KEY_BACKSPACE
Ncurses::Form::REQ_DEL_PREV
- when ?\001
+ when 1 #ctrl-a
Ncurses::Form::REQ_BEG_FIELD
- when ?\005
+ when 5 #ctrl-e
Ncurses::Form::REQ_END_FIELD
+ when 11 # ctrl-k
+ Ncurses::Form::REQ_CLR_EOF
when Ncurses::KEY_UP
@i ||= @history.size
@history[@i] = get_cursed_value