10 ## read in stored people
11 IO.readlines(fn).map do |l|
12 l =~ /^(.*)?:\s+(\d+)\s+(.*)$/ or raise "can't parse: #{l}"
13 email, time, name = $1, $2, $3
14 @@people[email] = Person.new name, email, time, false
15 end if File.exists? fn
17 self.class.i_am_the_instance self
21 File.open(@fn, "w") do |f|
22 @@people.each do |email, p|
23 next if p.email == p.name
24 next if p.email =~ /=/ # drop rfc2047-encoded, and lots of other useless emails. definitely a heuristic.
25 f.puts "#{p.email}: #{p.timestamp} #{p.name}"
30 def self.people_for s, opts={}
32 s.split_on_commas.map { |ss| self.person_for ss, opts }
35 def self.person_for s, opts={}
36 p = Person.from_address(s) or return nil
37 p.definitive = true if opts[:definitive]
42 oldp = @@people[p.email]
44 if oldp.nil? || p.better_than?(oldp)
48 @@people[p.email].touch!
53 ## don't create these by hand. rather, go through personmanager, to
54 ## ensure uniqueness and overriding.
56 attr_accessor :name, :email, :timestamp
57 bool_accessor :definitive
59 def initialize name, email, timestamp=0, definitive=false
60 raise ArgumentError, "email can't be nil" unless email
63 @name = name.gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ")
64 if @name =~ /^(['"]\s*)(.*?)(\s*["'])$/
69 @email = email.gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ").downcase
70 @definitive = definitive
71 @timestamp = timestamp
74 ## heuristic: whether the name attached to this email is "real", i.e.
75 ## we should bother to store it.
77 @email =~ /no\-?reply/
81 return false if o.definitive? || generic?
82 return true if definitive?
83 o.name.nil? || (name && name.length > o.name.length && name =~ /[a-z]/)
86 def to_s; "#@name <#@email>" end
88 def touch!; @timestamp = Time.now.to_i end
90 # def == o; o && o.email == email; end
92 # def hash; [name, email].hash; end
115 def mediumname; @name || @email; end
120 "#{@name.inspect} <#{@email}>" # escape quotes
122 "#{@name} <#{@email}>"
129 ## when sorting addresses, sort by this
134 when /^\S+ \S+ (\S+)/
145 def self.from_address s
148 ## try and parse an email address and name
151 when /["'](.*?)["'] <(.*?)>/, /([^,]+) <(.*?)>/
153 [a.gsub('\"', '"'), b]
154 when /<((\S+?)@\S+?)>/
162 Person.new name, email
165 def eql? o; email.eql? o.email end
166 def hash; email.hash end