termtter 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/History.txt +4 -0
  2. data/README.rdoc +97 -0
  3. data/Rakefile +46 -0
  4. data/bin/kill_termtter +22 -0
  5. data/bin/termtter +7 -0
  6. data/lib/filter/en2ja.rb +11 -0
  7. data/lib/filter/english.rb +8 -0
  8. data/lib/filter/expand-tinyurl.rb +24 -0
  9. data/lib/filter/fib.rb +15 -0
  10. data/lib/filter/ignore.rb +19 -0
  11. data/lib/filter/reply.rb +8 -0
  12. data/lib/filter/reverse.rb +13 -0
  13. data/lib/filter/url_addspace.rb +16 -0
  14. data/lib/filter/yhara.rb +20 -0
  15. data/lib/plugin/april_fool.rb +15 -0
  16. data/lib/plugin/bomb.rb +29 -0
  17. data/lib/plugin/clear.rb +14 -0
  18. data/lib/plugin/confirm.rb +9 -0
  19. data/lib/plugin/cool.rb +10 -0
  20. data/lib/plugin/devel.rb +13 -0
  21. data/lib/plugin/english.rb +59 -0
  22. data/lib/plugin/erb.rb +17 -0
  23. data/lib/plugin/favorite.rb +75 -0
  24. data/lib/plugin/fib.rb +8 -0
  25. data/lib/plugin/filter.rb +69 -0
  26. data/lib/plugin/follow.rb +56 -0
  27. data/lib/plugin/graduatter.rb +9 -0
  28. data/lib/plugin/grass.rb +27 -0
  29. data/lib/plugin/group.rb +60 -0
  30. data/lib/plugin/growl.rb +62 -0
  31. data/lib/plugin/hatebu.rb +59 -0
  32. data/lib/plugin/history.rb +82 -0
  33. data/lib/plugin/keyword.rb +18 -0
  34. data/lib/plugin/log.rb +63 -0
  35. data/lib/plugin/modify_arg_hook_sample.rb +7 -0
  36. data/lib/plugin/msagent.rb +26 -0
  37. data/lib/plugin/multi_reply.rb +36 -0
  38. data/lib/plugin/notify-send.rb +17 -0
  39. data/lib/plugin/otsune.rb +21 -0
  40. data/lib/plugin/outputz.rb +35 -0
  41. data/lib/plugin/pause.rb +3 -0
  42. data/lib/plugin/plugin.rb +53 -0
  43. data/lib/plugin/post_exec_hook_sample.rb +9 -0
  44. data/lib/plugin/pre_exec_hook_sample.rb +9 -0
  45. data/lib/plugin/primes.rb +23 -0
  46. data/lib/plugin/quicklook.rb +38 -0
  47. data/lib/plugin/reblog.rb +40 -0
  48. data/lib/plugin/reload.rb +3 -0
  49. data/lib/plugin/say.rb +24 -0
  50. data/lib/plugin/scrape.rb +41 -0
  51. data/lib/plugin/screen.rb +24 -0
  52. data/lib/plugin/shell.rb +14 -0
  53. data/lib/plugin/sl.rb +48 -0
  54. data/lib/plugin/spam.rb +9 -0
  55. data/lib/plugin/standard_plugins.rb +269 -0
  56. data/lib/plugin/stdout.rb +62 -0
  57. data/lib/plugin/system_status.rb +33 -0
  58. data/lib/plugin/translation.rb +28 -0
  59. data/lib/plugin/update_editor.rb +53 -0
  60. data/lib/plugin/uri-open.rb +69 -0
  61. data/lib/plugin/wassr_post.rb +22 -0
  62. data/lib/plugin/yhara.rb +148 -0
  63. data/lib/plugin/yonda.rb +20 -0
  64. data/lib/termtter/api.rb +14 -0
  65. data/lib/termtter/client.rb +399 -0
  66. data/lib/termtter/command.rb +77 -0
  67. data/lib/termtter/connection.rb +39 -0
  68. data/lib/termtter/hook.rb +18 -0
  69. data/lib/termtter/status.rb +26 -0
  70. data/lib/termtter/task.rb +16 -0
  71. data/lib/termtter/task_manager.rb +116 -0
  72. data/lib/termtter/twitter.rb +173 -0
  73. data/lib/termtter/user.rb +13 -0
  74. data/lib/termtter/version.rb +3 -0
  75. data/lib/termtter.rb +157 -0
  76. data/spec/plugin/cool_spec.rb +10 -0
  77. data/spec/plugin/fib_spec.rb +16 -0
  78. data/spec/plugin/filter_spec.rb +18 -0
  79. data/spec/plugin/plugin_spec.rb +25 -0
  80. data/spec/plugin/shell_spec.rb +10 -0
  81. data/spec/plugin/spam_spec.rb +17 -0
  82. data/spec/plugin/standard_plugins_spec.rb +31 -0
  83. data/spec/spec_helper.rb +4 -0
  84. data/spec/termtter/client_spec.rb +175 -0
  85. data/spec/termtter/command_spec.rb +161 -0
  86. data/spec/termtter/task_manager_spec.rb +78 -0
  87. data/spec/termtter/task_spec.rb +22 -0
  88. data/spec/termtter/user_spec.rb +27 -0
  89. data/spec/termtter_spec.rb +43 -0
  90. data/test/friends_timeline.json +5 -0
  91. data/test/search.json +8 -0
  92. data/test/test_termtter.rb +86 -0
  93. metadata +177 -0
