jugyo-termtter 1.1.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/ChangeLog +115 -0
  2. data/README.rdoc +25 -10
  3. data/Rakefile +53 -34
  4. data/lib/plugins/cool.rb +2 -5
  5. data/lib/plugins/curry.rb +43 -0
  6. data/lib/plugins/db.rb +91 -0
  7. data/lib/plugins/{auto_reload.rb → defaults/auto_reload.rb} +5 -1
  8. data/lib/plugins/defaults/command_line.rb +111 -0
  9. data/lib/plugins/{exec.rb → defaults/exec.rb} +2 -7
  10. data/lib/plugins/{fib.rb → defaults/fib.rb} +1 -4
  11. data/lib/plugins/defaults/retweet.rb +34 -0
  12. data/lib/plugins/{standard_commands.rb → defaults/standard_commands.rb} +88 -162
  13. data/lib/plugins/defaults/standard_completion.rb +67 -0
  14. data/lib/plugins/defaults/stdout.rb +148 -0
  15. data/lib/plugins/defaults.rb +14 -0
  16. data/lib/plugins/en2ja.rb +11 -5
  17. data/lib/plugins/english.rb +2 -2
  18. data/lib/plugins/expand-tinyurl.rb +27 -6
  19. data/lib/plugins/github-issues.rb +192 -0
  20. data/lib/plugins/group.rb +30 -4
  21. data/lib/plugins/growl.rb +10 -1
  22. data/lib/plugins/http_server/favicon.ico +0 -0
  23. data/lib/plugins/http_server/index.html +117 -0
  24. data/lib/plugins/http_server.rb +82 -0
  25. data/lib/plugins/irb.rb +6 -0
  26. data/lib/plugins/l2.rb +1 -1
  27. data/lib/plugins/list_with_opts.rb +0 -3
  28. data/lib/plugins/log.rb +6 -9
  29. data/lib/plugins/modify_arg_hook_sample.rb +3 -5
  30. data/lib/plugins/multi_reply.rb +0 -5
  31. data/lib/plugins/notify-send.rb +1 -1
  32. data/lib/plugins/notify-send2.rb +1 -1
  33. data/lib/plugins/notify-send3.rb +11 -3
  34. data/lib/plugins/open_url.rb +5 -17
  35. data/lib/plugins/otsune.rb +3 -9
  36. data/lib/plugins/outputz.rb +1 -1
  37. data/lib/plugins/pool.rb +30 -0
  38. data/lib/plugins/protected_filter.rb +9 -0
  39. data/lib/plugins/quicklook.rb +1 -1
  40. data/lib/plugins/saykanji.rb +81 -0
  41. data/lib/plugins/shell.rb +1 -6
  42. data/lib/plugins/sl.rb +8 -8
  43. data/lib/plugins/tinyurl.rb +26 -7
  44. data/lib/plugins/trends.rb +84 -0
  45. data/lib/plugins/twitpic.rb +46 -0
  46. data/lib/plugins/uri-open.rb +33 -28
  47. data/lib/plugins/wassr.rb +0 -3
  48. data/lib/plugins/whois.rb +45 -0
  49. data/lib/plugins/yhara.rb +2 -6
  50. data/lib/termtter/client.rb +91 -103
  51. data/lib/termtter/command.rb +24 -9
  52. data/lib/termtter/config.rb +8 -6
  53. data/lib/termtter/config_setup.rb +1 -1
  54. data/lib/termtter/config_template.erb +1 -4
  55. data/lib/termtter/hook.rb +2 -2
  56. data/lib/termtter/optparse.rb +14 -1
  57. data/lib/termtter/system_extensions.rb +3 -2
  58. data/lib/termtter/task_manager.rb +1 -5
  59. data/lib/termtter/version.rb +1 -1
  60. data/spec/plugins/cool_spec.rb +1 -1
  61. data/spec/plugins/curry_spec.rb +13 -0
  62. data/spec/plugins/db_spec.rb +62 -0
  63. data/spec/plugins/english_spec.rb +2 -2
  64. data/spec/plugins/fib_spec.rb +2 -2
  65. data/spec/plugins/filter_spec.rb +2 -2
  66. data/spec/plugins/pause_spec.rb +1 -1
  67. data/spec/plugins/primes_spec.rb +2 -2
  68. data/spec/plugins/shell_spec.rb +1 -1
  69. data/spec/plugins/sl_spec.rb +1 -1
  70. data/spec/plugins/{standard_plugins_spec.rb → standard_commands_spec.rb} +2 -2
  71. data/spec/plugins/whois_spec.rb +20 -0
  72. data/spec/termtter/client_spec.rb +151 -33
  73. data/spec/termtter/command_spec.rb +68 -35
  74. data/spec/termtter/config_spec.rb +10 -0
  75. data/spec/termtter/optparse_spec.rb +16 -0
  76. data/spec/termtter_spec.rb +7 -8
  77. metadata +48 -19
  78. data/History.txt +0 -4
  79. data/lib/plugins/direct_messages.rb +0 -36
  80. data/lib/plugins/retweet.rb +0 -46
  81. data/lib/plugins/stdout.rb +0 -77
