sup 0.8.1 → 0.9

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.

Files changed (67) hide show
  1. data/CONTRIBUTORS +13 -6
  2. data/History.txt +19 -0
  3. data/ReleaseNotes +35 -0
  4. data/bin/sup +82 -77
  5. data/bin/sup-add +7 -7
  6. data/bin/sup-config +104 -85
  7. data/bin/sup-dump +4 -5
  8. data/bin/sup-recover-sources +9 -10
  9. data/bin/sup-sync +121 -100
  10. data/bin/sup-sync-back +18 -15
  11. data/bin/sup-tweak-labels +24 -21
  12. data/lib/sup.rb +53 -33
  13. data/lib/sup/account.rb +0 -2
  14. data/lib/sup/buffer.rb +47 -22
  15. data/lib/sup/colormap.rb +6 -6
  16. data/lib/sup/contact.rb +0 -2
  17. data/lib/sup/crypto.rb +34 -23
  18. data/lib/sup/draft.rb +6 -14
  19. data/lib/sup/ferret_index.rb +471 -0
  20. data/lib/sup/hook.rb +30 -43
  21. data/lib/sup/hook.rb.BACKUP.8625.rb +158 -0
  22. data/lib/sup/hook.rb.BACKUP.8681.rb +158 -0
  23. data/lib/sup/hook.rb.BASE.8625.rb +155 -0
  24. data/lib/sup/hook.rb.BASE.8681.rb +155 -0
  25. data/lib/sup/hook.rb.LOCAL.8625.rb +142 -0
  26. data/lib/sup/hook.rb.LOCAL.8681.rb +142 -0
  27. data/lib/sup/hook.rb.REMOTE.8625.rb +145 -0
  28. data/lib/sup/hook.rb.REMOTE.8681.rb +145 -0
  29. data/lib/sup/imap.rb +18 -8
  30. data/lib/sup/index.rb +70 -528
  31. data/lib/sup/interactive-lock.rb +74 -0
  32. data/lib/sup/keymap.rb +26 -26
  33. data/lib/sup/label.rb +2 -4
  34. data/lib/sup/logger.rb +54 -35
  35. data/lib/sup/maildir.rb +41 -6
  36. data/lib/sup/mbox.rb +1 -1
  37. data/lib/sup/mbox/loader.rb +18 -6
  38. data/lib/sup/mbox/ssh-file.rb +1 -7
  39. data/lib/sup/message-chunks.rb +36 -23
  40. data/lib/sup/message.rb +126 -46
  41. data/lib/sup/mode.rb +3 -2
  42. data/lib/sup/modes/console-mode.rb +108 -0
  43. data/lib/sup/modes/edit-message-mode.rb +15 -5
  44. data/lib/sup/modes/inbox-mode.rb +2 -4
  45. data/lib/sup/modes/label-list-mode.rb +1 -1
  46. data/lib/sup/modes/line-cursor-mode.rb +18 -18
  47. data/lib/sup/modes/log-mode.rb +29 -16
  48. data/lib/sup/modes/poll-mode.rb +7 -9
  49. data/lib/sup/modes/reply-mode.rb +5 -3
  50. data/lib/sup/modes/scroll-mode.rb +2 -2
  51. data/lib/sup/modes/search-results-mode.rb +9 -11
  52. data/lib/sup/modes/text-mode.rb +2 -2
  53. data/lib/sup/modes/thread-index-mode.rb +26 -16
  54. data/lib/sup/modes/thread-view-mode.rb +84 -39
  55. data/lib/sup/person.rb +6 -8
  56. data/lib/sup/poll.rb +46 -47
  57. data/lib/sup/rfc2047.rb +1 -5
  58. data/lib/sup/sent.rb +27 -20
  59. data/lib/sup/source.rb +90 -13
  60. data/lib/sup/textfield.rb +4 -4
  61. data/lib/sup/thread.rb +15 -13
  62. data/lib/sup/undo.rb +0 -1
  63. data/lib/sup/update.rb +0 -1
  64. data/lib/sup/util.rb +51 -43
  65. data/lib/sup/xapian_index.rb +566 -0
  66. metadata +57 -46
  67. data/lib/sup/suicide.rb +0 -36
