sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit 2faf46026d3d7ba637718d5d1e34ceef845652f1
parent 9ec08ed5fc47ffb65e3dceb9ab25334c380abe3c
Author: wmorgan <wmorgan@5c8cc53c-5e98-4d25-b20a-d8db53a31250>
Date:   Wed, 30 May 2007 17:43:30 +0000

better yamlication (and misc comment tweaks)

git-svn-id: svn://rubyforge.org/var/svn/sup/trunk@423 5c8cc53c-5e98-4d25-b20a-d8db53a31250

Diffstat:
M doc/TODO | 1 +
M lib/sup.rb | 34 +++++++++++++++++++---------------
M lib/sup/draft.rb | 3 +--
M lib/sup/imap.rb | 7 ++++---
M lib/sup/index.rb | 2 +-
M lib/sup/maildir.rb | 3 +--
M lib/sup/mbox/loader.rb | 3 +--
M lib/sup/mbox/ssh-loader.rb | 5 +++--
M lib/sup/sent.rb | 4 ++--
M lib/sup/source.rb | 15 +++++++--------
M lib/sup/util.rb | 4 ++++
11 files changed, 44 insertions(+), 37 deletions(-)
diff --git a/doc/TODO b/doc/TODO
@@ -1,5 +1,6 @@
 for 0.0.9
 ---------
+_ add arbitrary labels to sources
 _ detect other sup instances and do something intelligent (because ferret crashes violently with more than one index writer open)
 _ bugfix: need a way to force an address to a particular name, for things like evite addresses
 _ bugfix: read before thread-index has finished loading then hides the thread?!? wtf. (on jamie)
diff --git a/lib/sup.rb b/lib/sup.rb
@@ -12,6 +12,24 @@ class Object
   end
 end
 
+class Module
+  def yaml_properties *props
+    props = props.map { |p| p.to_s }
+    vars = props.map { |p| "@#{p}" }
+    klass = self
+    path = klass.name.gsub(/::/, "/")
+    
+    klass.instance_eval do
+      define_method(:to_yaml_properties) { vars }
+      define_method(:to_yaml_type) { "!#{Redwood::YAML_DOMAIN},#{Redwood::YAML_DATE}/#{path}" }
+    end
+
+    YAML.add_domain_type("#{Redwood::YAML_DOMAIN},#{Redwood::YAML_DATE}", path) do |type, val|
+      klass.new(*props.map { |p| val[p] })
+    end
+  end
+end
+
 module Redwood
   VERSION = "0.0.8"
 
@@ -50,20 +68,6 @@ module Redwood
   module_function :reporting_thread
 
 ## one-stop shop for yamliciousness
-  def register_yaml klass, props
-    vars = props.map { |p| "@#{p}" }
-    path = klass.name.gsub(/::/, "/")
-    
-    klass.instance_eval do
-      define_method(:to_yaml_properties) { vars }
-      define_method(:to_yaml_type) { "!#{YAML_DOMAIN},#{YAML_DATE}/#{path}" }
-    end
-
-    YAML.add_domain_type("#{YAML_DOMAIN},#{YAML_DATE}", path) do |type, val|
-      klass.new(*props.map { |p| val[p] })
-    end
-  end
-
   def save_yaml_obj object, fn, compress=false
     if compress
       Zlib::GzipWriter.open(fn) { |f| f.puts object.to_yaml }
@@ -142,7 +146,7 @@ EOM
     end
   end
 
-  module_function :register_yaml, :save_yaml_obj, :load_yaml_obj, :start, :finish, :report_broken_sources
+  module_function :save_yaml_obj, :load_yaml_obj, :start, :finish, :report_broken_sources
 end
 
 ## set up default configuration file
diff --git a/lib/sup/draft.rb b/lib/sup/draft.rb
@@ -42,6 +42,7 @@ end
 
 class DraftLoader < Source
   attr_accessor :dir
+  yaml_properties :cur_offset
 
   def initialize cur_offset=0
     dir = Redwood::DRAFT_DIR
@@ -119,6 +120,4 @@ private
   end
 end
 
-Redwood::register_yaml(DraftLoader, %w(cur_offset))
-
 end
diff --git a/lib/sup/imap.rb b/lib/sup/imap.rb
@@ -35,7 +35,8 @@ require 'rmail'
 ## of the spec actually happens in practice. you'll request flags for
 ## one message, and get it interspersed with a random bunch of flags
 ## for some other messages, including a different set of flags for the
-## same message! totally ok by the imap spec. totally retarded.
+## same message! totally ok by the imap spec. totally retarded by any
+## other metric.
 ##
 ## fuck you, imap committee. you managed to design something nearly as
 ## shitty as mbox but goddamn THIRTY YEARS LATER.
@@ -48,6 +49,8 @@ class IMAP < Source
   RECOVERABLE_ERRORS = [ Errno::EPIPE, Errno::ETIMEDOUT, OpenSSL::SSL::SSLError ]
 
   attr_accessor :username, :password
+  yaml_properties :uri, :username, :password, :cur_offset, :usual,
+                  :archived, :id
 
   def initialize uri, username, password, last_idate=nil, usual=true, archived=false, id=nil
     raise ArgumentError, "username and password must be specified" unless username && password
@@ -282,6 +285,4 @@ private
 
 end
 
-Redwood::register_yaml(IMAP, %w(uri username password cur_offset usual archived id))
-
 end
