jugyo-termtter 0.7.7 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/Manifest.txt +10 -0
  2. data/Rakefile +25 -0
  3. data/bin/kill_termtter +22 -0
  4. data/lib/filter/en2ja.rb +2 -0
  5. data/lib/filter/expand-tinyurl.rb +2 -0
  6. data/lib/filter/fib.rb +2 -0
  7. data/lib/filter/ignore.rb +2 -0
  8. data/lib/filter/reverse.rb +2 -0
  9. data/lib/plugin/april_fool.rb +15 -0
  10. data/lib/plugin/bomb.rb +11 -8
  11. data/lib/plugin/confirm.rb +9 -24
  12. data/lib/plugin/cool.rb +8 -10
  13. data/lib/plugin/english.rb +2 -0
  14. data/lib/plugin/erb.rb +9 -9
  15. data/lib/plugin/favorite.rb +2 -0
  16. data/lib/plugin/fib.rb +2 -0
  17. data/lib/plugin/filter.rb +41 -36
  18. data/lib/plugin/follow.rb +36 -20
  19. data/lib/plugin/graduatter.rb +2 -0
  20. data/lib/plugin/group.rb +32 -34
  21. data/lib/plugin/growl.rb +3 -1
  22. data/lib/plugin/hatebu.rb +46 -44
  23. data/lib/plugin/history.rb +16 -4
  24. data/lib/plugin/keyword.rb +2 -0
  25. data/lib/plugin/log.rb +32 -32
  26. data/lib/plugin/modify_arg_hook_sample.rb +7 -0
  27. data/lib/plugin/msagent.rb +2 -0
  28. data/lib/plugin/multi_reply.rb +2 -0
  29. data/lib/plugin/notify-send.rb +2 -0
  30. data/lib/plugin/otsune.rb +17 -13
  31. data/lib/plugin/outputz.rb +2 -0
  32. data/lib/plugin/pause.rb +3 -0
  33. data/lib/plugin/plugin.rb +29 -24
  34. data/lib/plugin/post_exec_hook_sample.rb +9 -0
  35. data/lib/plugin/pre_exec_hook_sample.rb +9 -0
  36. data/lib/plugin/primes.rb +2 -0
  37. data/lib/plugin/quicklook.rb +2 -0
  38. data/lib/plugin/reblog.rb +27 -25
  39. data/lib/plugin/reload.rb +3 -3
  40. data/lib/plugin/say.rb +2 -0
  41. data/lib/plugin/scrape.rb +35 -37
  42. data/lib/plugin/screen.rb +2 -0
  43. data/lib/plugin/shell.rb +12 -2
  44. data/lib/plugin/sl.rb +42 -25
  45. data/lib/plugin/spam.rb +2 -0
  46. data/lib/plugin/standard_plugins.rb +99 -49
  47. data/lib/plugin/stdout.rb +2 -0
  48. data/lib/plugin/system_status.rb +7 -15
  49. data/lib/plugin/translation.rb +2 -0
  50. data/lib/plugin/update_editor.rb +21 -21
  51. data/lib/plugin/uri-open.rb +2 -0
  52. data/lib/plugin/wassr_post.rb +10 -9
  53. data/lib/plugin/yhara.rb +16 -25
  54. data/lib/plugin/yonda.rb +2 -0
  55. data/lib/termtter.rb +44 -24
  56. data/lib/termtter/api.rb +2 -0
  57. data/lib/termtter/client.rb +140 -56
  58. data/lib/termtter/command.rb +15 -5
  59. data/lib/termtter/connection.rb +3 -1
  60. data/lib/termtter/hook.rb +18 -0
  61. data/lib/termtter/status.rb +2 -0
  62. data/lib/termtter/task.rb +16 -0
  63. data/lib/termtter/task_manager.rb +116 -0
  64. data/lib/termtter/twitter.rb +15 -4
  65. data/lib/termtter/user.rb +13 -0
  66. data/run_termtter.rb +1 -0
  67. data/test/test_termtter.rb +2 -0
  68. metadata +14 -3
data/lib/plugin/stdout.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  require 'highline'
2
4
  require 'erb'
3
5
 
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  require 'erb'
2
4
 
3
5
  configatron.plugins.system_status.set_default(:default_status_proc, proc { Time.now.strftime("%x %X") })