@@ -7,43 +7,39 @@ config.plugins.standard.set_default(
7
7
  :limit_format,
8
8
  '<<%=remaining_color%>><%=limit.remaining_hits%></<%=remaining_color%>>/<%=limit.hourly_limit%> until <%=limit.reset_time%> (<%=remaining_time%> remaining)')
9
9
 
10
+ config.set_default(:easy_reply, true)
11
+
10
12
  module Termtter::Client
11
13
 
12
14
  register_command(
13
15
  :name => :reload,
14
- :exec_proc => lambda {|arg|
15
- begin
16
- args = @since_id ? [{:since_id => @since_id}] : []
17
- statuses = Termtter::API.twitter.friends_timeline(*args)
18
- unless statuses.empty?
19
- print "\e[1K\e[0G" unless win?
20
- @since_id = statuses[0].id
21
- output(statuses, :update_friends_timeline)
22
- Readline.refresh_line
23
- end
24
- rescue OpenURI::HTTPError => e
25
- if e.message == '401 Unauthorized'
26
- puts 'Could not login'
27
- puts 'plese check your account settings'
28
- exit!
29
- end
30
- rescue => e
31
- handle_error(e)
16
+ :exec => lambda {|arg|
17
+ args = @since_id ? [{:since_id => @since_id}] : []
18
+ statuses = Termtter::API.twitter.friends_timeline(*args)
19
+ unless statuses.empty?
20
+ print "\e[1K\e[0G" unless win?
21
+ @since_id = statuses[0].id
22
+ output(statuses, :update_friends_timeline)
23
+ Readline.refresh_line
32
24
  end
33
25
  }
34
26
  )
35
27
 
36
28
  register_command(
37
- :name => :update, :aliases => [:u],
38
- :exec_proc => lambda {|arg|
29
+ :name => :update, :alias => :u,
30
+ :exec => lambda {|arg|
39
31
  unless arg.empty?
40
- result = Termtter::API.twitter.update(arg)
41
- puts TermColor.parse("updated => #{result.text} <90>#{result.id}</90>")
42
- end
43
- },
44
- :completion_proc => lambda {|cmd, args|
45
- if /(.*)@([^\s]*)$/ =~ args
46
- find_user_candidates $2, "#{cmd} #{$1}@%s"
32
+ params =
33
+ if config.easy_reply && /^\s*(@\w+)/ =~ arg
34
+ user_name = normalize_as_user_name($1)
35
+ in_reply_to_status_id = Termtter::API.twitter.user(user_name).status.id rescue nil
36
+ in_reply_to_status_id ? {:in_reply_to_status_id => in_reply_to_status_id} : {}
37
+ else
38
+ {}
39
+ end
40
+
41
+ result = Termtter::API.twitter.update(arg, params)
42
+ puts "updated => #{result.text}"
47
43
  end
48
44
  },
49
45
  :help => ["update,u TEXT", "Post a new message"]
@@ -61,7 +57,7 @@ module Termtter::Client
61
57
  end
62
58
  if id
63
59
  result = Termtter::API.twitter.remove_status(id)
64
- puts TermColor.parse("deleted => #{result.text} <90>#{result.id}</90>")
60
+ puts "deleted => #{result.text}"
65
61
  end
66
62
  },
67
63
  :help => ['delete,del [STATUS ID]', 'Delete a status']
@@ -77,8 +73,8 @@ module Termtter::Client
77
73
  :name => :direct, :aliases => [:d],
78
74
  :exec_proc => lambda {|arg|
79
75
  case arg
80
- when /^([^\s]+)\s+(.*)\s*$/
81
- user, text = $1, $2
76
+ when /^([^\s]+)\s+?(.*)\s*$/
77
+ user, text = normalize_as_user_name($1), $2
82
78
  Termtter::API.twitter.direct_message(user, text)
83
79
  puts "=> to:#{user} message:#{text}"
84
80
  when 'list'
@@ -97,10 +93,6 @@ module Termtter::Client
97
93
  )
98
94
  end
99
95
  },
100
- :completion_proc => lambda {|cmd, arg|
101
- find_user_candidates(arg, "#{cmd} %s") +
102
- ["list", "sent_list"].grep(/^#{Regexp.quote(arg)}/).map { |i| "#{cmd} #{i}" }
103
- },
104
96
  :help => [
105
97
  ["direct,d USERNAME TEXT", "Send direct message"],
106
98
  ["direct,d list", 'List direct messages'],
@@ -111,7 +103,7 @@ module Termtter::Client
111
103
  register_command(
112
104
  :name => :profile, :aliases => [:p],
113
105
  :exec_proc => lambda {|arg|
114
- user = Termtter::API.twitter.user(arg.strip)
106
+ user = Termtter::API.twitter.user(normalize_as_user_name(arg))
115
107
  attrs = %w[ name screen_name url description profile_image_url location protected following
116
108
  friends_count followers_count statuses_count favourites_count
117
109
  id time_zone created_at utc_offset notifications
@@ -122,16 +114,13 @@ module Termtter::Client
122
114
  puts "#{attr.gsub('_', ' ').rjust(label_width)}: #{value}"
123
115
  end
124
116
  },
125
- :completion_proc => lambda {|cmd, arg|
126
- find_user_candidates arg, "#{cmd} %s"
127
- },
128
117
  :help => ["profile,p USERNAME", "Show user's profile"]
129
118
  )
130
119
 
131
120
  register_command(
132
121
  :name => :followers,
133
122
  :exec_proc => lambda {|arg|
134
- user_name = arg.strip
123
+ user_name = normalize_as_user_name(arg)
135
124
  user_name = config.user_name if user_name.empty?
136
125
 
137
126
  followers = []
@@ -143,9 +132,6 @@ module Termtter::Client
143
132
  public_storage[:users] += followers.map(&:screen_name)
144
133
  puts followers.map(&:screen_name).join(' ')
145
134
  },
146
- :completion_proc => lambda {|cmd, arg|
147
- find_user_candidates arg, "#{cmd} %s"
148
- },
149
135
  :help => ["followers", "Show followers"]
150
136
  )
151
137
 
@@ -157,13 +143,11 @@ module Termtter::Client
157
143
  statuses = Termtter::API.twitter.friends_timeline
158
144
  else
159
145
  event = :list_user_timeline
160
- statuses = Termtter::API.twitter.user_timeline(arg)
146
+ user_name = normalize_as_user_name(arg)
147
+ statuses = Termtter::API.twitter.user_timeline(user_name)
161
148
  end
162
149
  output(statuses, event)
163
150
  },
164
- :completion_proc => lambda {|cmd, arg|
165
- find_user_candidates arg, "#{cmd} %s"
166
- },
167
151
  :help => ["list,l [USERNAME]", "List the posts"]
168
152
  )
169
153
 
@@ -176,7 +160,7 @@ module Termtter::Client
176
160
  output(statuses, :search)
177
161
  },
178
162
  :completion_proc => lambda {|cmd, arg|
179
- public_storage[:search_keywords].grep(/#{Regexp.quote(arg)}/).map { |i| "#{cmd} #{i}" }
163
+ public_storage[:search_keywords].grep(/^#{Regexp.quote(arg)}/).map { |i| "#{cmd} #{i}" }
180
164
  },
181
165
  :help => ["search,s TEXT", "Search for Twitter"]
182
166
  )
@@ -184,9 +168,13 @@ module Termtter::Client
184
168
  register_command(
185
169
  :name => :replies, :aliases => [:r],
186
170
  :exec_proc => lambda {|arg|
187
- output(Termtter::API.twitter.replies, :replies)
171
+ res = Termtter::API.twitter.replies
172
+ unless arg.empty?
173
+ res = res.map {|e| e.user.screen_name == arg ? e : nil }.compact
174
+ end
175
+ output(res, :replies)
188
176
  },
189
- :help => ["replies,r", "List the most recent @replies for the authenticating user"]
177
+ :help => ["replies,r", "List the replies"]
190
178
  )
191
179
 
192
180
  register_command(
@@ -226,14 +214,10 @@ module Termtter::Client
226
214
  :name => :follow, :aliases => [],
227
215
  :exec_proc => lambda {|args|
228
216
  args.split(' ').each do |arg|
229
- if /^(\w+)/ =~ arg
230
- res = Termtter::API::twitter.follow($1.strip)
231
- end
217
+ user_name = normalize_as_user_name(arg)
218
+ res = Termtter::API::twitter.follow(user_name)
232
219
  end
233
220
  },
234
- :completion_proc => lambda {|cmd, args|
235
- find_user_candidates args, "#{cmd} %s"
236
- },
237
221
  :help => ['follow USER', 'Follow user']
238
222
  )
239
223
 
@@ -241,14 +225,10 @@ module Termtter::Client
241
225
  :name => :leave, :aliases => [],
242
226
  :exec_proc => lambda {|args|
243
227
  args.split(' ').each do |arg|
244
- if /^(\w+)/ =~ arg
245
- res = Termtter::API::twitter.leave($1.strip)
246
- end
228
+ user_name = normalize_as_user_name(arg)
229
+ res = Termtter::API::twitter.leave(user_name)
247
230
  end
248
231
  },
249
- :completion_proc => lambda {|cmd, args|
250
- find_user_candidates args, "#{cmd} %s"
251
- },
252
232
  :help => ['leave USER', 'Leave user']
253
233
  )
254
234
 
@@ -260,15 +240,19 @@ module Termtter::Client
260
240
  when /^\d+/
261
241
  id = arg.to_i
262
242
  when /^@([A-Za-z0-9_]+)/
263
- user = $1
264
- statuses = Termtter::API.twitter.user_timeline(user)
243
+ user_name = normalize_as_user_name($1)
244
+ statuses = Termtter::API.twitter.user_timeline(user_name)
265
245
  return if statuses.empty?
266
246
  id = statuses[0].id
267
247
  when /^\/(.*)$/
268
248
  word = $1
269
249
  raise "Not implemented yet."
270
250
  else
271
- return
251
+ if public_storage[:typable_id] && typable_id?(arg)
252
+ id = typable_id_convert(arg)
253
+ else
254
+ return
255
+ end
272
256
  end
273
257
 
274
258
  r = Termtter::API.twitter.favorite id
@@ -276,15 +260,17 @@ module Termtter::Client
276
260
  },