diff --git a/lib/sup/index.rb b/lib/sup/index.rb
@@ -310,7 +310,7 @@ protected
         File.chmod 0600, fn
         FileUtils.mv fn, bakfn, :force => true unless File.exists?(bakfn) && File.size(bakfn) > File.size(fn)
       end
-      Redwood::save_yaml_obj @sources.values, fn
+      Redwood::save_yaml_obj @sources.values.sort_by { |s| s.id.to_i }, fn
       File.chmod 0600, fn
     end
     @sources_dirty = false
diff --git a/lib/sup/maildir.rb b/lib/sup/maildir.rb
@@ -11,6 +11,7 @@ module Redwood
 class Maildir < Source
   SCAN_INTERVAL = 30 # seconds
 
+  yaml_properties :uri, :cur_offset, :usual, :archived, :id
   def initialize uri, last_date=nil, usual=true, archived=false, id=nil
     super
     uri = URI(uri)
@@ -122,6 +123,4 @@ private
   end
 end
 
-Redwood::register_yaml(Maildir, %w(uri cur_offset usual archived id))
-
 end
diff --git a/lib/sup/mbox/loader.rb b/lib/sup/mbox/loader.rb
@@ -5,6 +5,7 @@ module Redwood
 module MBox
 
 class Loader < Source
+  yaml_properties :uri, :cur_offset, :usual, :archived, :id
   def initialize uri_or_fp, start_offset=nil, usual=true, archived=false, id=nil
     super
 
@@ -131,7 +132,5 @@ class Loader < Source
   end
 end
 
-Redwood::register_yaml(Loader, %w(uri cur_offset usual archived id))
-
 end
 end
diff --git a/lib/sup/mbox/ssh-loader.rb b/lib/sup/mbox/ssh-loader.rb
@@ -6,6 +6,9 @@ module MBox
 class SSHLoader < Source
   attr_accessor :username, :password
 
+  yaml_properties :uri, :username, :password, :cur_offset, :usual, 
+                  :archived, :id
+
   def initialize uri, username=nil, password=nil, start_offset=nil, usual=true, archived=false, id=nil
     raise ArgumentError, "not an mbox+ssh uri: #{uri.inspect}" unless uri =~ %r!^mbox\+ssh://!
 
@@ -66,7 +69,5 @@ class SSHLoader < Source
   end
 end
 
-Redwood::register_yaml(SSHLoader, %w(uri username password cur_offset usual archived id))
-
 end
 end
diff --git a/lib/sup/sent.rb b/lib/sup/sent.rb
@@ -30,6 +30,8 @@ class SentManager
 end
 
 class SentLoader < MBox::Loader
+  yaml_properties :cur_offset
+
   def initialize cur_offset=0
     filename = Redwood::SENT_FN
     File.open(filename, "w") { } unless File.exists? filename
@@ -42,6 +44,4 @@ class SentLoader < MBox::Loader
   def labels; [:sent, :inbox]; end
 end
 
-Redwood::register_yaml(SentLoader, %w(cur_offset))
-
 end
diff --git a/lib/sup/source.rb b/lib/sup/source.rb
@@ -5,15 +5,15 @@ class OutOfSyncSourceError < SourceError; end
 class FatalSourceError < SourceError; end
 
 class Source
-  ## Implementing a new source is typically quite easy, because Sup
-  ## only needs to be able to:
+  ## Implementing a new source should be easy, because Sup only needs
+  ## to be able to:
   ##  1. See how many messages it contains
   ##  2. Get an arbitrary message
   ##  3. (optional) see whether the source has marked it read or not
   ##
   ## In particular, Sup doesn't need to move messages, mark them as
-  ## read, delete them, or anything else. (Well, at some point it will
-  ## need to delete them, but that will be an optional capability.)
+  ## read, delete them, or anything else. (Well, it's nice to be able
+  ## to delete them, but that is optional.)
   ##
   ## On the other hand, Sup assumes that you can assign each message a
   ## unique integer id, such that newer messages have higher ids than
@@ -33,7 +33,8 @@ class Source
   ## - raw_header offset
   ## - raw_full_message offset
   ## - check
-  ## - next (or each, if you prefer)
+  ## - next (or each, if you prefer): should return a message and an
+  ##   array of labels.
   ##
   ## ... where "offset" really means unique id. (You can tell I
   ## started with mbox.)
@@ -46,7 +47,7 @@ class Source
   ## else (e.g. the imap server is down or the maildir is missing.)
   ##
   ## Finally, be sure the source is thread-safe, since it WILL be
-  ## pummeled from multiple threads at once.
+  ## pummelled from multiple threads at once.
   ##
   ## Examples for you to look at: mbox/loader.rb, imap.rb, and
   ## maildir.rb.
@@ -97,6 +98,4 @@ protected
   end
 end
 
-Redwood::register_yaml(Source, %w(uri cur_offset usual archived id))
-
 end
diff --git a/lib/sup/util.rb b/lib/sup/util.rb
@@ -344,6 +344,10 @@ end
 ## h2[:a].val # => 0
 ## h2[:a].val = 1
 ## h2[:a].val # => 1
+##
+## important note: you REALLY want to use #member? to test existence,
+## because just checking h[anything] will always evaluate to true
+## (except for degenerate constructor blocks that return nil or false)
 class SavingHash
   def initialize &b
     @constructor = b