]> git.cworth.org Git - sup/blob - lib/sup.rb
cf46b8de7b1153f79d36acc7ce14c998e1bebbe5
[sup] / lib / sup.rb
1 require 'rubygems'
2 require 'yaml'
3 require 'zlib'
4 require 'thread'
5 require 'fileutils'
6
7 class Object
8   ## this is for debugging purposes because i keep calling #id on the
9   ## wrong object and i want it to throw an exception
10   def id
11     raise "wrong id called on #{self.inspect}"
12   end
13 end
14
15 module Redwood
16   VERSION = "0.0.7"
17
18   BASE_DIR   = ENV["SUP_BASE"] || File.join(ENV["HOME"], ".sup")
19   CONFIG_FN  = File.join(BASE_DIR, "config.yaml")
20   SOURCE_FN  = File.join(BASE_DIR, "sources.yaml")
21   LABEL_FN   = File.join(BASE_DIR, "labels.txt")
22   PERSON_FN  = File.join(BASE_DIR, "people.txt")
23   CONTACT_FN = File.join(BASE_DIR, "contacts.txt")
24   DRAFT_DIR  = File.join(BASE_DIR, "drafts")
25   SENT_FN    = File.join(BASE_DIR, "sent.mbox")
26
27   YAML_DOMAIN = "masanjin.net"
28   YAML_DATE = "2006-10-01"
29
30 ## record exceptions thrown in threads nicely
31   $exception = nil
32   def reporting_thread
33     ::Thread.new do
34       begin
35         yield
36       rescue Exception => e
37         File.open("sup-exception-log.txt", "w") do |f|
38           f.puts "--- #{e.class.name} at #{Time.now}"
39           f.puts e.message, e.backtrace
40         end
41         $exception ||= e
42         raise
43       end
44     end
45   end
46   module_function :reporting_thread
47
48 ## one-stop shop for yamliciousness
49   def register_yaml klass, props
50     vars = props.map { |p| "@#{p}" }
51     path = klass.name.gsub(/::/, "/")
52     
53     klass.instance_eval do
54       define_method(:to_yaml_properties) { vars }
55       define_method(:to_yaml_type) { "!#{YAML_DOMAIN},#{YAML_DATE}/#{path}" }
56     end
57
58     YAML.add_domain_type("#{YAML_DOMAIN},#{YAML_DATE}", path) do |type, val|
59       klass.new(*props.map { |p| val[p] })
60     end
61   end
62
63   def save_yaml_obj object, fn, compress=false
64     if compress
65       Zlib::GzipWriter.open(fn) { |f| f.puts object.to_yaml }
66     else
67       File.open(fn, "w") { |f| f.puts object.to_yaml }
68     end
69   end
70
71   def load_yaml_obj fn, compress=false
72     if File.exists? fn
73       if compress
74         Zlib::GzipReader.open(fn) { |f| YAML::load f }
75       else
76         YAML::load_file fn
77       end
78     end
79   end
80
81   def start
82     Redwood::PersonManager.new Redwood::PERSON_FN
83     Redwood::SentManager.new Redwood::SENT_FN
84     Redwood::ContactManager.new Redwood::CONTACT_FN
85     Redwood::LabelManager.new Redwood::LABEL_FN
86     Redwood::AccountManager.new $config[:accounts]
87     Redwood::DraftManager.new Redwood::DRAFT_DIR
88     Redwood::UpdateManager.new
89     Redwood::PollManager.new
90   end
91
92   def finish
93     Redwood::LabelManager.save
94     Redwood::ContactManager.save
95     Redwood::PersonManager.save
96   end
97
98   ## not really a good place for this, so I'll just dump it here.
99   def report_broken_sources
100     return unless BufferManager.instantiated?
101     broken_sources = Index.usual_sources.select { |s| s.broken? }
102     unless broken_sources.empty?
103       BufferManager.spawn "Out-of-sync soure notification", TextMode.new(<<EOM)
104 Out-of-sync source notification
105 -------------------------------
106
107 Hi there. It looks like one or more sources have fallen out of sync
108 with my index. This can happen when you modify these sources with
109 other email clients. (Sorry, I don't play well with others.)
110
111 Until this is corrected, messages from these sources cannot be viewed,
112 and new messages will not be detected. Luckily, this is easy to correct!
113
114 #{broken_sources.map { |s| "Source: " + s.to_s + "\n Error: " + s.broken_msg.wrap(70).join("\n        ") }.join('\n\n')}
115 EOM
116     end
117   end
118
119   module_function :register_yaml, :save_yaml_obj, :load_yaml_obj, :start, :finish, :report_broken_sources
120 end
121
122 ## set up default configuration file
123 if File.exists? Redwood::CONFIG_FN
124   $config = Redwood::load_yaml_obj Redwood::CONFIG_FN
125 else
126   $config = {
127     :accounts => {
128       :default => {
129         :name => "Your Name Here",
130         :email => "your.email.here@domain.tld",
131         :alternates => [],
132         :sendmail => "/usr/sbin/sendmail -oem -ti",
133         :signature => File.join(ENV["HOME"], ".signature")
134       }
135     },
136     :editor => ENV["EDITOR"] || "/usr/bin/vi",
137   }
138   begin
139     FileUtils.mkdir_p Redwood::BASE_DIR
140     Redwood::save_yaml_obj $config, Redwood::CONFIG_FN
141   rescue StandardError => e
142     $stderr.puts "warning: #{e.message}"
143   end
144 end
145
146 require "sup/util"
147 require "sup/update"
148 require "sup/message"
149 require "sup/source"
150 require "sup/mbox"
151 require "sup/maildir"
152 require "sup/imap"
153 require "sup/person"
154 require "sup/account"
155 require "sup/thread"
156 require "sup/index"
157 require "sup/textfield"
158 require "sup/buffer"
159 require "sup/keymap"
160 require "sup/mode"
161 require "sup/colormap"
162 require "sup/label"
163 require "sup/contact"
164 require "sup/tagger"
165 require "sup/draft"
166 require "sup/poll"
167 require "sup/modes/scroll-mode"
168 require "sup/modes/text-mode"
169 require "sup/modes/line-cursor-mode"
170 require "sup/modes/help-mode"
171 require "sup/modes/edit-message-mode"
172 require "sup/modes/compose-mode"
173 require "sup/modes/resume-mode"
174 require "sup/modes/forward-mode"
175 require "sup/modes/reply-mode"
176 require "sup/modes/label-list-mode"
177 require "sup/modes/contact-list-mode"
178 require "sup/modes/thread-view-mode"
179 require "sup/modes/thread-index-mode"
180 require "sup/modes/label-search-results-mode"
181 require "sup/modes/search-results-mode"
182 require "sup/modes/person-search-results-mode"
183 require "sup/modes/inbox-mode"
184 require "sup/modes/buffer-list-mode"
185 require "sup/modes/log-mode"
186 require "sup/modes/poll-mode"
187 require "sup/logger"
188 require "sup/sent"
189
190 module Redwood
191   def log s; Logger.log s; end
192   module_function :log
193 end
194
195 $:.each do |base|
196   d = File.join base, "sup/share/modes/"
197   Redwood::Mode.load_all_modes d if File.directory? d
198 end