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 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: tweetwine [options...] [command]
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 "#{File.basename($0)} #{Tweetwine::VERSION}"
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
@@ -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[:io]
16
- @rest_client = dependencies[:rest_client]
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[:url_shortener].call(options[:shorten_urls])
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 = /@\w+/
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
- colorize_all!(:yellow, status, USERNAME_REGEX)
83
- colorize_all!(:magenta, status, HASHTAG_REGEX)
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
- "\033[#{color_code}m#{str}\033[0m"
118
+ "\e[#{color_code}m#{str}\e[0m"
115
119
  end
116
120
  end
117
121
  end
@@ -1,3 +1,3 @@
1
1
  module Tweetwine
2
- VERSION = "0.2.4"
2
+ VERSION = "0.2.5"
3
3
  end
@@ -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
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
- \033[32mfooman\033[0m
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
- \033[32mfooman\033[0m, 2 secs ago:
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
- \033[32mbarman\033[0m, in reply to \033[32mfooman\033[0m, 2 secs ago:
158
- Hi, \033[33m@fooman\033[0m! How are you doing? \033[35m#hellos\033[0m
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
- \033[33m@nick\033[0m, check \033[36mhttp://bit.ly/18rU_Vx\033[0m
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
- \033[32mbarman\033[0m, 2 secs ago:
187
- Three links: \033[36mhttp://bit.ly/18rU_Vx\033[0m \033[36mhttp://is.gd/1qLk3\033[0m and \033[36mhttps://is.gd/2rLk4\033[0m
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
- \033[32mbarman\033[0m, 2 secs ago:
205
- Duplicate links: \033[36mhttp://is.gd/1qLk3\033[0m and \033[36mhttp://is.gd/1qLk3\033[0m
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
- \033[32mbarman\033[0m, 2 secs ago:
223
- I salute you \033[33m@fooman\033[0m, \033[33m@barbaz\033[0m, and \033[33m@spoonman\033[0m!
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
 
@@ -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
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 00:00:00 +03:00
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
- - lib/tweetwine
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.4
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.1
93
+ rubygems_version: 1.3.5
89
94
  signing_key:
90
- specification_version: 2
95
+ specification_version: 3
91
96
  summary: A simple Twitter agent for command line use
92
97
  test_files: []
93
98