]> git.notmuchmail.org Git - sup/blob - lib/sup/person.rb
bugfix in PersonManager.name_for
[sup] / lib / sup / person.rb
1 module Redwood
2
3 class PersonManager
4   include Singleton
5
6   def initialize fn
7     @fn = fn
8     @names = {}
9     IO.readlines(fn).map { |l| l =~ /^(.*)?:\s+(\d+)\s+(.*)$/ && @names[$1] = [$2.to_i, $3] } if File.exists? fn
10     self.class.i_am_the_instance self
11   end
12
13   def name_for email; @names.member?(email) ? @names[email][1] : nil; end
14   def register email, name
15     return unless name
16
17     name = name.gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ")
18
19     ## all else being equal, prefer longer names, unless the prior name
20     ## doesn't contain any capitalization
21     oldcount, oldname = @names[email]
22     @names[email] = [0, name] if oldname.nil? || oldname.length < name.length || (oldname !~ /[A-Z]/ && name =~ /[A-Z]/)
23     @names[email][0] = Time.now.to_i
24   end
25
26   def save; File.open(@fn, "w") { |f| @names.each { |email, (time, name)| f.puts "#{email}: #{time} #{name}" } }; end
27 end
28
29 class Person
30   @@email_map = {}
31
32   attr_accessor :name, :email
33
34   def initialize name, email
35     raise ArgumentError, "email can't be nil" unless email
36     @email = email.gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ").downcase
37     PersonManager.register @email, name
38     @name = PersonManager.name_for @email
39   end
40
41   def == o; o && o.email == email; end
42   alias :eql? :==
43   def hash; [name, email].hash; end
44
45   def shortname
46     case @name
47     when /\S+, (\S+)/
48       $1
49     when /(\S+) \S+/
50       $1
51     when nil
52       @email
53     else
54       @name
55     end
56   end
57
58   def longname
59     if @name && @email
60       "#@name <#@email>"
61     else
62       @email
63     end
64   end
65
66   def mediumname; @name || @email; end
67
68   def full_address
69     if @name && @email
70       if @name =~ /"/
71         "#{@name.inspect} <#@email>" # escape quotes
72       else
73         "#@name <#@email>"
74       end
75     else
76       @email
77     end
78   end
79
80   ## when sorting addresses, sort by this 
81   def sort_by_me
82     case @name
83     when /^(\S+), \S+/
84       $1
85     when /^\S+ \S+ (\S+)/
86       $1
87     when /^\S+ (\S+)/
88       $1
89     when nil
90       @email
91     else
92       @name
93     end.downcase
94   end
95
96   def self.for s
97     return nil if s.nil?
98
99     ## try and parse an email address and name
100     name, email =
101       case s
102       when /["'](.*?)["'] <(.*?)>/, /([^,]+) <(.*?)>/
103         a, b = $1, $2
104         [a.gsub('\"', '"'), b]
105       when /<((\S+?)@\S+?)>/
106         [$2, $1]
107       when /((\S+?)@\S+)/
108         [$2, $1]
109       else
110         [nil, s]
111       end
112
113     @@email_map[email] ||= Person.new name, email
114   end
115
116   def self.for_several s
117     return [] if s.nil?
118
119     s.split_on_commas.map { |ss| self.for ss }
120   end
121 end
122
123 end