opt :compose, "Compose message to this recipient upon startup", :type => String
end
+Redwood::HookManager.register "startup", <<EOS
+Executes at startup
+No variables.
+No return value.
+EOS
+
if $opts[:list_hooks]
Redwood::HookManager.print_hooks
exit
Index.add_source SentManager.new_source
end
+ HookManager.run "startup"
+
log "starting curses"
start_cursing
Ncurses::A_BOLD
c.add :index_starred_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK,
Ncurses::A_BOLD
+ c.add :index_draft_color, Ncurses::COLOR_RED, Ncurses::COLOR_BLACK,
+ Ncurses::A_BOLD
c.add :labellist_old_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK
c.add :labellist_new_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK,
Ncurses::A_BOLD
end
unless opts[:drop_deleted] || opts[:move_deleted] || opts[:drop_spam] || opts[:move_spam]
- puts "Nothing to do."
+ puts <<EOS
+Nothing to do. Please specify at least one of --drop-deleted, --move-deleted,
+--drop-spam, or --move-spam.
+EOS
+
exit
end
multipart.rb to:
chunk = chunk[0..start]
This is because RubyMail hasn't been updated since like Ruby 1.8.2.
- Please bug Matt Lickey.
+ Please bug Matt Armstrong.
P: I see this error:
/usr/local/lib/ruby/1.8/yaml.rb:133:in `transfer': allocator undefined for Bignum (TypeError)
raise Error, (output || "gpg command failed: #{cmd}") unless $?.success?
envelope = RMail::Message.new
- envelope.header["Content-Type"] = 'multipart/signed; protocol="application/pgp-signature"; micalg=pgp-sha1'
+ envelope.header["Content-Type"] = 'multipart/signed; protocol=application/pgp-signature; micalg=pgp-sha1'
envelope.add_part payload
signature = RMail::Message.make_attachment output, "application/pgp-signature", nil, "signature.asc"
log "error running hook: #{e.message}"
log e.backtrace.join("\n")
@hooks[name] = nil # disable it
- BufferManager.flash "Error running hook: #{e.message}"
+ BufferManager.flash "Error running hook: #{e.message}" if BufferManager.instantiated?
end
context.__cleanup
result
else
Redwood::log "creating index..."
field_infos = Ferret::Index::FieldInfos.new :store => :yes
- field_infos.add_field :message_id
+ field_infos.add_field :message_id, :index => :untokenized
field_infos.add_field :source_id
field_infos.add_field :source_info
field_infos.add_field :date, :index => :untokenized
def parse_user_query_string s
extraopts = {}
- ## this is a little hacky, but it works, at least until ferret changes
- ## its api. we parse the user query string with ferret twice: the first
- ## time we just turn the resulting object back into a string, which has
- ## the next effect of transforming the original string into a nice
- ## normalized form with + and - instead of AND, OR, etc. then we do some
- ## string substitutions which depend on this normalized form, re-parse
- ## the string with Ferret, and return the resulting query object.
-
- norms = @qparser.parse(s).to_s
- Redwood::log "normalized #{s.inspect} to #{norms.inspect}" unless s == norms
-
- subs = norms.gsub(/\b(to|from):(\S+)\b/) do
+ subs = s.gsub(/\b(to|from):(\S+)\b/) do
field, name = $1, $2
if(p = ContactManager.contact_for(name))
[field, p.email]
subs = nil if chronic_failure
end
- Redwood::log "translated #{norms.inspect} to #{subs.inspect}" unless subs == norms
if subs
[@qparser.parse(subs), extraopts]
else
## when scanning over large mbox files.
while(line = f.gets)
case line
- when /^(From):\s+(.*?)\s*$/i,
- /^(To):\s+(.*?)\s*$/i,
- /^(Cc):\s+(.*?)\s*$/i,
- /^(Bcc):\s+(.*?)\s*$/i,
- /^(Subject):\s+(.*?)\s*$/i,
- /^(Date):\s+(.*?)\s*$/i,
- /^(References):\s+(.*?)\s*$/i,
- /^(In-Reply-To):\s+(.*?)\s*$/i,
- /^(Reply-To):\s+(.*?)\s*$/i,
- /^(List-Post):\s+(.*?)\s*$/i,
- /^(List-Subscribe):\s+(.*?)\s*$/i,
- /^(List-Unsubscribe):\s+(.*?)\s*$/i,
- /^(Status):\s+(.*?)\s*$/i: header[last = $1] = $2
- when /^(Message-Id):\s+(.*?)\s*$/i: header[mid_field = last = $1] = $2
+ when /^(From):\s*(.*?)\s*$/i,
+ /^(To):\s*(.*?)\s*$/i,
+ /^(Cc):\s*(.*?)\s*$/i,
+ /^(Bcc):\s*(.*?)\s*$/i,
+ /^(Subject):\s*(.*?)\s*$/i,
+ /^(Date):\s*(.*?)\s*$/i,
+ /^(References):\s*(.*?)\s*$/i,
+ /^(In-Reply-To):\s*(.*?)\s*$/i,
+ /^(Reply-To):\s*(.*?)\s*$/i,
+ /^(List-Post):\s*(.*?)\s*$/i,
+ /^(List-Subscribe):\s*(.*?)\s*$/i,
+ /^(List-Unsubscribe):\s*(.*?)\s*$/i,
+ /^(Status):\s*(.*?)\s*$/i: header[last = $1] = $2
+ when /^(Message-Id):\s*(.*?)\s*$/i: header[mid_field = last = $1] = $2
## these next three can occur multiple times, and we want the
## first one
- when /^(Delivered-To):\s+(.*)$/i,
- /^(X-Original-To):\s+(.*)$/i,
- /^(Envelope-To):\s+(.*)$/i: header[last = $1] ||= $2
+ when /^(Delivered-To):\s*(.*)$/i,
+ /^(X-Original-To):\s*(.*)$/i,
+ /^(Envelope-To):\s*(.*)$/i: header[last = $1] ||= $2
when /^$/: break
when /^\S+: /: last = nil # some other header we don't care about
class Loader < Source
yaml_properties :uri, :cur_offset, :usual, :archived, :id, :labels
+ attr_accessor :labels
## uri_or_fp is horrific. need to refactor.
def initialize uri_or_fp, start_offset=nil, usual=true, archived=false, id=nil, labels=[]
end
self.cur_offset = next_offset
- [returned_offset, (@labels + [:unread]).uniq]
+ [returned_offset, (self.labels + [:unread]).uniq]
end
end
@source.fn_for_offset @source_info
end
- def sanitize_message_id mid; mid.gsub(/\s/, "") end
+ def sanitize_message_id mid; mid.gsub(/\s+/, "")[0..254] end
def save index
return unless @dirty
end
def initialize
- super [:inbox, :sent], { :label => :inbox, :skip_killed => true }
+ super [:inbox, :sent, :draft], { :label => :inbox, :skip_killed => true }
raise "can't have more than one!" if defined? @@instance
@@instance = self
end
end
start = @search_line || search_start_line
- line = find_text @search_query, start
+ line, col = find_text @search_query, start
if line.nil? && (start > 0)
- line = find_text @search_query, 0
+ line, col = find_text @search_query, 0
BufferManager.flash "Search wrapped to top!" if line
end
if line
@search_line = line + 1
- search_goto_line line
+ search_goto_pos line, col, col + @search_query.length
buffer.mark_dirty
else
BufferManager.flash "Not found!"
end
## subclasses can override these two!
- def search_goto_line line; jump_to_line line end
+ def search_goto_pos line, leftcol, rightcol
+ jump_to_line line
+
+ if rightcol > self.rightcol # if it's occluded...
+ jump_to_col [rightcol - buffer.content_width + 1, 0].max # move right
+ end
+ end
def search_start_line; @topline end
def col_left
(start_line ... lines).each do |i|
case(s = self[i])
when String
- return i if s =~ regex
+ match = s =~ regex
+ return [i, match] if match
when Array
- return i if s.any? { |color, string| string =~ regex }
+ offset = 0
+ s.each do |color, string|
+ match = string =~ regex
+ if match
+ return [i, offset + match]
+ else
+ offset += string.length
+ end
+ end
end
end
nil
date = t.date.to_nice_s
- new = t.has_label?(:unread)
starred = t.has_label?(:starred)
## format the from column
p = dp || t.participants.any? { |p| AccountManager.is_account? p }
subj_color =
- if new
+ if t.has_label?(:draft)
+ :index_draft_color
+ elsif t.has_label?(:unread)
:index_new_color
elsif starred
:index_starred_color
docid, entry = Index.load_entry_for_id m.id
HookManager.run "before-add-message", :message => m
- m = yield(m, offset, entry) or next
+ m = yield(m, offset, entry) or next if block_given?
Index.sync_message m, docid, entry
UpdateManager.relay self, :added, m unless entry
rescue MessageFormatError => e
yield f
end
- @source.each do |offset, labels|
- m = Message.new :source => @source, :source_info => offset, :labels => @source.labels
- Index.sync_message m
- UpdateManager.relay self, :added, m
+ PollManager.add_messages_from(@source) do |m, o, e|
+ m.remove_label :unread
+ m
end
end
end
@thread_by_subj = thread_by_subj
end
- def thread_for_id mid; (c = @messages[mid]) && c.root.thread end
+ def thread_for_id mid; @messages.member?(mid) && @messages[mid].root.thread end
def contains_id? id; @messages.member?(id) && !@messages[id].empty? end
def thread_for m; thread_for_id m.id end
def contains? m; contains_id? m.id end