termtter 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/Rakefile +1 -1
  2. data/lib/plugins/bomb.rb +9 -12
  3. data/lib/plugins/expand-tinyurl.rb +12 -3
  4. data/lib/plugins/group.rb +10 -6
  5. data/lib/plugins/history.rb +21 -10
  6. data/lib/plugins/log.rb +10 -10
  7. data/lib/plugins/msagent.rb +23 -11
  8. data/lib/plugins/notify-send.rb +17 -12
  9. data/lib/plugins/say.rb +8 -6
  10. data/lib/plugins/scrape.rb +1 -1
  11. data/lib/plugins/screen-notify.rb +17 -10
  12. data/lib/plugins/standard_plugins.rb +29 -17
  13. data/lib/plugins/stdout.rb +35 -54
  14. data/lib/plugins/storage.rb +17 -23
  15. data/lib/plugins/storage/status.rb +23 -20
  16. data/lib/plugins/update_editor.rb +1 -1
  17. data/lib/plugins/uri-open.rb +7 -5
  18. data/lib/plugins/url_addspace.rb +2 -2
  19. data/lib/termtter/api.rb +2 -1
  20. data/lib/termtter/client.rb +88 -108
  21. data/lib/termtter/command.rb +1 -0
  22. data/lib/termtter/hook.rb +5 -0
  23. data/lib/termtter/system_extensions.rb +13 -3
  24. data/lib/termtter/version.rb +1 -1
  25. data/spec/{plugin → plugins}/cool_spec.rb +0 -0
  26. data/spec/{plugin → plugins}/english_spec.rb +0 -0
  27. data/spec/{plugin → plugins}/favorite_spec.rb +0 -0
  28. data/spec/{plugin → plugins}/fib_spec.rb +0 -0
  29. data/spec/{plugin → plugins}/filter_spec.rb +0 -0
  30. data/spec/{plugin → plugins}/pause_spec.rb +0 -0
  31. data/spec/{plugin → plugins}/plugin_spec.rb +0 -0
  32. data/spec/{plugin → plugins}/primes_spec.rb +0 -0
  33. data/spec/{plugin → plugins}/shell_spec.rb +0 -0
  34. data/spec/{plugin → plugins}/sl_spec.rb +0 -0
  35. data/spec/{plugin → plugins}/spam_spec.rb +0 -0
  36. data/spec/{plugin → plugins}/standard_plugins_spec.rb +0 -0
  37. data/spec/{plugin → plugins}/storage/DB_spec.rb +0 -0
  38. data/spec/{plugin → plugins}/storage/status_spec.rb +1 -1
  39. data/spec/termtter/client_spec.rb +1 -4
  40. metadata +17 -17
@@ -11,68 +11,49 @@ config.plugins.stdout.set_default(
11
11
  '<90><%=time%></90> <<%=status_color%>><%=status%></<%=status_color%>> <90><%=id%></90>')
12
12
  config.plugins.stdout.set_default(:search_highlihgt_format, '<on_magenta><white>\1</white></on_magenta>')
13
13
 
14
- $highline = HighLine.new
15
-
16
- def color(str, value)
17
- return str if value == :none
18
- case value
19
- when String, Symbol
20
- $highline.color(str, value)
21
- else
22
- "\e[#{value}m#{str}\e[0m"
23
- end
24
- end
25
-
26
- module Termtter::Client
27
-
28
- def self.print_statuses(statuses, sort = true, time_format = '%H:%M:%S')
29
- (sort ? statuses.sort_by{ |s| s.id} : statuses).each do |s|
30
- text = s.text
31
- status_color = config.plugins.stdout.colors[s.user.screen_name.hash % config.plugins.stdout.colors.size]
32
- status = "#{s.user.screen_name}: #{text}"
33
- if s.in_reply_to_status_id
34
- status += " (repl. to #{s.in_reply_to_status_id})"
35
- end
36
-
37
- time = "(#{Time.parse(s.created_at).strftime(time_format)})"
38
- id = s.id
39
- erbed_text = ERB.new(config.plugins.stdout.timeline_format).result(binding)
40
- puts TermColor.parse(erbed_text)
14
+ module Termtter
15
+ class StdOut < Hook
16
+ def initialize
17
+ super(:name => :stdout, :points => [:output])
41
18
  end
