Skip to content

Commit aa08ea2

Browse files
author
Robin Message
committed
Implement --relative-dates CLI flag
1 parent 4c2f663 commit aa08ea2

File tree

5 files changed

+102
-5
lines changed

5 files changed

+102
-5
lines changed

lib/t/cli.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ def block(user, *users)
125125
desc 'direct_messages', "Returns the #{DEFAULT_NUM_RESULTS} most recent Direct Messages sent to you."
126126
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
127127
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
128+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
128129
method_option 'number', :aliases => '-n', :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => 'Limit the number of results.'
129130
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
130131
def direct_messages # rubocop:disable CyclomaticComplexity
@@ -157,6 +158,7 @@ def direct_messages # rubocop:disable CyclomaticComplexity
157158
desc 'direct_messages_sent', "Returns the #{DEFAULT_NUM_RESULTS} most recent Direct Messages you've sent."
158159
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
159160
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
161+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
160162
method_option 'number', :aliases => '-n', :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => 'Limit the number of results.'
161163
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
162164
def direct_messages_sent # rubocop:disable CyclomaticComplexity
@@ -190,6 +192,7 @@ def direct_messages_sent # rubocop:disable CyclomaticComplexity
190192
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
191193
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
192194
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
195+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
193196
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
194197
method_option 'sort', :aliases => '-s', :type => :string, :enum => %w(favorites followers friends listed screen_name since tweets tweeted), :default => 'screen_name', :desc => 'Specify the order of the results.', :banner => 'ORDER'
195198
method_option 'unsorted', :aliases => '-u', :type => :boolean, :default => false, :desc => 'Output is not sorted.'
@@ -282,6 +285,7 @@ def favorite(status_id, *status_ids)
282285
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
283286
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
284287
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
288+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
285289
method_option 'max_id', :aliases => '-m', :type => :numeric, :desc => 'Returns only the results with an ID less than the specified ID.'
286290
method_option 'number', :aliases => '-n', :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => 'Limit the number of results.'
287291
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
@@ -319,6 +323,7 @@ def follow(user, *users)
319323
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
320324
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
321325
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
326+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
322327
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
323328
method_option 'sort', :aliases => '-s', :type => :string, :enum => %w(favorites followers friends listed screen_name since tweets tweeted), :default => 'screen_name', :desc => 'Specify the order of the results.', :banner => 'ORDER'
324329
method_option 'unsorted', :aliases => '-u', :type => :boolean, :default => false, :desc => 'Output is not sorted.'
@@ -339,6 +344,7 @@ def followings(user = nil)
339344
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
340345
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
341346
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
347+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
342348
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
343349
method_option 'sort', :aliases => '-s', :type => :string, :enum => %w(favorites followers friends listed screen_name since tweets tweeted), :default => 'screen_name', :desc => 'Specify the order of the results.', :banner => 'ORDER'
344350
method_option 'unsorted', :aliases => '-u', :type => :boolean, :default => false, :desc => 'Output is not sorted.'
@@ -359,6 +365,7 @@ def followers(user = nil)
359365
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
360366
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
361367
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
368+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
362369
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
363370
method_option 'sort', :aliases => '-s', :type => :string, :enum => %w(favorites followers friends listed screen_name since tweets tweeted), :default => 'screen_name', :desc => 'Specify the order of the results.', :banner => 'ORDER'
364371
method_option 'unsorted', :aliases => '-u', :type => :boolean, :default => false, :desc => 'Output is not sorted.'
@@ -387,6 +394,7 @@ def friends(user = nil)
387394
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
388395
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
389396
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
397+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
390398
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
391399
method_option 'sort', :aliases => '-s', :type => :string, :enum => %w(favorites followers friends listed screen_name since tweets tweeted), :default => 'screen_name', :desc => 'Specify the order of the results.', :banner => 'ORDER'
392400
method_option 'unsorted', :aliases => '-u', :type => :boolean, :default => false, :desc => 'Output is not sorted.'
@@ -415,6 +423,7 @@ def leaders(user = nil)
415423
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
416424
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
417425
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
426+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
418427
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
419428
method_option 'sort', :aliases => '-s', :type => :string, :enum => %w(members mode since slug subscribers), :default => 'slug', :desc => 'Specify the order of the results.', :banner => 'ORDER'
420429
method_option 'unsorted', :aliases => '-u', :type => :boolean, :default => false, :desc => 'Output is not sorted.'
@@ -435,6 +444,7 @@ def lists(user = nil)
435444
desc 'mentions', "Returns the #{DEFAULT_NUM_RESULTS} most recent Tweets mentioning you."
436445
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
437446
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
447+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
438448
method_option 'number', :aliases => '-n', :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => 'Limit the number of results.'
439449
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
440450
def mentions
@@ -513,6 +523,7 @@ def retweet(status_id, *status_ids)
513523
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
514524
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
515525
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
526+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
516527
method_option 'number', :aliases => '-n', :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => 'Limit the number of results.'
517528
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
518529
def retweets(user = nil)
@@ -542,6 +553,7 @@ def ruler
542553
desc 'status TWEET_ID', 'Retrieves detailed information about a Tweet.'
543554
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
544555
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
556+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
545557
def status(status_id) # rubocop:disable CyclomaticComplexity
546558
status = client.status(status_id.to_i, :include_my_retweet => false)
547559
location = if status.place?
@@ -575,7 +587,7 @@ def status(status_id) # rubocop:disable CyclomaticComplexity
575587
array << ['ID', status.id.to_s]
576588
array << ['Text', decode_full_text(status).gsub(/\n+/, ' ')]
577589
array << ['Screen name', "@#{status.user.screen_name}"]
578-
array << ['Posted at', "#{ls_formatted_time(status)} (#{time_ago_in_words(status.created_at)} ago)"]
590+
array << ['Posted at', "#{ls_formatted_time(status, :created_at, false)} (#{time_ago_in_words(status.created_at)} ago)"]
579591
array << ['Retweets', number_with_delimiter(status.retweet_count)]
580592
array << ['Favorites', number_with_delimiter(status.favorite_count)]
581593
array << ['Source', strip_tags(status.source)]
@@ -589,6 +601,7 @@ def status(status_id) # rubocop:disable CyclomaticComplexity
589601
method_option 'exclude', :aliases => '-e', :type => :string, :enum => %w(replies retweets), :desc => 'Exclude certain types of Tweets from the results.', :banner => 'TYPE'
590602
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
591603
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
604+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
592605
method_option 'max_id', :aliases => '-m', :type => :numeric, :desc => 'Returns only the results with an ID less than the specified ID.'
593606
method_option 'number', :aliases => '-n', :type => :numeric, :default => DEFAULT_NUM_RESULTS, :desc => 'Limit the number of results.'
594607
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
@@ -627,6 +640,7 @@ def trends(woe_id = 1)
627640
desc 'trend_locations', 'Returns the locations for which Twitter has trending topic information.'
628641
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
629642
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
643+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
630644
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
631645
method_option 'sort', :aliases => '-s', :type => :string, :enum => %w(country name parent type woeid), :default => 'name', :desc => 'Specify the order of the results.', :banner => 'ORDER'
632646
method_option 'unsorted', :aliases => '-u', :type => :boolean, :default => false, :desc => 'Output is not sorted.'
@@ -696,6 +710,7 @@ def update(message = nil)
696710
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
697711
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify input as Twitter user IDs instead of screen names.'
698712
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
713+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
699714
method_option 'reverse', :aliases => '-r', :type => :boolean, :default => false, :desc => 'Reverse the order of the sort.'
700715
method_option 'sort', :aliases => '-s', :type => :string, :enum => %w(favorites followers friends listed screen_name since tweets tweeted), :default => 'screen_name', :desc => 'Specify the order of the results.', :banner => 'ORDER'
701716
method_option 'unsorted', :aliases => '-u', :type => :boolean, :default => false, :desc => 'Output is not sorted.'
@@ -719,6 +734,7 @@ def version
719734
method_option 'csv', :aliases => '-c', :type => :boolean, :default => false, :desc => 'Output in CSV format.'
720735
method_option 'id', :aliases => '-i', :type => :boolean, :default => false, :desc => 'Specify user via ID instead of screen name.'
721736
method_option 'long', :aliases => '-l', :type => :boolean, :default => false, :desc => 'Output in long format.'
737+
method_option 'relative_dates', :aliases => '-a', :type => :boolean, :desc => 'Show relative dates.'
722738
def whois(user) # rubocop:disable CyclomaticComplexity
723739
require 't/core_ext/string'
724740
user = options['id'] ? user.to_i : user.strip_ats
@@ -729,7 +745,7 @@ def whois(user) # rubocop:disable CyclomaticComplexity
729745
else
730746
array = []
731747
array << ['ID', user.id.to_s]
732-
array << ['Since', "#{ls_formatted_time(user)} (#{time_ago_in_words(user.created_at)} ago)"]
748+
array << ['Since', "#{ls_formatted_time(user, :created_at, false)} (#{time_ago_in_words(user.created_at)} ago)"]
733749
array << ['Last update', "#{decode_full_text(user.status).gsub(/\n+/, ' ')} (#{time_ago_in_words(user.status.created_at)} ago)"] unless user.status.nil?
734750
array << ['Screen name', "@#{user.screen_name}"]
735751
array << [user.verified ? 'Name (Verified)' : 'Name', user.name] unless user.name.nil?

