t 0.8.1 → 0.8.2
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/README.md +121 -103
- data/lib/t/cli.rb +12 -6
- data/lib/t/core_ext/enumerable.rb +5 -8
- data/lib/t/printable.rb +16 -9
- data/lib/t/search.rb +4 -2
- data/lib/t/version.rb +1 -1
- data/spec/cli_spec.rb +181 -181
- data/spec/helper.rb +2 -0
- data/spec/list_spec.rb +37 -37
- data/spec/search_spec.rb +100 -100
- data/t.gemspec +1 -1
- metadata +10 -4
data/README.md
CHANGED
@@ -1,159 +1,171 @@
|
|
1
1
|
# Twitter CLI [][travis] [][gemnasium]
|
2
2
|
### A command-line power tool for Twitter.
|
3
3
|
|
4
|
-
The CLI
|
5
|
-
|
6
|
-
SMS.
|
4
|
+
The CLI takes syntactic cues from the [Twitter SMS commands][sms], however it
|
5
|
+
offers vastly more commands and capabilities than are available via SMS.
|
7
6
|
|
8
7
|
[travis]: http://travis-ci.org/sferik/t
|
9
8
|
[gemnasium]: https://gemnasium.com/sferik/t
|
10
9
|
[gem]: https://rubygems.org/gems/twitter
|
11
10
|
[sms]: https://support.twitter.com/articles/14020-twitter-sms-command
|
12
11
|
|
13
|
-
##
|
12
|
+
## Installation
|
13
|
+
# Requires Ruby :)
|
14
14
|
gem install t
|
15
15
|
|
16
|
-
##
|
16
|
+
## Configuration
|
17
17
|
|
18
|
-
|
18
|
+
Twitter requires OAuth for most of its functionality, so you'll need to
|
19
19
|
register a new application at <http://dev.twitter.com/apps/new>. Once you
|
20
|
-
create your application make sure to set
|
21
|
-
and Access direct messages", otherwise you
|
22
|
-
|
20
|
+
create your application, make sure to set your application's Access Level to
|
21
|
+
"Read, Write and Access direct messages", otherwise you may receive an error
|
22
|
+
that looks something like this:
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
Read-only application cannot POST
|
25
|
+
|
26
|
+
Once you've successfully registered your application, you'll be given a
|
27
|
+
consumer key and secret, which you can use to authorize your Twitter account.
|
26
28
|
|
27
29
|
t authorize -c YOUR_CONSUMER_KEY -s YOUR_CONSUMER_SECRET
|
28
30
|
|
29
|
-
This
|
30
|
-
enter the returned PIN back into the terminal.
|
31
|
-
authorized to use `t` as that user. To authorize
|
32
|
-
repeat the last step
|
31
|
+
This command directs you to a URL where you can sign-in to Twitter and then
|
32
|
+
enter the returned PIN back into the terminal. If you type the PIN correctly,
|
33
|
+
you should now be authorized authorized to use `t` as that user. To authorize
|
34
|
+
multiple accounts, simply repeat the last step, signing into Twitter as a
|
35
|
+
different user.
|
33
36
|
|
34
|
-
You can see a list of all the accounts you've authorized
|
37
|
+
You can see a list of all the accounts you've authorized by typing the command:
|
35
38
|
|
36
39
|
t accounts
|
37
40
|
|
41
|
+
The output of which will be structured like this:
|
42
|
+
|
38
43
|
sferik
|
39
44
|
UDfNTpOz5ZDG4a6w7dIWj
|
40
45
|
uuP7Xbl2mEfGMiDu1uIyFN
|
41
46
|
gem
|
42
47
|
thG9EfWoADtIr6NjbL9ON (active)
|
43
48
|
|
44
|
-
|
45
|
-
use the `set` subcommand, passing either
|
46
|
-
unambiguous, or the username and consumer key pair
|
49
|
+
**Note**: One account (specifically, the last one you authorized) is marked as
|
50
|
+
active. To change the active account use the `set` subcommand, passing either
|
51
|
+
just the username, if it's unambiguous, or the username and consumer key pair.
|
52
|
+
Something like this:
|
47
53
|
|
48
54
|
t set active sferik UDfNTpOz5ZDG4a6w7dIWj
|
49
55
|
|
50
|
-
Account information is stored in
|
51
|
-
Anyone with access to this file can masquerade as you on Twitter, so
|
52
|
-
important to keep it secure, just as you would treat your SSH private key.
|
53
|
-
this reason, the file is hidden and has the permission bits set to 0600.
|
56
|
+
Account information is stored in a YAML-formatted file located at `~/.trc`.
|
57
|
+
**Note**: Anyone with access to this file can masquerade as you on Twitter, so
|
58
|
+
it's important to keep it secure, just as you would treat your SSH private key.
|
59
|
+
For this reason, the file is hidden and has the permission bits set to 0600.
|
54
60
|
|
55
|
-
##
|
56
|
-
Typing `t help` will
|
57
|
-
|
61
|
+
## Usage Examples
|
62
|
+
Typing `t help` will list all the available commands. You can type `t help
|
63
|
+
TASK` to get help for a specific command.
|
58
64
|
|
59
65
|
t help
|
60
66
|
|
61
|
-
###
|
67
|
+
### Update your status
|
62
68
|
t update "I'm tweeting from the command line. Isn't that special?"
|
63
69
|
|
64
70
|
**Note**: If your tweet includes special characters (e.g. `!`), make sure to
|
65
71
|
wrap it in single quotes instead of double quotes, so those characters are not
|
66
|
-
interpreted by your shell. However, if you use single quotes, your Tweet
|
67
|
-
contain any apostrophes.
|
72
|
+
interpreted by your shell. (However, if you use single quotes, your Tweet
|
73
|
+
obviously can't contain any apostrophes.)
|
74
|
+
|
75
|
+
### Retrieve detailed information about a Twitter user
|
76
|
+
t whois @sferik
|
68
77
|
|
69
|
-
###
|
78
|
+
### Retrieve stats for multiple users
|
70
79
|
t users -l @sferik @gem
|
71
80
|
|
72
|
-
###
|
81
|
+
### Follow users
|
73
82
|
t follow @sferik @gem
|
74
83
|
|
75
|
-
###
|
84
|
+
### Check whether one user follows another
|
76
85
|
t does_follow @ev @sferik
|
77
86
|
|
78
|
-
**Note**: If the first user
|
79
|
-
non-zero exit code. This allows you to execute
|
80
|
-
example
|
87
|
+
**Note**: If the first user does not follow the second, `t` will exit with a
|
88
|
+
non-zero exit code. This allows you to execute commands conditionally, for
|
89
|
+
example, only attempt to send a user a direct message if he are already
|
90
|
+
follows you:
|
81
91
|
|
82
|
-
t does_follow @ev
|
92
|
+
t does_follow @ev && t dm @ev "What's up, bro?"
|
83
93
|
|
84
|
-
###
|
94
|
+
### Create a list for everyone you're following
|
95
|
+
t list create following-`date "+%Y-%m-%d"`
|
96
|
+
|
97
|
+
### Add everyone you're following to that list (up to 500 users)
|
98
|
+
t followings | xargs t list add following-`date "+%Y-%m-%d"`
|
99
|
+
|
100
|
+
### List all the members of a list, in long format
|
101
|
+
t list members -l following-`date "+%Y-%m-%d"`
|
102
|
+
|
103
|
+
### List all your lists, in long format
|
104
|
+
t lists -l
|
105
|
+
|
106
|
+
### List all your friends, ordered by number of followers
|
85
107
|
t friends -lf
|
86
108
|
|
87
|
-
###
|
109
|
+
### List all your leaders (people you follow who don't follow you back)
|
88
110
|
t leaders -lf
|
89
111
|
|
90
|
-
###
|
112
|
+
### Unfollow everyone you follow who doesn't follow you back
|
91
113
|
t leaders | xargs t unfollow
|
92
114
|
|
93
|
-
###
|
94
|
-
t disciples | xargs t follow
|
95
|
-
|
96
|
-
### <a name="follow-roulette"></a>Follow roulette: randomly follow someone who follows you
|
115
|
+
### Follow roulette: randomly follow someone who follows you (who you don't already follow)
|
97
116
|
t disciples | shuf | head -1 | xargs t follow
|
98
117
|
|
99
|
-
###
|
100
|
-
t timeline -n 200 --csv > timeline.csv
|
101
|
-
|
102
|
-
### <a name="favorite"></a>Favorite the last 10 tweets that mention you
|
118
|
+
### Favorite the last 10 tweets that mention you
|
103
119
|
t mentions -n 10 -l | awk '{print $1}' | xargs t favorite
|
104
120
|
|
105
|
-
###
|
106
|
-
t
|
107
|
-
|
108
|
-
### <a name="list-add"></a>Add users to a list
|
109
|
-
t list add presidents @BarackObama @Jasonfinn
|
110
|
-
|
111
|
-
### Create a list that contains today's date in the name
|
112
|
-
t list create following-`date "+%Y-%m-%d"`
|
113
|
-
|
114
|
-
### <a name="followings"></a>Add everyone you're following to a list
|
115
|
-
t followings | xargs t list add following-`date "+%Y-%m-%d"`
|
116
|
-
|
117
|
-
### <a name="list-members"></a>Display members of a list
|
118
|
-
t list members following-`date "+%Y-%m-%d"`
|
121
|
+
### Output the last 200 tweets in your timeline to a CSV file
|
122
|
+
t timeline -n 200 --csv > timeline.csv
|
119
123
|
|
120
|
-
###
|
124
|
+
### Count the number of employees who work for Twitter
|
121
125
|
t list members twitter team | wc -l
|
122
126
|
|
123
|
-
###
|
127
|
+
### Search Twitter for the 20 most recent Tweets that match a specified query
|
124
128
|
t search all "query"
|
125
129
|
|
126
|
-
###
|
130
|
+
### Download the latest Linux kernel via BitTorrent (possibly NSFW, depending where you work)
|
131
|
+
t search all "lang:en filter:links linux torrent" -n 1 | grep -o "http://t.co/[0-9A-Za-z]*" | xargs open
|
132
|
+
|
133
|
+
### Search Tweets you've favorited that match a specified query
|
127
134
|
t search favorites "query"
|
128
135
|
|
129
|
-
###
|
136
|
+
### Search Tweets mentioning you that match a specified query
|
130
137
|
t search mentions "query"
|
131
138
|
|
132
|
-
###
|
139
|
+
### Search Tweets you've retweeted that match a specified query
|
133
140
|
t search retweets "query"
|
134
141
|
|
135
|
-
###
|
142
|
+
### Search Tweets in your timeline that match a specified query
|
136
143
|
t search timeline "query"
|
137
144
|
|
138
|
-
###
|
145
|
+
### Search Tweets in another user's timeline that match a specified query
|
139
146
|
t search user @sferik "query"
|
140
147
|
|
141
|
-
##
|
148
|
+
## Features
|
149
|
+
* Deep search: Instead of using the Twitter Search API, [which only only goes
|
150
|
+
back 6-9 days][index], `t search` fetches up to 3,200 tweets via the REST API
|
151
|
+
and then checks each one against a regular expression.
|
142
152
|
* Multithreaded: Whenever possible, Twitter API requests are made in parallel,
|
143
153
|
resulting in faster performance for bulk operations.
|
144
|
-
* Designed for Unix:
|
145
|
-
|
146
|
-
*
|
147
|
-
|
148
|
-
|
154
|
+
* Designed for Unix: Output is designed to be piped to other Unix utilities,
|
155
|
+
like grep, cut, awk, bc, wc, and xargs for advanced text processing.
|
156
|
+
* Generate spreadsheets: Convert the output of any command to CSV format simply
|
157
|
+
by adding the `--csv` flag.
|
158
|
+
* 98% C0 Code Coverage: Well tested, with a 3:1 test-to-code ratio.
|
159
|
+
|
160
|
+
[search]: https://dev.twitter.com/docs/using-search
|
149
161
|
|
150
|
-
##
|
162
|
+
## Relationship Terminology
|
151
163
|
|
152
164
|
There is some ambiguity in the terminology used to describe relationships on
|
153
|
-
Twitter. For example, some people use the term "friends" to mean
|
154
|
-
|
155
|
-
|
156
|
-
|
165
|
+
Twitter. For example, some people use the term "friends" to mean everyone you
|
166
|
+
follow. In `t`, "friends" refers to just the subset of people who follow you
|
167
|
+
back (i.e., friendship is bidirectional). Here is the full table of terminology
|
168
|
+
used by `t`:
|
157
169
|
|
158
170
|
___________________________________________________
|
159
171
|
| | |
|
@@ -169,17 +181,20 @@ terminology used throughout `t`:
|
|
169
181
|
| followings |
|
170
182
|
|_________________________|
|
171
183
|
|
172
|
-
##
|
173
|
-

|
186
|
+

|
174
187
|
|
188
|
+
## History
|
175
189
|
The [twitter gem][gem] previously contained a command-line interface, up until
|
176
190
|
version 0.5.0, when it was [removed][]. This project is offered as a sucessor
|
177
191
|
to that effort, however it is a clean room implementation that contains none of
|
178
|
-
|
192
|
+
the original code.
|
179
193
|
|
180
194
|
[removed]: https://github.com/jnunemaker/twitter/commit/dd2445e3e2c97f38b28a3f32ea902536b3897adf
|
195
|
+

|
181
196
|
|
182
|
-
##
|
197
|
+
## Contributing
|
183
198
|
In the spirit of [free software][fsf], **everyone** is encouraged to help
|
184
199
|
improve this project.
|
185
200
|
|
@@ -200,7 +215,7 @@ Here are some ways *you* can contribute:
|
|
200
215
|
|
201
216
|
[issues]: https://github.com/sferik/t/issues
|
202
217
|
|
203
|
-
##
|
218
|
+
## Submitting an Issue
|
204
219
|
We use the [GitHub issue tracker][issues] to track bugs and features. Before
|
205
220
|
submitting a bug report or feature request, check to make sure it hasn't
|
206
221
|
already been submitted. You can indicate support for an existing issue by
|
@@ -211,19 +226,23 @@ bug report should include a pull request with failing specs.
|
|
211
226
|
|
212
227
|
[gist]: https://gist.github.com/
|
213
228
|
|
214
|
-
##
|
215
|
-
1. Fork the
|
216
|
-
2. Create a topic branch.
|
217
|
-
3.
|
218
|
-
4.
|
219
|
-
5.
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
229
|
+
## Submitting a Pull Request
|
230
|
+
1. [Fork the repository.][fork]
|
231
|
+
2. [Create a topic branch.][branch]
|
232
|
+
3. Add specs for your unimplemented feature or bug fix.
|
233
|
+
4. Run `bundle exec rake spec`. If your specs pass, return to step 3.
|
234
|
+
5. Implement your feature or bug fix.
|
235
|
+
6. Run `bundle exec rake spec`. If your specs fail, return to step 5.
|
236
|
+
7. Run `open coverage/index.html`. If your changes are not completely covered
|
237
|
+
by your tests, return to step 3.
|
238
|
+
6. Add, commit, and push your changes.
|
239
|
+
7. [Submit a pull request.][pr]
|
240
|
+
|
241
|
+
[fork]: http://help.github.com/fork-a-repo/
|
242
|
+
[branch]: http://learn.github.com/p/branching.html
|
243
|
+
[pr]: http://help.github.com/send-pull-requests/
|
244
|
+
|
245
|
+
## Supported Ruby Versions
|
227
246
|
This library aims to support and is [tested against][travis] the following Ruby
|
228
247
|
implementations:
|
229
248
|
|
@@ -234,8 +253,7 @@ implementations:
|
|
234
253
|
|
235
254
|
[rubinius]: http://rubini.us/
|
236
255
|
|
237
|
-
If something doesn't work on one of these
|
238
|
-
a bug.
|
256
|
+
If something doesn't work on one of these Ruby versions, it's a bug.
|
239
257
|
|
240
258
|
This library may inadvertently work (or seem to work) on other Ruby
|
241
259
|
implementations, however support will only be provided for the versions listed
|
@@ -244,11 +262,11 @@ above.
|
|
244
262
|
If you would like this library to support another Ruby version, you may
|
245
263
|
volunteer to be a maintainer. Being a maintainer entails making sure all tests
|
246
264
|
run and pass on that implementation. When something breaks on your
|
247
|
-
implementation, you will be
|
248
|
-
|
249
|
-
|
265
|
+
implementation, you will be responsible for providing patches in a timely
|
266
|
+
fashion. If critical issues for a particular implementation exist at the time
|
267
|
+
of a major release, support for that Ruby version may be dropped.
|
250
268
|
|
251
|
-
##
|
269
|
+
## Copyright
|
252
270
|
Copyright (c) 2011 Erik Michaels-Ober. See [LICENSE][] for details.
|
253
271
|
|
254
272
|
[license]: https://github.com/sferik/t/blob/master/LICENSE.md
|
data/lib/t/cli.rb
CHANGED
@@ -142,13 +142,15 @@ module T
|
|
142
142
|
elsif options['long']
|
143
143
|
array = direct_messages.map do |direct_message|
|
144
144
|
created_at = direct_message.created_at > 6.months.ago ? direct_message.created_at.strftime("%b %e %H:%M") : direct_message.created_at.strftime("%b %e %Y")
|
145
|
-
[direct_message.id
|
145
|
+
[direct_message.id, created_at, "@#{direct_message.sender.screen_name}", direct_message.text.gsub(/\n+/, ' ')]
|
146
146
|
end
|
147
147
|
if STDOUT.tty?
|
148
148
|
headings = ["ID", "Posted at", "Screen name", "Text"]
|
149
149
|
array.unshift(headings) unless direct_messages.empty?
|
150
|
+
print_table(array, :truncate => true)
|
151
|
+
else
|
152
|
+
print_table(array)
|
150
153
|
end
|
151
|
-
print_table(array)
|
152
154
|
else
|
153
155
|
direct_messages.each do |direct_message|
|
154
156
|
say "#{direct_message.sender.screen_name.rjust(MAX_SCREEN_NAME_SIZE)}: #{direct_message.text.gsub(/\n+/, ' ')} (#{time_ago_in_words(direct_message.created_at)} ago)"
|
@@ -174,13 +176,15 @@ module T
|
|
174
176
|
elsif options['long']
|
175
177
|
array = direct_messages.map do |direct_message|
|
176
178
|
created_at = direct_message.created_at > 6.months.ago ? direct_message.created_at.strftime("%b %e %H:%M") : direct_message.created_at.strftime("%b %e %Y")
|
177
|
-
[direct_message.id
|
179
|
+
[direct_message.id, created_at, "@#{direct_message.recipient.screen_name}", direct_message.text.gsub(/\n+/, ' ')]
|
178
180
|
end
|
179
181
|
if STDOUT.tty?
|
180
182
|
headings = ["ID", "Posted at", "Screen name", "Text"]
|
181
183
|
array.unshift(headings) unless direct_messages.empty?
|
184
|
+
print_table(array, :truncate => true)
|
185
|
+
else
|
186
|
+
print_table(array)
|
182
187
|
end
|
183
|
-
print_table(array)
|
184
188
|
else
|
185
189
|
direct_messages.each do |direct_message|
|
186
190
|
say "#{direct_message.recipient.screen_name.rjust(MAX_SCREEN_NAME_SIZE)}: #{direct_message.text.gsub(/\n+/, ' ')} (#{time_ago_in_words(direct_message.created_at)} ago)"
|
@@ -727,13 +731,15 @@ module T
|
|
727
731
|
end
|
728
732
|
elsif options['long']
|
729
733
|
array = places.map do |place|
|
730
|
-
[place.woeid
|
734
|
+
[place.woeid, place.parent_id, place.place_type, place.name, place.country]
|
731
735
|
end
|
732
736
|
if STDOUT.tty?
|
733
737
|
headings = ["WOEID", "Parent ID", "Type", "Name", "Country"]
|
734
738
|
array.unshift(headings) unless places.empty?
|
739
|
+
print_table(array, :truncate => true)
|
740
|
+
else
|
741
|
+
print_table(array)
|
735
742
|
end
|
736
|
-
print_table(array)
|
737
743
|
else
|
738
744
|
if STDOUT.tty?
|
739
745
|
print_in_columns(places.map(&:name))
|
@@ -2,21 +2,18 @@ module Enumerable
|
|
2
2
|
|
3
3
|
def threaded_each
|
4
4
|
threads = []
|
5
|
-
|
5
|
+
each do |object|
|
6
6
|
threads << Thread.new{yield object}
|
7
7
|
end
|
8
|
-
threads.each(&:
|
9
|
-
result
|
8
|
+
threads.each(&:value)
|
10
9
|
end
|
11
10
|
|
12
11
|
def threaded_map
|
13
|
-
results = map{nil}
|
14
12
|
threads = []
|
15
|
-
|
16
|
-
threads << Thread.new{
|
13
|
+
each do |object|
|
14
|
+
threads << Thread.new{yield object}
|
17
15
|
end
|
18
|
-
threads.
|
19
|
-
results
|
16
|
+
threads.map(&:value)
|
20
17
|
end
|
21
18
|
|
22
19
|
end
|
data/lib/t/printable.rb
CHANGED
@@ -44,13 +44,15 @@ module T
|
|
44
44
|
elsif options['long']
|
45
45
|
array = lists.map do |list|
|
46
46
|
created_at = list.created_at > 6.months.ago ? list.created_at.strftime("%b %e %H:%M") : list.created_at.strftime("%b %e %Y")
|
47
|
-
[list.id
|
47
|
+
[list.id, created_at, list.full_name, number_with_delimiter(list.member_count), number_with_delimiter(list.subscriber_count), list.mode, list.description]
|
48
48
|
end
|
49
49
|
if STDOUT.tty?
|
50
50
|
headings = ["ID", "Created at", "Slug", "Members", "Subscribers", "Mode", "Description"]
|
51
51
|
array.unshift(headings) unless lists.empty?
|
52
|
+
print_table(array, :truncate => true)
|
53
|
+
else
|
54
|
+
print_table(array)
|
52
55
|
end
|
53
|
-
print_table(array)
|
54
56
|
else
|
55
57
|
if STDOUT.tty?
|
56
58
|
print_in_columns(lists.map(&:full_name))
|
@@ -72,26 +74,29 @@ module T
|
|
72
74
|
elsif options['long']
|
73
75
|
array = statuses.map do |status|
|
74
76
|
created_at = status.created_at > 6.months.ago ? status.created_at.strftime("%b %e %H:%M") : status.created_at.strftime("%b %e %Y")
|
75
|
-
[status.id
|
77
|
+
[status.id, created_at, "@#{status.user.screen_name}", status.text.gsub(/\n+/, ' ')]
|
76
78
|
end
|
77
79
|
if STDOUT.tty?
|
78
80
|
headings = ["ID", "Posted at", "Screen name", "Text"]
|
79
81
|
array.unshift(headings) unless statuses.empty?
|
82
|
+
print_table(array, :truncate => true)
|
83
|
+
else
|
84
|
+
print_table(array)
|
80
85
|
end
|
81
|
-
print_table(array)
|
82
86
|
else
|
83
|
-
ENV['THOR_COLUMNS'] = "80"
|
84
87
|
if STDOUT.tty? && !options['no-color']
|
88
|
+
say unless statuses.empty?
|
85
89
|
statuses.each do |status|
|
86
90
|
say(" #{Thor::Shell::Color::BOLD}@#{status.user.screen_name}", :yellow)
|
87
|
-
|
91
|
+
print_wrapped(status.text, :indent => 3)
|
88
92
|
say(" #{Thor::Shell::Color::BOLD}#{time_ago_in_words(status.created_at)} ago", :black)
|
89
93
|
say
|
90
94
|
end
|
91
95
|
else
|
96
|
+
say unless statuses.empty?
|
92
97
|
statuses.each do |status|
|
93
98
|
say(" @#{status.user.screen_name}")
|
94
|
-
|
99
|
+
print_wrapped(status.text, :indent => 3)
|
95
100
|
say(" #{time_ago_in_words(status.created_at)} ago")
|
96
101
|
say
|
97
102
|
end
|
@@ -123,13 +128,15 @@ module T
|
|
123
128
|
elsif options['long']
|
124
129
|
array = users.map do |user|
|
125
130
|
created_at = user.created_at > 6.months.ago ? user.created_at.strftime("%b %e %H:%M") : user.created_at.strftime("%b %e %Y")
|
126
|
-
[user.id
|
131
|
+
[user.id, created_at, number_with_delimiter(user.statuses_count), number_with_delimiter(user.favourites_count), number_with_delimiter(user.listed_count), number_with_delimiter(user.friends_count), number_with_delimiter(user.followers_count), "@#{user.screen_name}", user.name]
|
127
132
|
end
|
128
133
|
if STDOUT.tty?
|
129
134
|
headings = ["ID", "Since", "Tweets", "Favorites", "Listed", "Following", "Followers", "Screen name", "Name"]
|
130
135
|
array.unshift(headings) unless users.empty?
|
136
|
+
print_table(array, :truncate => true)
|
137
|
+
else
|
138
|
+
print_table(array)
|
131
139
|
end
|
132
|
-
print_table(array)
|
133
140
|
else
|
134
141
|
if STDOUT.tty?
|
135
142
|
print_in_columns(users.map{|user| "@#{user.screen_name}"})
|