jugyo-termtter 1.1.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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