lib/t/list.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def information(list)
6464
array << ['Description', list.description] unless list.description.nil?
6565
array << ['Slug', list.slug]
6666
array << ['Screen name', "@#{list.user.screen_name}"]
67-
array << ['Created at', "#{ls_formatted_time(list)} (#{time_ago_in_words(list.created_at)} ago)"]
67+
array << ['Created at', "#{ls_formatted_time(list, :created_at, false)} (#{time_ago_in_words(list.created_at)} ago)"]
6868
array << ['Members', number_with_delimiter(list.member_count)]
6969
array << ['Subscribers', number_with_delimiter(list.subscriber_count)]
7070
array << ['Status', list.following ? 'Following' : 'Not following']

lib/t/printable.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ def csv_formatted_time(object, key = :created_at)
2525
time.utc.strftime('%Y-%m-%d %H:%M:%S %z')
2626
end
2727

28-
def ls_formatted_time(object, key = :created_at)
28+
def ls_formatted_time(object, key = :created_at, allow_relative = true)
2929
return '' if object.nil?
3030
time = T.local_time(object.send(key.to_sym))
31-
if time > Time.now - MONTH_IN_SECONDS * 6
31+
if allow_relative && options['relative_dates']
32+
distance_of_time_in_words(time) + ' ago'
33+
elsif time > Time.now - MONTH_IN_SECONDS * 6
3234
time.strftime('%b %e %H:%M')
3335
else
3436
time.strftime('%b %e %Y')