@@ -13,20 +15,11 @@ def out_put_status(status, color)
13
15
  end
14
16
 
15
17
  module Termtter::Client
16
- Thread.new do
17
- loop do
18
- begin
19
- status = public_storage[:system_status] ||
20
- configatron.plugins.system_status.default_status_proc.call
21
- color = public_storage[:system_status_color] ||
22
- configatron.plugins.system_status.default_color
23
- rescue => e
24
- status = e.message
25
- color = :on_red
26
- end
27
- out_put_status(status, color)
28
- sleep configatron.plugins.system_status.interval
29
- end
18
+ add_task(:name => :system_status, :interval => configatron.plugins.system_status.interval) do
19
+ status = (@@task_manager.get_task(:update_timeline).exec_at - Time.now).to_i.to_s
20
+ color = public_storage[:system_status_color] ||
21
+ configatron.plugins.system_status.default_color
22
+ out_put_status(status, color)
30
23
  end
31
24
  end
32
25
 
@@ -38,4 +31,3 @@ end
38
31
  # configatron.plugins.system_status.interval = 1
39
32
  # configatron.plugins.system_status.default_color = :on_blue
40
33
  # configatron.plugins.system_status.format = '<%= status %>'
41
-
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  require 'nokogiri'
2
4
  require 'net/http'
3
5
  require 'kconv'
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  require 'tempfile'
2
4
 
3
5
  module Termtter::Client
@@ -22,27 +24,25 @@ module Termtter::Client
22
24
  result
23
25
  end
24
26
 