42
- end
43
-
44
- def self.print_statuses_with_date(statuses, sort = true)
45
- print_statuses(statuses, sort, '%m-%d %H:%M')
46
- end
47
19
 
48
- def self.print_search_results(result, time_format = '%H:%M:%S')
49
- result.results.sort_by{|r| r.created_at}.each do |r|
50
- text = r.text.
51
- gsub(/(\n|\r)/, '').
52
- gsub(/(#{Regexp.escape(result.query)})/i, config.plugins.stdout.search_highlihgt_format)
53
- status_color = config.plugins.stdout.colors[r.from_user_id.to_i.hash % config.plugins.stdout.colors.size]
54
- status = "#{r.from_user}: #{text}"
55
- time = "(#{Time.parse(r.created_at).strftime(time_format)})"
56
- id = r.id
57
- erbed_text = ERB.new(config.plugins.stdout.timeline_format).result(binding)
58
- puts TermColor.parse(erbed_text)
20
+ def execute(statuses, event)
21
+ print_statuses(statuses)
59
22
  end
60
- end
61
23
 
62
- add_hook do |result, event|
63
- case event
64
- when :update_friends_timeline, :list_friends_timeline
65
- print_statuses(result) unless result.empty?
66
- when :list_user_timeline, :replies
67
- print_statuses_with_date(result) unless result.empty?
68
- when :show
69
- print_statuses_with_date([result])
70
- when :search
71
- print_search_results(result)
24
+ def print_statuses(statuses, sort = true, time_format = nil)
25
+ return unless statuses
26
+ unless time_format
27
+ # 最初と最後の日付がちがうとき日付も出す
28
+ t1 = Time.parse(statuses.first[:created_at])
29
+ t2 = Time.parse(statuses.last[:created_at])
30
+ time_format =
31
+ if [t1.year, t1.month, t1.day] == [t2.year, t2.month, t2.day]
32
+ '%H:%M:%S'
33
+ else
34
+ '%y/%m/%d %H:%M'
35
+ end
36
+ end
37
+
38
+ statuses.each do |s|
39
+ text = s.text
40
+ status_color = config.plugins.stdout.colors[s.user.id.hash % config.plugins.stdout.colors.size]
41
+ status = "#{s.user.screen_name}: #{text}"
42
+ if s.in_reply_to_status_id
43
+ status += " (repl. to #{s.in_reply_to_status_id})"
44
+ end
45
+
46
+ time = "(#{Time.parse(s.created_at).strftime(time_format)})"
47
+ id = s.id
48
+ erbed_text = ERB.new(config.plugins.stdout.timeline_format).result(binding)
49
+ puts TermColor.parse(erbed_text)
50
+ end
72
51
  end
73
52
  end
74
53
 
54
+ Client.register_hook(StdOut.new)
75
55
  end
56
+
76
57
  # stdout.rb
77
58
  # output statuses to stdout
78
59
  # example config
@@ -8,40 +8,34 @@ require File.dirname(__FILE__) + '/storage/status'
8
8
  module Termtter::Client
9
9
  public_storage[:log] = []
10
10
 
11
- add_hook do |statuses, event|
12
- case event
13
- when :pre_filter
11
+ register_hook(
12
+ :name => :storage,
13
+ :points => [:pre_filter],
14
+ :exec_proc => lambda {|statuses, event|
14
15
  statuses.each do |s|
15
16
  Termtter::Storage::Status.insert(
16
17
  :post_id => s.id,
17
18
  :created_at => Time.parse(s.created_at).to_i,
18
19
  :in_reply_to_status_id => s.in_reply_to_status_id,
19
20
  :in_reply_to_user_id => s.in_reply_to_user_id,
20
- :post_text => s.text,
21
+ :post => s.text,
21
22
  :user_id => s.user.id,
22
- :screen_name => s.user.screen_name)
23
+ :screen_name => s.user.screen_name
24
+ )
23
25
  end
24
- end
25
- end
26
+ }
27
+ )
26
28
 
27
29
  register_command(
28
- :name => :search_storage, :aliases => [:ss],
30
+ :name => :search_storage,
31
+ :aliases => [:ss],
29
32
  :exec_proc => lambda {|arg|
30
33
  unless arg.strip.empty?
31
34
  key = arg.strip
32
- Termtter::Storage::Status.search({ :post_text => key})
33
- =begin
34
- statuses = public_storage[:storage].search({ :post_text => key})
35
-
36
- statuses.each do |s|
37
- p s
38
- end
39
- call_hooks(statuses, :search)
40
- =end
41
- end
42
-
43
- },
44
-
45
- :help => [ 'search_storage WORD', 'Search storage for WORD' ]
46
- )
35
+ statuses = Termtter::Storage::Status.search({:text => key})
36
+ output(statuses, :search)
37
+ end
38
+ },
39
+ :help => [ 'search_storage WORD', 'Search storage for WORD' ]
40
+ )
47
41
  end
