]> git.cworth.org Git - sup/blob - lib/sup/draft.rb
tweak Refine Search keybinding
[sup] / lib / sup / draft.rb
1 module Redwood
2
3 class DraftManager
4   include Singleton
5
6   attr_accessor :source
7   def initialize dir
8     @dir = dir
9     @source = nil
10     self.class.i_am_the_instance self
11   end
12
13   def self.source_name; "sup://drafts"; end
14   def self.source_id; 9999; end
15   def new_source; @source = Recoverable.new DraftLoader.new; end
16
17   def write_draft
18     offset = @source.gen_offset
19     fn = @source.fn_for_offset offset
20     File.open(fn, "w") { |f| yield f }
21
22     my_message = nil
23     @source.each do |thisoffset, theselabels|
24       m = Message.new :source => @source, :source_info => thisoffset, :labels => theselabels
25       Index.sync_message m
26       UpdateManager.relay self, :added, m
27       my_message = m if thisoffset == offset
28     end
29
30     my_message
31   end
32
33   def discard m
34     docid, entry = Index.load_entry_for_id m.id
35     raise ArgumentError, "can't find entry for draft: #{m.id.inspect}" unless entry
36     raise ArgumentError, "not a draft: source id #{entry[:source_id].inspect}, should be #{DraftManager.source_id.inspect} for #{m.id.inspect} / docno #{docid}" unless entry[:source_id].to_i == DraftManager.source_id
37     Index.drop_entry docid
38     File.delete @source.fn_for_offset(entry[:source_info])
39     UpdateManager.relay self, :single_message_deleted, m
40   end
41 end
42
43 class DraftLoader < Source
44   attr_accessor :dir
45   yaml_properties :cur_offset
46
47   def initialize cur_offset=0
48     dir = Redwood::DRAFT_DIR
49     Dir.mkdir dir unless File.exists? dir
50     super DraftManager.source_name, cur_offset, true, false
51     @dir = dir
52   end
53
54   def id; DraftManager.source_id; end
55   def to_s; DraftManager.source_name; end
56   def uri; DraftManager.source_name; end
57
58   def each
59     ids = get_ids
60     ids.each do |id|
61       if id >= cur_offset
62         self.cur_offset = id + 1
63         yield [id, [:draft, :inbox]]
64       end
65     end
66   end
67
68   def gen_offset
69     i = cur_offset
70     while File.exists? fn_for_offset(i)
71       i += 1
72     end
73     i
74   end
75
76   def fn_for_offset o; File.join(@dir, o.to_s); end
77
78   def load_header offset
79     File.open fn_for_offset(offset) do |f|
80       return MBox::read_header(f)
81     end
82   end
83   
84   def load_message offset
85     File.open fn_for_offset(offset) do |f|
86       RMail::Mailbox::MBoxReader.new(f).each_message do |input|
87         return RMail::Parser.read(input)
88       end
89     end
90   end
91
92   def raw_header offset
93     ret = ""
94     File.open fn_for_offset(offset) do |f|
95       until f.eof? || (l = f.gets) =~ /^$/
96         ret += l
97       end
98     end
99     ret
100   end
101
102   def each_raw_message_line offset
103     File.open(fn_for_offset(offset)) do |f|
104       yield f.gets until f.eof?
105     end
106   end
107
108   def raw_message offset
109     IO.readlines(fn_for_offset(offset)).join
110   end
111
112   def start_offset; 0; end
113   def end_offset
114     ids = get_ids
115     ids.empty? ? 0 : (ids.last + 1)
116   end
117
118 private
119
120   def get_ids
121     Dir.entries(@dir).select { |x| x =~ /^\d+$/ }.map { |x| x.to_i }.sort
122   end
123 end
124
125 end