277
261
  :completion_proc => lambda {|cmd, arg|
278
262
  case arg
279
- when /@(.*)/
280
- find_user_candidates $1, "#{cmd} @%s"
281
263
  when /(\d+)/
282
264
  find_status_ids(arg).map{|id| "#{cmd} #{id}"}
283
265
  else
284
- %w(favorite).grep(/^#{Regexp.quote arg}/)
266
+ if data = Termtter::Client.typable_id_to_data(arg)
267
+ "#{cmd} #{data}"
268
+ else
269
+ %w(favorite).grep(/^#{Regexp.quote arg}/)
270
+ end
285
271
  end
286
272
  },
287
- :help => ['favorite,fav (ID|@USER|/WORD)', 'Mark a status as a favorite']
273
+ :help => ['favorite,fav (ID|@USER|TYPABLE|/WORD)', 'Mark a status as a favorite']
288
274
  )
289
275
 
290
276
  def self.show_settings(conf, level = 0)
@@ -339,7 +325,7 @@ module Termtter::Client
339
325
  )
340
326
 
341
327
  register_command(
342
- :name => :exit, :aliases => [:e],
328
+ :name => :exit, :aliases => [:quit],
343
329
  :exec_proc => lambda {|arg| exit},
344
330
  :help => ['exit,e', 'Exit']
345
331
  )
