From: wmorgan Date: Mon, 6 Aug 2007 00:05:54 +0000 (+0000) Subject: to, cc, bcc prompting and editing, with tab completion X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=b3b672127f31675db4c697c3d657d49f2c4b0eb5;p=sup 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 --- diff --git a/bin/sup b/bin/sup index 59785c9..cb4542a 100644 --- 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 index 2eb2998..a6086bc 100644 --- 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 index 91c0869..40bd6fc 100644 --- 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 index 0706725..94d076d 100644 --- 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 index 16528a4..694800d 100644 --- 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 index 87fce0e..22fedc7 100644 --- 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 index f147785..7fe020c 100644 --- 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