]> git.cworth.org Git - sup/commitdiff
add gpg interface to all outgoing messages (but no implementation yet)
authorwmorgan <wmorgan@5c8cc53c-5e98-4d25-b20a-d8db53a31250>
Sat, 8 Dec 2007 21:20:17 +0000 (21:20 +0000)
committerwmorgan <wmorgan@5c8cc53c-5e98-4d25-b20a-d8db53a31250>
Sat, 8 Dec 2007 21:20:17 +0000 (21:20 +0000)
git-svn-id: svn://rubyforge.org/var/svn/sup/trunk@744 5c8cc53c-5e98-4d25-b20a-d8db53a31250

Manifest.txt
lib/sup.rb
lib/sup/colormap.rb
lib/sup/crypto.rb
lib/sup/modes/edit-message-mode.rb
lib/sup/modes/reply-mode.rb
lib/sup/modes/scroll-mode.rb
lib/sup/util.rb

index d24764c6828042dee2440f84449a58326137abb4..a423a6fa31687ed19b8a062c691647395f33a183 100644 (file)
@@ -24,6 +24,7 @@ lib/sup/contact.rb
 lib/sup/crypto.rb
 lib/sup/draft.rb
 lib/sup/hook.rb
+lib/sup/horizontal-selector.rb
 lib/sup/imap.rb
 lib/sup/index.rb
 lib/sup/keymap.rb
index 9cd2fd7109cc187c25141f0f2420a3f03c0ce785..60679ee882757c517eaa1223ae1bc824f1b70e80 100644 (file)
@@ -255,6 +255,7 @@ require "sup/tagger"
 require "sup/draft"
 require "sup/poll"
 require "sup/crypto"
+require "sup/horizontal-selector"
 require "sup/modes/line-cursor-mode"
 require "sup/modes/help-mode"
 require "sup/modes/edit-message-mode"
index 004df263197039c5ad3dbd8da71c80abacfbd600..9c6869a8744989f91f89e7e26eddedd49edfce98 100644 (file)
@@ -51,6 +51,8 @@ class Colormap
       case bg
       when Curses::COLOR_CYAN
         Curses::COLOR_YELLOW
+      when Curses::COLOR_YELLOW
+        Curses::COLOR_BLUE
       else
         Curses::COLOR_CYAN
       end
index 148456d62f59e4269be3683a1290e642b37c7e0d..5db576b900915edccdd3e552d30e448b65c4fe2f 100644 (file)
@@ -3,6 +3,12 @@ module Redwood
 class CryptoManager
   include Singleton
 
+  OUTGOING_MESSAGE_OPERATIONS = OrderedHash.new(
+    [:sign, "Sign"],
+    [:sign_and_encrypt, "Sign and encrypt"],
+    [:encrypt, "Encrypt only"]
+  )
+
   def initialize
     @mutex = Mutex.new
     self.class.i_am_the_instance self
@@ -13,13 +19,16 @@ class CryptoManager
     @cmd =
       case bin
       when /\S/
+        Redwood::log "crypto: detected gpg binary in #{bin}"
         "#{bin} --quiet --batch --no-verbose --logger-fd 1 --use-agent"
       else
+        Redwood::log "crypto: no gpg binary detected"
         nil
       end
   end
 
-  # returns a cryptosignature
+  def have_crypto?; !@cmd.nil? end
+
   def verify payload, signature # both RubyMail::Message objects
     return unknown_status(cant_find_binary) unless @cmd
 
index e04fc3033dfc4f80f6a9012bba5769cc4625a3fb..43bf9f0318964fe7fc2acbbffecd2e6820bed81e 100644 (file)
@@ -8,6 +8,8 @@ module Redwood
 class SendmailCommandFailed < StandardError; end
 
 class EditMessageMode < LineCursorMode
+  DECORATION_LINES = 1
+
   FORCE_HEADERS = %w(From To Cc Bcc Subject)
   MULTI_HEADERS = %w(To Cc Bcc)
   NON_EDITABLE_HEADERS = %w(Message-Id Date)
@@ -48,6 +50,8 @@ EOS
     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'
+    k.add :move_cursor_right, "Move selector to the right", :right
+    k.add :move_cursor_left, "Move selector to the left", :left
   end
 
   def initialize opts={}