@@ -0,0 +1,173 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'highline'
4
+ require 'time'
5
+
6
+ module Termtter
7
+ class Twitter
8
+
9
+ def initialize(user_name, password, connection, host = "twitter.com")
10
+ @user_name = user_name
11
+ @password = password
12
+ @connection = connection
13
+ @host = host
14
+ end
15
+
16
+ def update_status(status)
17
+ @connection.start(@host, @connection.port) do |http|
18
+ uri = '/statuses/update.xml'
19
+ http.request(post_request(uri), "status=#{CGI.escape(status)}&source=#{APP_NAME}")
20
+ end
21
+ status
22
+ end
23
+
24
+ def direct_message(user, status)
25
+ @connection.start(@host, @connection.port) do |http|
26
+ uri = '/direct_messages/new.xml'
27
+ http.request(post_request(uri), "user=#{CGI.escape(user)}&text=#{CGI.escape(status)}&source=#{APP_NAME}")
28
+ end
29
+ [user, status]
30
+ end
31
+
32
+ def get_user_profile(screen_name)
33
+ result = fetch_as_json(url_for("/users/show/#{screen_name}.json"))
34
+ return hash_to_user(result)
35
+ end
36
+
37
+ def get_friends_timeline(since_id = nil)
38
+ uri = url_for("/statuses/friends_timeline.json")
39
+ uri << "?since_id=#{since_id}" if since_id
40
+ return get_timeline(uri)
41
+ end
42
+
43
+ def get_user_timeline(screen_name)
44
+ return get_timeline(url_for("/statuses/user_timeline/#{screen_name}.json"))
45
+ rescue OpenURI::HTTPError => e
46
+ puts "No such user: #{screen_name}"
47
+ nears = near_users(screen_name)
48
+ puts "near users: #{nears}" unless nears.empty?
49
+ return []
50
+ end
51
+
52
+ def search(query)
53
+ results = fetch_as_json(search_url_for("/search.json?q=#{CGI.escape(query)}"))['results']
54
+ return results.map do |s|
55
+ status = Status.new
56
+ status.id = s['id']
57
+ status.text = CGI.unescapeHTML(s['text']).gsub(/(\n|\r)/, '').gsub(/#{Regexp.escape(query)}/i, color(color('\0', 41), 37))
58
+ status.created_at = Time.parse(s["created_at"])
59
+ status.user_screen_name = s['from_user']
60
+ status
61
+ end
62
+ end
63
+
64
+ def show(id, rth = false)
65
+ get_status = lambda { get_timeline(url_for("/statuses/show/#{id}.json"))[0] }
66
+ statuses = []
67
+ statuses << status = Array(Client.public_storage[:log]).detect(get_status) {|s| s.id == id.to_i }
68
+ statuses << show(id, true) if rth && id = status.in_reply_to_status_id
69
+ statuses.flatten
70
+ end
71
+
72
+ def replies
73
+ return get_timeline(url_for("/statuses/replies.json"))
74
+ end
75
+
76
+ def followers
77
+ users = []
78
+ page = 0
79
+ begin
80
+ users += tmp = fetch_as_json(url_for("/statuses/followers.json?page=#{page+=1}"))
81
+ end until tmp.empty?
82
+ return users.map{|u| hash_to_user(u)}
83
+ end
84
+
85
+ def get_timeline(uri)
86
+ data = fetch_as_json(uri)
87
+ data = [data] unless data.instance_of? Array
88
+ return data.map do |s|
89
+ status = Status.new
90
+ status.created_at = Time.parse(s["created_at"])
91
+ %w(id text truncated in_reply_to_status_id in_reply_to_user_id in_reply_to_screen_name).each do |key|
92
+ status.__send__("#{key}=".to_sym, s[key])
93
+ end
94
+ %w(id name screen_name url profile_image_url).each do |key|
95
+ status.__send__("user_#{key}=".to_sym, s["user"][key])
96
+ end
97
+ status.text = CGI.unescapeHTML(status.text).gsub(/(\n|\r)/, '')
98
+ status
99
+ end
100
+ end
101
+
102
+ # note: APILimit.reset_time_in_seconds == APILimit.reset_time.to_i
103
+ APILIMIT = Struct.new("APILimit", :reset_time, :reset_time_in_seconds, :remaining_hits, :hourly_limit)
104
+ def get_rate_limit_status
105
+ data = fetch_as_json(url_for("/account/rate_limit_status.json"))
106
+ reset_time = Time.parse(data['reset_time'])
107
+ reset_time_in_seconds = data['reset_time_in_seconds'].to_i
108
+
109
+ APILIMIT.new(reset_time, reset_time_in_seconds, data['remaining_hits'], data['hourly_limit'])
110
+ end
111
+
112
+ alias :api_limit :get_rate_limit_status
113
+
114
+ private
115
+
116
+ def hash_to_user(hash)
117
+ user = User.new
118
+ %w[ name favourites_count url id description protected utc_offset time_zone
119
+ screen_name notifications statuses_count followers_count friends_count
120
+ profile_image_url location following created_at
121
+ ].each do |attr|
122
+ user.__send__("#{attr}=".to_sym, hash[attr])
123
+ end
124
+ return user
125
+ end
126
+
127
+ def fetch_as_json(uri)
128
+ JSON.parse(open_uri(uri).read)
129
+ end
130
+
131
+ def open_uri(uri)
132
+ return open(uri, :http_basic_authentication => [user_name, password], :proxy => @connection.proxy_uri)
133
+ end
134
+
135
+ def url_for(path)
136
+ return "#{@connection.protocol}://#{@host}/#{path.sub(/^\//, '')}"
137
+ end
138
+
139
+ def search_url_for(path)
140
+ return "#{@connection.protocol}://search.#{@host}/#{path.sub(/^\//, '')}"
141
+ end
142
+
143
+ def user_name
144
+ unless @user_name.instance_of? String
145
+ Termtter::Client.create_highline.ask('your twitter username: ')
146
+ end
147
+ @user_name
148
+ end
149
+
150
+ def password
151
+ unless @password.instance_of? String
152
+ @password = Termtter::Client.create_highline.ask('your twitter password: ') { |q| q.echo = false }
153
+ end
154
+ @password
155
+ end
156
+
157
+ def near_users(screen_name)
158
+ Client::public_storage[:users].select {|user|
159
+ /#{user}/i =~ screen_name || /#{screen_name}/i =~ user
160
+ }.join(', ')
161
+ end
162
+
163
+ def post_request(uri)
164
+ req = Net::HTTP::Post.new(uri)
165
+ req.basic_auth(user_name, password)
166
+ req.add_field('User-Agent', 'Termtter http://github.com/jugyo/termtter')
167
+ req.add_field('X-Twitter-Client', 'Termtter')
168
+ req.add_field('X-Twitter-Client-URL', 'http://github.com/jugyo/termtter')
169
+ req.add_field('X-Twitter-Client-Version', '0.1')
170
+ req
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,13 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ class User
5
+ %w[ name favourites_count url id description protected utc_offset time_zone
6
+ screen_name notifications statuses_count followers_count friends_count
7
+ profile_image_url location following created_at
8
+ ].each do |attr|
9
+ attr_accessor attr.to_sym
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,3 @@
1
+ module Termtter
2
+ VERSION = '0.8.3'
3
+ end
data/lib/termtter.rb ADDED
@@ -0,0 +1,157 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ $:.unshift(File.dirname(__FILE__)) unless
4
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
5
+
6
+ require 'rubygems'
7
+ require 'json'
8
+ require 'net/https'
9
+ require 'open-uri'
10
+ require 'cgi'
11
+ require 'readline'
12
+ require 'enumerator'
13
+ require 'configatron'
14
+
15
+ Thread.abort_on_exception = true
16
+
17
+ configatron.set_default(:update_interval, 300)
18
+ configatron.set_default(:prompt, '> ')
19
+ configatron.set_default(:enable_ssl, false)
20
+ configatron.proxy.set_default(:port, '8080')
21
+
22
+ require 'termtter/twitter'
23
+ require 'termtter/connection'
24
+ require 'termtter/status'
25
+ require 'termtter/user'
26
+ require 'termtter/command'
27
+ require 'termtter/hook'
28
+ require 'termtter/task'
29
+ require 'termtter/task_manager'
30
+ require 'termtter/client'
31
+ require 'termtter/api'
32
+ require 'termtter/version'
33
+
34
+ module Termtter
35
+ APP_NAME = 'termtter'
36
+ CONF_FILE = '~/.termtterrc' # still does not use
37
+ CONF_DIR = '~/.termtter' # still does not use
38
+ end
39
+
40
+ if RUBY_VERSION < '1.8.7'
41
+ class Array
42
+ def take(n) self[0...n] end
43
+ end
44
+ end
45
+
46
+ def win?
47
+ RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin/
48
+ end
49
+
50
+ if win?
51
+ require 'iconv'
52
+ require 'Win32API'
53
+ $wGetACP = Win32API.new('kernel32','GetACP','','I')
54
+
55
+ module Readline
56
+ $iconv_sj_to_u8 = Iconv.new('UTF-8', "CP#{$wGetACP.call()}")
57
+ alias :old_readline :readline
58
+ def readline(*a)
59
+ str = old_readline(*a)
60
+ out = ''
61
+ loop do
62
+ begin
63
+ out << $iconv_sj_to_u8.iconv(str)
64
+ break
65
+ rescue Iconv::Failure
66
+ out << "#{$!.success}?"
67
+ str = $!.failed[1..-1]
68
+ end
69
+ end
70
+ return out
71
+ end
72
+ module_function :old_readline, :readline
73
+ end
74
+
75
+ $wSetConsoleTextAttribute = Win32API.new('kernel32','SetConsoleTextAttribute','II','I')
76
+ $wGetConsoleScreenBufferInfo = Win32API.new("kernel32", "GetConsoleScreenBufferInfo", ['l', 'p'], 'i')
77
+ $wGetStdHandle = Win32API.new('kernel32','GetStdHandle','I','I')
78
+ $wGetACP = Win32API.new('kernel32','GetACP','','I')
79
+
80
+ $hStdOut = $wGetStdHandle.call(0xFFFFFFF5)
81
+ lpBuffer = ' ' * 22
82
+ $wGetConsoleScreenBufferInfo.call($hStdOut, lpBuffer)
83
+ $oldColor = lpBuffer.unpack('SSSSSssssSS')[4]
84
+
85
+ $colorMap = {
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
105
+ }
106
+ $iconv_u8_to_sj = Iconv.new("CP#{$wGetACP.call()}", 'UTF-8')
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/
111
+ $wSetConsoleTextAttribute.call $hStdOut, $colorMap[$1.to_i].to_i
112
+ when /\e\[\d*[a-zA-Z]/
113
+ # do nothing
114
+ else
115
+ loop do
116
+ begin
117
+ STDOUT.print $iconv_u8_to_sj.iconv(token)
118
+ break
119
+ rescue Iconv::Failure
120
+ STDOUT.print "#{$!.success}?"
121
+ token = $!.failed[1..-1]
122
+ end
123
+ end
124
+ end
125
+ end
126
+ $wSetConsoleTextAttribute.call $hStdOut, $oldColor
127
+ $iconv_u8_to_sj.iconv(nil)
128
+ end
129
+ def puts(str)
130
+ print str
131
+ STDOUT.puts
132
+ end
133
+ end
134
+
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
141
+ require "plugin/#{s}"
142
+ rescue => e
143
+ Termtter::Client.handle_error(e)
144
+ end
145
+
146
+ def filter(s)
147
+ load "filter/#{s}.rb"
148
+ rescue => e
149
+ Termtter::Client.handle_error(e)
150
+ else
151
+ Termtter::Client.public_storage[:filters] ||= []
152
+ Termtter::Client.public_storage[:filters] << s
153
+ true
154
+ end
155
+
156
+ $:.unshift(Termtter::CONF_DIR) # still does not use
157
+
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe Termtter::Client, 'when the plugin cool is loaded' do
6
+ it 'should add something about cool' do
7
+ Termtter::Client.should_receive(:register_macro)
8
+ plugin 'cool'
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe Termtter::Client, 'when the plugin fib is loaded' do
6
+ it 'should add command fib' do
7
+ Termtter::Client.should_receive(:add_command).with(/^fib\s+(\d+)/)
8
+ Termtter::Client.should_receive(:add_command).with(/^fibyou\s(\w+)\s(\d+)/)
9
+ plugin 'fib'
10
+ end
11
+
12
+ it 'should define fib method' do
13
+ plugin 'fib'
14
+ (0..10).map {|i| fib i }.should == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ module Termtter
6
+ describe Client, 'when the filter plugin is loaded' do
7
+ it 'should add command filter, filters and unfilter' do
8
+ Termtter::Client.should_receive(:register_command).exactly(3)
9
+ plugin 'filter'
10
+ end
11
+
12
+ it 'should set public_storage[:filters]' do
13
+ plugin 'filter'
14
+ Client::public_storage.keys.should be_include(:filters)
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/../../lib/termtter'
4
+
5
+ module Termtter
6
+ describe Client, 'when the plugin plugin is loaded' do
7
+ it 'should add command plugin and plugins' do
8
+ Termtter::Client.should_receive(:register_command).twice
9
+ plugin 'plugin'
10
+ end
11
+
12
+ it 'should set public_storage[:plugins]' do
13
+ plugin 'plugin'
14
+ Client::public_storage[:plugins].should_not be_empty
15
+ end
16
+
17
+ describe 'after the plugin plugin is loaded' do
18
+ before { plugin 'plugin' }
19
+
20
+ it 'should load the given plugin in the command plugin'
21
+ # hmm... How can I write it...?
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe Termtter::Client, 'when the plugin shell is loaded' do
6
+ it 'should add command shell' do
7
+ Termtter::Client.should_receive(:register_command)
8
+ plugin 'shell'
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe Termtter::Client, 'when the plugin spam is loaded' do
6
+ it 'should add command spam and post immediately' do
7
+ connection = mock('connection', :null_object => true)
8
+ t = Termtter::Twitter.new('a', 'b', connection)
9
+ Termtter::Twitter.should_receive(:new).and_return(t)
10
+ t.should_receive(:update_status).with('*super spam time*')
11
+
12
+ Termtter::Client.should_receive(:clear_commands)
13
+ Termtter::Client.should_receive(:add_command).with(/.+/)
14
+ plugin 'spam'
15
+ end
16
+ end
17
+
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+ plugin 'standard_plugins'
5
+
6
+ module Termtter
7
+ describe Client do
8
+ it 'shold return registerd commands' do
9
+ [
10
+ [:update, [:u]], [:direct, [:d]],
11
+ [:profile, [:p]], [:list, [:l]],
12
+ [:search, [:s]], [:replies, [:r]],
13
+ [:show, [ ]], [:shows, [ ]],
14
+ [:limit, [:lm]], [:pause, [ ]],
15
+ [:resume, [ ]], [:exit, [:e]],
16
+ ].each do |name, aliases|
17
+ command = Client.get_command(name)
18
+ command.name.should == name
19
+ command.aliases.should == aliases
20
+ end
21
+ end
22
+
23
+ it 'should return candidates when call find_status_id_candidates' do
24
+ Client.public_storage[:status_ids] = %w[1 2 22 3 4 5]
25
+ Client.find_status_id_candidates("1", "%s").should == ["1"]
26
+ Client.find_status_id_candidates("2", "%s").should == ["2", "22"]
27
+ #TODO: more spec for like "jugyo:1113830"
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
4
+ require 'termtter'
@@ -0,0 +1,175 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ module Termtter
6
+
7
+ describe Client do
8
+
9
+ it 'should take new_command' do
10
+ command = Command.new(:name => :test)
11
+ Client.register_command(command)
12
+ Client.get_command(:test).should == command
13
+ end
14
+
15
+ it 'should take command as Hash' do
16
+ Client.register_command(:name => :test)
17
+ Client.get_command(:test).name.should == :test
18
+ end
19
+
20
+ it 'should call new_command' do
21
+ command_arg = nil
22
+ command = Command.new(:name => :test, :exec_proc => lambda {|arg| command_arg = arg})
23
+ Client.register_command(command)
24
+ command_arg.should == nil
25
+
26
+ [
27
+ ['test', ''],
28
+ ['test foo bar', 'foo bar'],
29
+ ['test foo bar ', 'foo bar'],
30
+ ['test foo bar ', 'foo bar'],
31
+ ].each do |input, args|
32
+ Client.call_commands(input, nil)
33
+ command_arg.should == args
34
+ end
35
+ end
36
+
37
+ it 'should take new_hook' do
38
+ hook = Hook.new(:name => :test)
39
+ Client.register_hook(hook)
40
+ Client.get_hook(:test).should == hook
41
+ end
42
+
43
+ it 'should take hook as Hash' do
44
+ Client.register_hook(:name => :test)
45
+ Client.get_hook(:test).name.should == :test
46
+ end
47
+
48
+ it 'should call new_hook' do
49
+ hook_called = false
50
+ Client.register_hook(:name => :test1, :points => [:point1], :exec_proc => lambda {hook_called = true})
51
+ hook_called.should == false
52
+ Client.call_new_hooks(:point1)
53
+ hook_called.should == true
54
+ end
55
+
56
+ it 'should call new_hook with args' do
57
+ arg1 = nil
58
+ arg2 = nil
59
+ Client.register_hook(:name => :test1, :points => [:point1], :exec_proc => lambda {|a1, a2| arg1 = a1; arg2 = a2})
60
+ arg1.should == nil
61
+ arg2.should == nil
62
+ Client.call_new_hooks(:point1, 'foo', 'bar')
63
+ arg1.should == 'foo'
64
+ arg2.should == 'bar'
65
+ end
66
+
67
+ it 'should return hooks when call get_hooks' do
68
+ hook1 = Client.register_hook(:name => :test1, :points => [:point1])
69
+ hook2 = Client.register_hook(:name => :test2, :points => [:point1])
70
+ hook3 = Client.register_hook(:name => :test3, :points => [:point2])
71
+
72
+ hooks = Client.get_hooks(:point1)
73
+ hooks.size.should == 2
74
+ hooks.include?(hook1).should == true
75
+ hooks.include?(hook2).should == true
76
+ hooks.include?(hook3).should == false
77
+ end
78
+
79
+ it 'should call decide_arg hooks' do
80
+ input_command = nil
81
+ input_arg = nil
82
+ decided_arg = nil
83
+ Client.register_hook( :name => :test1,
84
+ :points => [:modify_arg_for_update],
85
+ :exec_proc => lambda {|cmd, arg| input_command = cmd; input_arg = arg; arg.upcase})
86
+ Client.register_hook( :name => :test2,
87
+ :points => [:pre_exec_update],
88
+ :exec_proc => lambda {|cmd, arg| decided_arg = arg})
89
+ Client.register_command(:name => :update, :aliases => [:u])
90
+
91
+ input_command.should == nil
92
+ input_arg.should == nil
93
+ decided_arg.should == nil
94
+ Client.call_commands('u foo')
95
+ input_command.should == 'u'
96
+ input_arg.should == 'foo'
97
+ decided_arg.should == 'FOO'
98
+ end
99
+
100
+ it 'should call pre_exec hooks' do
101
+ hook_called = false
102
+ Client.register_hook( :name => :test,
103
+ :points => [:pre_exec_update],
104
+ :exec_proc => lambda {|cmd, arg| hook_called = true})
105
+ Client.register_command(:name => :update)
106
+
107
+ hook_called.should == false
108
+ Client.call_commands('update foo')
109
+ hook_called.should == true
110
+ end
111
+
112
+ it 'should able to cancel exec command' do
113
+ command_called = false
114
+ Client.register_hook( :name => :test,
115
+ :points => [:pre_exec_update],
116
+ :exec_proc => lambda {|cmd, arg| false})
117
+ Client.register_command(:name => :update, :exec_proc => lambda {|cmd, arg| command_called = true})
118
+
119
+ command_called.should == false
120
+ Client.call_commands('update foo')
121
+ command_called.should == false
122
+ end
123
+
124
+ it 'should call post_exec hooks' do
125
+ command_result = nil
126
+ Client.register_hook( :name => :test,
127
+ :points => [:post_exec_update],
128
+ :exec_proc => lambda {|cmd, arg, result| command_result = result })
129
+ Client.register_command(:name => :update, :exec_proc => lambda {|arg| 'foo'})
130
+
131
+ command_result.should == nil
132
+ Client.call_commands('update foo')
133
+ command_result.should == 'foo'
134
+ end
135
+
136
+ it 'should call exit hooks' do
137
+ hook_called = false
138
+ Client.register_hook(
139
+ :name => :test,
140
+ :points => [:exit],
141
+ :exec_proc => lambda { hook_called = true }
142
+ )
143
+
144
+ hook_called.should == false
145
+ Client.exit
146
+ hook_called.should == true
147
+ end
148
+
149
+ it 'should call plural hooks' do
150
+ hook1_called = false
151
+ hook2_called = false
152
+ Client.register_hook(:name => :hook1, :points => [:exit], :exec_proc => lambda {hook1_called = true})
153
+ Client.register_hook(:name => :hook2, :points => [:exit], :exec_proc => lambda {hook2_called = true})
154
+
155
+ hook1_called.should == false
156
+ hook2_called.should == false
157
+ Client.exit
158
+ hook1_called.should == true
159
+ hook2_called.should == true
160
+ end
161
+
162
+ it 'should able to override hooks' do
163
+ hook1_called = false
164
+ hook2_called = false
165
+ Client.register_hook(:name => :hook, :points => [:exit], :exec_proc => lambda {hook1_called = true})
166
+ Client.register_hook(:name => :hook, :points => [:exit], :exec_proc => lambda {hook2_called = true})
167
+
168
+ hook1_called.should == false
169
+ hook2_called.should == false
170
+ Client.exit
171
+ hook1_called.should == false
172
+ hook2_called.should == true
173
+ end
174
+ end
175
+ end