@@ -358,6 +344,9 @@ module Termtter::Client
358
344
  end
359
345
  end
360
346
  helps.compact!
347
+ unless arg.empty?
348
+ helps = helps.select {|n, _| /#{arg}/ =~ n }
349
+ end
361
350
  puts formatted_help(helps)
362
351
  },
363
352
  :help => ["help,h", "Print this help message"]
@@ -372,28 +361,6 @@ module Termtter::Client
372
361
  }.join("\n")
373
362
  end
374
363
 
375
- # completion for standard commands
376
-
377
- public_storage[:users] ||= Set.new
378
- public_storage[:status_ids] ||= Set.new
379
-
380
- register_hook(
381
- :name => :for_completion,
382
- :points => [:pre_filter],
383
- :exec_proc => lambda {|statuses, event|
384
- statuses.each do |s|
385
- public_storage[:users].add(s.user.screen_name)
386
- public_storage[:users] += s.text.scan(/@([a-zA-Z_0-9]*)/).flatten
387
- public_storage[:status_ids].add(s.id)
388
- public_storage[:status_ids].add(s.in_reply_to_status_id) if s.in_reply_to_status_id
389
- end
390
- }
391
- )
392
-
393
- public_storage[:plugins] = (Dir["#{File.dirname(__FILE__)}/*.rb"] + Dir["#{Termtter::CONF_DIR}/plugins/*.rb"]).map do |f|
394
- f.match(%r|([^/]+).rb$|)[1]
395
- end
396
-
397
364
  register_command(
398
365
  :name => :plug,
399
366
  :alias => :plugin,
@@ -410,22 +377,29 @@ module Termtter::Client
410
377
  end
411
378
  },
