termtter 0.8.3

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 (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