@@ -60,7 +64,15 @@ EOS
     @attachments = []
     @message_id = "<#{Time.now.to_i}-sup-#{rand 10000}@#{Socket.gethostname}>"
     @edited = false
-    @skip_top_rows = opts[:skip_top_rows] || 0
+    @reserve_top_rows = opts[:reserve_top_rows] || 0
+    @selectors = []
+    @selector_label_width = 0
+
+    @crypto_selector =
+      if CryptoManager.have_crypto?
+        HorizontalSelector.new "Crypto:", [:none] + CryptoManager::OUTGOING_MESSAGE_OPERATIONS.keys, ["None"] + CryptoManager::OUTGOING_MESSAGE_OPERATIONS.values
+      end
+    add_selector @crypto_selector if @crypto_selector
     
     HookManager.run "before-edit", :header => @header, :body => @body
 
@@ -68,17 +80,29 @@ EOS
     regen_text
   end
 
-  def lines; @text.length end
-  def [] i; @text[i] end
+  def lines; @text.length + (@selectors.empty? ? 0 : (@selectors.length + DECORATION_LINES)) end
+  
+  def [] i
+    if @selectors.empty?
+      @text[i]
+    elsif i < @selectors.length
+      @selectors[i].line @selector_label_width
+    elsif i == @selectors.length
+      "-" * buffer.content_width
+    else
+      @text[i - @selectors.length - DECORATION_LINES]
+    end
+  end
 
-  ## a hook
+  ## hook for subclasses. i hate this style of programming.
   def handle_new_text header, body; end
 
   def edit_message_or_field
-    if (curpos - @skip_top_rows) >= @header_lines.length
+    lines = DECORATION_LINES + @selectors.size
+    if (curpos - lines) >= @header_lines.length
       edit_message
     else
-      edit_field @header_lines[curpos - @skip_top_rows]
+      edit_field @header_lines[curpos - lines]
     end
   end
 
@@ -121,7 +145,7 @@ EOS
   end
 
   def delete_attachment
-    i = (curpos - @skip_top_rows) - @attachment_lines_offset
+    i = (curpos - @reserve_top_rows) - @attachment_lines_offset
     if i >= 0 && i < @attachments.size && BufferManager.ask_yes_or_no("Delete attachment #{@attachments[i]}?")
       @attachments.delete_at i
       update
@@ -130,6 +154,23 @@ EOS
 
 protected
 
+  def move_cursor_left
+    return unless curpos < @selectors.length
+    @selectors[curpos].roll_left
+    buffer.mark_dirty
+  end
+
+  def move_cursor_right
+    return unless curpos < @selectors.length
+    @selectors[curpos].roll_right
+    buffer.mark_dirty
+  end
+
+  def add_selector s
+    @selectors << s
+    @selector_label_width = [@selector_label_width, s.label.length].max
+  end
+
   def update
     regen_text
     buffer.mark_dirty if buffer
index fb7bfd69d0828e4e4179c944e32cbe3d4f407ff5..c95ffc0f1f16ca2ea16d221d5c80b2810e330f58 100644 (file)
@@ -3,18 +3,13 @@ module Redwood
 class ReplyMode < EditMessageMode
   REPLY_TYPES = [:sender, :recipient, :list, :all, :user]
   TYPE_DESCRIPTIONS = {
-    :sender => "Reply to sender",
-    :recipient => "Reply to recipient",
-    :all => "Reply to all",
-    :list => "Reply to mailing list",
-    :user => "Customized reply"
+    :sender => "Sender",
+    :recipient => "Recipient",
+    :all => "All",
+    :list => "Mailing list",
+    :user => "Customized"
   }
 
-  register_keymap do |k|
-    k.add :move_cursor_right, "Move cursor to the right", :right
-    k.add :move_cursor_left, "Move cursor to the left", :left
-  end
-
   def initialize message
     @m = message
 
@@ -41,7 +36,6 @@ class ReplyMode < EditMessageMode
 
     ## next, cc:
     cc = (@m.to + @m.cc - [from, to]).uniq
-    Redwood::log "cc = (#{@m.to.inspect} + #{@m.cc.inspect} - #{[from, to].inspect}).uniq = #{cc.inspect}"
 
     ## one potential reply type is "reply to recipient". this only happens
     ## in certain cases:
