tweetwine 0.4.0 → 0.4.1

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/.gitignore CHANGED
@@ -4,3 +4,4 @@
4
4
  /coverage/
5
5
  /man/
6
6
  !/man/*.ronn
7
+ /rdoc/
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,8 @@
1
+ === 0.4.1 released 2011-03-23
2
+
3
+ * Handle socket errors just like connection errors
4
+ * Minor cleanups
5
+
1
6
  === 0.4.0 released 2011-02-22
2
7
 
3
8
  * Add option <tt>-r</tt> to reverse the order of showing tweets
File without changes
data/Rakefile CHANGED
@@ -1,51 +1,51 @@
1
1
  # coding: utf-8
2
2
 
3
- require 'rake/clean'
3
+ require File.expand_path('project', File.dirname(__FILE__))
4
4
 
5
- $LOAD_PATH.unshift(File.expand_path('lib', File.dirname(__FILE__)))
6
- name = 'tweetwine'
7
- require "#{name}/version"
8
- version = Tweetwine.version
5
+ require 'rake/clean'
9
6
 
10
7
  namespace :gem do
11
- CLOBBER.include "#{name}-*.gem"
8
+ CLOBBER.include "#{Project.name}-*.gem"
12
9
 
13
- file "#{name}-#{version}.gem" do |f|
14
- sh %{gem build #{name}.gemspec}
10
+ current_gem = "#{Project.name}-#{Project.version}.gem"
11
+
12
+ file current_gem do |f|
13
+ sh %{gem build #{Project.name}.gemspec}
15
14
  end
16
15
 
17
16
  desc "Package the software as a gem"
18
- task :build => [:"man:build", :"test:all", "#{name}-#{version}.gem"]
17
+ task :build => [:"man:build", :"test:all", current_gem]
19
18
 
20
19
  desc "Install the software as a gem"
21
20
  task :install => :build do
22
- sh %{gem install #{name}-#{version}.gem}
21
+ sh %{gem install #{current_gem}}
23
22
  end
24
23
 
25
24
  desc "Uninstall the gem"
26
25
  task :uninstall => :clean do
27
- sh %{gem uninstall #{name}}
26
+ sh %{gem uninstall #{Project.name}}
28
27
  end
29
28
  end
30
29
 
31
30
  namespace :man do
32
- CLOBBER.include "man/#{name}.?", "man/#{name}.?.html"
31
+ CLOBBER.include "#{Project.dirs.man}/#{Project.name}.?", "#{Project.dirs.man}/#{Project.name}.?.html"
33
32
 
34
33
  desc "Build the manual"
35
34
  task :build do
36
- sh "ronn -br5 --manual='#{name.capitalize} Manual' --organization='Tuomas Kareinen' man/*.ronn"
35
+ sh %{ronn -br5 --manual='#{Project.name.capitalize} Manual' --organization='#{Project.authors.first}' #{Project.dirs.man}/*.ronn}
37
36
  end
38
37
 
39
38
  desc "Show the manual section 7"
40
39
  task :show => :build do
41
- sh "man man/#{name}.7"
40
+ sh %{man #{Project.dirs.man}/#{Project.name}.7}
42
41
  end
43
42
  end
44
43
 
45
- CLOBBER.include 'rdoc'
44
+ CLOBBER.include Project.dirs.rdoc
45
+
46
46
  desc "Generate RDoc"
47
47
  task :rdoc do
48
- sh %{rdoc --encoding=UTF-8 --line-numbers --title='#{name} #{version}' --output=rdoc *.rdoc LICENSE.txt lib}
48
+ sh %{rdoc --encoding=UTF-8 --line-numbers --title='#{Project.title}' --output=#{Project.dirs.rdoc} *.rdoc LICENSE.txt lib}
49
49
  end
50
50
 
51
51
  namespace :test do
@@ -53,7 +53,7 @@ namespace :test do
53
53
  base_dir = options[:base_dir]
54
54
  file_glob = options[:file_glob]
55
55
  test_desc = options[:desc] || "Run #{type} tests"
56
- includes = ['lib', 'test', base_dir].map { |dir| "-I #{dir}" }.join(' ')
56
+ includes = ['lib', Project.dirs.test, base_dir].map { |dir| "-I #{dir}" }.join(' ')
57
57
  warn_opt = options[:warn] ? '-w' : ''
58
58
 
59
59
  desc test_desc
@@ -68,11 +68,11 @@ namespace :test do
68
68
  end
69
69
 
70
70
  create_test_task :unit,
71
- :base_dir => 'test/unit',
71
+ :base_dir => "#{Project.dirs.test}/unit",
72
72
  :file_glob => '**/*_test.rb',
73
73
  :warn => true
74
74
  create_test_task :example,
75
- :base_dir => 'test/example',
75
+ :base_dir => "#{Project.dirs.test}/example",
76
76
  :file_glob => '**/*_example.rb',
77
77
  :desc => 'Run integration/example tests',
78
78
  :warn => false
@@ -80,12 +80,10 @@ module Tweetwine
80
80
  response = yield connection, uri
81
81
  raise HttpError.new(response.code, response.message) unless response.is_a? Net::HTTPSuccess
82
82
  response.body
83
- rescue Errno::ECONNABORTED, Errno::ECONNRESET => e
83
+ rescue Errno::ECONNABORTED, Errno::ECONNRESET, SocketError => e
84
84
  raise ConnectionError, e
85
85
  rescue Timeout::Error => e
86
86
  raise TimeoutError, e
87
- rescue Net::HTTPError => e
88
- raise HttpError, e
89
87
  end
90
88
 
91
89
  def https_scheme?(uri)
data/lib/tweetwine/ui.rb CHANGED
@@ -10,6 +10,7 @@ module Tweetwine
10
10
  }.freeze
11
11
  HASHTAG_REGEX = /#[\w-]+/
12
12
  USERNAME_REGEX = /^(@\w+)|\s+(@\w+)/
13
+ URI_SCHEMES_TO_COLORIZE = %w{http https}
13
14
 
14
15
  def initialize(options = {})
15
16
  @in = options[:in] || $stdin
@@ -96,7 +97,7 @@ module Tweetwine
96
97
  if @colors
97
98
  status = colorize_matching(:yellow, status, USERNAME_REGEX)
98
99
  status = colorize_matching(:magenta, status, HASHTAG_REGEX)
99
- status = colorize_matching(:cyan, status, Uri.extract(status, %w{http https}).uniq)
100
+ status = colorize_matching(:cyan, status, Uri.extract(status, URI_SCHEMES_TO_COLORIZE).uniq)
100
101
  end
101
102
  status
102
103
  end
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Tweetwine
4
- VERSION = '0.4.0'.freeze
4
+ VERSION = '0.4.1'.freeze
5
5
 
6
6
  class << self
7
7
  def version