@@ -7,42 +7,45 @@ module Termtter::Storage
7
7
  class Status
8
8
  KEYS = %w[post_id created_at in_reply_to_status_id in_reply_to_user_id post_text user_id screen_name]
9
9
 
10
- def size
10
+ def self.size
11
11
  DB.instance.db.get_first_value("select count(*) from post").to_i
12
12
  end
13
13
 
14
14
  def self.search(query)
15
15
  raise "query must be Hash(#{query}, #{query.class})" unless query.kind_of? Hash
16
-
17
- DB.instance.db.execute("select created_at, screen_name, post_text, in_reply_to_status_id, post_id from post inner join user on post.user_id = user.id where post_text like '%' || ? || '%' ", query[:post_text]) do |created_at, screen_name, post_text, in_reply_to_status_id, post_id|
18
-
19
- # DB.instance.db.execute("select created_at, screen_name, post_text, in_reply_to_status_id, post_id from post inner join user on post.user_id = user.id where post_text like '%of%' ", query[:post_text]) do |created_at, screen_name, post_text, in_reply_to_status_id, post_id|
20
- p [created_at, screen_name, post_text, in_reply_to_status_id, post_id]
16
+ result = []
17
+ DB.instance.db.execute("select created_at, screen_name, post_text, in_reply_to_status_id, post_id, user_id from post inner join user on post.user_id = user.id where post_text like '%' || ? || '%' ",
18
+ query[:text]) do |created_at, screen_name, post_text, in_reply_to_status_id, post_id, user_id|
19
+ created_at = Time.at(created_at).to_s
20
+ result << {
21
+ :id => post_id,
22
+ :created_at => created_at,
23
+ :text => post_text,
24
+ :in_reply_to_status_id => in_reply_to_status_id,
25
+ :in_reply_to_user_id => nil,
26
+ :user => {
27
+ :id => user_id,
28
+ :screen_name => screen_name
29
+ }
30
+ }
21
31
  end
32
+ Rubytter.json_to_struct(result)
22
33
  end
23
34
 
24
35
  def self.insert(data)
25
- raise "data must be Hash(#{data}, #{data.class})" unless data.kind_of? Hash
26
- # 条件しぼりたいけどやりかたがうまくわからない
27
- # raise "unko" unless data.keys.all?{|c| KEYS.include? c}
28
- begin
29
36
  DB.instance.db.execute(
30
37
  "insert into post values(?,?,?,?,?,?)",
31
38
  data[:post_id],
32
39
  data[:created_at],
33
40
  data[:in_reply_to_status_id],
34
41
  data[:in_reply_to_user_id],
35
- data[:post_text],
42
+ data[:text],
36
43
  data[:user_id])
