sup 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sup might be problematic. Click here for more details.

@@ -1,4 +1,17 @@
1
+ == 0.0.8 / 2007-04-01
2
+
3
+ * Maildir support!
4
+ * New command: sup-config. Interactively walks you through everything
5
+ you need to get up and running.
6
+ * Now proactive about notifying users of de-synced sources.
7
+ * Renamed sup-import => sup-sync with a brand new, less illogical
8
+ interface.
9
+ * Added a sup-dump, to enable backing up and rebuilding indices from
10
+ scratch (e.g. when Ferret upgrades break index formats).
11
+ * More bugfixes. Will they ever end?
12
+
1
13
  == 0.0.7 / 2007-02-12
14
+
2
15
  * Split sup-import into two bits: sup-import and sup-add.
3
16
  * Command-line arguments now handled by trollop.
4
17
  * Better error handling for IMAP and svn+ssh.
@@ -11,6 +24,7 @@
11
24
  * Removed hoe dependency.
12
25
 
13
26
  == 0.0.6 / 2007-01-06
27
+
14
28
  * Very minor fix to support more types of IMAP authentication.
15
29
 
16
30
  == 0.0.5 / 2007-01-05
@@ -44,4 +58,3 @@
44
58
 
45
59
  * Initial release. Unix-centrism, support for mbox only, no i18n.
46
60
  Untested on anything other than 1.8.5. Other than that, works great!
47
-
@@ -6,8 +6,10 @@ README.txt
6
6
  Rakefile
7
7
  bin/sup
8
8
  bin/sup-add
9
- bin/sup-import
9
+ bin/sup-config
10
+ bin/sup-dump
10
11
  bin/sup-recover-sources
12
+ bin/sup-sync
11
13
  doc/FAQ.txt
12
14
  doc/Philosophy.txt
13
15
  doc/TODO
@@ -23,6 +25,7 @@ lib/sup/index.rb
23
25
  lib/sup/keymap.rb
24
26
  lib/sup/label.rb
25
27
  lib/sup/logger.rb
28
+ lib/sup/maildir.rb
26
29
  lib/sup/mbox.rb
27
30
  lib/sup/mbox/loader.rb
28
31
  lib/sup/mbox/ssh-file.rb
data/README.txt CHANGED
@@ -11,9 +11,9 @@ with the speed and simplicity of a console interface.
11
11
  Sup makes it easy to:
12
12
  - Handle massive amounts of email.
13
13
 
14
- - Mix email from different sources: mbox files (even across
15
- different machines), IMAP folders, POP accounts, and GMail
16
- accounts.
14
+ - Mix email from different sources: mbox files (even across different
15
+ machines), Maildir directories, IMAP folders, POP accounts, and
16
+ GMail accounts.
17
17
 
18
18
  - Instantaneously search over your entire email collection. Search
19
19
  over body text, or use a query language to combine search
@@ -40,7 +40,7 @@ Features:
40
40
  operability, regardless of how much amount of email you have.
41
41
 
42
42
  - Immediate full-text search of your entire email archive, using the
43
- Ferret query langauge. Search over message bodies, labels, from: and
43
+ Ferret query language. Search over message bodies, labels, from: and
44
44
  to: fields, or any combination thereof.
45
45
 
46
46
  - Thread-centrism. Operations are performed at the thread, not the
@@ -109,22 +109,28 @@ Current limitations which will be fixed:
109
109
  * ncurses
110
110
  * rmail
111
111
  * highline
112
+ * trollop
113
+ * net-ssh
112
114
 
113
115
  == INSTALL:
114
116
 
115
117
  * gem install sup -y
116
118
 
117
119
  == KNOWN BUGS IN OTHER PACKAGES:
120
+
118
121
  * If you get an error about frozen strings in RubyMail when importing
119
122
  certain messages with attachments, in rmail, change line 159 of
120
123
  multipart.rb to:
121
124
  chunk = chunk[0..start]