data/project.rb ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+
3
+ require 'ostruct'
4
+
5
+ name = 'tweetwine'
6
+ $LOAD_PATH.unshift File.expand_path('lib', File.dirname(__FILE__))
7
+ require "#{name}/version"
8
+
9
+ Project = OpenStruct.new({
10
+ :name => name,
11
+ :version => Tweetwine.version.dup,
12
+ :summary => Tweetwine.summary,
13
+ :description => '',
14
+ :email => 'tkareine@gmail.com',
15
+ :homepage => 'https://github.com/tkareine/tweetwine',
16
+ :authors => ['Tuomas Kareinen'],
17
+ :dirs => OpenStruct.new({
18
+ :man => 'man',
19
+ :rdoc => 'rdoc',
20
+ :test => 'test'
21
+ }).freeze
22
+ })
23
+
24
+ Project.description = <<-END
25
+ A simple but tasty Twitter agent for command line use, designed for quickly
26
+ showing the latest tweets.
27
+ END
28
+ Project.title = "#{Project.name} #{Project.version}"
29
+
30
+ Project.freeze
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- require "test_helper"
3
+ require "unit_helper"
4
4
 
5
5
  require "fileutils"
6
6
  require "tempfile"
@@ -190,10 +190,7 @@ class ConfigTest < UnitTestCase
190
190
  end
191
191
 
192
192
  should "ignore nonexisting config file for initial read" do
193
- assert_contains_exactly(@default_config.keys, @config.keys) do |a, b|
194
- # On Ruby 1.8, Symbol does not have #<=> operator for comparison.
195
- a.to_s <=> b.to_s
196
- end
193
+ assert_contains_exactly @default_config.keys, @config.keys
197
194
  end
198
195
 
199
196
  should "save config to the file, implicitly without config file, env lookouts, and excludes set itself" do
@@ -79,17 +79,18 @@ class HttpTest < UnitTestCase
79
79
  end
80
80
 
81
81
  [
82
- [Errno::ECONNABORTED, 'abort'],
83
- [Errno::ECONNRESET, 'reset']
84
- ].each do |error, desc|
85
- should "retry connection upon connection #{desc} to #{method} request" do
82
+ [Errno::ECONNABORTED, 'connection abort'],
83
+ [Errno::ECONNRESET, 'connection reset'],
84
+ [SocketError, 'socket error']
85
+ ].each do |(error, desc)|
86
+ should "retry connection upon #{desc} to #{method} request" do
86
87
  stub_request(method, LATEST_ARTICLES_URL).to_raise(error).then.to_return(:body => RESPONSE_BODY)
87
88
  @ui.expects(:warn).with("Could not connect -- retrying in 4 seconds")
88
89
  @client.send(method, LATEST_ARTICLES_URL)
89
90
  assert_equal(RESPONSE_BODY, @client.send(method, LATEST_ARTICLES_URL))
90
91
  end
91
92
 
92
- should "retry connection a maximum of certain number of times upon connection #{desc} to #{method} request" do
93
+ should "retry connection a maximum of certain number of times upon #{desc} to #{method} request" do
93
94
  stub_request(method, LATEST_ARTICLES_URL).to_raise(error)
94
95
  io_calls = sequence("IO")
95
96
  Http::Client::MAX_RETRIES.times { @ui.expects(:warn).in_sequence(io_calls) }
@@ -48,6 +48,8 @@ class PromiseTest < UnitTestCase
48
48
  assert_equal(@result.to_s, @promise.to_s)
49
49
  end
50
50
 
51
+ private
52
+
51
53
  def eval_action
52
54
  @promise * 42 # just do something with it
53
55
  end
@@ -16,28 +16,28 @@ class SupportTest < UnitTestCase
16
16
  ["foo", false, "nonempty string"],
17
17
  [[], true, "empty array"],
18
18
  [%w{a b}, false, "nonempty array"]
19
- ].each do |(subject, emptiness, description)|
20
- should "return #{emptiness} for blank? with #{description}" do
19
+ ].each do |(subject, emptiness, desc)|
20
+ should "return #{emptiness} for blank? with #{desc}" do
21
21
  assert_equal emptiness, blank?(subject)
22
22
  end
23
23
 
24
- should "return #{!emptiness} for present? with #{description}" do
24
+ should "return #{!emptiness} for present? with #{desc}" do
25
25
  assert_equal !emptiness, present?(subject)
26
26
  end
27
27
 
28
- should "return non-empty subject for presence, when subject is #{description}" do
28
+ should "return non-empty subject for presence, when subject is #{desc}" do
29
29
  actual = presence(subject)
30
30
  expected = present?(subject) ? subject : nil
31
31
  assert_same expected, actual
32
32
  end
33
33
 
34
- should "return value of block for presence, when subject is #{description}" do
34
+ should "return value of block for presence, when subject is #{desc}" do
35
35
  actual = presence(subject) { |s| s.size }
36
36
  expected = present?(subject) ? subject.size : nil
37
37
  assert_same expected, actual
38
38
  end
39
39
 
40
- should "allow presence to be used with || operator, when subject is #{description}" do
40
+ should "allow presence to be used with || operator, when subject is #{desc}" do
41
41
  alternative = "hey"
42
42
  actual = presence(subject) || alternative
43
43
  expected = present?(subject) ? subject : alternative
@@ -47,31 +47,66 @@ class SupportTest < UnitTestCase
47
47
  end
48
48
 
49
49
  context "for humanizing time differences" do
50
+ should "accept string and time arguments" do
51
+ start = '2009-01-01 01:01:00'
52
+ stop = Time.parse '2009-01-01 01:03:00'
53
+ assert_commutative([2, 'min'], [start, stop]) do |a, b|
54
+ humanize_time_diff(a, b)
55
+ end
56
+ end
57
+
50
58
  should "use second granularity for time differences smaller than a minute" do
51
- assert_equal [1, "sec"], humanize_time_diff(Time.parse("2009-01-01 00:00:59").to_s, Time.parse("2009-01-01 00:01:00"))
52
- assert_equal [0, "sec"], humanize_time_diff(Time.parse("2009-01-01 01:00:00").to_s, Time.parse("2009-01-01 01:00:00"))
53
- assert_equal [1, "sec"], humanize_time_diff(Time.parse("2009-01-01 01:00:00").to_s, Time.parse("2009-01-01 01:00:01"))
54
- assert_equal [59, "sec"], humanize_time_diff(Time.parse("2009-01-01 01:00:00").to_s, Time.parse("2009-01-01 01:00:59"))
59
+ [
60
+ [0, '2009-01-01 01:00:00', '2009-01-01 01:00:00'],
61
+ [1, '2009-01-01 00:00:59', '2009-01-01 00:01:00'],
62
+ [1, '2009-01-01 01:00:00', '2009-01-01 01:00:01'],
63
+ [59, '2009-01-01 01:00:00', '2009-01-01 01:00:59']
64
+ ].each do |(diff, start, stop)|
65
+ assert_commutative([diff, 'sec'], [start, stop]) do |a, b|
66
+ humanize_time_diff(a, b)
67
+ end
68
+ end
55
69
  end