spec/cli_spec.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,69 @@
2929
$stdout = @old_stdout
3030
end
3131

32+
describe '--relative-dates' do
33+
before do
34+
stub_get('/1.1/statuses/show/55709764298092545.json').with(:query => {:include_my_retweet => 'false'}).to_return(:body => fixture('status.json'))
35+
stub_get('/1.1/users/show.json').with(:query => {:screen_name => 'sferik'}).to_return(:body => fixture('sferik.json'))
36+
@cli.options = @cli.options.merge('relative_dates' => true)
37+
end
38+
it 'status has the correct output (absolute and relative date together)' do
39+
@cli.status('55709764298092545')
40+
expect($stdout.string).to eq <<-eos
41+
ID 55709764298092545
42+
Text The problem with your code is that it's doing exactly what you told it to do.
43+
Screen name @sferik
44+
Posted at Apr 6 2011 (8 months ago)
45+
Retweets 320
46+
Favorites 50
47+
Source Twitter for iPhone
48+
Location Blowfish Sushi To Die For, 2170 Bryant St, San Francisco, California, United States
49+
eos
50+
end
51+
it 'whois has the correct output (absolute and relative date together)' do
52+
@cli.whois('sferik')
53+
expect($stdout.string).to eq <<-eos
54+
ID 7505382
55+
Since Jul 16 2007 (4 years ago)
56+
Last update @goldman You're near my home town! Say hi to Woodstock for me. (7 months ago)
57+
Screen name @sferik
58+
Name Erik Michaels-Ober
59+
Tweets 7,890
60+
Favorites 3,755
61+
Listed 118
62+
Following 212
63+
Followers 2,262
64+
Bio Vagabond.
65+
Location San Francisco
66+
URL https://github.com/sferik
67+
eos
68+
end
69+
context '--csv' do
70+
before do
71+
@cli.options = @cli.options.merge('csv' => true)
72+
end
73+
it 'has the correct output (absolute date in csv)' do
74+
@cli.status('55709764298092545')
75+
expect($stdout.string).to eq <<-eos
76+
ID,Posted at,Screen name,Text,Retweets,Favorites,Source,Location
77+
55709764298092545,2011-04-06 19:13:37 +0000,sferik,The problem with your code is that it's doing exactly what you told it to do.,320,50,Twitter for iPhone,"Blowfish Sushi To Die For, 2170 Bryant St, San Francisco, California, United States"
78+
eos
79+
end
80+
end
81+
context '--long' do
82+
before do
83+
@cli.options = @cli.options.merge('long' => true)
84+
end
85+
it 'outputs in long format' do
86+
@cli.status('55709764298092545')
87+
expect($stdout.string).to eq <<-eos
88+
ID Posted at Screen name Text ...
89+
55709764298092545 8 months ago @sferik The problem with your code is t...
90+
eos
91+
end
92+
end
93+
end
94+
3295
describe '#account' do
3396
before do
3497
@cli.options = @cli.options.merge('profile' => fixture_path + '/.trc')

0 commit comments

Comments
 (0)