25
- add_command /^(update_editor|ue)\s*$/ do |m, t|
26
- pause
27
- text = input_editor
28
- unless text.empty?
29
- text = ERB.new(text).result(binding)
30
- text.split("\n").each do |post|
31
- break if post =~ /^__END__$/
32
- unless post.empty?
33
- t.update_status(post)
34
- puts "=> #{post}"
35
- end
36
- end
37
- end
38
- resume
39
- end
40
-
41
- add_help 'update_editor,ue', 'Update status from editor.'
42
-
43
- add_completion do |input|
44
- %w[ update_editor ].grep(/^#{Regexp.quote input}/)
45
- end
27
+ register_command(
28
+ :name => :update_editor, :aliases => [:ue],
29
+ :exec_proc => proc{|arg|
30
+ pause
31
+ text = input_editor
32
+ unless text.empty?
33
+ text = ERB.new(text).result(binding)
34
+ text.split("\n").each do |post|
35
+ break if post =~ /^__END__$/
36
+ unless post.empty?
37
+ Termtter::API.twitter.update_status(post)
38
+ puts "=> #{post}"
39
+ end
40
+ end
41
+ end
42
+ resume
43
+ },
44
+ :help => ["update_editor,ue", "Update status from editor."]
45
+ )
46
46
  end
47
47
 
48
48
  # update_editor.rb
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  module Termtter::Client
2
4
  public_storage[:uris] = []
3
5
 
@@ -1,21 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  require 'uri'
2
4
  require 'net/http'
3
5
 
4
- module Termtter::Client
5
- # NOTE: overwrite original update command
6
- add_command /^(update|u)\s+(.*)/ do |m, t|
7
- text = ERB.new(m[2]).result(binding).gsub(/\n/, ' ')
8
- t.update_status(text)
9
- puts "=> #{text}"
6
+ Termtter::Client.register_hook(
7
+ :name => :wassr_post,
8
+ :points => [:modify_arg_for_update],
9
+ :exec_proc => proc {|cmd, arg|
10
10
  begin
11
11
  Net::HTTP.version_1_2
12
12
  req = Net::HTTP::Post.new("/statuses/update.json?")
13
13
  req.basic_auth configatron.plugins.wassr_post.username, configatron.plugins.wassr_post.password
14
14
  Net::HTTP.start('api.wassr.jp', 80) do |http|
15
- res = http.request(req, "status=#{URI.escape(text)}&source=Termtter")
15
+ res = http.request(req, "status=#{URI.escape(arg.strip)}&source=Termtter")
16
16
  end
17
17
  rescue
18
18
  puts "RuntimeError: #{$!}"
19
19
  end
20
- end
21
- end
20
+ return arg
21
+ }
22
+ )
data/lib/plugin/yhara.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  if RUBY_VERSION < "1.8.7"
2
4
  class Array
3
5
  def choice
@@ -123,31 +125,20 @@ module Yharian
123
125
  end
124
126
 
125
127
  module Termtter::Client
126
-
127
- add_help 'yhara', 'Post a new Yharian sentence'
128
- add_help 'yhara USER', 'Speak to the user in Yharian'
129
-
130
- add_command /^(yhara)\s*$/ do |m, t|
131
- text = Yharian::text
132
- t.update_status(text)
133
- puts "=> #{text}"
134
- end
135
-
136
- add_command /^(yhara)\s+(\w+)/ do |m, t|
137
- text = "@#{m[2]} #{Yharian::text}"
138
- t.update_status(text)
139
- puts "=> #{text}"
140
- end
141
-
142
- add_completion do |input|
143
- case input
144
- when /^(yhara)\s+(.*)/
145
- find_user_candidates $2, "#{$1} %s"
146
- else
147
- %w[ yhara ].grep(/^#{Regexp.quote input}/)
148
- end
149
- end
150
-
128
+ register_command(
129
+ :name => :yhara,
130
+ :exec_proc => proc{|arg|
131
+ text = "#{'@' if arg[0..0] != '@'}#{arg} #{Yharian::text}"
132
+ Termtter::API.twitter.update_status(text)
133
+ puts "=> #{text}"
134
+ },
135
+ :completion_proc => proc {|cmd, args|
136
+ if /(.*)@([^\s]*)$/ =~ args
137
+ find_user_candidates $2, "#{cmd} #{$1}@%s"
138
+ end
139
+ },
140
+ :help => ["yhara (USER)", 'Post a new Yharian sentence']
141
+ )
151
142
  end
152
143
 
153
144
  # yhara.rb
data/lib/plugin/yonda.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  module Termtter::Client
2
4
  public_storage[:unread_count] = 0
3
5
 
data/lib/termtter.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  $:.unshift(File.dirname(__FILE__)) unless
2
4
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
5
 
@@ -8,7 +10,6 @@ require 'open-uri'
8
10
  require 'cgi'
9
11
  require 'readline'
10
12
  require 'enumerator'
11
- require 'parsedate'
12
13
  require 'configatron'
13
14
 
14
15
  Thread.abort_on_exception = true
@@ -21,12 +22,16 @@ configatron.proxy.set_default(:port, '8080')
21
22
  require 'termtter/twitter'
22
23
  require 'termtter/connection'
23
24
  require 'termtter/status'
25
+ require 'termtter/user'
24
26
  require 'termtter/command'
27
+ require 'termtter/hook'
28
+ require 'termtter/task'
29
+ require 'termtter/task_manager'
25
30
  require 'termtter/client'
26
31
  require 'termtter/api'
27
32
 
28
33
  module Termtter
29
- VERSION = '0.7.7'
34
+ VERSION = '0.8.0'
30
35
  APP_NAME = 'termtter'
31
36
  CONF_FILE = '~/.termtterrc' # still does not use
32
37
  CONF_DIR = '~/.termtter' # still does not use
@@ -78,22 +83,34 @@ if win?
78
83
  $oldColor = lpBuffer.unpack('SSSSSssssSS')[4]
79
84
 
80
85
  $colorMap = {
81
- 0 => 7, # black/white
82
- 37 => 8, # white/intensity
83
- 31 => 4 + 8, # red/red
84
- 32 => 2 + 8, # green/green
85
- 33 => 6 + 8, # yellow/yellow
86
- 34 => 1 + 8, # blue/blue
87
- 35 => 5 + 8, # magenta/purple
88
- 36 => 3 + 8, # cyan/aqua
89
- 90 => 7, # erase/white
86
+ 0 => 0x07|0x00|0x00|0x00, # black/white
87
+ 37 => 0x08|0x00|0x00|0x00, # white/intensity
88
+ 31 => 0x04|0x08|0x00|0x00, # red/red
89
+ 32 => 0x02|0x08|0x00|0x00, # green/green
90
+ 33 => 0x06|0x08|0x00|0x00, # yellow/yellow
91
+ 34 => 0x01|0x08|0x00|0x00, # blue/blue
92
+ 35 => 0x05|0x08|0x00|0x00, # magenta/purple
93
+ 36 => 0x03|0x08|0x00|0x00, # cyan/aqua
94
+ 39 => 0x07, # default
95
+ 40 => 0x00|0x00|0xf0|0x00, # background:white
96
+ 41 => 0x07|0x00|0x40|0x00, # background:red
97
+ 42 => 0x07|0x00|0x20|0x00, # background:green
98
+ 43 => 0x07|0x00|0x60|0x00, # background:yellow
99
+ 44 => 0x07|0x00|0x10|0x00, # background:blue
100
+ 45 => 0x07|0x00|0x50|0x80, # background:magenta
101
+ 46 => 0x07|0x00|0x30|0x80, # background:cyan
102
+ 47 => 0x07|0x00|0x70|0x80, # background:gray
103
+ 49 => 0x70, # default
104
+ 90 => 0x07|0x00|0x00|0x00, # erase/white
90
105
  }
91
106
  $iconv_u8_to_sj = Iconv.new("CP#{$wGetACP.call()}", 'UTF-8')
92
- def puts(str)
93
- #str.to_s.tosjis.split(/(\e\[\d+m)/).each do |token|
94
- str.to_s.gsub("\xef\xbd\x9e", "\xe3\x80\x9c").split(/(\e\[\d+m)/).each do |token|
95
- if token =~ /\e\[(\d+)m/
107
+ def print(str)
108
+ str.to_s.gsub("\xef\xbd\x9e", "\xe3\x80\x9c").split(/(\e\[\d*[a-zA-Z])/).each do |token|
109
+ case token
110
+ when /\e\[(\d+)m/
96
111
  $wSetConsoleTextAttribute.call $hStdOut, $colorMap[$1.to_i].to_i
112
+ when /\e\[\d*[a-zA-Z]/
113
+ # do nothing
97
114
  else
98
115
  loop do
99
116
  begin
@@ -107,26 +124,29 @@ if win?
107
124
  end
108
125
  end
109
126
  $wSetConsoleTextAttribute.call $hStdOut, $oldColor
110
- STDOUT.puts
111
127
  $iconv_u8_to_sj.iconv(nil)
112
128
  end
129
+ def puts(str)
130
+ print str
131
+ STDOUT.puts
132
+ end
113
133
  end
114
134
 
115
- def handle_error(e)
116
- puts "Error: #{e}"
117
- puts e.backtrace.join("\n")
118
- end
119
-
120
- def plugin(s)
135
+ def plugin(s, init = {})
136
+ unless init.empty?
137
+ init.each do |key, value|
138
+ eval("configatron.plugins.#{s}").__send__("#{key}=", value)
139
+ end
140
+ end
121
141
  require "plugin/#{s}"
122
142
  rescue => e
123
- handle_error(e)
143
+ Termtter::Client.handle_error(e)
124
144
  end
125
145
 
126
146
  def filter(s)
127
147
  load "filter/#{s}.rb"
128
148
  rescue => e
129
- handle_error(e)
149
+ Termtter::Client.handle_error(e)
130
150
  else
131
151
  Termtter::Client.public_storage[:filters] ||= []
132
152
  Termtter::Client.public_storage[:filters] << s
data/lib/termtter/api.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  module Termtter
2
4
  module API
3
5
  class << self
@@ -1,16 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  module Termtter
2
4
  class CommandNotFound < StandardError; end
3
5
 
4
6
  module Client
5
7
 
6
- @@hooks = []
7
- @@commands = {}
8
- @@new_commands = {}
9
- @@completions = []
10
- @@filters = []
11
- @@helps = []
12
-
13
8
  class << self
9
+
10
+ def init
11
+ @@hooks = []
12
+ @@new_hooks = {}
13
+ @@commands = {}
14
+ @@new_commands = {}
15
+ @@completions = []
16
+ @@filters = []
17
+ @@helps = []
18
+ @@since_id = nil
19
+ @@main_thread = nil
20
+ @@input_thread = nil
21
+ @@task_manager = Termtter::TaskManager.new
22
+ end
23
+
14
24
  def public_storage
15
25
  @@public_storage ||= {}
16
26
  end
@@ -23,10 +33,35 @@ module Termtter
23
33
  EOF
24
34
  end
25
35
 
36
+ # Deprecated
37
+ # FIXME: delete when become unnecessary
26
38
  def add_command(regex, &block)
39
+ warn "Termtter:Client.add_command method will be removed. Use Termtter::Client.register_command() instead. (#{caller.first})"
27
40
  @@commands[regex] = block
28
41
  end
29
42
 
43
+ def register_hook(arg)
44
+ hook = case arg
45
+ when Hook
46
+ arg
47
+ when Hash
48
+ Hook.new(arg)
49
+ else
50
+ raise ArgumentError, 'must be given Termtter::Hook or Hash'
51
+ end
52
+ @@new_hooks[hook.name] = hook
53
+ end
54
+
55
+ def get_hook(name)
56
+ @@new_hooks[name]
57
+ end
58
+
59
+ def get_hooks(point)
60
+ @@new_hooks.values.select do |hook|
61
+ hook.match?(point)
62
+ end
63
+ end
64
+
30
65
  def register_command(arg)
31
66
  command = case arg
32
67
  when Command
@@ -43,10 +78,12 @@ module Termtter
43
78
  @@new_commands[name]
44
79
  end
45
80
 
46
- def add_macro(r, s)
47
- add_command(r) do |m, t|
48
- call_commands(s % m.to_a[1..-1])
49
- end
81
+ def register_macro(name, macro, options = {})
82
+ arg = {
83
+ :name => name.to_sym,
84
+ :exec_proc => proc {|arg| call_commands(macro % arg)}
85
+ }.merge(options)
86
+ register_command(arg)
50
87
  end
51
88
 
52
89
  def add_help(name, desc)
@@ -83,6 +120,22 @@ module Termtter
83
120
  end
84
121
  end
85
122
 
123
+ # return last hook return value
124
+ def call_new_hooks(point, *args)
125
+ result = nil
126
+ get_hooks(point).each {|hook|
127
+ break if result == false # interrupt if hook return false
128
+ result = hook.exec_proc.call(*args)
129
+ }
130
+ return result
131
+ rescue => e
132
+ if point.to_sym == :on_error
133
+ raise
134
+ else
135
+ handle_error(e)
136
+ end
137
+ end
138
+
86
139
  # TODO: delete argument "tw" when unnecessary
87
140
  def call_hooks(statuses, event, tw = nil)
88
141
  do_hooks(statuses, :pre_filter)
@@ -96,22 +149,29 @@ module Termtter
96
149
  @@commands.each do |key, command|
97
150
  if key =~ text
98
151
  command_found = true
99
- begin
152
+ @@task_manager.invoke_and_wait do
100
153
  command.call($~, Termtter::API.twitter)
101
- rescue => e
102
- handle_error(e)
103
154
  end
104
155
  end
105
156
  end
106
157
 
107
158
  @@new_commands.each do |key, command|
108
159
  command_info = command.match?(text)
109
- # TODO: call hook for before command here.
110
160
  if command_info
111
161
  command_found = true
112
- result = command.execute(command_info[1])
113
- if result
114
- # TODO: call hook for after command with result.
162
+ input_command, arg = *command_info
163
+
164
+ modified_arg = call_new_hooks("modify_arg_for_#{command.name.to_s}", input_command, arg) || arg || ''
165
+
166
+ @@task_manager.invoke_and_wait do
167
+ pre_exec_hook_result = call_new_hooks("pre_exec_#{command.name.to_s}", input_command, modified_arg)
168
+ next if pre_exec_hook_result == false
169
+
170
+ # exec command
171
+ result = command.execute(modified_arg)
172
+ if result
173
+ call_new_hooks("post_exec_#{command.name.to_s}", input_command, modified_arg, result)
174
+ end
115
175
  end
116
176
  end
117
177
  end
@@ -120,19 +180,25 @@ module Termtter
120
180
  end
121
181
 
122
182
  def pause
123
- @@pause = true
183
+ @@task_manager.pause
124
184
  end
125
185
 
126
186
  def resume
127
- @@pause = false
128
- @@update_thread.run
187
+ @@task_manager.resume
188
+ end
189
+
190
+ def add_task(*arg, &block)
191
+ @@task_manager.add_task(*arg, &block)
129
192
  end
130
193
 
131
194
  def exit
195
+ puts 'finalizing...'
196
+
132
197
  call_hooks([], :exit)
133
- @@main_thread.kill
134
- @@update_thread.kill
135
- @@input_thread.kill
198
+ call_new_hooks(:exit)
199
+ @@task_manager.kill
200
+ @@main_thread.kill if @@main_thread
201
+ @@input_thread.kill if @@input_thread
136
202
  end
137
203
 
138
204
  def load_default_plugins
@@ -202,35 +268,17 @@ module Termtter
202
268
  end
203
269
  end
204
270
 
205
- def setup_api()
206
- Termtter::API.setup()
207
- end
208
-
209
- def run
210
- load_default_plugins()
211
- load_config()
212
- setup_readline()
213
- setup_api()
214
-
215
- puts 'initializing...'
216
- initialized = false
217
- @@pause = false
218
- call_hooks([], :initialize)
219
-
220
- @@input_thread = nil
221
- @@update_thread = Thread.new do
222
- since_id = nil
223
- loop do
271
+ def setup_update_timeline_task()
272
+ register_command(
273
+ :name => :_update_timeline,
274
+ :exec_proc => proc {|arg|
224
275
  begin
225
- Thread.stop if @@pause
226
-
227
- statuses = Termtter::API.twitter.get_friends_timeline(since_id)
276
+ statuses = Termtter::API.twitter.get_friends_timeline(@@since_id)
228
277
  unless statuses.empty?
229
- since_id = statuses[0].id
278
+ @@since_id = statuses[0].id
230
279
  end
231
280
  print "\e[1K\e[0G" if !statuses.empty? && !win?
232
281
  call_hooks(statuses, :update_friends_timeline)
233
- initialized = true
234
282
  @@input_thread.kill if @@input_thread && !statuses.empty?
235
283
  rescue OpenURI::HTTPError => e
236
284
  if e.message == '401 Unauthorized'
@@ -238,20 +286,32 @@ module Termtter
238
286
  puts 'plese check your account settings'
239
287
  exit!
240
288
  end
241
- ensure
242
- sleep configatron.update_interval
243
289
  end
244
- end
245
- end
290
+ }
291
+ )
246
292
 
247
- until initialized; end
293
+ add_task(:name => :update_timeline, :interval => configatron.update_interval) do
294
+ call_commands('_update_timeline')
295
+ end
296
+ end
248
297
 
298
+ def trap_setting()
249
299
  begin
250
300
  stty_save = `stty -g`.chomp
251
- trap("INT") { system "stty", stty_save; exit }
301
+ trap("INT") do
302
+ begin
303
+ system "stty", stty_save
304
+ ensure
305
+ exit
306
+ end
307
+ end
252
308
  rescue Errno::ENOENT
253
309
  end
310
+ end
254
311
 
312
+ def start_input_thread
313
+ setup_readline()
314
+ trap_setting()
255
315
  @@main_thread = Thread.new do
256
316
  loop do
257
317
  @@input_thread = create_input_thread()
@@ -261,10 +321,26 @@ module Termtter
261
321
  @@main_thread.join
262
322
  end
263
323
 
324
+ def run
325
+ puts 'initializing...'
326
+
327
+ load_default_plugins()
328
+ load_config()
329
+ Termtter::API.setup()
330
+
331
+ call_hooks([], :initialize)
332
+ call_new_hooks(:initialize)
333
+
334
+ setup_update_timeline_task()
335
+ call_commands('_update_timeline')
336
+
337
+ @@task_manager.run()
338
+ start_input_thread()
339
+ end
340
+
264
341
  def create_input_thread()
265
342
  Thread.new do
266
- erb = ERB.new(configatron.prompt)
267
- while buf = Readline.readline(erb.result(Termtter::API.twitter.__send__(:binding)), true)
343
+ while buf = Readline.readline(ERB.new(configatron.prompt).result(API.twitter.__send__(:binding)), true)
268
344
  Readline::HISTORY.pop if /^(u|update)\s+(.+)$/ =~ buf
269
345
  begin
270
346
  call_commands(buf)
@@ -277,6 +353,13 @@ module Termtter
277
353
  end
278
354
  end
279
355
 
356
+ def handle_error(e)
357
+ call_new_hooks("on_error", e)
358
+ rescue => e
359
+ puts "Error: #{e}"
360
+ puts e.backtrace.join("\n")
361
+ end
362
+
280
363
  def wrap_require
281
364
  # FIXME: delete this method after the major version up
282
365
  alias original_require require
@@ -296,3 +379,4 @@ module Termtter
296
379
  end
297
380
  end
298
381
 
382
+ Termtter::Client.init