56
70
 
57
71
  should "use minute granularity for time differences greater than a minute but smaller than an hour" do
58
- assert_equal [59, "min"], humanize_time_diff(Time.parse("2009-01-01 01:00").to_s, Time.parse("2009-01-01 01:59"))
59
- assert_equal [59, "min"], humanize_time_diff(Time.parse("2009-01-01 01:00:30").to_s, Time.parse("2009-01-01 01:59:00"))
60
- assert_equal [57, "min"], humanize_time_diff(Time.parse("2009-01-01 01:01:00").to_s, Time.parse("2009-01-01 01:58:00"))
61
- assert_equal [56, "min"], humanize_time_diff(Time.parse("2009-01-01 01:01:31").to_s, Time.parse("2009-01-01 01:58:00"))
62
- assert_equal [57, "min"], humanize_time_diff(Time.parse("2009-01-01 01:01:00").to_s, Time.parse("2009-01-01 01:58:29"))
63
- assert_equal [58, "min"], humanize_time_diff(Time.parse("2009-01-01 01:01:00").to_s, Time.parse("2009-01-01 01:58:30"))
72
+ [
73
+ [1, '2009-01-01 01:00:00', '2009-01-01 01:01:00'],
74
+ [2, '2009-01-01 01:01:00', '2009-01-01 01:03:29'],
75
+ [3, '2009-01-01 01:01:00', '2009-01-01 01:03:30'],
76
+ [59, '2009-01-01 01:00:00', '2009-01-01 01:59:00'],
77
+ [59, '2009-01-01 01:00:30', '2009-01-01 01:59:00'],
78
+ [57, '2009-01-01 01:01:00', '2009-01-01 01:58:00']
79
+ ].each do |(diff, start, stop)|
80
+ assert_commutative([diff, 'min'], [start, stop]) do |a, b|
81
+ humanize_time_diff(a, b)
82
+ end
83
+ end
64
84
  end
65
85
 
66
86
  should "use hour granularity for time differences greater than an hour but smaller than a day" do
67
- assert_equal [1, "hour"], humanize_time_diff(Time.parse("2009-01-01 01:00").to_s, Time.parse("2009-01-01 02:00"))
68
- assert_equal [1, "hour"], humanize_time_diff(Time.parse("2009-01-01 02:00").to_s, Time.parse("2009-01-01 01:00"))
69
- assert_equal [2, "hours"], humanize_time_diff(Time.parse("2009-01-01 01:00").to_s, Time.parse("2009-01-01 03:00"))
87
+ [
88
+ [1, 'hour', '2009-01-01 01:00', '2009-01-01 02:00'],
89
+ [2, 'hours', '2009-01-01 01:00', '2009-01-01 03:00'],
90
+ [2, 'hours', '2009-01-01 01:00', '2009-01-01 03:29'],
91
+ [3, 'hours', '2009-01-01 01:00', '2009-01-01 03:30']
92
+ ].each do |(diff, unit, start, stop)|
93
+ assert_commutative([diff, unit], [start, stop]) do |a, b|
94
+ humanize_time_diff(a, b)
95
+ end
96
+ end
70
97
  end
71
98
 
72
99
  should "use day granularity for time differences greater than a day" do
73
- assert_equal [1, "day"], humanize_time_diff(Time.parse("2009-01-01 01:00").to_s, Time.parse("2009-01-02 03:00"))
74
- assert_equal [2, "days"], humanize_time_diff(Time.parse("2009-01-01 01:00").to_s, Time.parse("2009-01-03 03:00"))
100
+ [
101
+ [1, 'day', '2009-01-01 01:00', '2009-01-02 01:00'],
102
+ [2, 'days', '2009-01-01 01:00', '2009-01-03 01:00'],
103
+ [2, 'days', '2009-01-01 01:00', '2009-01-03 12:59'],
104
+ [3, 'days', '2009-01-01 01:00', '2009-01-03 13:00']
105
+ ].each do |(diff, unit, start, stop)|
106
+ assert_commutative([diff, unit], [start, stop]) do |a, b|
107
+ humanize_time_diff(a, b)
108
+ end
109
+ end
75
110
  end
76
111
  end
77
112
 
@@ -194,7 +229,7 @@ class SupportTest < UnitTestCase
194
229
  %w{- dash},
195
230
  %w{_ underscore},
196
231
  %w{+ plus}
197
- ].each do |char, desc|
232
+ ].each do |(char, desc)|
198
233
  should "not affect already unescaped characters, case #{desc}" do
199
234
  assert_equal char, unescape_html(char)
200
235
  end
@@ -206,7 +241,7 @@ class SupportTest < UnitTestCase
206
241
  %w{&amp; &},
207
242
  %w{&quot; "},
208
243
  %W{&nbsp; \ }
209
- ].each do |input, expected|
244
+ ].each do |(input, expected)|
210
245
  should "unescape HTML-escaped characters, case '#{input}'" do
211
246
  assert_equal expected, unescape_html(input)
212
247
  end
@@ -228,12 +263,12 @@ class SupportTest < UnitTestCase
228
263
  end
229
264
 
230
265
  should "support both a non-array and a single element array path for finding the value" do
231
- assert_equal "beautiful", find_hash_path(@outer_hash, :simple)
232
- assert_equal "beautiful", find_hash_path(@outer_hash, [:simple])
266
+ assert_equal @outer_hash[:simple], find_hash_path(@outer_hash, :simple)
267
+ assert_equal @outer_hash[:simple], find_hash_path(@outer_hash, [:simple])
233
268
  end
234
269
 
235
270
  should "find a nested value with an array path" do
236
- assert_equal "slick", find_hash_path(@outer_hash, [:inner, :salmon])
271
+ assert_equal @inner_hash[:salmon], find_hash_path(@outer_hash, [:inner, :salmon])
237
272
  end
238
273
 
239
274
  should "return the default value of the hash if the value cannot be found" do
@@ -243,15 +278,19 @@ class SupportTest < UnitTestCase
243
278
  end
244
279
 
245
280
  should "return the default value of the hash if invalid path value" do
246
- assert_equal @outer_hash.default, find_hash_path(@outer_hash, nil)
247
- assert_equal @outer_hash.default, find_hash_path(@outer_hash, [:no_such, nil])
248
- assert_equal @outer_hash.default, find_hash_path(@outer_hash, [:simple, nil])
249
- assert_equal @outer_hash.default, find_hash_path(@outer_hash, [:inner, nil])
250
- assert_equal @outer_hash.default, find_hash_path(@outer_hash, [:inner, :salmon, nil])
281
+ [
282
+ nil,
283
+ [:no_such, nil],
284
+ [:simple, nil],
285
+ [:inner, nil],
286
+ [:inner, :salmon, nil]
287
+ ].each do |path|
288
+ assert_equal @outer_hash.default, find_hash_path(@outer_hash, path)
289
+ end
251
290
  end
