tweetwine 0.2.4 → 0.2.5
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.
- data/CHANGELOG.rdoc +8 -0
- data/Rakefile +10 -2
- data/bin/tweetwine +8 -7
- data/example/example_helper.rb +59 -0
- data/example/fixtures/statuses.json +1 -0
- data/example/show_latest_statuses_example.rb +45 -0
- data/example/show_metadata_example.rb +35 -0
- data/lib/tweetwine/client.rb +5 -3
- data/lib/tweetwine/io.rb +8 -4
- data/lib/tweetwine/meta.rb +1 -1
- data/lib/tweetwine/util.rb +27 -0
- data/test/client_test.rb +1 -5
- data/test/{test_config.yaml → fixtures/test_config.yaml} +0 -0
- data/test/io_test.rb +34 -12
- data/test/startup_config_test.rb +1 -1
- data/test/util_test.rb +31 -0
- metadata +12 -7
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
=== 0.2.5 released 2009-10-14
|
2
|
+
|
3
|
+
* Improved username highlighting for colorization. For example, email
|
4
|
+
addresses are not highlighted as usernames anymore.
|
5
|
+
* Command line option "--no-colorize" to (temporarily) disable colors from the
|
6
|
+
output.
|
7
|
+
* Added first set of acceptance tests under "example" directory.
|
8
|
+
|
1
9
|
=== 0.2.4 released 2009-09-16
|
2
10
|
|
3
11
|
* Retry connection upon connection reset, trying maximum of three times.
|
data/Rakefile
CHANGED
@@ -20,7 +20,7 @@ spec = Gem::Specification.new do |s|
|
|
20
20
|
s.email = "tkareine@gmail.com"
|
21
21
|
|
22
22
|
s.platform = Gem::Platform::RUBY
|
23
|
-
s.files = FileList["Rakefile", "MIT-LICENSE.txt", "*.rdoc", "bin/**/*", "lib/**/*", "test/**/*"].to_a
|
23
|
+
s.files = FileList["Rakefile", "MIT-LICENSE.txt", "*.rdoc", "bin/**/*", "example/**/*", "lib/**/*", "test/**/*"].to_a
|
24
24
|
s.executables = ["tweetwine"]
|
25
25
|
|
26
26
|
s.add_dependency("rest-client", ">= 1.0.0")
|
@@ -73,6 +73,14 @@ Rake::TestTask.new(:test) do |t|
|
|
73
73
|
t.libs << "test"
|
74
74
|
end
|
75
75
|
|
76
|
+
Rake::TestTask.new(:example) do |t|
|
77
|
+
t.test_files = FileList["example/**/*_example.rb"]
|
78
|
+
t.verbose = true
|
79
|
+
t.warning = false
|
80
|
+
t.ruby_opts << "-rrubygems"
|
81
|
+
t.libs << "example"
|
82
|
+
end
|
83
|
+
|
76
84
|
desc "Find code smells"
|
77
85
|
task :roodi do
|
78
86
|
sh %{roodi "**/*.rb"}
|
@@ -83,4 +91,4 @@ task :todo do
|
|
83
91
|
FileList["**/*.rb", "**/*.rdoc", "**/*.txt"].egrep /(TODO|FIXME)/
|
84
92
|
end
|
85
93
|
|
86
|
-
task :default => :test
|
94
|
+
task :default => [:test, :example]
|
data/bin/tweetwine
CHANGED
@@ -19,8 +19,10 @@ cmd_parser = lambda do |args|
|
|
19
19
|
options = {}
|
20
20
|
begin
|
21
21
|
OptionParser.new do |opt|
|
22
|
+
executable_name = File.basename($0)
|
23
|
+
|
22
24
|
opt.banner =<<-END
|
23
|
-
Usage:
|
25
|
+
Usage: #{executable_name} [options...] [command]
|
24
26
|
|
25
27
|
Commands: #{Client::COMMANDS.join(", ")}
|
26
28
|
|
@@ -36,6 +38,9 @@ Usage: tweetwine [options...] [command]
|
|
36
38
|
opt.on("-n", "--num N", Integer, "The number of statuses to fetch, defaults to #{Client::DEFAULT_NUM_STATUSES}") do |arg|
|
37
39
|
options[:num_statuses] = arg
|
38
40
|
end
|
41
|
+
opt.on("--no-colorize", "Do not colorize output with ANSI escape codes") do
|
42
|
+
options[:colorize] = false
|
43
|
+
end
|
39
44
|
opt.on("--no-url-shorten", "Do not shorten URLs for status update") do
|
40
45
|
options[:shorten_urls] = { :enable => false }
|
41
46
|
end
|
@@ -43,7 +48,7 @@ Usage: tweetwine [options...] [command]
|
|
43
48
|
options[:page_num] = arg
|
44
49
|
end
|
45
50
|
opt.on("-v", "--version", "Show version information and exit") do
|
46
|
-
puts "#{
|
51
|
+
puts "#{executable_name} #{Tweetwine::VERSION}"
|
47
52
|
exit(EXIT_VERSION)
|
48
53
|
end
|
49
54
|
opt.on_tail("-h", "--help", "Show this help message and exit") do
|
@@ -61,11 +66,7 @@ def create_dependencies(options)
|
|
61
66
|
io = Tweetwine::IO.new(options)
|
62
67
|
rest_client = RestClientWrapper.new(io)
|
63
68
|
url_shortener = lambda { |opts| UrlShortener.new(rest_client, opts) }
|
64
|
-
|
65
|
-
:io => io,
|
66
|
-
:rest_client => rest_client,
|
67
|
-
:url_shortener => url_shortener
|
68
|
-
}
|
69
|
+
Client::Dependencies.new io, rest_client, url_shortener
|
69
70
|
end
|
70
71
|
|
71
72
|
begin
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "coulda"
|
2
|
+
require "matchy"
|
3
|
+
require "open4"
|
4
|
+
require "tweetwine"
|
5
|
+
|
6
|
+
module Tweetwine
|
7
|
+
module ExampleHelpers
|
8
|
+
DEFAULT_INJECTION =<<-END
|
9
|
+
require "fakeweb"
|
10
|
+
FakeWeb.allow_net_connect = false
|
11
|
+
|
12
|
+
require "date"
|
13
|
+
require "time"
|
14
|
+
require "timecop"
|
15
|
+
Timecop.freeze(Time.parse("2009-10-14 01:56:15 +0300"))
|
16
|
+
|
17
|
+
def fixture(filename)
|
18
|
+
contents = nil
|
19
|
+
filepath = File.dirname(__FILE__) << "/example/fixtures/" << filename
|
20
|
+
File.open(filepath) do |f|
|
21
|
+
contents = f.readlines.join("\n")
|
22
|
+
end
|
23
|
+
contents
|
24
|
+
end
|
25
|
+
END
|
26
|
+
|
27
|
+
def launch_app(args, injection_code = "", &blk)
|
28
|
+
lib = File.dirname(__FILE__) << "/../lib"
|
29
|
+
executable = File.dirname(__FILE__) << "/../bin/tweetwine"
|
30
|
+
code =<<-END
|
31
|
+
#{escape_injection_for_shell(DEFAULT_INJECTION)}
|
32
|
+
#{escape_injection_for_shell(injection_code)}
|
33
|
+
`cat #{executable}`
|
34
|
+
END
|
35
|
+
launch_cmd = "ruby -rubygems -I#{lib} -e \"#{code}\" -- #{args}"
|
36
|
+
Open4::popen4(launch_cmd, &blk)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def escape_injection_for_shell(code)
|
42
|
+
code_dup = code.dup
|
43
|
+
code_dup.gsub!('\'', '\\\'')
|
44
|
+
code_dup.gsub!('"', '\\"')
|
45
|
+
code_dup
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module Test
|
51
|
+
module Unit
|
52
|
+
class TestCase
|
53
|
+
include Tweetwine::ExampleHelpers
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
include Coulda
|
59
|
+
include Tweetwine
|
@@ -0,0 +1 @@
|
|
1
|
+
[{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Fri Oct 02 11:47:12 +0000 2009","truncated":false,"user":{"verified":false,"profile_background_tile":false,"description":"Suomen suurin pelilehti.","friends_count":27,"profile_background_color":"9ae4e8","notifications":false,"profile_image_url":"http://a1.twimg.com/profile_images/67613662/pelittw_normal.jpg","favourites_count":0,"profile_sidebar_fill_color":"e0ff92","url":"http://www.pelit.fi","following":true,"screen_name":"pelit","profile_sidebar_border_color":"87bc44","geo_enabled":false,"created_at":"Sat Nov 22 13:23:32 +0000 2008","statuses_count":391,"time_zone":"Greenland","protected":false,"profile_text_color":"000000","location":"Finland","name":"Pelit","profile_background_image_url":"http://s.twimg.com/a/1255039715/images/themes/theme1/bg.png","id":17556985,"utc_offset":-10800,"profile_link_color":"0000ff","followers_count":70},"in_reply_to_status_id":null,"id":4550677399,"text":"F1-kausi alkaa marraskuussa http://bit.ly/1qQwjQ"},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Fri Oct 02 10:42:43 +0000 2009","truncated":false,"user":{"geo_enabled":false,"statuses_count":576,"profile_background_tile":false,"followers_count":6571,"description":"O'Reilly Media's group blog about emerging technologies including Web 2.0, location, open source, ambient computing, mobile, web operations, and more.","profile_background_color":"9ae4e8","friends_count":6,"profile_image_url":"http://a3.twimg.com/profile_images/55297199/iphone_icon_radar_normal.png","profile_sidebar_fill_color":"e0ff92","url":"http://radar.oreilly.com","following":true,"favourites_count":0,"screen_name":"radar","verified":false,"profile_sidebar_border_color":"87bc44","created_at":"Mon Jun 02 19:45:48 +0000 2008","time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"Sebastopol, CA","name":"O'Reilly Radar","notifications":false,"profile_background_image_url":"http://s.twimg.com/a/1255384803/images/themes/theme1/bg.png","id":14984090,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4549851544,"text":"Four short links: 2 October 2009 http://bit.ly/9sbgV"},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://www.atebits.com/\" rel=\"nofollow\">Tweetie</a>","created_at":"Fri Oct 02 09:28:10 +0000 2009","truncated":false,"user":{"notifications":false,"statuses_count":1490,"profile_background_tile":false,"description":"jQuery/Merb/DM FTW","profile_background_color":"333333","geo_enabled":false,"followers_count":3007,"profile_image_url":"http://a1.twimg.com/profile_images/427781590/yehuda_normal.jpg","profile_sidebar_fill_color":"a8caa0","url":"http://www.yehudakatz.com","following":false,"friends_count":117,"screen_name":"wycats","profile_sidebar_border_color":"87bc44","favourites_count":3,"created_at":"Thu Aug 30 04:07:52 +0000 2007","verified":false,"time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"iPhone: 37.786461,-122.394867","name":"wycats","profile_background_image_url":"http://a3.twimg.com/profile_background_images/12633131/Twit3.gif","id":8526432,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4549018421,"text":"Enjoyed giving a less technical talk about how Rails makes it easier to get your app in your users' hands quickly and easily."},{"favorited":false,"in_reply_to_user_id":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://www.atebits.com/\" rel=\"nofollow\">Tweetie</a>","created_at":"Fri Oct 02 01:01:20 +0000 2009","geo":null,"user":{"profile_background_tile":false,"favourites_count":3,"profile_image_url":"http://a1.twimg.com/profile_images/427781590/yehuda_normal.jpg","description":"jQuery/Merb/DM FTW","statuses_count":1478,"profile_background_color":"333333","url":"http://www.yehudakatz.com","following":true,"time_zone":"Pacific Time (US & Canada)","screen_name":"wycats","verified":false,"profile_sidebar_fill_color":"a8caa0","created_at":"Thu Aug 30 04:07:52 +0000 2007","profile_sidebar_border_color":"87bc44","notifications":false,"followers_count":2978,"protected":false,"profile_text_color":"000000","location":"iPhone: 37.786461,-122.394867","name":"wycats","geo_enabled":false,"profile_background_image_url":"http://a3.twimg.com/profile_background_images/12633131/Twit3.gif","friends_count":117,"id":8526432,"utc_offset":-28800,"profile_link_color":"0000ff"},"truncated":false,"id":4540204389,"in_reply_to_status_id":null,"text":"Ruby is like steroids for programmers. It should be considered cheating :P"},{"in_reply_to_screen_name":null,"geo":null,"source":"<a href=\"http://adium.im\" rel=\"nofollow\">Adium</a>","created_at":"Thu Oct 01 18:08:19 +0000 2009","truncated":false,"in_reply_to_status_id":null,"user":{"verified":false,"profile_sidebar_fill_color":"a290ea","description":"","url":"http://pragdave.pragprog.com","following":true,"notifications":false,"profile_sidebar_border_color":"783a4e","followers_count":4718,"created_at":"Mon May 21 00:21:44 +0000 2007","friends_count":37,"profile_text_color":"1160a2","geo_enabled":false,"profile_background_image_url":"http://a1.twimg.com/profile_background_images/3232584/303213676_b1a058e6a3.jpg","statuses_count":971,"favourites_count":0,"profile_link_color":"06066f","protected":false,"profile_image_url":"http://a3.twimg.com/profile_images/62575979/dave_notepaper_small_normal.png","profile_background_tile":false,"location":"Southlake, Texas","name":"Dave Thomas","profile_background_color":"051d7f","screen_name":"pragdave","id":6186692,"time_zone":"Central Time (US & Canada)","utc_offset":-21600},"favorited":false,"id":4530763642,"in_reply_to_user_id":null,"text":"It's royalty check day. I love getting them all out."},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Thu Oct 01 14:13:18 +0000 2009","truncated":false,"user":{"geo_enabled":false,"statuses_count":576,"profile_background_tile":false,"followers_count":6571,"description":"O'Reilly Media's group blog about emerging technologies including Web 2.0, location, open source, ambient computing, mobile, web operations, and more.","profile_background_color":"9ae4e8","friends_count":6,"profile_image_url":"http://a3.twimg.com/profile_images/55297199/iphone_icon_radar_normal.png","profile_sidebar_fill_color":"e0ff92","url":"http://radar.oreilly.com","following":true,"favourites_count":0,"screen_name":"radar","verified":false,"profile_sidebar_border_color":"87bc44","created_at":"Mon Jun 02 19:45:48 +0000 2008","time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"Sebastopol, CA","name":"O'Reilly Radar","notifications":false,"profile_background_image_url":"http://s.twimg.com/a/1255384803/images/themes/theme1/bg.png","id":14984090,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4525352423,"text":"More on how web performance impacts revenue... http://bit.ly/tEpMP"},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Thu Oct 01 12:46:07 +0000 2009","truncated":false,"user":{"verified":false,"profile_background_tile":false,"description":"Suomen suurin pelilehti.","friends_count":27,"profile_background_color":"9ae4e8","notifications":false,"profile_image_url":"http://a1.twimg.com/profile_images/67613662/pelittw_normal.jpg","favourites_count":0,"profile_sidebar_fill_color":"e0ff92","url":"http://www.pelit.fi","following":true,"screen_name":"pelit","profile_sidebar_border_color":"87bc44","geo_enabled":false,"created_at":"Sat Nov 22 13:23:32 +0000 2008","statuses_count":391,"time_zone":"Greenland","protected":false,"profile_text_color":"000000","location":"Finland","name":"Pelit","profile_background_image_url":"http://s.twimg.com/a/1255039715/images/themes/theme1/bg.png","id":17556985,"utc_offset":-10800,"profile_link_color":"0000ff","followers_count":70},"in_reply_to_status_id":null,"id":4523641304,"text":"PSPgo kaupoissa http://bit.ly/2n7evK"},{"geo":null,"truncated":false,"source":"web","created_at":"Thu Oct 01 11:37:47 +0000 2009","in_reply_to_status_id":null,"favorited":false,"user":{"geo_enabled":false,"profile_background_image_url":"http://s.twimg.com/a/1254344155/images/themes/theme1/bg.png","description":"","statuses_count":45,"profile_link_color":"0000ff","url":"http://minigore.blogspot.com","following":null,"profile_background_tile":false,"profile_background_color":"9ae4e8","time_zone":"Helsinki","created_at":"Fri Jun 26 10:09:29 +0000 2009","followers_count":1495,"verified":false,"profile_sidebar_fill_color":"e0ff92","friends_count":9,"profile_sidebar_border_color":"87bc44","protected":false,"profile_image_url":"http://a1.twimg.com/profile_images/423903314/SwayGoreAvatar_normal.jpg","favourites_count":0,"location":"Finland","name":"Mountain Sheep","notifications":null,"screen_name":"minigore","id":51000682,"utc_offset":7200,"profile_text_color":"000000"},"in_reply_to_user_id":null,"in_reply_to_screen_name":null,"id":4522561867,"text":"We have picked a bit over 60 new beta testers so far. Last chance to send those applications in! http://bit.ly/3sVIAb"},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Thu Oct 01 10:42:46 +0000 2009","truncated":false,"user":{"geo_enabled":false,"statuses_count":576,"profile_background_tile":false,"followers_count":6571,"description":"O'Reilly Media's group blog about emerging technologies including Web 2.0, location, open source, ambient computing, mobile, web operations, and more.","profile_background_color":"9ae4e8","friends_count":6,"profile_image_url":"http://a3.twimg.com/profile_images/55297199/iphone_icon_radar_normal.png","profile_sidebar_fill_color":"e0ff92","url":"http://radar.oreilly.com","following":true,"favourites_count":0,"screen_name":"radar","verified":false,"profile_sidebar_border_color":"87bc44","created_at":"Mon Jun 02 19:45:48 +0000 2008","time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"Sebastopol, CA","name":"O'Reilly Radar","notifications":false,"profile_background_image_url":"http://s.twimg.com/a/1255384803/images/themes/theme1/bg.png","id":14984090,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4521842026,"text":"Four short links: 1 October 2009 http://bit.ly/UisfL"},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://www.atebits.com/\" rel=\"nofollow\">Tweetie</a>","created_at":"Thu Oct 01 01:56:01 +0000 2009","truncated":false,"user":{"notifications":false,"statuses_count":1490,"profile_background_tile":false,"description":"jQuery/Merb/DM FTW","profile_background_color":"333333","geo_enabled":false,"followers_count":3007,"profile_image_url":"http://a1.twimg.com/profile_images/427781590/yehuda_normal.jpg","profile_sidebar_fill_color":"a8caa0","url":"http://www.yehudakatz.com","following":false,"friends_count":117,"screen_name":"wycats","profile_sidebar_border_color":"87bc44","favourites_count":3,"created_at":"Thu Aug 30 04:07:52 +0000 2007","verified":false,"time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"iPhone: 37.786461,-122.394867","name":"wycats","profile_background_image_url":"http://a3.twimg.com/profile_background_images/12633131/Twit3.gif","id":8526432,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4513811464,"text":"There's a picture of a mac next to the \"universal\" laptop charger available on the flight. Cruel."},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://www.atebits.com/\" rel=\"nofollow\">Tweetie</a>","created_at":"Thu Oct 01 00:56:13 +0000 2009","truncated":false,"user":{"notifications":false,"statuses_count":1490,"profile_background_tile":false,"description":"jQuery/Merb/DM FTW","profile_background_color":"333333","geo_enabled":false,"followers_count":3007,"profile_image_url":"http://a1.twimg.com/profile_images/427781590/yehuda_normal.jpg","profile_sidebar_fill_color":"a8caa0","url":"http://www.yehudakatz.com","following":false,"friends_count":117,"screen_name":"wycats","profile_sidebar_border_color":"87bc44","favourites_count":3,"created_at":"Thu Aug 30 04:07:52 +0000 2007","verified":false,"time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"iPhone: 37.786461,-122.394867","name":"wycats","profile_background_image_url":"http://a3.twimg.com/profile_background_images/12633131/Twit3.gif","id":8526432,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4512344880,"text":"Is there someplace to buy apple power cord in SFO International terminal?"},{"text":"http://yfrog.com/0lvi6j\nAwesome seats for the cubs game. Thanks Kenny and DRW","created_at":"Thu Oct 01 00:05:04 +0000 2009","truncated":false,"in_reply_to_status_id":null,"source":"<a href=\"http://twitterrific.com\" rel=\"nofollow\">Twitterrific</a>","user":{"favourites_count":0,"profile_background_color":"EBEBEB","verified":false,"utc_offset":-21600,"created_at":"Mon Apr 21 00:02:22 +0000 2008","screen_name":"jaycfields","profile_sidebar_fill_color":"F3F3F3","profile_sidebar_border_color":"DFDFDF","notifications":false,"location":"Chicago, IL","time_zone":"Central Time (US & Canada)","geo_enabled":false,"profile_text_color":"333333","followers_count":560,"protected":false,"statuses_count":1296,"profile_background_image_url":"http://s.twimg.com/a/1255039715/images/themes/theme7/bg.gif","name":"Jay Fields","friends_count":33,"profile_link_color":"990000","url":"http://www.jayfields.com","id":14456381,"following":true,"profile_background_tile":false,"profile_image_url":"http://a1.twimg.com/profile_images/54137880/JayFields_normal.jpg","description":"Programmer, Alcoholic, Gambler"},"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"id":4511163054},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://www.atebits.com/\" rel=\"nofollow\">Tweetie</a>","created_at":"Wed Sep 30 21:08:03 +0000 2009","truncated":false,"user":{"notifications":false,"statuses_count":1490,"profile_background_tile":false,"description":"jQuery/Merb/DM FTW","profile_background_color":"333333","geo_enabled":false,"followers_count":3007,"profile_image_url":"http://a1.twimg.com/profile_images/427781590/yehuda_normal.jpg","profile_sidebar_fill_color":"a8caa0","url":"http://www.yehudakatz.com","following":false,"friends_count":117,"screen_name":"wycats","profile_sidebar_border_color":"87bc44","favourites_count":3,"created_at":"Thu Aug 30 04:07:52 +0000 2007","verified":false,"time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"iPhone: 37.786461,-122.394867","name":"wycats","profile_background_image_url":"http://a3.twimg.com/profile_background_images/12633131/Twit3.gif","id":8526432,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4507179861,"text":"Looking forward to my FOWA talk. \"Rails 3 and the Future of Agile\""},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Wed Sep 30 10:42:39 +0000 2009","truncated":false,"user":{"geo_enabled":false,"statuses_count":576,"profile_background_tile":false,"followers_count":6571,"description":"O'Reilly Media's group blog about emerging technologies including Web 2.0, location, open source, ambient computing, mobile, web operations, and more.","profile_background_color":"9ae4e8","friends_count":6,"profile_image_url":"http://a3.twimg.com/profile_images/55297199/iphone_icon_radar_normal.png","profile_sidebar_fill_color":"e0ff92","url":"http://radar.oreilly.com","following":true,"favourites_count":0,"screen_name":"radar","verified":false,"profile_sidebar_border_color":"87bc44","created_at":"Mon Jun 02 19:45:48 +0000 2008","time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"Sebastopol, CA","name":"O'Reilly Radar","notifications":false,"profile_background_image_url":"http://s.twimg.com/a/1255384803/images/themes/theme1/bg.png","id":14984090,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4494333077,"text":"Four short links: 30 September 2009 http://bit.ly/hQHat"},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Wed Sep 30 07:15:59 +0000 2009","truncated":false,"user":{"verified":false,"profile_background_tile":false,"description":"Suomen suurin pelilehti.","friends_count":27,"profile_background_color":"9ae4e8","notifications":false,"profile_image_url":"http://a1.twimg.com/profile_images/67613662/pelittw_normal.jpg","favourites_count":0,"profile_sidebar_fill_color":"e0ff92","url":"http://www.pelit.fi","following":true,"screen_name":"pelit","profile_sidebar_border_color":"87bc44","geo_enabled":false,"created_at":"Sat Nov 22 13:23:32 +0000 2008","statuses_count":391,"time_zone":"Greenland","protected":false,"profile_text_color":"000000","location":"Finland","name":"Pelit","profile_background_image_url":"http://s.twimg.com/a/1255039715/images/themes/theme1/bg.png","id":17556985,"utc_offset":-10800,"profile_link_color":"0000ff","followers_count":70},"in_reply_to_status_id":null,"id":4492072996,"text":"Left 4 Dead laajeni http://bit.ly/aPmwY"},{"text":"Mexican for dinner with Shane Harvie. Then a cigar on my balcony solo. A nice peaceful evening.","created_at":"Wed Sep 30 03:25:53 +0000 2009","truncated":false,"in_reply_to_status_id":null,"source":"<a href=\"http://twitterrific.com\" rel=\"nofollow\">Twitterrific</a>","user":{"favourites_count":0,"profile_background_color":"EBEBEB","verified":false,"utc_offset":-21600,"created_at":"Mon Apr 21 00:02:22 +0000 2008","screen_name":"jaycfields","profile_sidebar_fill_color":"F3F3F3","profile_sidebar_border_color":"DFDFDF","notifications":false,"location":"Chicago, IL","time_zone":"Central Time (US & Canada)","geo_enabled":false,"profile_text_color":"333333","followers_count":560,"protected":false,"statuses_count":1296,"profile_background_image_url":"http://s.twimg.com/a/1255039715/images/themes/theme7/bg.gif","name":"Jay Fields","friends_count":33,"profile_link_color":"990000","url":"http://www.jayfields.com","id":14456381,"following":true,"profile_background_tile":false,"profile_image_url":"http://a1.twimg.com/profile_images/54137880/JayFields_normal.jpg","description":"Programmer, Alcoholic, Gambler"},"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"id":4488550494},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Wed Sep 30 02:42:57 +0000 2009","truncated":false,"user":{"geo_enabled":false,"statuses_count":576,"profile_background_tile":false,"followers_count":6571,"description":"O'Reilly Media's group blog about emerging technologies including Web 2.0, location, open source, ambient computing, mobile, web operations, and more.","profile_background_color":"9ae4e8","friends_count":6,"profile_image_url":"http://a3.twimg.com/profile_images/55297199/iphone_icon_radar_normal.png","profile_sidebar_fill_color":"e0ff92","url":"http://radar.oreilly.com","following":true,"favourites_count":0,"screen_name":"radar","verified":false,"profile_sidebar_border_color":"87bc44","created_at":"Mon Jun 02 19:45:48 +0000 2008","time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"Sebastopol, CA","name":"O'Reilly Radar","notifications":false,"profile_background_image_url":"http://s.twimg.com/a/1255384803/images/themes/theme1/bg.png","id":14984090,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4487612897,"text":"Review of Guobin Yang's \"Power of the Internet in China\" http://bit.ly/19jf69"},{"truncated":false,"source":"<a href=\"http://www.atebits.com/\" rel=\"nofollow\">Tweetie</a>","created_at":"Wed Sep 30 01:11:13 +0000 2009","in_reply_to_status_id":null,"favorited":false,"user":{"profile_sidebar_border_color":"86A4A6","description":"","verified":false,"url":"http://blog.fallingsnow.net","following":true,"notifications":true,"profile_text_color":"333333","followers_count":1321,"profile_image_url":"http://a3.twimg.com/profile_images/52576575/DSCN0363_2_normal.JPG","profile_background_image_url":"http://s.twimg.com/a/1253743961/images/themes/theme6/bg.gif","created_at":"Mon Apr 23 20:51:19 +0000 2007","friends_count":130,"profile_link_color":"FF3300","screen_name":"evanphx","profile_background_tile":false,"favourites_count":1,"profile_background_color":"709397","protected":false,"statuses_count":1253,"time_zone":"Pacific Time (US & Canada)","location":"Los Angeles, California","name":"Evan Phoenix","profile_sidebar_fill_color":"A0C5C7","id":5444392,"utc_offset":-28800},"in_reply_to_user_id":null,"in_reply_to_screen_name":null,"id":4485439470,"text":"Thanks to @malafortune, a little elbow grease, and a lot of specs, Rubinius is now largely updated to ruby 1.8.7!"},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Tue Sep 29 14:42:51 +0000 2009","truncated":false,"user":{"geo_enabled":false,"statuses_count":576,"profile_background_tile":false,"followers_count":6571,"description":"O'Reilly Media's group blog about emerging technologies including Web 2.0, location, open source, ambient computing, mobile, web operations, and more.","profile_background_color":"9ae4e8","friends_count":6,"profile_image_url":"http://a3.twimg.com/profile_images/55297199/iphone_icon_radar_normal.png","profile_sidebar_fill_color":"e0ff92","url":"http://radar.oreilly.com","following":true,"favourites_count":0,"screen_name":"radar","verified":false,"profile_sidebar_border_color":"87bc44","created_at":"Mon Jun 02 19:45:48 +0000 2008","time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"Sebastopol, CA","name":"O'Reilly Radar","notifications":false,"profile_background_image_url":"http://s.twimg.com/a/1255384803/images/themes/theme1/bg.png","id":14984090,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4471331911,"text":"David Hoover's Top 5 Tips for Apprentices http://bit.ly/ZOgVm"},{"favorited":false,"in_reply_to_user_id":null,"geo":null,"in_reply_to_screen_name":null,"source":"<a href=\"http://twitterfeed.com\" rel=\"nofollow\">twitterfeed</a>","created_at":"Tue Sep 29 10:42:45 +0000 2009","truncated":false,"user":{"geo_enabled":false,"statuses_count":576,"profile_background_tile":false,"followers_count":6571,"description":"O'Reilly Media's group blog about emerging technologies including Web 2.0, location, open source, ambient computing, mobile, web operations, and more.","profile_background_color":"9ae4e8","friends_count":6,"profile_image_url":"http://a3.twimg.com/profile_images/55297199/iphone_icon_radar_normal.png","profile_sidebar_fill_color":"e0ff92","url":"http://radar.oreilly.com","following":true,"favourites_count":0,"screen_name":"radar","verified":false,"profile_sidebar_border_color":"87bc44","created_at":"Mon Jun 02 19:45:48 +0000 2008","time_zone":"Pacific Time (US & Canada)","protected":false,"profile_text_color":"000000","location":"Sebastopol, CA","name":"O'Reilly Radar","notifications":false,"profile_background_image_url":"http://s.twimg.com/a/1255384803/images/themes/theme1/bg.png","id":14984090,"utc_offset":-28800,"profile_link_color":"0000ff"},"in_reply_to_status_id":null,"id":4467285671,"text":"Four short links: 29 September 2009 http://bit.ly/dYxay"}]
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "example_helper"
|
2
|
+
|
3
|
+
Feature "show the latest statuses" do
|
4
|
+
in_order_to "stay up-to-date"
|
5
|
+
as_a "user"
|
6
|
+
i_want_to "see the latest statuses"
|
7
|
+
|
8
|
+
INJECTION = 'FakeWeb.register_uri(:get, "https://foouser:barpwd@twitter.com/statuses/friends_timeline.json?count=20&page=1", :body => fixture("statuses.json"))'
|
9
|
+
|
10
|
+
Scenario "see the latest statuses with colorization disabled" do
|
11
|
+
When "application is launched with command 'home'" do
|
12
|
+
@status = launch_app("-a foouser:barpwd --no-colorize", INJECTION) do |pid, stdin, stdout|
|
13
|
+
@output = stdout.readlines
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Then "the latest statuses are shown" do
|
18
|
+
@output[0].should == "pelit, 11 days ago:\n"
|
19
|
+
@output[1].should == "F1-kausi alkaa marraskuussa http://bit.ly/1qQwjQ\n"
|
20
|
+
@output[2].should == "\n"
|
21
|
+
@output[58].should == "radar, 15 days ago:\n"
|
22
|
+
@output[59].should == "Four short links: 29 September 2009 http://bit.ly/dYxay\n"
|
23
|
+
@output[60].should == "\n"
|
24
|
+
@status.exitstatus.should == 0
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Scenario "see the latest statuses with colorization enabled" do
|
29
|
+
When "application is launched with command 'home'" do
|
30
|
+
@status = launch_app("-a foouser:barpwd --colorize", INJECTION) do |pid, stdin, stdout|
|
31
|
+
@output = stdout.readlines
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Then "the latest statuses are shown" do
|
36
|
+
@output[0].should == "\e[32mpelit\e[0m, 11 days ago:\n"
|
37
|
+
@output[1].should == "F1-kausi alkaa marraskuussa \e[36mhttp://bit.ly/1qQwjQ\e[0m\n"
|
38
|
+
@output[2].should == "\n"
|
39
|
+
@output[58].should == "\e[32mradar\e[0m, 15 days ago:\n"
|
40
|
+
@output[59].should == "Four short links: 29 September 2009 \e[36mhttp://bit.ly/dYxay\e[0m\n"
|
41
|
+
@output[60].should == "\n"
|
42
|
+
@status.exitstatus.should == 0
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "example_helper"
|
2
|
+
|
3
|
+
Feature "show metadata" do
|
4
|
+
in_order_to "know about the application"
|
5
|
+
as_a "user"
|
6
|
+
i_want_to "see application metadata"
|
7
|
+
|
8
|
+
Scenario "see version" do
|
9
|
+
When "application is launched with -v" do
|
10
|
+
@status = launch_app("-v") do |pid, stdin, stdout|
|
11
|
+
@output = stdout.gets
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Then "version is shown" do
|
16
|
+
@output.should =~ /\d\.\d\.\d$/
|
17
|
+
@status.exitstatus.should == 2
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Scenario "see help" do
|
22
|
+
When "application is launched with -h" do
|
23
|
+
@status = launch_app("-h") do |pid, stdin, stdout|
|
24
|
+
@output = stdout.readlines
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Then "help is shown" do
|
29
|
+
@output[0].should =~ /^Usage:.* \[options\.\.\.\] \[command\]/
|
30
|
+
@output[2].should =~ /Commands: #{Client::COMMANDS.join(", ")}/
|
31
|
+
@output[4].should =~ /Options:$/
|
32
|
+
@status.exitstatus.should == 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/tweetwine/client.rb
CHANGED
@@ -3,6 +3,8 @@ require "uri"
|
|
3
3
|
|
4
4
|
module Tweetwine
|
5
5
|
class Client
|
6
|
+
Dependencies = Struct.new :io, :rest_client, :url_shortener
|
7
|
+
|
6
8
|
attr_reader :num_statuses, :page_num
|
7
9
|
|
8
10
|
COMMANDS = [:home, :mentions, :user, :update, :friends, :followers]
|
@@ -12,15 +14,15 @@ module Tweetwine
|
|
12
14
|
MAX_STATUS_LENGTH = 140
|
13
15
|
|
14
16
|
def initialize(dependencies, options)
|
15
|
-
@io = dependencies
|
16
|
-
@rest_client = dependencies
|
17
|
+
@io = dependencies.io
|
18
|
+
@rest_client = dependencies.rest_client
|
17
19
|
@username = options[:username].to_s
|
18
20
|
raise ArgumentError, "No authentication data given" if @username.empty?
|
19
21
|
@base_url = "https://#{@username}:#{options[:password]}@twitter.com/"
|
20
22
|
@num_statuses = Util.parse_int_gt(options[:num_statuses], DEFAULT_NUM_STATUSES, 1, "number of statuses_to_show")
|
21
23
|
@page_num = Util.parse_int_gt(options[:page_num], DEFAULT_PAGE_NUM, 1, "page number")
|
22
24
|
@url_shortener = if options[:shorten_urls] && options[:shorten_urls][:enable]
|
23
|
-
dependencies
|
25
|
+
dependencies.url_shortener.call(options[:shorten_urls])
|
24
26
|
else
|
25
27
|
nil
|
26
28
|
end
|
data/lib/tweetwine/io.rb
CHANGED
@@ -10,7 +10,7 @@ module Tweetwine
|
|
10
10
|
}
|
11
11
|
|
12
12
|
HASHTAG_REGEX = /#[\w-]+/
|
13
|
-
USERNAME_REGEX =
|
13
|
+
USERNAME_REGEX = /^(@\w+)|\s+(@\w+)/
|
14
14
|
|
15
15
|
def initialize(options)
|
16
16
|
@input = options[:input] || $stdin
|
@@ -79,8 +79,8 @@ module Tweetwine
|
|
79
79
|
def format_status(status)
|
80
80
|
status = status.dup
|
81
81
|
if @colorize
|
82
|
-
|
83
|
-
|
82
|
+
colorize_all_by_group!(:yellow, status, USERNAME_REGEX)
|
83
|
+
colorize_all_by_group!(:magenta, status, HASHTAG_REGEX)
|
84
84
|
URI.extract(status, ["http", "https"]).uniq.each do |url|
|
85
85
|
colorize_all!(:cyan, status, url)
|
86
86
|
end
|
@@ -106,12 +106,16 @@ module Tweetwine
|
|
106
106
|
str.gsub!(pattern) { |s| colorize_str(COLOR_CODES[color.to_sym], s) }
|
107
107
|
end
|
108
108
|
|
109
|
+
def colorize_all_by_group!(color, str, pattern)
|
110
|
+
str.replace Util.str_gsub_by_group(str, pattern) { |s| colorize_str(COLOR_CODES[color.to_sym], s) }
|
111
|
+
end
|
112
|
+
|
109
113
|
def colorize!(color, str)
|
110
114
|
str.replace colorize_str(COLOR_CODES[color.to_sym], str)
|
111
115
|
end
|
112
116
|
|
113
117
|
def colorize_str(color_code, str)
|
114
|
-
"\
|
118
|
+
"\e[#{color_code}m#{str}\e[0m"
|
115
119
|
end
|
116
120
|
end
|
117
121
|
end
|
data/lib/tweetwine/meta.rb
CHANGED
data/lib/tweetwine/util.rb
CHANGED
@@ -40,6 +40,25 @@ module Tweetwine
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
def self.str_gsub_by_group(str, regexp)
|
44
|
+
dup_str = str.dup
|
45
|
+
index, dup_index = 0, 0
|
46
|
+
while index < str.size && (match_data = regexp.match(str[index..-1]))
|
47
|
+
matching_group_indexes = indexes_of_filled_matches(match_data)
|
48
|
+
|
49
|
+
matching_group_indexes.each do |i|
|
50
|
+
replacement = (yield match_data[i]).to_s
|
51
|
+
dup_str[dup_index + match_data.begin(i), match_data[i].size] = replacement
|
52
|
+
replacement_delta = replacement.size - match_data[i].size
|
53
|
+
dup_index += replacement_delta
|
54
|
+
end
|
55
|
+
skip_delta = match_data.end(0)
|
56
|
+
index += skip_delta
|
57
|
+
dup_index += skip_delta
|
58
|
+
end
|
59
|
+
dup_str
|
60
|
+
end
|
61
|
+
|
43
62
|
private
|
44
63
|
|
45
64
|
def self.pluralize_unit(value, unit)
|
@@ -48,5 +67,13 @@ module Tweetwine
|
|
48
67
|
end
|
49
68
|
unit
|
50
69
|
end
|
70
|
+
|
71
|
+
def self.indexes_of_filled_matches(match_data)
|
72
|
+
if match_data.size > 1
|
73
|
+
(1...match_data.size).to_a.reject { |i| match_data[i].nil? }
|
74
|
+
else
|
75
|
+
[0]
|
76
|
+
end
|
77
|
+
end
|
51
78
|
end
|
52
79
|
end
|
data/test/client_test.rb
CHANGED
@@ -12,11 +12,7 @@ class ClientTest < Test::Unit::TestCase
|
|
12
12
|
@rest_client = mock()
|
13
13
|
@url_shortener = mock()
|
14
14
|
url_shortener = lambda { |options| @url_shortener }
|
15
|
-
@deps =
|
16
|
-
:io => @io,
|
17
|
-
:rest_client => @rest_client,
|
18
|
-
:url_shortener => url_shortener
|
19
|
-
}
|
15
|
+
@deps = Client::Dependencies.new @io, @rest_client, url_shortener
|
20
16
|
end
|
21
17
|
|
22
18
|
context "upon initialization" do
|
File without changes
|
data/test/io_test.rb
CHANGED
@@ -118,7 +118,7 @@ barman, in reply to fooman, 2 secs ago:
|
|
118
118
|
should "output a record as user info when no status is given" do
|
119
119
|
record = { :user => "fooman" }
|
120
120
|
@output.expects(:puts).with(<<-END
|
121
|
-
\
|
121
|
+
\e[32mfooman\e[0m
|
122
122
|
|
123
123
|
END
|
124
124
|
)
|
@@ -135,7 +135,7 @@ barman, in reply to fooman, 2 secs ago:
|
|
135
135
|
}
|
136
136
|
Util.expects(:humanize_time_diff).returns([2, "secs"])
|
137
137
|
@output.expects(:puts).with(<<-END
|
138
|
-
\
|
138
|
+
\e[32mfooman\e[0m, 2 secs ago:
|
139
139
|
Wondering the meaning of life.
|
140
140
|
|
141
141
|
END
|
@@ -154,8 +154,8 @@ Wondering the meaning of life.
|
|
154
154
|
}
|
155
155
|
Util.expects(:humanize_time_diff).returns([2, "secs"])
|
156
156
|
@output.expects(:puts).with(<<-END
|
157
|
-
\
|
158
|
-
Hi, \
|
157
|
+
\e[32mbarman\e[0m, in reply to \e[32mfooman\e[0m, 2 secs ago:
|
158
|
+
Hi, \e[33m@fooman\e[0m! How are you doing? \e[35m#hellos\e[0m
|
159
159
|
|
160
160
|
END
|
161
161
|
)
|
@@ -166,7 +166,7 @@ Hi, \033[33m@fooman\033[0m! How are you doing? \033[35m#hellos\033[0m
|
|
166
166
|
status = "@nick, check http://bit.ly/18rU_Vx"
|
167
167
|
@output.expects(:puts).with(<<-END
|
168
168
|
|
169
|
-
\
|
169
|
+
\e[33m@nick\e[0m, check \e[36mhttp://bit.ly/18rU_Vx\e[0m
|
170
170
|
|
171
171
|
END
|
172
172
|
)
|
@@ -183,8 +183,8 @@ Hi, \033[33m@fooman\033[0m! How are you doing? \033[35m#hellos\033[0m
|
|
183
183
|
}
|
184
184
|
Util.expects(:humanize_time_diff).returns([2, "secs"])
|
185
185
|
@output.expects(:puts).with(<<-END
|
186
|
-
\
|
187
|
-
Three links: \
|
186
|
+
\e[32mbarman\e[0m, 2 secs ago:
|
187
|
+
Three links: \e[36mhttp://bit.ly/18rU_Vx\e[0m \e[36mhttp://is.gd/1qLk3\e[0m and \e[36mhttps://is.gd/2rLk4\e[0m
|
188
188
|
|
189
189
|
END
|
190
190
|
)
|
@@ -201,8 +201,8 @@ Three links: \033[36mhttp://bit.ly/18rU_Vx\033[0m \033[36mhttp://is.gd/1qLk3\033
|
|
201
201
|
}
|
202
202
|
Util.expects(:humanize_time_diff).returns([2, "secs"])
|
203
203
|
@output.expects(:puts).with(<<-END
|
204
|
-
\
|
205
|
-
Duplicate links: \
|
204
|
+
\e[32mbarman\e[0m, 2 secs ago:
|
205
|
+
Duplicate links: \e[36mhttp://is.gd/1qLk3\e[0m and \e[36mhttp://is.gd/1qLk3\e[0m
|
206
206
|
|
207
207
|
END
|
208
208
|
)
|
@@ -219,8 +219,26 @@ Duplicate links: \033[36mhttp://is.gd/1qLk3\033[0m and \033[36mhttp://is.gd/1qLk
|
|
219
219
|
}
|
220
220
|
Util.expects(:humanize_time_diff).returns([2, "secs"])
|
221
221
|
@output.expects(:puts).with(<<-END
|
222
|
-
\
|
223
|
-
I salute you \
|
222
|
+
\e[32mbarman\e[0m, 2 secs ago:
|
223
|
+
I salute you \e[33m@fooman\e[0m, \e[33m@barbaz\e[0m, and \e[33m@spoonman\e[0m!
|
224
|
+
|
225
|
+
END
|
226
|
+
)
|
227
|
+
@io.show_record(record)
|
228
|
+
end
|
229
|
+
|
230
|
+
should "not highlight email addresses as usernames in a status" do
|
231
|
+
record = {
|
232
|
+
:user => "barman",
|
233
|
+
:status => {
|
234
|
+
:created_at => Time.at(1),
|
235
|
+
:text => "Hi, @fooman! You should notify @barbaz, barbaz@foo.net",
|
236
|
+
}
|
237
|
+
}
|
238
|
+
Util.expects(:humanize_time_diff).returns([2, "secs"])
|
239
|
+
@output.expects(:puts).with(<<-END
|
240
|
+
\e[32mbarman\e[0m, 2 secs ago:
|
241
|
+
Hi, \e[33m@fooman\e[0m! You should notify \e[33m@barbaz\e[0m, barbaz@foo.net
|
224
242
|
|
225
243
|
END
|
226
244
|
)
|
@@ -233,15 +251,19 @@ I salute you \033[33m@fooman\033[0m, \033[33m@barbaz\033[0m, and \033[33m@spoonm
|
|
233
251
|
should "match a proper username reference" do
|
234
252
|
assert_full_match IO::USERNAME_REGEX, "@nick"
|
235
253
|
assert_full_match IO::USERNAME_REGEX, "@nick_man"
|
254
|
+
assert_full_match IO::USERNAME_REGEX, "@nick"
|
255
|
+
assert_full_match IO::USERNAME_REGEX, " @nick"
|
236
256
|
end
|
237
257
|
|
238
258
|
should "not match an inproper username reference" do
|
239
259
|
assert_no_full_match IO::USERNAME_REGEX, "@"
|
240
260
|
assert_no_full_match IO::USERNAME_REGEX, "nick"
|
261
|
+
assert_no_full_match IO::USERNAME_REGEX, "-@nick"
|
241
262
|
assert_no_full_match IO::USERNAME_REGEX, "@nick-man"
|
242
|
-
assert_no_full_match IO::USERNAME_REGEX, " @nick"
|
243
263
|
assert_no_full_match IO::USERNAME_REGEX, "@nick "
|
244
264
|
assert_no_full_match IO::USERNAME_REGEX, " @nick "
|
265
|
+
assert_no_full_match IO::USERNAME_REGEX, "man @nick"
|
266
|
+
assert_no_full_match IO::USERNAME_REGEX, "man@nick"
|
245
267
|
end
|
246
268
|
end
|
247
269
|
|
data/test/startup_config_test.rb
CHANGED
@@ -3,7 +3,7 @@ require "test_helper"
|
|
3
3
|
module Tweetwine
|
4
4
|
|
5
5
|
class StartupConfigTest < Test::Unit::TestCase
|
6
|
-
TEST_CONFIG_FILE = File.dirname(__FILE__) << "/test_config.yaml"
|
6
|
+
TEST_CONFIG_FILE = File.dirname(__FILE__) << "/fixtures/test_config.yaml"
|
7
7
|
|
8
8
|
context "A StartupConfig instance" do
|
9
9
|
context "upon initialization" do
|
data/test/util_test.rb
CHANGED
@@ -50,6 +50,37 @@ class UtilTest < Test::Unit::TestCase
|
|
50
50
|
assert_equal 8, Util.parse_int_gt(false, 8, 4, "ethical working hours per day")
|
51
51
|
assert_raise(ArgumentError) { Util.parse_int_gt(3, 8, 4, "ethical working hours per day") }
|
52
52
|
end
|
53
|
+
|
54
|
+
context "for replacing the contents of a string with a regexp that uses group syntax" do
|
55
|
+
should "replace the contents by using the matching groups of the regexp" do
|
56
|
+
assert_equal "hello", Util.str_gsub_by_group("hello", /he(f)/) { |s| s.upcase }
|
57
|
+
assert_equal "", Util.str_gsub_by_group("", /.+([ai])/) { |s| s.upcase }
|
58
|
+
assert_equal "hello", Util.str_gsub_by_group("hello", /.+([ai])/) { |s| s.upcase }
|
59
|
+
assert_equal "hEllo", Util.str_gsub_by_group("hello", /.+(e)/) { |s| s.upcase }
|
60
|
+
assert_equal "hEllO", Util.str_gsub_by_group("hello", /([aeio])/) { |s| s.upcase }
|
61
|
+
assert_equal "hEEllOO", Util.str_gsub_by_group("hello", /([aeio])/) { |s| s.upcase * 2 }
|
62
|
+
assert_equal "hEllO", Util.str_gsub_by_group("hello", /([ae]).+([io])/) { |s| s.upcase }
|
63
|
+
assert_equal "hXEXllXOX", Util.str_gsub_by_group("hello", /([ae]).+([io])/) { |s| "X" + s.upcase + "X" }
|
64
|
+
assert_equal "hll", Util.str_gsub_by_group("hello", /.+([ae]).+([io])/) { |s| "" }
|
65
|
+
assert_equal "hll", Util.str_gsub_by_group("hello", /([ae]).+([io])/) { |s| "" }
|
66
|
+
assert_equal "hll", Util.str_gsub_by_group("hello", /([aeio])/) { |s| "" }
|
67
|
+
assert_equal "hell", Util.str_gsub_by_group("hello", /.+([io])/) { |s| "" }
|
68
|
+
assert_equal "hEllo", Util.str_gsub_by_group("hello", /^(a)|.+(e)/) { |s| s.upcase }
|
69
|
+
end
|
70
|
+
|
71
|
+
should "replace the contents by using the whole match if there are no groups in the regexp" do
|
72
|
+
assert_equal "", Util.str_gsub_by_group("", /el/) { |s| s.upcase }
|
73
|
+
assert_equal "hELlo", Util.str_gsub_by_group("hello", /el/) { |s| s.upcase }
|
74
|
+
end
|
75
|
+
|
76
|
+
should "return a new string as the result" do
|
77
|
+
org_str = "hello"
|
78
|
+
new_str = Util.str_gsub_by_group(org_str, /e/) { |s| s.upcase }
|
79
|
+
assert_not_same new_str, org_str
|
80
|
+
assert_equal "hello", org_str
|
81
|
+
assert_equal "hEllo", new_str
|
82
|
+
end
|
83
|
+
end
|
53
84
|
end
|
54
85
|
|
55
86
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tweetwine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tuomas Kareinen
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10-
|
12
|
+
date: 2009-10-14 00:00:00 +03:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -38,7 +38,10 @@ files:
|
|
38
38
|
- CHANGELOG.rdoc
|
39
39
|
- README.rdoc
|
40
40
|
- bin/tweetwine
|
41
|
-
-
|
41
|
+
- example/example_helper.rb
|
42
|
+
- example/fixtures/statuses.json
|
43
|
+
- example/show_latest_statuses_example.rb
|
44
|
+
- example/show_metadata_example.rb
|
42
45
|
- lib/tweetwine/client.rb
|
43
46
|
- lib/tweetwine/io.rb
|
44
47
|
- lib/tweetwine/meta.rb
|
@@ -49,20 +52,22 @@ files:
|
|
49
52
|
- lib/tweetwine/util.rb
|
50
53
|
- lib/tweetwine.rb
|
51
54
|
- test/client_test.rb
|
55
|
+
- test/fixtures/test_config.yaml
|
52
56
|
- test/io_test.rb
|
53
57
|
- test/options_test.rb
|
54
58
|
- test/rest_client_wrapper_test.rb
|
55
59
|
- test/startup_config_test.rb
|
56
|
-
- test/test_config.yaml
|
57
60
|
- test/test_helper.rb
|
58
61
|
- test/url_shortener_test.rb
|
59
62
|
- test/util_test.rb
|
60
63
|
has_rdoc: true
|
61
64
|
homepage: http://github.com/tuomas/tweetwine
|
65
|
+
licenses: []
|
66
|
+
|
62
67
|
post_install_message:
|
63
68
|
rdoc_options:
|
64
69
|
- --title
|
65
|
-
- tweetwine 0.2.
|
70
|
+
- tweetwine 0.2.5
|
66
71
|
- --main
|
67
72
|
- README.rdoc
|
68
73
|
- --exclude
|
@@ -85,9 +90,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
90
|
requirements: []
|
86
91
|
|
87
92
|
rubyforge_project:
|
88
|
-
rubygems_version: 1.3.
|
93
|
+
rubygems_version: 1.3.5
|
89
94
|
signing_key:
|
90
|
-
specification_version:
|
95
|
+
specification_version: 3
|
91
96
|
summary: A simple Twitter agent for command line use
|
92
97
|
test_files: []
|
93
98
|
|