125
+ This is because RubyMail hasn't been updated since like Ruby 1.8.2.
126
+ Please bug Matt Lickey.
122
127
  * Occasionally Ferret produces something the Ruby GC doesn't like
123
128
  (particularly when importing messages from very large sources).
124
129
  No worries, just re-run sup-import. (This is unresolved atm.)
125
- * There are a couple other Ferret issues with outstanding patches but
126
- they are pretty rare.
127
-
130
+ * If you are using IMAP or Maildir and see this error:
131
+ /usr/local/lib/ruby/1.8/yaml.rb:133:in `transfer': allocator undefined for Bignum (TypeError)
132
+ then you need to upgrade to Ruby 1.8.5. YAML in earlier versions
133
+ can't parse BigNums.
128
134
 
129
135
  == LICENSE:
130
136
 
data/Rakefile CHANGED
@@ -12,11 +12,11 @@ Hoe.new('sup', Redwood::VERSION) do |p|
12
12
  p.rubyforge_name = 'sup'
13
13
  p.author = "William Morgan"
14
14
  p.summary = 'A console-based email client with the best features of GMail, mutt, and emacs. Features full text search, labels, tagged operations, multiple buffers, recent contacts, and more.'
15
- p.description = p.paragraphs_of('README.txt', 2..4).join("\n\n")
15
+ p.description = p.paragraphs_of('README.txt', 2..9).join("\n\n")
16
16
  p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[2].gsub(/^\s+/, "")
17
- p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
17
+ p.changes = p.paragraphs_of('History.txt', 0..0).join("\n\n")
18
18
  p.email = "wmorgan-sup@masanjin.net"
19
- p.extra_deps = [['ferret', '>= 0.10.13'], ['ncurses', '>= 0.9.1'], ['rmail', '>= 0.17'], 'highline', 'net-ssh', 'trollop']
19
+ p.extra_deps = [['ferret', '>= 0.10.13'], ['ncurses', '>= 0.9.1'], ['rmail', '>= 0.17'], 'highline', 'net-ssh', ['trollop', '>= 1.5']]
20
20
  end
21
21
 
22
22
  rule 'ss?.png' => 'ss?-small.png' do |t|
data/bin/sup CHANGED
@@ -83,6 +83,8 @@ begin
83
83
  Ncurses::A_BOLD
84
84
  c.add :starred_patina_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_GREEN,
85
85
  Ncurses::A_BOLD
86
+ c.add :alternate_starred_patina_color, Ncurses::COLOR_YELLOW,
87
+ Ncurses::COLOR_BLUE, Ncurses::A_BOLD
86
88
  c.add :snippet_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
87
89
  c.add :option_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK
88
90
  c.add :tagged_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK,
@@ -98,16 +100,24 @@ begin
98
100
  imode = InboxMode.new
99
101
  ibuf = bm.spawn "inbox", imode
100
102
 
101
- log "ready for (inter)action!"
103
+ log "ready for interaction!"
102
104
  Logger.make_buf
103
105
 
104
106
  bm.draw_screen
107
+
108
+ begin
109
+ Index.usual_sources.each { |s| s.check }
110
+ rescue SourceError
111
+ # do nothing! we'll report it at the next step
112
+ end
113
+ Redwood::report_broken_sources
114
+
105
115
  Index.usual_sources.each do |s|
106
116
  reporting_thread do
107
117
  begin
108
118
  s.connect
109
119
  rescue SourceError => e
110
- Redwood::log "Fatal error loading from #{s}: #{e.message}"
120
+ Redwood::log "fatal error loading from #{s}: #{e.message}"
111
121
  end
112
122
  end if s.respond_to? :connect
113
123
  end
@@ -197,12 +207,11 @@ rescue Exception => e
197
207
  ensure
198
208
  Redwood::finish
199
209
  stop_cursing
200
-
201
- # don't ask me why, but sometimes it's necessary to print something
202
- # to stderr at this point or the exception doesn't get printed.
203
- # doesn't get printed. WHY?
204
-
205
- $stderr.puts " "
210
+ if $exception
211
+ Redwood::log "oh crap, an exception"
212
+ else
213
+ Redwood::log "good night, sweet prince!"
214
+ end
206
215
  end
207
216
 
208
217
  Index.save unless $exception # TODO: think about this
@@ -6,22 +6,19 @@ require 'highline/import'
6
6
  require 'trollop'
7
7
  require "sup"
8
8
 
9
- Thread.abort_on_exception = true # make debugging possible
10
-
11
9
  $opts = Trollop::options do
12
10
  version "sup-add (sup #{Redwood::VERSION})"
13
11
  banner <<EOS
14
12
  Adds a source to the Sup source list.
15
13
 
16
14
  Usage:
17
- sup-add [options] <source>+
15
+ sup-add [options] <source uri>+
18
16
 
19
- where <source>+ is one or more sources.
17
+ where <source uri>+ is one or more source URIs.
20
18
 
21
19
  For mbox files on local disk, use the form:
20
+ mbox:<path to mbox file>, or
22
21
  mbox://<path to mbox file>
23
- or simply
24
- <path to mbox file>
25
22
 
26
23
  For mbox files on remote machines, use the form:
27
24
  mbox+ssh://<machine name>/<path to mbox file>
@@ -32,6 +29,10 @@ For IMAP folders, use the form (note no username or password!):
32
29
  imaps://<machine name>/ # secure, "INBOX" folder
33
30
  imaps://<machine name>/<folder> # secure, arbitrary folder
34
31
 
32
+ For Maildir folders, use the form:
33
+ maildir:<path to Maildir directory>; or
34
+ maildir://<path to Maildir directory>
35
+
35
36
  Options are:
36
37
  EOS
37
38
  opt :archive, "Automatically archive all new messages from these sources."
@@ -79,28 +80,33 @@ index = Redwood::Index.new
79
80
  index.load
80
81
 
81
82
  ARGV.each do |uri|
82
- uri = "mbox://#{uri}" unless uri =~ %r!://!
83
83
  if !$opts[:force_new] && index.source_for(uri)
84
84
  say "Already know about #{uri}; skipping."
85
85
  next
86
86
  end
87
+
88
+ parsed_uri = URI(uri)
89
+
87
90
  source =
88
- case uri
89
- when %r!^mbox\+ssh://!
91
+ case parsed_uri.scheme
92
+ when "mbox+ssh"
90
93
  say "For SSH connections, if you will use public key authentication, you may leave the username and password blank."
91
94
  say ""
92
95
  username, password = get_login_info uri, index.sources
93
- Redwood::MBox::SSHLoader.new(uri, username, password, nil, !$opts[:unusual], $opts[:archive])
94
- when %r!^imaps?://!
96
+ Redwood::MBox::SSHLoader.new uri, username, password, nil, !$opts[:unusual], $opts[:archive]
97
+ when "imap", "imaps"
95
98
  username, password = get_login_info uri, index.sources
96
- Redwood::IMAP.new(uri, username, password, nil, !$opts[:unusual], $opts[:archive])
99
+ Redwood::IMAP.new uri, username, password, nil, !$opts[:unusual], $opts[:archive]
100
+ when "maildir"
101
+ Redwood::Maildir.new uri, nil, !$opts[:unusual], $opts[:archive]
102
+ when "mbox"
103
+ Redwood::MBox::Loader.new uri, nil, !$opts[:unusual], $opts[:archive]
97
104
  else
98
- Redwood::MBox::Loader.new(uri, nil, !$opts[:unusual], $opts[:archive])
105
+ Trollop::die "Unknown source type #{parsed_uri.scheme.inspect}"
99
106
  end
100
107
  say "Adding #{source}..."
101
108
  index.add_source source
102
109
  end
103
110
 
104
- say "Saving source list..."
105
111
  index.save
106
112
  Redwood::finish
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'highline/import'
5
+ require 'yaml'
6
+ require 'trollop'
7
+ require "sup"
8
+
9
+ $opts = Trollop::options do
10
+ version "sup-config (sup #{Redwood::VERSION})"
11
+ banner <<EOS
12
+ Interactive configuration tool for Sup. Won't destroy existing
13
+ configuration.
14
+
15
+ Usage:
16
+ sup-config
17
+
18
+ Options:
19
+ EOS
20
+ end #' stupid ruby-mode
21
+
22
+ def axe q, default=nil
23
+ ans =
24
+ if default && !default.empty?
25
+ ask "#{q} (enter for \"#{default}\"): "
26
+ else
27
+ ask "#{q}: "
28
+ end
29
+ ans.empty? ? default : ans
30
+ end
31
+
32
+ def axe_yes q, default="n"
33
+ axe(q, default) =~ /^y|yes$/i
34
+ end
35
+
36
+ def build_cmd cmd
37
+ (ENV["RUBY_INVOCATION"] ? ENV["RUBY_INVOCATION"] + " " : "") + File.join(File.dirname($0), cmd)
38
+ end
39
+
40
+ def add_source
41
+ type = nil
42
+
43
+ say "Ok, adding a new source."
44
+ choose do |menu|
45
+ menu.prompt = "What type of mail source is it?"
46
+ menu.choice("mbox file") { type = :mbox }
47
+ menu.choice("maildir directory") { type = :maildir }
48
+ menu.choice("remote mbox file (accessible via ssh)") { type = :mboxssh }
49
+ menu.choice("IMAP server (secure)") { type = :imaps }
50
+ menu.choice("IMAP server (unsecure)") { type = :imap }
51
+ menu.choice("Get me out of here!") { return }
52
+ end
53
+
54
+ while true do
55
+ say "Now for the details."
56
+
57
+ components =
58
+ case type
59
+ when :mbox
60
+ fn = axe "What's the full path to the mbox file?", ENV["MAIL"] #"srm
61
+ return if fn.nil? || fn.empty?
62
+ { :scheme => "mbox", :path => fn }
63
+ when :maildir
64
+ fn = axe "What's the full path to the maildir directory?", ENV["MAIL"] #"srm
65
+ return if fn.nil? || fn.empty?
66
+ { :scheme => "maildir", :path => fn }
67
+ when :mboxssh
68
+ srv = axe "What server is the mbox file located on?", $last_server
69
+ return if srv.nil? || srv.empty?
70
+ $last_server = srv
71
+ fn = axe "What's the full path to the mbox file?", ENV["MAIL"] #"srm
72
+ return if fn.nil? || fn.empty?
73
+ fn = "/#{fn}" # lame
74
+ { :scheme => "mbox+ssh", :host => srv, :path => fn }
75
+ when :imap, :imaps
76
+ srv = axe "What is the IMAP server?", $last_server
77
+ return if srv.nil? || srv.empty?
78
+ $last_server = srv
79
+ fn = axe "What's the folder path?", "INBOX" #"srm
80
+ return if fn.nil? || fn.empty?
81
+ fn = "/#{fn}" # lame
82
+ { :scheme => type.to_s, :host => srv, :path => fn }
83
+ end
84
+
85
+ uri =
86
+ begin
87
+ URI::Generic.build components
88
+ rescue URI::Error => e
89
+ say "Whoopsie! I couldn't build a URI from that: #{e.message}"
90
+ if axe_yes("Try again?") then next else return end
91
+ end
92
+
93
+ say "I'm going to add this source: #{uri}."
94
+ unless axe("Does that look right?", "y") =~ /^y|yes$/i
95
+ if axe_yes("Try again?") then next else return end
96
+ end
97
+
98
+ usual = axe_yes "Does this source ever receive new messages?", "y"
99
+ archive = usual ? axe_yes("Should those new messages be automatically archived?") : false
100
+
101
+ cmd = build_cmd "sup-add"
102
+ cmd += " --unusual" unless usual
103
+ cmd += " --archive" if archive
104
+ cmd += " #{uri}"
105
+
106
+ puts "Ok, trying to run \"#{cmd}\"..."
107
+
108
+ system cmd
109
+ if $?.success?
110
+ say "Great! Added!"
111
+ break
112
+ else
113
+ say "Rats, that failed. You may have to do it manually."
114
+ if axe_yes("Try again?") then next else return end
115
+ end
116
+ end
117
+ end
118
+
119
+ $terminal.wrap_at = :auto
120
+ Redwood::start
121
+ index = Redwood::Index.new
122
+ index.load_sources
123
+
124
+ say <<EOS
125
+ Howdy neighbor! This here's sup-config, ready to help you jack in to
126
+ the next generation of digital cyberspace: the text-based email
127
+ program. Get ready to be the envy of everyone in your internets
128
+ with your amazing keyboarding skills! Jump from email to email with
129
+ nary a click of the mouse!
130
+
131
+ Just answer these simple questions and you'll be on your way! Press
132
+ enter at any point to accept the default answer.
133
+
134
+ EOS
135
+ #' stupid ruby-mode
136
+
137
+ account = $config[:accounts][:default]
138
+
139
+ name = axe "What's your name?", account[:name]
140
+ email = axe "What's your email address?", account[:email] #'srm
141
+
142
+ say "Ok, your header will look like this:"
143
+ say " From: #{name} <#{email}>"
144
+
145
+ say "\nDo you have any alternate email addresses that also receive email?"
146
+ say "If so, enter them now, separated by spaces."
147
+ alts = axe("Alternate email addresses", account[:alternates].join(" ")).split(/\s+/)
148
+
149
+ sigfn = axe "What file contains your signature?", account[:signature]
150
+ editor = axe "What editor would you like to use?", $config[:editor]
151
+
152
+ $config[:accounts][:default][:name] = name
153
+ $config[:accounts][:default][:email] = email
154
+ $config[:accounts][:default][:alternates] = alts
155
+ $config[:accounts][:default][:signature] = sigfn
156
+ $config[:editor] = editor
157
+
158
+ Redwood::save_yaml_obj $config, Redwood::CONFIG_FN
159
+
160
+ say "Ok, I've saved you up a nice lil' #{Redwood::CONFIG_FN}."
161
+
162
+ done = false
163
+ until done
164
+ say "\nNow, we'll tell Sup where to find all your email."
165
+ index.load_sources
166
+ say "Current sources:"
167
+ if index.sources.empty?
168
+ say " No sources!"
169
+ else
170
+ index.sources.each { |s| puts "* #{s}" }
171
+ end
172
+
173
+ say "\n"
174
+ choose do |menu|
175
+ menu.prompt = "Your wish?"
176
+ menu.choice("Add a new source.") { add_source }
177
+ menu.choice("Done adding sources!") { done = true }
178
+ end
179
+ end
180
+
181
+ say <<EOS
182
+
183
+ Ok. The final step is to import all your messages into the Sup index.
184
+ Depending on how many messages are in the sources, this could take
185
+ quite a while.
186
+
187
+ IMPORTANT NOTE: this import will archive messages if the source is
188
+ marked archival, and won't otherwise. It will preserve read/unread
189
+ status as given by the source, and it will automatically add one label
190
+ per source. All of this behavior can be controlled on per-source
191
+ basis by running sup-sync manually.
192
+
193
+ EOS
194
+ #'
195
+ if axe_yes "Run sup-sync to import all messages now?"
196
+ while true
197
+ cmd = build_cmd("sup-sync") + " --all-sources"
198
+ puts "Ok, trying to run \"#{cmd}\"..."
199
+ system cmd
200
+ if $?.success?
201
+ say "Great! It worked!"
202
+ break
203
+ else
204
+ say "Rats, that failed. You may have to do it manually."
205
+ if axe_yes("Try again?") then next else break end
206
+ end
207
+ end
208
+ end
209
+
210
+ index.load
211
+
212
+ say <<EOS
213
+
214
+ Okee doke, you've got yourself an index of #{index.size} messages. Looks
215
+ like you're ready to jack in to cyberspace there, cowboy.
216
+
217
+ Just one last command:
218
+
219
+ sup
220
+
221
+ Have fun!
222
+ EOS