252
291
 
253
292
  should "return nil if nil hash value" do
254
- assert_equal nil, find_hash_path(nil, nil)
293
+ assert_equal nil, find_hash_path(nil, [:salmon])
255
294
  end
256
295
  end
257
296
  end
@@ -1,5 +1,7 @@
1
1
  # coding: utf-8
2
2
 
3
+ require 'timecop'
4
+
3
5
  module Tweetwine::Test
4
6
  module TweetHelper
5
7
  FIELD_PATHS = {
@@ -10,11 +12,13 @@ module Tweetwine::Test
10
12
  :status => %w{status text}
11
13
  }.freeze
12
14
 
15
+ DEFAULT_TIMESTAMP = Time.utc(2011, 'feb', 17, 22, 28, 0)
16
+
13
17
  DEFAULT_FIELD_VALUES = {
14
18
  :from_user => 'fred',
15
19
  :to_user => nil,
16
20
  :retweet => nil,
17
- :created_at => Time.utc(2011, 'feb', 17, 22, 28, 0).iso8601,
21
+ :created_at => DEFAULT_TIMESTAMP.iso8601,
18
22
  :status => nil
19
23
  }.freeze
20
24
 
@@ -38,6 +42,14 @@ module Tweetwine::Test
38
42
  Tweetwine::Tweet.new(create_record(fields), FIELD_PATHS)
39
43
  end
40
44
 
45
+ def at_default_time(&block)
46
+ Timecop.freeze(TweetHelper::DEFAULT_TIMESTAMP, &block)
47
+ end
48
+
49
+ def create_timestamp(minus_seconds)
50
+ (TweetHelper::DEFAULT_TIMESTAMP - minus_seconds).iso8601
51
+ end
52
+
41
53
  private
42
54
 
43
55
  def find_hash_of_field_path(hash, path)
@@ -14,7 +14,7 @@ class TweetTest < UnitTestCase
14
14
  end
15
15
  end
16
16
 
17
- context "for equivalence" do
17
+ context "for equality" do
18
18
  should "equal to another tweet with same content" do
19
19
  status = 'foo'
20
20
  first = create_tweet(:status => status)
data/test/unit/ui_test.rb CHANGED
@@ -86,18 +86,19 @@ class UITest < UnitTestCase
86
86
  should "output regular tweet" do
87
87
  from_user = "fooman"
88
88
  status = "Hi, @barman! Lulz woo! #hellos"
89
+ time = 2
89
90
  tweet = create_tweet(
90
91
  :from_user => from_user,
91
- :status => status
92
+ :status => status,
93
+ :created_at => create_timestamp(time)
92
94
  )
93
- Support.expects(:humanize_time_diff).returns([2, "secs"])
94
95
  @out.expects(:puts).with(<<-END
95
- #{from_user}, 2 secs ago:
96
+ #{from_user}, #{time} sec ago:
96
97
  #{status}
97
98
 
98
99
  END
99
100
  )
100
- @ui.show_tweet(tweet)
101
+ show_tweet_at_default_time(tweet)
101
102
  end
102
103
 
103
104
  should "output replying tweet" do
@@ -109,14 +110,13 @@ class UITest < UnitTestCase
109
110
  :status => status,
110
111
  :to_user => to_user
111
112
  )
112
- Support.expects(:humanize_time_diff).returns([2, "secs"])
113
113
  @out.expects(:puts).with(<<-END
114
- #{from_user}, in reply to #{to_user}, 2 secs ago:
114
+ #{from_user}, in reply to #{to_user}, 0 sec ago:
115
115
  #{status}
116
116
 
117
117
  END
118
118
  )
119
- @ui.show_tweet(tweet)
119
+ show_tweet_at_default_time(tweet)
120
120
  end
121
121
 
122
122
  should "output regular retweet" do
@@ -128,14 +128,13 @@ class UITest < UnitTestCase
128
128
  :status => status,
129
129
  :rt_user => rt_user
130
130
  )
131
- Support.expects(:humanize_time_diff).returns([2, "secs"])
132
131
  @out.expects(:puts).with(<<-END
133
- #{rt_user} RT #{from_user}, 2 secs ago:
132
+ #{rt_user} RT #{from_user}, 0 sec ago:
134
133
  #{status}
135
134
 
136
135
  END
137
136
  )
138
- @ui.show_tweet(tweet)
137
+ show_tweet_at_default_time(tweet)
139
138
  end
140
139
 
141
140
  should "output replying retweet" do
@@ -149,14 +148,13 @@ class UITest < UnitTestCase
149
148
  :status => status,
150
149
  :rt_user => rt_user
151
150
  )
152
- Support.expects(:humanize_time_diff).returns([2, "secs"])
153
151
  @out.expects(:puts).with(<<-END
154
- #{rt_user} RT #{from_user}, in reply to #{to_user}, 2 secs ago:
152
+ #{rt_user} RT #{from_user}, in reply to #{to_user}, 0 sec ago:
155
153
  #{status}
156
154
 
157
155
  END
158
156
  )
159
- @ui.show_tweet(tweet)
157
+ show_tweet_at_default_time(tweet)
160
158
  end
161
159
 
162
160
  should "unescape HTML in a status" do
@@ -167,14 +165,13 @@ class UITest < UnitTestCase
167
165
  :from_user => from_user,
168
166
  :status => escaped_status
169
167
  )
170
- Support.expects(:humanize_time_diff).returns([2, "secs"])
171
168
  @out.expects(:puts).with(<<-END
172
- #{from_user}, 2 secs ago:
169
+ #{from_user}, 0 sec ago:
173
170
  #{unescaped_status}
174
171
 
175
172
  END
176
173
  )
177
- @ui.show_tweet(tweet)
174
+ show_tweet_at_default_time(tweet)
178
175
  end
179
176
 
180
177
  should "output a preview of a status" do
@@ -212,14 +209,13 @@ class UITest < UnitTestCase
212
209
  :from_user => from_user,
213
210
  :status => status
214
211
  )