412
379
  :completion_proc => lambda {|cmd, args|
413
- find_user_candidates args, "#{cmd} %s"
414
- unless args.empty?
415
- find_plugin_candidates args, "#{cmd} %s"
416
- else
417
- public_storage[:plugins].sort
418
- end
380
+ plugin_list.grep(/^#{Regexp.quote(args)}/).map{|i| "#{cmd} #{i}"}
419
381
  },
420
- :help => ['plugin FILE', 'Load a plugin']
382
+ :help => ['plug FILE', 'Load a plugin']
421
383
  )
422
384
 
385
+ def self.plugin_list
386
+ (Dir["#{File.dirname(__FILE__)}/../*.rb"] + Dir["#{Termtter::CONF_DIR}/plugins/*.rb"]).
387
+ map{|f| File.basename(f).sub(/\.rb$/, '')}.
388
+ sort
389
+ end
390
+
423
391
  register_command(
424
- :name => :plugins,
392
+ :name => :plugins,
425
393
  :exec_proc => lambda {|arg|
426
- puts public_storage[:plugins].sort.join("\n")
427
- },
428
- :help => ['plugins', 'Show list of plugins']
394
+ list = plugin_list
395
+ width = list.map{|i|i.size}.max + 2
396
+ a = []
397
+ list.sort.each_slice(4) {|i|
398
+ a << i.map{|j| j + (" " * (width - j.size))}.join
399
+ }
400
+ puts TermColor.parse('<green>' + TermColor.escape(a.join("\n")) + '</green>')
401
+ },
402
+ :help => ['plugins', 'Show list of plugins']
429
403
  )
430
404
 
431
405
  register_command(
@@ -453,19 +427,20 @@ module Termtter::Client
453
427
  when /^\s*(\d+)\s+(.+)$/
454
428
  s = Termtter::API.twitter.show($1) rescue nil
455
429
  if s
456
- update_with_user_and_id($2, s.user.screen_name, id)
430
+ update_with_user_and_id($2, s.user.screen_name, s.id)
431
+ end
432
+ when /^\s*(@\w+)/
433
+ user_name = normalize_as_user_name($1)
434
+ s = Termtter::API.twitter.user(user_name).status
435
+ if s
436
+ params = s ? {:in_reply_to_status_id => s.id} : {}
437
+ Termtter::API.twitter.update(arg, params)
438
+ puts "=> #{arg}"
457
439
  end
458
- when /^\s*@(\w+)/
459
- in_reply_to_status_id = Termtter::API.twitter.user($1).status.id rescue nil
460
- params = in_reply_to_status_id ? {:in_reply_to_status_id => in_reply_to_status_id} : {}
461
- Termtter::API.twitter.update(arg, params)
462
- puts "=> #{arg}"
463
440
  end
464
441
  },