@@ -0,0 +1,155 @@
1
+ module Redwood
2
+
3
+ class HookManager
4
+ ## there's probably a better way to do this, but to evaluate a hook
5
+ ## with a bunch of pre-set "local variables" i define a function
6
+ ## per variable and then instance_evaluate the code.
7
+ ##
8
+ ## how does rails do it, when you pass :locals into a partial?
9
+ ##
10
+ ## i don't bother providing setters, since i'm pretty sure the
11
+ ## charade will fall apart pretty quickly with respect to scoping.
12
+ ## "fail-fast", we'll call it.
13
+ class HookContext
14
+ def initialize name
15
+ @__say_id = nil
16
+ @__name = name
17
+ @__locals = {}
18
+ end
19
+
20
+ attr_writer :__locals
21
+
22
+ def method_missing m, *a
23
+ case @__locals[m]
24
+ when Proc
25
+ @__locals[m] = @__locals[m].call(*a) # only call the proc once
26
+ when nil
27
+ super
28
+ else
29
+ @__locals[m]
30
+ end
31
+ end
32
+
33
+ def say s
34
+ if BufferManager.instantiated?
35
+ @__say_id = BufferManager.say s, @__say_id
36
+ BufferManager.draw_screen
37
+ else
38
+ log s
39
+ end
40
+ end
41
+
42
+ def log s
43
+ Redwood::log "hook[#@__name]: #{s}"
44
+ end
45
+
46
+ def ask_yes_or_no q
47
+ if BufferManager.instantiated?
48
+ BufferManager.ask_yes_or_no q
49
+ else
50
+ print q
51
+ gets.chomp.downcase == 'y'
52
+ end
53
+ end
54
+
55
+ def get tag
56
+ HookManager.tags[tag]
57
+ end
58
+
59
+ def set tag, value
60
+ HookManager.tags[tag] = value
61
+ end
62
+
63
+ def __binding
64
+ binding
65
+ end
66
+
67
+ def __cleanup
68
+ BufferManager.clear @__say_id if @__say_id
69
+ end
70
+ end
71
+
72
+ include Singleton
73
+
74
+ def initialize dir
75
+ @dir = dir
76
+ @hooks = {}
77
+ @descs = {}
78
+ @contexts = {}
79
+ @tags = {}
80
+
81
+ Dir.mkdir dir unless File.exists? dir
82
+
83
+ self.class.i_am_the_instance self
84
+ end
85
+
86
+ attr_reader :tags
87
+
88
+ def run name, locals={}
89
+ hook = hook_for(name) or return
90
+ context = @contexts[hook] ||= HookContext.new(name)
91
+ context.__locals = locals
92
+
93
+ result = nil
94
+ begin
95
+ result = context.instance_eval @hooks[name], fn_for(name)
96
+ rescue Exception => e
97
+ log "error running hook: #{e.message}"
98
+ log e.backtrace.join("\n")
99
+ @hooks[name] = nil # disable it
100
+ BufferManager.flash "Error running hook: #{e.message}" if BufferManager.instantiated?
101
+ end
102
+ context.__cleanup
103
+ result
104
+ end
105
+
106
+ def register name, desc
107
+ @descs[name] = desc
108
+ end
109
+
110
+ def print_hooks f=$stdout
111
+ puts <<EOS
112
+ Have #{@descs.size} registered hooks:
113
+
114
+ EOS
115
+
116
+ @descs.sort.each do |name, desc|
117
+ f.puts <<EOS
118
+ #{name}
119
+ #{"-" * name.length}
120
+ File: #{fn_for name}
121
+ #{desc}
122
+ EOS
123
+ end
124
+ end
125
+
126
+ def enabled? name; !hook_for(name).nil? end
127
+
128
+ private
129
+
130
+ def hook_for name
131
+ unless @hooks.member? name
132
+ @hooks[name] =
133
+ begin
134
+ returning IO.read(fn_for(name)) do
135
+ log "read '#{name}' from #{fn_for(name)}"
136
+ end
137
+ rescue SystemCallError => e
138
+ #log "disabled hook for '#{name}': #{e.message}"
139
+ nil
140
+ end
141
+ end
142
+
143
+ @hooks[name]
144
+ end
145
+
146
+ def fn_for name
147
+ File.join @dir, "#{name}.rb"
148
+ end
149
+
150
+ def log m
151
+ Redwood::log("hook: " + m)
152
+ end
153
+ end
154
+
155
+ end
@@ -0,0 +1,155 @@
1
+ module Redwood
2
+
3
+ class HookManager
4
+ ## there's probably a better way to do this, but to evaluate a hook
5
+ ## with a bunch of pre-set "local variables" i define a function
6
+ ## per variable and then instance_evaluate the code.
7
+ ##
8
+ ## how does rails do it, when you pass :locals into a partial?
9
+ ##
10
+ ## i don't bother providing setters, since i'm pretty sure the
11
+ ## charade will fall apart pretty quickly with respect to scoping.
12
+ ## "fail-fast", we'll call it.
13
+ class HookContext
14
+ def initialize name
15
+ @__say_id = nil
16
+ @__name = name
17
+ @__locals = {}
18
+ end
19
+
20
+ attr_writer :__locals
21
+
22
+ def method_missing m, *a
23
+ case @__locals[m]
24
+ when Proc
25
+ @__locals[m] = @__locals[m].call(*a) # only call the proc once
26
+ when nil
27
+ super
28
+ else
29
+ @__locals[m]
30
+ end
31
+ end
32
+
33
+ def say s
34
+ if BufferManager.instantiated?
35
+ @__say_id = BufferManager.say s, @__say_id
36
+ BufferManager.draw_screen
37
+ else
38
+ log s
39
+ end
40
+ end
41
+
42
+ def log s
43
+ Redwood::log "hook[#@__name]: #{s}"
44
+ end
45
+
46
+ def ask_yes_or_no q
47
+ if BufferManager.instantiated?
48
+ BufferManager.ask_yes_or_no q
49
+ else
50
+ print q
51
+ gets.chomp.downcase == 'y'
52
+ end
53
+ end
54
+
55
+ def get tag
56
+ HookManager.tags[tag]
57
+ end
58
+
59
+ def set tag, value
60
+ HookManager.tags[tag] = value
61
+ end
62
+
63
+ def __binding
64
+ binding
65
+ end
66
+
67
+ def __cleanup
68
+ BufferManager.clear @__say_id if @__say_id
69
+ end
70
+ end
71
+
72
+ include Singleton
73
+
74
+ def initialize dir
75
+ @dir = dir
76
+ @hooks = {}
77
+ @descs = {}
78
+ @contexts = {}
79
+ @tags = {}
80
+
81
+ Dir.mkdir dir unless File.exists? dir
82
+
83
+ self.class.i_am_the_instance self
84
+ end
85
+
86
+ attr_reader :tags
87
+
88
+ def run name, locals={}
89
+ hook = hook_for(name) or return
90
+ context = @contexts[hook] ||= HookContext.new(name)
91
+ context.__locals = locals
92
+
93
+ result = nil
94
+ begin
95
+ result = context.instance_eval @hooks[name], fn_for(name)
96
+ rescue Exception => e
97
+ log "error running hook: #{e.message}"
98
+ log e.backtrace.join("\n")
99
+ @hooks[name] = nil # disable it
100
+ BufferManager.flash "Error running hook: #{e.message}" if BufferManager.instantiated?
101
+ end
102
+ context.__cleanup
103
+ result
104
+ end
105
+
106
+ def register name, desc
107
+ @descs[name] = desc
108
+ end
109
+
110
+ def print_hooks f=$stdout
111
+ puts <<EOS
112
+ Have #{@descs.size} registered hooks:
113
+
114
+ EOS
115
+
116
+ @descs.sort.each do |name, desc|
117
+ f.puts <<EOS
118
+ #{name}
119
+ #{"-" * name.length}
120
+ File: #{fn_for name}
121
+ #{desc}
122
+ EOS
123
+ end
124
+ end
125
+
126
+ def enabled? name; !hook_for(name).nil? end
127
+
128
+ private
129
+
130
+ def hook_for name
131
+ unless @hooks.member? name
132
+ @hooks[name] =
133
+ begin
134
+ returning IO.read(fn_for(name)) do
135
+ log "read '#{name}' from #{fn_for(name)}"
136
+ end
137
+ rescue SystemCallError => e
138
+ #log "disabled hook for '#{name}': #{e.message}"
139
+ nil
140
+ end
141
+ end
142
+
143
+ @hooks[name]
144
+ end
145
+
146
+ def fn_for name
147
+ File.join @dir, "#{name}.rb"
148
+ end
149
+
150
+ def log m
151
+ Redwood::log("hook: " + m)
152
+ end
153
+ end
154
+
155
+ end
@@ -0,0 +1,142 @@
1
+ module Redwood
2
+
3
+ class HookManager
4
+ class HookContext
5
+ def initialize name
6
+ @__say_id = nil
7
+ @__name = name
8
+ @__cache = {}
9
+ end
10
+
11
+ def say s
12
+ if BufferManager.instantiated?
13
+ @__say_id = BufferManager.say s, @__say_id
14
+ BufferManager.draw_screen
15
+ else
16
+ log s
17
+ end
18
+ end
19
+
20
+ def log s
21
+ info "hook[#@__name]: #{s}"
22
+ end
23
+
24
+ def ask_yes_or_no q
25
+ if BufferManager.instantiated?
26
+ BufferManager.ask_yes_or_no q
27
+ else
28
+ print q
29
+ gets.chomp.downcase == 'y'
30
+ end
31
+ end
32
+
33
+ def get tag
34
+ HookManager.tags[tag]
35
+ end
36
+
37
+ def set tag, value
38
+ HookManager.tags[tag] = value
39
+ end
40
+
41
+ def __run __hook, __filename, __locals
42
+ __binding = binding
43
+ __lprocs, __lvars = __locals.partition { |k, v| v.is_a?(Proc) }
44
+ eval __lvars.map { |k, v| "#{k} = __locals[#{k.inspect}];" }.join, __binding
45
+ ## we also support closures for delays evaluation. unfortunately
46
+ ## we have to do this via method calls, so you don't get all the
47
+ ## semantics of a regular variable. not ideal.
48
+ __lprocs.each do |k, v|
49
+ self.class.instance_eval do
50
+ define_method k do
51
+ @__cache[k] ||= v.call
52
+ end
53
+ end
54
+ end
55
+ ret = eval __hook, __binding, __filename
56
+ BufferManager.clear @__say_id if @__say_id
57
+ @__cache = {}
58
+ ret
59
+ end
60
+ end
61
+
62
+ include Singleton
63
+
64
+ def initialize dir
65
+ @dir = dir
66
+ @hooks = {}
67
+ @descs = {}
68
+ @contexts = {}
69
+ @tags = {}
70
+
71
+ Dir.mkdir dir unless File.exists? dir
72
+ end
73
+
74
+ attr_reader :tags
75
+
76
+ def run name, locals={}
77
+ hook = hook_for(name) or return
78
+ context = @contexts[hook] ||= HookContext.new(name)
79
+
80
+ result = nil
81
+ begin
82
+ result = context.__run hook, fn_for(name), locals
83
+ rescue Exception => e
84
+ log "error running hook: #{e.message}"
85
+ log e.backtrace.join("\n")
86
+ @hooks[name] = nil # disable it
87
+ BufferManager.flash "Error running hook: #{e.message}" if BufferManager.instantiated?
88
+ end
89
+ result
90
+ end
91
+
92
+ def register name, desc
93
+ @descs[name] = desc
94
+ end
95
+
96
+ def print_hooks f=$stdout
97
+ puts <<EOS
98
+ Have #{@descs.size} registered hooks:
99
+
100
+ EOS
101
+
102
+ @descs.sort.each do |name, desc|
103
+ f.puts <<EOS
104
+ #{name}
105
+ #{"-" * name.length}
106
+ File: #{fn_for name}
107
+ #{desc}
108
+ EOS
109
+ end
110
+ end
111
+
112
+ def enabled? name; !hook_for(name).nil? end
113
+
114
+ def clear; @hooks.clear; end
115
+
116
+ private
117
+
118
+ def hook_for name
119
+ unless @hooks.member? name
120
+ @hooks[name] = begin
121
+ returning IO.read(fn_for(name)) do
122
+ debug "read '#{name}' from #{fn_for(name)}"
123
+ end
124
+ rescue SystemCallError => e
125
+ #debug "disabled hook for '#{name}': #{e.message}"
126
+ nil
127
+ end
128
+ end
129
+
130
+ @hooks[name]
131
+ end
132
+
133
+ def fn_for name
134
+ File.join @dir, "#{name}.rb"
135
+ end
136
+
137
+ def log m
138
+ info("hook: " + m)
139
+ end
140
+ end
141
+
142
+ end