215
- Support.expects(:humanize_time_diff).returns([2, "secs"])
216
212
  @out.expects(:puts).with(<<-END
217
- \e[32m#{from_user}\e[0m, 2 secs ago:
213
+ \e[32m#{from_user}\e[0m, 0 sec ago:
218
214
  #{status}
219
215
 
220
216
  END
221
217
  )
222
- @ui.show_tweet(tweet)
218
+ show_tweet_at_default_time(tweet)
223
219
  end
224
220
 
225
221
  should "output replying tweet" do
@@ -230,14 +226,13 @@ class UITest < UnitTestCase
230
226
  :status => "@#{to_user}! How are you doing?",
231
227
  :to_user => to_user
232
228
  )
233
- Support.expects(:humanize_time_diff).returns([2, "secs"])
234
229
  @out.expects(:puts).with(<<-END
235
- \e[32m#{from_user}\e[0m, in reply to \e[32m#{to_user}\e[0m, 2 secs ago:
230
+ \e[32m#{from_user}\e[0m, in reply to \e[32m#{to_user}\e[0m, 0 sec ago:
236
231
  \e[33m@#{to_user}\e[0m! How are you doing?
237
232
 
238
233
  END
239
234
  )
240
- @ui.show_tweet(tweet)
235
+ show_tweet_at_default_time(tweet)
241
236
  end
242
237
 
243
238
  should "output regular retweet" do
@@ -249,14 +244,13 @@ class UITest < UnitTestCase
249
244
  :status => status,
250
245
  :rt_user => rt_user
251
246
  )
252
- Support.expects(:humanize_time_diff).returns([2, "secs"])
253
247
  @out.expects(:puts).with(<<-END
254
- \e[32m#{rt_user}\e[0m RT \e[32m#{from_user}\e[0m, 2 secs ago:
248
+ \e[32m#{rt_user}\e[0m RT \e[32m#{from_user}\e[0m, 0 sec ago:
255
249
  #{status}
256
250
 
257
251
  END
258
252
  )
259
- @ui.show_tweet(tweet)
253
+ show_tweet_at_default_time(tweet)
260
254
  end
261
255
 
262
256
  should "output replying retweet" do
@@ -269,14 +263,13 @@ class UITest < UnitTestCase
269
263
  :status => "@#{to_user}, reply worth retweeting",
270
264
  :rt_user => rt_user
271
265
  )
272
- Support.expects(:humanize_time_diff).returns([2, "secs"])
273
266
  @out.expects(:puts).with(<<-END
274
- \e[32m#{rt_user}\e[0m RT \e[32m#{from_user}\e[0m, in reply to \e[32m#{to_user}\e[0m, 2 secs ago:
267
+ \e[32m#{rt_user}\e[0m RT \e[32m#{from_user}\e[0m, in reply to \e[32m#{to_user}\e[0m, 0 sec ago:
275
268
  \e[33m@#{to_user}\e[0m, reply worth retweeting
276
269
 
277
270
  END
278
271
  )
279
- @ui.show_tweet(tweet)
272
+ show_tweet_at_default_time(tweet)
280
273
  end
281
274
 
282
275
  should "output a preview of a status" do
@@ -297,14 +290,13 @@ class UITest < UnitTestCase
297
290
  :from_user => from_user,
298
291
  :status => "Lulz, so happy! #{hashtags[0]} #{hashtags[1]}"
299
292
  )
300
- Support.expects(:humanize_time_diff).returns([2, "secs"])
301
293
  @out.expects(:puts).with(<<-END
302
- \e[32m#{from_user}\e[0m, 2 secs ago:
294
+ \e[32m#{from_user}\e[0m, 0 sec ago:
303
295
  Lulz, so happy! \e[35m#{hashtags[0]}\e[0m \e[35m#{hashtags[1]}\e[0m
304
296
 
305
297
  END
306
298
  )
307
- @ui.show_tweet(tweet)
299
+ show_tweet_at_default_time(tweet)
308
300
  end
309
301
 
310
302
  %w{http://is.gd/1qLk3 http://is.gd/1qLk3?id=foo}.each do |url|
@@ -314,14 +306,13 @@ Lulz, so happy! \e[35m#{hashtags[0]}\e[0m \e[35m#{hashtags[1]}\e[0m
314
306
  :from_user => from_user,
315
307
  :status => "New Rails³ - #{url}"
316
308
  )
317
- Support.expects(:humanize_time_diff).returns([2, "secs"])
318
309
  @out.expects(:puts).with(<<-END
319
- \e[32m#{from_user}\e[0m, 2 secs ago:
310
+ \e[32m#{from_user}\e[0m, 0 sec ago:
320
311
  New Rails³ - \e[36m#{url}\e[0m
321
312
 
322
313
  END
323
314
  )
324
- @ui.show_tweet(tweet)
315
+ show_tweet_at_default_time(tweet)
325
316
  end
326
317
  end
327
318
 
@@ -335,14 +326,13 @@ New Rails³ - \e[36m#{url}\e[0m
335
326
  :from_user => from_user,
336
327
  :status => "Links: #{first_url} and #{second_url} np"
337
328
  )
338
- Support.expects(:humanize_time_diff).returns([2, "secs"])
339
329
  @out.expects(:puts).with(<<-END
340
- \e[32m#{from_user}\e[0m, 2 secs ago:
330
+ \e[32m#{from_user}\e[0m, 0 sec ago:
341
331
  Links: \e[36m#{first_url}\e[0m and \e[36m#{second_url}\e[0m np
342
332
 
343
333
  END
344
334
  )
345
- @ui.show_tweet(tweet)
335
+ show_tweet_at_default_time(tweet)
346
336
  end
347
337
  end
348
338
 
@@ -353,14 +343,13 @@ Links: \e[36m#{first_url}\e[0m and \e[36m#{second_url}\e[0m np
353
343
  :from_user => from_user,
354
344
  :status => "I salute you #{users[0]}, #{users[1]}, and #{users[2]}!"
355
345
  )
356
- Support.expects(:humanize_time_diff).returns([2, "secs"])
357
346
  @out.expects(:puts).with(<<-END
358
- \e[32m#{from_user}\e[0m, 2 secs ago:
347
+ \e[32m#{from_user}\e[0m, 0 sec ago:
359
348
  I salute you \e[33m#{users[0]}\e[0m, \e[33m#{users[1]}\e[0m, and \e[33m#{users[2]}\e[0m!
360
349
 
361
350
  END
362
351
  )
363
- @ui.show_tweet(tweet)
352
+ show_tweet_at_default_time(tweet)
364
353
  end
365
354
 
366
355
  should "not highlight email addresses as usernames in a status" do
@@ -371,86 +360,118 @@ I salute you \e[33m#{users[0]}\e[0m, \e[33m#{users[1]}\e[0m, and \e[33m#{users[2
371
360
  :from_user => from_user,
372
361
  :status => "Hi, #{users[0]}! You should notify #{users[1]}, #{email}"
373
362
  )
374
- Support.expects(:humanize_time_diff).returns([2, "secs"])
375
363
  @out.expects(:puts).with(<<-END
376
- \e[32m#{from_user}\e[0m, 2 secs ago:
364
+ \e[32m#{from_user}\e[0m, 0 sec ago:
377
365
  Hi, \e[33m#{users[0]}\e[0m! You should notify \e[33m#{users[1]}\e[0m, #{email}
378
366
 
379
367
  END
380
368
  )
381
- @ui.show_tweet(tweet)
369
+ show_tweet_at_default_time(tweet)
382
370
  end
383
371
  end
384
372
 
385
373
  context "for outputting a collection of tweets" do
386
374
  setup do
387
- @users = %w{first_user second_user}
388
- statuses = @users.map { |from| "Hi, I'm #{from}." }
389
- @users_and_statuses = @users.zip statuses
390
- @outputs = @users_and_statuses.map { |(user, status)| <<-END
391
- #{user}, 2 secs ago:
375
+ users_and_times = [
376
+ ['first', 11],
377
+ ['second', 12],
378
+ ['third', 13]
379
+ ]
380
+ statuses = users_and_times.map { |(user, _)| "Hi, I'm #{user}." }
381
+ users_and_statuses = users_and_times.zip(statuses)
382
+ @outputs = Hash[users_and_statuses.map { |(user, time), status|
383
+ output = <<-END
384
+ #{user}, #{time} sec ago:
392
385
  #{status}
393
386
 
394
- END
395
- }
396
- @tweets = @users_and_statuses.map { |(user, status)| create_tweet(
397
- :from_user => user,
398
- :status => status
387
+ END
388
+ [user.to_sym, output]
389
+ }]
390
+ @tweets = users_and_statuses.map { |(user, time), status| create_tweet(
391
+ :from_user => user,
392
+ :status => status,
393
+ :created_at => create_timestamp(time)
399
394
  )}
400
- Support.expects(:humanize_time_diff).twice.returns([2, "secs"])
401
395
  end
402
396
 
403
- should "output tweets in descending order" do
404
- ui = UI.new({ :out => @out, :show_reverse => false })
405
- @out.expects(:puts).with(@outputs[0])
406
- @out.expects(:puts).with(@outputs[1])
407
- ui.show_tweets(@tweets)
397
+ should "output tweets in normal order" do
398
+ @ui = UI.new({ :out => @out, :show_reverse => false })
399
+ [:first, :second, :third].each do |user|
400
+ @out.expects(:puts).with(@outputs[user])
401
+ end
402
+ show_tweets_at_default_time(@tweets)
408
403
  end
409
404
 
410
- should "output tweets in ascending order" do
411
- ui = UI.new({ :out => @out, :show_reverse => true })
412
- @out.expects(:puts).with(@outputs[1])
413
- @out.expects(:puts).with(@outputs[0])
414
- ui.show_tweets(@tweets)
405
+ should "output tweets in reverse order" do
406
+ @ui = UI.new({ :out => @out, :show_reverse => true })
407
+ [:third, :second, :first].each do |user|
408
+ @out.expects(:puts).with(@outputs[user])
409
+ end
410
+ show_tweets_at_default_time(@tweets)
415
411
  end
416
412
  end
417
413
  end
418
414
 
419
415
  context "username regex" do
420
- should "match a proper username reference" do
421
- assert_full_match UI::USERNAME_REGEX, "@nick"
422
- assert_full_match UI::USERNAME_REGEX, "@nick_man"
423
- assert_full_match UI::USERNAME_REGEX, "@nick"
424
- assert_full_match UI::USERNAME_REGEX, " @nick"
416
+ [
417
+ ['@nick', 'normal'],
418
+ ['@nick_man', 'underscore separated'],
419
+ [' @nick', 'beginning with space']
420
+ ].each do |(nick, desc)|
421
+ should "match proper username reference, case #{desc}" do
422
+ assert_full_match UI::USERNAME_REGEX, nick
423
+ end
425
424
  end
426
425
 
427
- should "not match an inproper username reference" do
428
- assert_no_full_match UI::USERNAME_REGEX, "@"
429
- assert_no_full_match UI::USERNAME_REGEX, "nick"
430
- assert_no_full_match UI::USERNAME_REGEX, "-@nick"
431
- assert_no_full_match UI::USERNAME_REGEX, "@nick-man"
432
- assert_no_full_match UI::USERNAME_REGEX, "@nick "
433
- assert_no_full_match UI::USERNAME_REGEX, " @nick "
434
- assert_no_full_match UI::USERNAME_REGEX, "man @nick"
435
- assert_no_full_match UI::USERNAME_REGEX, "man@nick"
426
+ [
427
+ ['@', 'just prefix'],
428
+ ['nick', 'just body'],
429
+ ['-@nick', 'beginning with dash'],
430
+ ['@nick-man', 'dash separated'],
431
+ ['@nick ', 'ending with space'],
432
+ [' @nick ', 'surrounded with space'],
433
+ ['man @nick', 'space separated'],
434
+ ['man@nick', 'prefix in between']
435
+ ].each do |(no_nick, desc)|
436
+ should "not match an inproper username reference, case #{desc}" do
437
+ assert_no_full_match UI::USERNAME_REGEX, no_nick
438
+ end
436
439
  end
437
440
  end
438
441
 
439
442
  context "hashtag regex" do
440
- should "match a proper hashtag reference" do
441
- assert_full_match UI::HASHTAG_REGEX, "#mayhem"
442
- assert_full_match UI::HASHTAG_REGEX, "#friday_mayhem"
443
- assert_full_match UI::HASHTAG_REGEX, "#friday-mayhem"
443
+ [
444
+ ['#mayhem', 'normal'],
445
+ ['#friday_mayhem', 'underscore separated'],
446
+ ['#friday-mayhem', 'dash separated']
447
+ ].each do |(hashtag, desc)|
448
+ should "match a proper hashtag reference, case #{desc}" do
449
+ assert_full_match UI::HASHTAG_REGEX, hashtag
450
+ end
444
451
  end
445
452
 
446
- should "not match an inproper hashtag reference" do
447
- assert_no_full_match UI::USERNAME_REGEX, "#"
448
- assert_no_full_match UI::USERNAME_REGEX, "mayhem"
449
- assert_no_full_match UI::USERNAME_REGEX, " #mayhem"
450
- assert_no_full_match UI::USERNAME_REGEX, "#mayhem "
451
- assert_no_full_match UI::USERNAME_REGEX, " #mayhem "
453
+ [
454
+ ['#', 'just prefix'],
455
+ ['mayhem', 'just body'],
456
+ [' #mayhem', 'beginning with space'],
457
+ ['#mayhem ', 'ending with space'],
458
+ [' #mayhem ', 'surrounded with space']
459
+ ].each do |(no_hashtag, desc)|
460
+ should "not match an inproper hashtag reference, case #{desc}" do
461
+ assert_no_full_match UI::HASHTAG_REGEX, no_hashtag
462
+ end
452
463
  end
453
464
  end
465
+
466
+ private
467
+
468
+ def show_tweet_at_default_time(tweet)
469
+ at_default_time { @ui.show_tweet(tweet) }
470
+ end
471
+
472
+ def show_tweets_at_default_time(tweets)
473
+ at_default_time { @ui.show_tweets(tweets) }
474
+ end
454
475
  end
455
476
 
456
477
  end
@@ -9,42 +9,64 @@ Mocha::Configuration.prevent(:stubbing_non_existent_method)
9
9
 
10
10
  module Tweetwine::Test
11
11
  module Assertions
12
- # Asserts whether an Enumeration like object contains all the elements.
12
+ # Asserts whether an Enumeration-like object contains all the elements.
13
13
  # Fails unless +actual+ contains the same elements as +expected+, ignoring
14
14
  # the order of the elements.
15
- #
16
- # The method sorts +expected+ and +actual+ in order to compare them. By
17
- # default, this sorting is done by calling #sort for each of them. If the
18
- # method is called with a block, it is passed to the #sort calls.
19
- def assert_contains_exactly(expected, actual, msg = nil, &sorter)
20
- expected = block_given? ? expected.sort(&sorter) : expected.sort
21
- actual = block_given? ? actual.sort(&sorter) : actual.sort
22
- assert_equal(expected, actual, get_message(msg) {
23
- 'after sorting, collection %s is not equal to %s' % [expected.inspect, actual.inspect]
15
+ def assert_contains_exactly(expected, actual, msg_diff_size = nil, msg_diff_elems = nil)
16
+ assert_equal(expected.size, actual.size, message(msg_diff_size) {
17
+ 'Expected %s to be of same size as %s' % [actual.inspect, expected.inspect]
18
+ })
19
+ assert(enumerable_minus_each_element(actual, expected).empty?, message(msg_diff_elems) {
20
+ 'Expected %s to contain all the elements of %s' % [actual.inspect, expected.inspect]
24
21
  })
25
22
  end
26
23
 
27
24
  # Fails unless +str+ is a full match to +regex+.
28
25
  def assert_full_match(regex, str, msg = nil)
29
26
  match_data = regex.match(str)
30
- assert(str == match_data.to_s, get_message(msg) {
31
- '%s is not a full match to %s' % [str, regex.inspect]
27
+ assert(str == match_data.to_s, message(msg) {
28
+ 'Expected %s to be a full match to %s' % [str, regex.inspect]
32
29
  })
33
30
  end
34
31
 
35
32
  # Fails if +str+ is a full match to +regex+.
36
33
  def assert_no_full_match(regex, str, msg = nil)
37
34
  match_data = regex.match(str)
38
- assert(str != match_data.to_s, get_message(msg) {
39
- '%s is a full match to %s' % [str, regex.inspect]
35
+ assert(str != match_data.to_s, message(msg) {
36
+ 'Expected %s not to be a full match to %s' % [str, regex.inspect]
37
+ })
38
+ end
39
+
40
+ # Fails unless +fun.call(*args)+ is equal to +expected+ and
41
+ # +fun.call(*args)+ is equal to +fun.call(*args.reverse)+.
42
+ def assert_commutative(expected, args, msg_not_expected = nil, msg_not_commutative = nil, &fun)
43
+ left_args = args
44
+ left_actual = fun.call(left_args)
45
+ assert_equal(expected, left_actual, message(msg_not_expected) {
46
+ 'Expected %s, not %s' % [expected.inspect, left_actual.inspect]
47
+ })
48
+ right_args = args.reverse
49
+ right_actual = fun.call(*right_args)
50
+ assert_equal(left_actual, right_actual, message(msg_not_commutative) {
51
+ 'Expected fun%s => %s to be commutative with fun%s => %s' %
52
+ [left_args.inspect, left_actual.inspect, right_args.inspect, right_actual.inspect]
40
53
  })
41
54
  end
42
55
 
43
56
  private
44
57
 
45
- def get_message(given, &default)
58
+ def message(given, &default)
46
59
  given.nil? ? default.call : given
47
60
  end
61
+
62
+ def enumerable_minus_each_element(enumerable, elements)
63
+ remaining = enumerable.dup.to_a
64
+ elements.each do |e|
65
+ index = remaining.index(e)
66
+ remaining.delete_at(index) if index
67
+ end
68
+ remaining
69
+ end
48
70
  end
49
71
 
50
72
  module Doubles
@@ -13,7 +13,7 @@ class UriTest < UnitTestCase
13
13
  %w{. period},
14
14
  %w{- dash},
15
15
  %w{_ underscore},
16
- ].each do |char, desc|
16
+ ].each do |(char, desc)|
17
17
  should "not encode safe characters, case #{desc}" do
18
18
  assert_equal char, Uri.percent_encode(char)
19
19
  end
@@ -29,7 +29,7 @@ class UriTest < UnitTestCase
29
29
  %w{/ %2F slash},
30
30
  %w{: %3A colon},
31
31
  %w{, %2C comma}
32
- ].each do |char, expected, desc|
32
+ ].each do |(char, expected, desc)|
33
33
  should "encode unsafe characters that URI.encode leaves by default unencoded, case #{desc}" do
34
34
  assert_equal char, Uri.parser.escape(char)
35
35
  assert_equal expected, Uri.percent_encode(char)
data/tweetwine.gemspec CHANGED
@@ -1,27 +1,18 @@
1
1
  # coding: utf-8
2
2
 
3
- $LOAD_PATH.unshift(File.expand_path('lib', File.dirname(__FILE__)))
4
- name = 'tweetwine'
5
- require "#{name}/version"
6
- version = Tweetwine.version
3
+ require File.expand_path('project', File.dirname(__FILE__))
7
4
 
8
5
  Gem::Specification.new do |s|
9
- s.name = name
10
- s.version = version.dup
11
-
12
- s.summary = Tweetwine.summary
13
- s.description = <<-END
14
- A simple but tasty Twitter agent for command line use, designed for quickly
15
- showing the latest tweets.
16
- END
17
-
18
- s.email = 'tkareine@gmail.com'
19
- s.homepage = 'https://github.com/tkareine/tweetwine'
20
-
21
- s.authors = ['Tuomas Kareinen']
22
-
23
- s.files = `git ls-files`.split("\n") + Dir['man/**/*.[1-9]']
24
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
6
+ s.name = Project.name
7
+ s.version = Project.version
8
+ s.summary = Project.summary
9
+ s.description = Project.description
10
+ s.email = Project.email
11
+ s.homepage = Project.homepage
12
+ s.authors = Project.authors
13
+
14
+ s.files = `git ls-files`.split("\n") + Dir["#{Project.dirs.man}/**/*.[1-9]"]
15
+ s.test_files = `git ls-files -- #{Project.dirs.test}/*`.split("\n")
25
16
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
26
17
 
27
18
  s.add_dependency 'oauth', '~> 0.4.4'
@@ -45,6 +36,5 @@ default. For Ruby 1.8, you can install 'json' gem, for example.
45
36
 
46
37
  s.has_rdoc = true
47
38
  s.extra_rdoc_files = Dir['*.rdoc', 'LICENSE.txt']
48
- s.rdoc_options << '--title' << "#{name} #{version}" \
49
- << '--exclude' << 'test'
39
+ s.rdoc_options << '--title' << Project.title << '--exclude' << Project.dirs.test
50
40
  end
metadata CHANGED
@@ -1,8 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tweetwine
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 13
4
5
  prerelease:
5
- version: 0.4.0
6
+ segments:
7
+ - 0
8
+ - 4
9
+ - 1
10
+ version: 0.4.1
6
11
  platform: ruby
7
12
  authors:
8
13
  - Tuomas Kareinen
@@ -10,7 +15,7 @@ autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
17
 
13
- date: 2011-02-22 00:00:00 +02:00
18
+ date: 2011-03-23 00:00:00 +02:00
14
19
  default_executable:
15
20
  dependencies:
16
21
  - !ruby/object:Gem::Dependency
@@ -21,6 +26,11 @@ dependencies:
21
26
  requirements:
22
27
  - - ~>
23
28
  - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 0
32
+ - 4
33
+ - 4
24
34
  version: 0.4.4
25
35
  type: :runtime
26
36
  version_requirements: *id001
@@ -32,6 +42,11 @@ dependencies:
32
42
  requirements:
33
43
  - - ~>
34
44
  - !ruby/object:Gem::Version
45
+ hash: 31
46
+ segments:
47
+ - 0
48
+ - 1
49
+ - 2
35
50
  version: 0.1.2
36
51
  type: :development
37
52
  version_requirements: *id002
@@ -43,6 +58,11 @@ dependencies:
43
58
  requirements:
44
59
  - - ~>
45
60
  - !ruby/object:Gem::Version
61
+ hash: 1
62
+ segments:
63
+ - 0
64
+ - 6
65
+ - 3
46
66
  version: 0.6.3
47
67
  type: :development
48
68
  version_requirements: *id003
@@ -54,6 +74,11 @@ dependencies:
54
74
  requirements:
55
75
  - - ~>
56
76
  - !ruby/object:Gem::Version
77
+ hash: 23
78
+ segments:
79
+ - 0
80
+ - 2
81
+ - 0
57
82
  version: 0.2.0
58
83
  type: :development
59
84
  version_requirements: *id004
@@ -65,6 +90,11 @@ dependencies:
65
90
  requirements:
66
91
  - - ~>
67
92
  - !ruby/object:Gem::Version
93
+ hash: 15
94
+ segments:
95
+ - 0
96
+ - 5
97
+ - 2
68
98
  version: 0.5.2
69
99
  type: :development
70
100
  version_requirements: *id005
@@ -76,6 +106,11 @@ dependencies:
76
106
  requirements:
77
107
  - - ~>
78
108
  - !ruby/object:Gem::Version
109
+ hash: 35
110
+ segments:
111
+ - 0
112
+ - 9
113
+ - 12
79
114
  version: 0.9.12
80
115
  type: :development
81
116
  version_requirements: *id006
@@ -87,6 +122,11 @@ dependencies:
87
122
  requirements:
88
123
  - - ~>
89
124
  - !ruby/object:Gem::Version
125
+ hash: 21
126
+ segments:
127
+ - 1
128
+ - 0
129
+ - 1
90
130
  version: 1.0.1
91
131
  type: :development
92
132
  version_requirements: *id007
@@ -98,6 +138,11 @@ dependencies:
98
138
  requirements:
99
139
  - - ~>
100
140
  - !ruby/object:Gem::Version
141
+ hash: 49
142
+ segments:
143
+ - 0
144
+ - 8
145
+ - 7
101
146
  version: 0.8.7
102
147
  type: :development
103
148
  version_requirements: *id008
@@ -109,6 +154,11 @@ dependencies:
109
154
  requirements:
110
155
  - - ~>
111
156
  - !ruby/object:Gem::Version
157
+ hash: 5
158
+ segments:
159
+ - 0
160
+ - 7
161
+ - 3
112
162
  version: 0.7.3
113
163
  type: :development
114
164
  version_requirements: *id009
@@ -120,6 +170,11 @@ dependencies:
120
170
  requirements:
121
171
  - - ~>
122
172
  - !ruby/object:Gem::Version
173
+ hash: 25
174
+ segments:
175
+ - 0
176
+ - 3
177
+ - 5
123
178
  version: 0.3.5
124
179
  type: :development
125
180
  version_requirements: *id010
@@ -131,6 +186,11 @@ dependencies:
131
186
  requirements:
132
187
  - - ~>
133
188
  - !ruby/object:Gem::Version
189
+ hash: 11
190
+ segments:
191
+ - 1
192
+ - 6
193
+ - 2
134
194
  version: 1.6.2
135
195
  type: :development
136
196
  version_requirements: *id011
@@ -152,6 +212,7 @@ files:
152
212
  - Gemfile
153
213
  - LICENSE.txt
154
214
  - README.md
215
+ - RELEASING.txt
155
216
  - Rakefile
156
217
  - bin/tweetwine
157
218
  - contrib/tweetwine-completion.bash
@@ -174,7 +235,7 @@ files:
174
235
  - lib/tweetwine/url_shortener.rb
175
236
  - lib/tweetwine/version.rb
176
237
  - man/tweetwine.7.ronn
177
- - release-script.txt
238
+ - project.rb
178
239
  - test/example/authorization_example.rb
179
240
  - test/example/example_helper.rb
180
241
  - test/example/global_options_example.rb
@@ -223,12 +284,14 @@ has_rdoc: true
223
284
  homepage: https://github.com/tkareine/tweetwine
224
285
  licenses: []
225
286
 
226
- post_install_message: "\n\
227
- Tweetwine requires a JSON parser library. Ruby 1.9 comes bundled with one by\n\
228
- default. For Ruby 1.8, you can install 'json' gem, for example.\n\n"
287
+ post_install_message: |+
288
+
289
+ Tweetwine requires a JSON parser library. Ruby 1.9 comes bundled with one by
290
+ default. For Ruby 1.8, you can install 'json' gem, for example.
291
+
229
292
  rdoc_options:
230
293
  - --title
231
- - tweetwine 0.4.0
294
+ - tweetwine 0.4.1
232
295
  - --exclude
233
296
  - test
234
297
  require_paths:
@@ -238,17 +301,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
238
301
  requirements:
239
302
  - - ">="
240
303
  - !ruby/object:Gem::Version
304
+ hash: 3
305
+ segments:
306
+ - 0
241
307
  version: "0"
242
308
  required_rubygems_version: !ruby/object:Gem::Requirement
243
309
  none: false
244
310
  requirements:
245
311
  - - ">="
246
312
  - !ruby/object:Gem::Version
313
+ hash: 3
314
+ segments:
315
+ - 0
247
316
  version: "0"
248
317
  requirements: []
249
318
 
250
319
  rubyforge_project:
251
- rubygems_version: 1.5.2
320
+ rubygems_version: 1.6.2
252
321
  signing_key:
253
322
  specification_version: 3
254
323
  summary: Tweetwine shows the latest tweets from the command line quickly.