465
442
  :completion_proc => lambda {|cmd, arg|
466
443
  case arg
467
- when /(.*)@([^\s]*)$/
468
- find_user_candidates $2, "#{cmd} #{$1}@%s"
469
444
  when /(\d+)/
470
445
  find_status_ids(arg).map{|id| "#{cmd} #{id}"}
471
446
  end
@@ -500,50 +475,11 @@ module Termtter::Client
500
475
  def self.update_with_user_and_id(text, username, id)
501
476
  text = "@#{username} #{text}"
502
477
  result = Termtter::API.twitter.update(text, {'in_reply_to_status_id' => id})
503
- puts TermColor.parse("replied => #{result.text} <90>#{result.id}</90>")
478
+ puts "replied => #{result.text}"
504
479
  end
505
480
 
506
- =begin
507
- = Termtter reply command
508
- == Usage
509
- === list
510
- * ステータスリストを連番と一緒に出す。
511
- > reply [list|ls]
512
- 0: foo: foo's message
513
- 1: bar: bar's message
514
- ..
515
-
516
- * ユーザ指定してリスト作成。
517
- > reply [list|ls] foo
518
- 0: foo: foo's message0
519
- 1: foo: foo's message1
520
-
521
- === reply
522
- メッセージ送信の際、@usernameが自動的に付与される。
523
-
524
- * status_idを自分で入力してreply送信
525
- > reply 1234567890 message to status_id
526
- => @foo message to status_id (reply to 1234567890)
527
-
528
- * reply listコマンドで出したステータス番号に対してreply送信
529
- > reply up 0 message to status no
530
- => @foo message to status_no
531
-
532
- * 対象ユーザの最後の発言に対してreply
533
- > reply @foo message to foo
534
- => @foo message to foo
535
-
536
- == Todo
537
- * 英語で説明 => ヘルプを設定する
538
- * リファクタ
539
- * 補完
540
- * 確認画面を出したい
541
- =end
542
-
543
- def self.find_plugin_candidates(a, b)
544
- public_storage[:plugins].
545
- grep(/^#{Regexp.quote a}/i).
546
- map {|u| b % u }
481
+ def self.normalize_as_user_name(text)
482
+ text.strip.sub(/^@/, '')
547
483
  end
548
484
 
549
485
  def self.find_status_ids(text)
@@ -553,14 +489,4 @@ module Termtter::Client
553
489
  def self.find_users(text)
554
490
  public_storage[:users].select {|user| /^#{Regexp.quote(text)}/ =~ user}
555
491
  end
556
-
557
- def self.find_user_candidates(a, b)
558
- users =
559
- if a.nil? || a.empty?
560
- public_storage[:users].to_a
561
- else
562
- public_storage[:users].grep(/^#{Regexp.quote a}/i)
563
- end
564
- users.map {|u| b % u }
565
- end
566
492
  end
@@ -0,0 +1,67 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'set'
4
+
5
+ module Termtter::Client
6
+
7
+ #
8
+ # completion for status ids
9
+ # (I want to delete)
10
+ #
11
+
12
+ public_storage[:status_ids] ||= Set.new
13
+
14
+ register_hook(:collect_status_ids, :point => :pre_filter) do |statuses, event|
15
+ statuses.each do |s|
16
+ public_storage[:status_ids].add(s.id)
17
+ public_storage[:status_ids].add(s.in_reply_to_status_id) if s.in_reply_to_status_id
18
+ end
19
+ end
20
+
21
+ #
22
+ # completion for user names
23
+ #
24
+
25
+ public_storage[:users] ||= Set.new
26
+
27
+ register_hook(:collect_user_names, :point => :pre_filter) do |statuses, event|
28
+ statuses.each do |s|
29
+ public_storage[:users].add(s.user.screen_name)
30
+ public_storage[:users] += s.text.scan(/@([a-zA-Z_0-9]*)/).flatten
31
+ end
32
+ end
33
+
34
+ register_hook(:user_names_completion, :point => :completion) do |input|
35
+ if /(.*)@([^\s]*)$/ =~ input
36
+ command_str = $1
37
+ part_of_user_name = $2
38
+
39
+ users =
40
+ if part_of_user_name.nil? || part_of_user_name.empty?
41
+ public_storage[:users].to_a
42
+ else
43
+ public_storage[:users].grep(/^#{Regexp.quote(part_of_user_name)}/)
44
+ end
45
+
46
+ users.map {|u| "#{command_str}@%s" % u }
47
+ end
48
+ end
49
+
50
+ #
51
+ # completion for hashtags
52
+ #
53
+
54
+ public_storage[:hashtag] ||= Set.new
55
+
56
+ register_hook(:collect_hashtags, :point => /^post_exec_/) do |cmd, arg, result|
57
+ public_storage[:hashtag] += arg.scan(/\s+#([^\s]+)/).flatten if arg
58
+ end
59
+
60
+ register_hook(:hashtags_completion, :point => :completion) do |input|
61
+ if /(.*)#([^\s]*)$/ =~ input
62
+ command_str = $1
63
+ part_of_hashtag = $2
64
+ public_storage[:hashtag].grep(/^#{Regexp.quote(part_of_hashtag)}/i).map { |i| "#{command_str}##{i}" }
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,148 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'termcolor'
4
+ require 'erb'
5
+ require 'tempfile'
6
+
7
+ config.plugins.stdout.set_default(:colors, (31..36).to_a + (91..96).to_a)
8
+ config.plugins.stdout.set_default(
9
+ :timeline_format,
10
+ '<90><%=time%> [<%=status_id%>]</90> <<%=color%>><%=s.user.screen_name%>: <%=text%></<%=color%>> ' +
11
+ '<90><%=reply_to_status_id ? " (reply_to [#{reply_to_status_id}]) " : ""%><%=source%></90>'
12
+ )
13
+ config.plugins.stdout.set_default(:enable_pager, true)
14
+ config.plugins.stdout.set_default(:pager, 'less -R -f +G')
15
+ config.plugins.stdout.set_default(:window_height, 50)
16
+ config.plugins.stdout.set_default(:typable_ids, ('aa'..'zz').to_a)
17
+ config.plugins.stdout.set_default(:typable_id_prefix, '$')
18
+ config.plugins.stdout.set_default(:show_as_thread, false)
19
+
20
+ module Termtter
21
+ class TypableIdGenerator
22
+ def initialize(ids)
23
+ if not ids.kind_of?(Array)
24
+ raise ArgumentError, 'ids should be an Array'
25
+ elsif ids.empty?
26
+ raise ArgumentError, 'ids should not be empty'
27
+ end
28
+ @ids = ids
29
+ @table = {}
30
+ end
31
+
32
+ def next(data)
33
+ id = @ids.shift
34
+ @ids.push id
35
+ @table[id] = data
36
+ id
37
+ end
38
+
39
+ def get(id)
40
+ @table[id]
41
+ end
42
+ end
43
+
44
+ module Client
45
+ @typable_id_generator = TypableIdGenerator.new(config.plugins.stdout.typable_ids)
46
+
47
+ def self.data_to_typable_id(data)
48
+ id = config.plugins.stdout.typable_id_prefix + @typable_id_generator.next(data)
49
+ end
50
+
51
+ def self.typable_id_to_data(id)
52
+ @typable_id_generator.get(id)
53
+ end
54
+ end
55
+
56
+ class StdOut < Hook
57
+ def initialize
58
+ super(:name => :stdout, :points => [:output])
59
+ end
60
+
61
+ def call(statuses, event)
62
+ print_statuses(statuses)
63
+ end
64
+
65
+ def print_statuses(statuses, sort = true, time_format = nil)
66
+ return unless statuses and statuses.first
67
+ unless time_format
68
+ t0 = Time.now
69
+ t1 = Time.parse(statuses.first[:created_at])
70
+ t2 = Time.parse(statuses.last[:created_at])
71
+ time_format =
72
+ if [t0.year, t0.month, t0.day] == [t1.year, t1.month, t1.day] \
73
+ and [t1.year, t1.month, t1.day] == [t2.year, t2.month, t2.day]
74
+ '%H:%M:%S'
75
+ else
76
+ '%y/%m/%d %H:%M'
77
+ end
78
+ end
79
+
80
+ output_text = ''
81
+ statuses.each do |s|
82
+ output_text << status_line(s, time_format)
83
+ end
84
+
85
+ if config.plugins.stdout.enable_pager && ENV['LINES'] && statuses.size > ENV['LINES'].to_i
86
+ file = Tempfile.new('termtter')
87
+ file.print output_text
88
+ file.close
89
+ system "#{config.plugins.stdout.pager} #{file.path}"
90
+ file.close(true)
91
+ else
92
+ print output_text
93
+ end
94
+ end
95
+
96
+ def status_line(s, time_format, indent = 0)
97
+ return '' unless s
98
+ text = TermColor.escape(s.text)
99
+ color = config.plugins.stdout.colors[s.user.id.to_i % config.plugins.stdout.colors.size]
100
+ status_id = Termtter::Client.data_to_typable_id(s.id)
101
+ reply_to_status_id =
102
+ if s.in_reply_to_status_id.nil?
103
+ nil
104
+ else
105
+ Termtter::Client.data_to_typable_id(s.in_reply_to_status_id)
106
+ end
107
+
108
+ time = "(#{Time.parse(s.created_at).strftime(time_format)})"
109
+ source =
110
+ case s.source
111
+ when />(.*?)</ then $1
112
+ when 'web' then 'web'
113
+ end
114
+
115
+ erbed_text = ERB.new(config.plugins.stdout.timeline_format).result(binding)
116
+ indent_text = indent > 0 ? "#{' ' * (indent - 1)} ┗ " : ''
117
+ text = TermColor.parse(indent_text + erbed_text) + "\n"
118
+ if config.plugins.stdout.show_as_thread && s.in_reply_to_status_id
119
+ text << status_line(Status[s.in_reply_to_status_id], time_format, indent + 1)
120
+ end
121
+ text
122
+ end
123
+ end
124
+
125
+ Client.register_hook(StdOut.new)
126
+
127
+ Client.register_hook(
128
+ :name => :stdout_typable_id,
129
+ :point => /^modify_arg_for_.*/,
130
+ :exec => lambda { |cmd, arg|
131
+ if arg
132
+ prefix = config.plugins.stdout.typable_id_prefix
133
+ arg.gsub(/#{Regexp.quote(prefix)}\w+/) do |id|
134
+ Termtter::Client.typable_id_to_data(id[1..-1]) || id
135
+ end
136
+ else
137
+ arg
138
+ end
139
+ }
140
+ )
141
+ end
142
+
143
+ # stdout.rb
144
+ # output statuses to stdout
145
+ # example config
146
+ # config.plugins.stdout.colors = [:none, :red, :green, :yellow, :blue, :magenta, :cyan]
147
+ # config.plugins.stdout.timeline_format = '<90><%=time%> [<%=status_id%>]</90> <<%=color%>><%=s.user.screen_name%>: <%=text%></<%=color%>> ' +
148
+ # '<90><%=reply_to_status_id ? " (reply_to [#{reply_to_status_id}]) " : ""%><%=source%></90>'
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter::Client
4
+ config.set_default(:stdout, true)
5
+ config.set_default(:standard_commands, true)
6
+ config.set_default(:standard_completion, true)
7
+ config.set_default(:auto_reload, true)
8
+
9
+ defaults = Dir[File.dirname(__FILE__) + '/defaults/*.rb'].map { |f|
10
+ f.match(%r|defaults/(.*?).rb$|)[1]
11
+ }.each { |plugin|
12
+ plug "defaults/#{plugin}" if config.__refer__(plugin.to_sym)
13
+ }
14
+ end
data/lib/plugins/en2ja.rb CHANGED
@@ -1,11 +1,17 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- plugin 'translation'
3
+ module Termtter::Client
4
+ plug 'translation'
4
5
 
5
- Termtter::Client.add_filter do |statuses, event|
6
- statuses.each do |s|
7
- if s.english?
8
- s.text = translate(s.text, 'en|ja')
6
+ register_hook(:en2ja, :point => :filter_for_output) do |statuses, event|
7
+ statuses.each do |s|
8
+ if english?(s.text)
9
+ s.text = translate(s.text, 'en|ja')
10
+ end
9
11
  end
10
12
  end
13
+
14
+ def self.english?(text)
15
+ /[一-龠]+|[ぁ-ん]+|[ァ-ヴー]+|[a-zA-Z0-9]+/ !~ text
16
+ end
11
17
  end