@@ -85,36 +79,39 @@ class ReplyMode < EditMessageMode
              }.merge v
     end
 
-    @type_labels = REPLY_TYPES.select { |t| @headers.member?(t) }
-    @selected_type = 
+    types = REPLY_TYPES.select { |t| @headers.member?(t) }
+    @type_selector = HorizontalSelector.new "Reply to:", types, types.map { |x| TYPE_DESCRIPTIONS[x] }
+
+    @type_selector.set_to(
       if @m.is_list_message?
         :list
       elsif @headers.member? :sender
         :sender
       else
         :recipient
-      end
+      end)
 
-    super :header => @headers[@selected_type], :body => body,
-          :skip_top_rows => 2, :twiddles => false
+    super :header => @headers[@type_selector.val], :body => body, :twiddles => false
+    add_selector @type_selector
   end
 
-  def lines; super + 2; end
-  def [] i
-    case i
-    when 0
-      @type_labels.inject([]) do |array, t|
-        array + [[(t == @selected_type ? :none_highlight : :none), 
-          "#{TYPE_DESCRIPTIONS[t]}"], [:none, "  "]]
-      end + [[:none, ""]]
-    when 1
-      ""
-    else
-      super(i - 2)
+protected
+
+  def move_cursor_right
+    super
+    if @headers[@type_selector.val] != self.header
+      self.header = @headers[@type_selector.val]
+      update
     end
   end
 
-protected
+  def move_cursor_left
+    super
+    if @headers[@type_selector.val] != self.header
+      self.header = @headers[@type_selector.val]
+      update
+    end
+  end
 
   def reply_body_lines m
     lines = ["Excerpts from #{@m.from.name}'s message of #{@m.date}:"] + m.quotable_body_lines.map { |l| "> #{l}" }
@@ -123,9 +120,9 @@ protected
   end
 
   def handle_new_text new_header, new_body
-    old_header = @headers[@selected_type]
+    old_header = @headers[@type_selector.val]
     if new_header.size != old_header.size || old_header.any? { |k, v| new_header[k] != v }
-      @selected_type = :user
+      @type_selector.set_to :user
       self.header = @headers[:user] = new_header
       update
     end
@@ -138,24 +135,10 @@ protected
   def edit_field field
     edited_field = super
     if edited_field && edited_field != "Subject"
-      @selected_type = :user
+      @type_selector.set_to :user
       update
     end
   end
-  
-  def move_cursor_left
-    i = @type_labels.index @selected_type
-    @selected_type = @type_labels[(i - 1) % @type_labels.length]
-    self.header = @headers[@selected_type]
-    update
-  end
-
-  def move_cursor_right
-    i = @type_labels.index @selected_type
-    @selected_type = @type_labels[(i + 1) % @type_labels.length]
-    self.header = @headers[@selected_type]
-    update
-  end
 end
 
 end
index 328a07de457cc5e2b00d1f719a2bd3c6f51309d4..1ff91707d279a0948fef495c01cb65e8e776789a 100644 (file)
@@ -176,7 +176,7 @@ protected
         draw_line_from_array ln, s, opts
       end
     else
-      raise "unknown drawable object: #{s.inspect}" # good for debugging
+      raise "unknown drawable object: #{s.inspect} in #{self} for line #{ln}" # good for debugging
     end
 
       ## speed test
index cc15803b1ddb4ed9a6b4d91d7c6ceb935e26a9e5..e2b82e1f6cbbeeb321654c456b4a6d339fe2a838 100644 (file)
@@ -577,23 +577,26 @@ end
 class OrderedHash < Hash
   alias_method :store, :[]=
   alias_method :each_pair, :each
+  attr_reader :keys
 
-  def initialize
+  def initialize *a
     @keys = []
+    a.each { |k, v| self[k] = v }
   end
 
-  def []=(key, val)
+  def []= key, val
     @keys << key unless member?(key)
     super
   end
 
-  def delete(key)
-    @keys.delete(key)
+  def values; keys.map { |k| self[k] } end
+  def index key; @keys.index key end
+
+  def delete key
+    @keys.delete key
     super
   end
 
-  def each
-    @keys.each { |k| yield k, self[k] }
-  end
+  def each; @keys.each { |k| yield k, self[k] } end
 end