37
- begin
38
- DB.instance.db.execute(
39
- "insert into user values(?,?)",
40
- data[:user_id],
41
- data[:screen_name])
42
- rescue # FIXME: specify exceptions here
43
- end
44
- rescue # FIXME: specify exceptions here
45
- end
44
+ DB.instance.db.execute(
45
+ "insert into user values(?,?)",
46
+ data[:user_id],
47
+ data[:screen_name])
48
+ rescue SQLite3::SQLException
46
49
  end
47
50
  end
48
51
  end
@@ -8,7 +8,7 @@ module Termtter::Client
8
8
  else
9
9
  config.plugins.update_editor.set_default('editor', 'vi')
10
10
  end
11
- config.plugins.update_editor.set_default('add_completion', false)
11
+ config.plugins.update_editor.set_default('add_completion', true)
12
12
 
13
13
 
14
14
  def self.input_editor
@@ -3,13 +3,15 @@
3
3
  module Termtter::Client
4
4
  public_storage[:uris] = []
5
5
 
6
- add_hook do |statuses, event, t|
7
- if event == :update_friends_timeline
6
+ register_hook(
7
+ :name => :uri_open,
8
+ :points => [:post_filter],
9
+ :exec_proc => lambda {|statuses, event|
8
10
  statuses.each do |s|
9
- public_storage[:uris] += s.text.scan(%r|https?://[^\s]+|)
11
+ public_storage[:uris] += s[:post_text].scan(%r|https?://[^\s]+|)
10
12
  end
11
- end
12
- end
13
+ }
14
+ )
13
15
 
14
16
  def self.open_uri(uri)
15
17
  unless config.plugins.uri_open.browser.empty?
@@ -1,9 +1,9 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module Termtter::Client
4
- add_filter do |statuses|
4
+ add_filter do |statuses, event|
5
5
  statuses.each do |s|
6
- s.text.gsub!(/(\S)(https?:\/\/)/, '\1 \2')
6
+ s[:post_text].gsub!(/(\S)(https?:\/\/)/, '\1 \2')
7
7
  end
8
8
  statuses
9
9
  end
data/lib/termtter/api.rb CHANGED
@@ -19,12 +19,13 @@ module Termtter
19
19
  config.user_name,
20
20
  config.password,
21
21
  {
22
+ :app_name => Termtter::APP_NAME,
22
23
  :host => config.host,
23
24
  :header => {
24
25
  'User-Agent' => 'Termtter http://github.com/jugyo/termtter',
25
26
  'X-Twitter-Client' => 'Termtter',
26
27
  'X-Twitter-Client-URL' => 'http://github.com/jugyo/termtter',
27
- 'X-Twitter-Client-Version' => '0.1'
28
+ 'X-Twitter-Client-Version' => Termtter::VERSION
28
29
  },
29
30
  :enable_ssl => config.enable_ssl,
30
31
  :proxy_host => config.proxy.host,
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'fileutils'
3
+ require 'logger'
3
4
 
4
5
  module Termtter
5
6
  APP_NAME = 'termtter'
@@ -18,15 +19,14 @@ module Termtter
18
19
  class << self
19
20
 
20
21
  def init
21
- @@hooks = []
22
- @@new_hooks = {}
23
- @@new_commands = {}
24
- @@completions = []
25
- @@filters = []
26
- @@helps = []
27
- @@since_id = nil
28
- @@input_thread = nil
29
- @@task_manager = Termtter::TaskManager.new
22
+ @hooks = {}
23
+ @commands = {}
24
+ @filters = []
25
+ @since_id = nil
26
+ @input_thread = nil
27
+ @task_manager = Termtter::TaskManager.new
28
+ config.log.set_default(:logger, nil)
29
+ config.log.set_default(:level, nil)
30
30
  config.set_default(:update_interval, 300)
31
31
  config.set_default(:prompt, '> ')
32
32
  config.set_default(:devel, false)
@@ -34,15 +34,15 @@ module Termtter
34
34
  end
35
35
 
36
36
  def public_storage
37
- @@public_storage ||= {}
37
+ @public_storage ||= {}
38
38
  end
39
39
 
40
- %w[hook completion filter].each do |n|
41
- eval <<-EOF
42
- def add_#{n}(&b)
43
- @@#{n}s << b
44
- end
45
- EOF
40
+ def add_filter(&b)
41
+ filters << b
42
+ end
43
+
44
+ def clear_filter
45
+ filters.clear
46
46
  end
47
47
 
48
48
  def register_hook(arg)
@@ -54,15 +54,15 @@ module Termtter
54
54
  else
55
55
  raise ArgumentError, 'must be given Termtter::Hook or Hash'
56
56
  end
57
- @@new_hooks[hook.name] = hook
57
+ @hooks[hook.name] = hook
58
58
  end
59
59
 
60
60
  def get_hook(name)
61
- @@new_hooks[name]
61
+ @hooks[name]
62
62
  end
63
63
 
64
64
  def get_hooks(point)
65
- @@new_hooks.values.select do |hook|
65
+ @hooks.values.select do |hook|
66
66
  hook.match?(point)
67
67
  end
68
68
  end
@@ -76,11 +76,11 @@ module Termtter
76
76
  else
77
77
  raise ArgumentError, 'must be given Termtter::Command or Hash'
78
78
  end
79
- @@new_commands[command.name] = command
79
+ @commands[command.name] = command
80
80
  end
81
81
 
82
82
  def get_command(name)
83
- @@new_commands[name]
83
+ @commands[name]
84
84
  end
85
85
 
86
86
  def register_macro(name, macro, options = {})
@@ -91,58 +91,44 @@ module Termtter
91
91
  register_command(command)
92
92
  end
93
93
 
94
- def add_help(name, desc)
95
- @@helps << [name, desc]
96
- end
97
-
98
- %w[hooks completions helps filters].each do |n|
99
- eval <<-EOF
100
- def clear_#{n}
101
- @@#{n}.clear
102
- end
103
- EOF
94
+ # statuses => [status, status, ...]
95
+ # status => {
96
+ # :id => status id,
97
+ # :created_at => created time,
98
+ # :user_id => user id,
99
+ # :name => user name,
100
+ # :screen_name => user screen_name,
101
+ # :source => source,
102
+ # :reply_to => reply_to status id,
103
+ # :text => status,
104
+ # :original_data => original data,
105
+ # }
106
+ def output(statuses, event)
107
+ return if statuses.nil? || statuses.empty?
108
+
109
+ statuses = statuses.sort_by{|s|s.id}
110
+ call_hooks(:pre_filter, statuses, event)
111
+ filtered = apply_filters(statuses, event)
112
+ call_hooks(:post_filter, filtered, event)
113
+ call_hooks(:output, filtered, event)
104
114
  end
105
115
 
106
- # memo: each filter must return Array of Status
107
- def apply_filters(result, event = nil)
108
- case event
109
- when :show
110
- result
111
- when :search
112
- filtered = result.results.map(&:dup)
113
- @@filters.each do |f|
114
- filtered = f.call(filtered, event)
115
- end
116
- result.results = filtered
117
- result
118
- else
119
- filtered = result.map(&:dup)
120
- @@filters.each do |f|
116
+ def apply_filters(statuses, event)
117
+ filtered = statuses.map(&:dup)
118
+ @filters.each do |f|
121
119
  filtered = f.call(filtered, event)
122
120
  end
123
121
  filtered
124
- end
125
- rescue => e
126
- handle_error(e)
127
- result
128
- end
129
-
130
- def do_hooks(statuses, event)
131
- @@hooks.each do |h|
132
- begin
133
- h.call(statuses.dup, event, Termtter::API.twitter)
134
- rescue => e
135
- handle_error(e)
136
- end
137
- end
122
+ rescue => e
123
+ handle_error(e)
138
124
  end
139
125
 
140
126
  # return last hook return value
141
- def call_new_hooks(point, *args)
127
+ def call_hooks(point, *args)
142
128
  result = nil
143
129
  get_hooks(point).each {|hook|
144
130
  break if result == false # interrupt if hook return false
145
- result = hook.exec_proc.call(*args)
131
+ result = hook.execute(*args)
146
132
  }
147
133
  result
148
134
  rescue => e
@@ -153,36 +139,29 @@ module Termtter
153
139
  end
154
140
  end
155
141
 
156
- # TODO: delete argument "tw" when unnecessary
157
- def call_hooks(statuses, event, tw = nil)
158
- do_hooks(statuses, :pre_filter)
159
- filtered = apply_filters(statuses, event)
160
- do_hooks(filtered, :post_filter)
161
- do_hooks(filtered, event)
162
- end
163
-
164
142
  def call_commands(text, tw = nil)
165
143
  return if text.empty?
166
144
 
167
145
  command_found = false
168
- @@new_commands.each do |key, command|
146
+ @commands.each do |key, command|
147
+ # match? メソッドがなんかきもちわるいので変える予定
169
148
  command_str, command_arg = command.match?(text)
170
149
  if command_str
171
150
  command_found = true
172
151
 
173
- modified_arg = call_new_hooks(
152
+ modified_arg = call_hooks(
174
153
  "modify_arg_for_#{command.name.to_s}",
175
154
  command_str,
176
155
  command_arg) || command_arg || ''
177
156
 
178
- @@task_manager.invoke_and_wait do
157
+ @task_manager.invoke_and_wait do
179
158
 
180
- pre_exec_hook_result = call_new_hooks("pre_exec_#{command.name.to_s}", command_str, modified_arg)
159
+ pre_exec_hook_result = call_hooks("pre_exec_#{command.name.to_s}", command_str, modified_arg)
181
160
  next if pre_exec_hook_result == false
182
161
  # exec command
183
162
  result = command.execute(modified_arg)
184
163
  if result
185
- call_new_hooks("post_exec_#{command.name.to_s}", command_str, modified_arg, result)
164
+ call_hooks("post_exec_#{command.name.to_s}", command_str, modified_arg, result)
186
165
  end
187
166
 
188
167
  end
@@ -193,24 +172,23 @@ module Termtter
193
172
  end
194
173
 
195
174
  def pause
196
- @@task_manager.pause
175
+ @task_manager.pause
197
176
  end
198
177
 
199
178
  def resume
200
- @@task_manager.resume
179
+ @task_manager.resume
201
180
  end
202
181
 
203
182
  def add_task(*arg, &block)
204
- @@task_manager.add_task(*arg, &block)
183
+ @task_manager.add_task(*arg, &block)
205
184
  end
206
185
 
207
186
  def exit
208
187
  puts 'finalizing...'
209
188
 
210
- call_hooks([], :exit)
211
- call_new_hooks(:exit)
212
- @@task_manager.kill
213
- @@input_thread.kill if @@input_thread
189
+ call_hooks(:exit)
190
+ @task_manager.kill
191
+ @input_thread.kill if @input_thread
214
192
  end
215
193
 
216
194
  def load_default_plugins
@@ -246,7 +224,7 @@ module Termtter
246
224
  Termtter::CONF_FILE)
247
225
  end
248
226
 
249
- def pre_config_load()
227
+ def post_config_load()
250
228
  if config.system.devel
251
229
  plugin 'devel'
252
230
  end
@@ -258,14 +236,7 @@ module Termtter
258
236
  end
259
237
  Readline.completion_proc = lambda {|input|
260
238
  begin
261
- # FIXME: when migrate to Termtter::Command
262
- completions = @@completions.map {|completion|
263
- completion.call(input)
264
- }
265
- completions += @@new_commands.map {|name, command|
266
- command.complement(input)
267
- }
268
- completions.flatten.compact
239
+ @commands.map {|name, command| command.complement(input) }.flatten.compact
269
240
  rescue => e
270
241
  handle_error(e)
271
242
  end
@@ -276,19 +247,20 @@ module Termtter
276
247
  end
277
248
  end
278
249
 
250
+ # TODO: Make pluggable
279
251
  def setup_update_timeline_task()
280
252
  register_command(
281
253
  :name => :_update_timeline,
282
254
  :exec_proc => lambda {|arg|
283
255
  begin
284
- args = @@since_id ? [{:since_id => @@since_id}] : []
256
+ args = @since_id ? [{:since_id => @since_id}] : []
285
257
  statuses = Termtter::API.twitter.friends_timeline(*args)
286
258
  unless statuses.empty?
287
- @@since_id = statuses[0].id
259
+ print "\e[1K\e[0G" unless win?
260
+ @since_id = statuses[0].id
261
+ output(statuses, :update_friends_timeline)
262
+ Readline.refresh_line
288
263
  end
289
- call_hooks(statuses, :update_friends_timeline)
290
- Readline.refresh_line
291
- statuses
292
264
  rescue OpenURI::HTTPError => e
293
265
  if e.message == '401 Unauthorized'
294
266
  puts 'Could not login'
@@ -299,9 +271,11 @@ module Termtter
299
271
  }
300
272
  )
301
273
 
302
- add_task(:name => :update_timeline, :interval => config.update_interval) do
274
+ add_task(:name => :update_timeline, :interval => config.update_interval, :after => config.update_interval) do
303
275
  call_commands('_update_timeline')
304
276
  end
277
+
278
+ call_commands('_update_timeline')
305
279
  end
306
280
 
307
281
  def trap_setting()
@@ -321,9 +295,9 @@ module Termtter
321
295
  def start_input_thread
322
296
  setup_readline()
323
297
  trap_setting()
324
- @@input_thread = Thread.new do
298
+ @input_thread = Thread.new do
325
299
  while buf = Readline.readline(ERB.new(config.prompt).result(API.twitter.__send__(:binding)), true)
326
- Readline::HISTORY.pop if /^(u|update)\s+(.+)$/ =~ buf
300
+ Readline::HISTORY.pop if buf.empty?
327
301
  begin
328
302
  call_commands(buf)
329
303
  rescue CommandNotFound => e
@@ -334,29 +308,35 @@ module Termtter
334
308
  end
335
309
  end
336
310
  end
337
- @@input_thread.join
311
+ @input_thread.join
338
312
  end
339
313
 
340
- def run
341
- puts 'initializing...'
314
+ def logger
315
+ @logger
316
+ end
342
317
 
318
+ def setup_logger
319
+ @logger = config.log.logger || Logger.new(STDOUT)
320
+ @logger.level = config.log.level || Logger::WARN
321
+ end
322
+
323
+ def run
343
324
  load_default_plugins()
344
325
  load_config()
345
326
  Termtter::API.setup()
346
- pre_config_load()
327
+ setup_logger()
328
+ post_config_load()
347
329
 
348
- call_hooks([], :initialize)
349
- call_new_hooks(:initialize)
330
+ call_hooks(:initialize)
350
331
 
351
332
  setup_update_timeline_task()
352
- call_commands('_update_timeline')
353
333
 
354
- @@task_manager.run()
334
+ @task_manager.run()
355
335
  start_input_thread()
356
336
  end
357
337
 
358
338
  def handle_error(e)
359
- call_new_hooks("on_error", e)
339
+ call_hooks("on_error", e)
360
340
  rescue => e
361
341
  puts "Error: #{e}"
362
342
  puts e.backtrace.join("\n")