usaidwat 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef237332f70848558231f2efa1d72ae670c0b1d2
4
- data.tar.gz: c79816dfb00af261f512ff612330a5e86d2b46b2
3
+ metadata.gz: 04536acd69f58116dbc58388d79dea104407598c
4
+ data.tar.gz: acb24952c11f213b5677808eda93bfe65329a4b9
5
5
  SHA512:
6
- metadata.gz: f899ceb86532ec8f506f6318ac5afeeba0251b466a7c0bbe5c0289f3d9cd307924d1f63af14c408f646155dfe0d1b2299a23593568ea5b28bd069badd5177e3c
7
- data.tar.gz: a91b962fe4a7de6bcc5c4ba69b6a8c695672fad3e895b59e175880efa5b415c3b309684cfd8df80c3a892da0ae6f56af0fc72d198786a82c1a20d96b783fa856
6
+ metadata.gz: 3c6b186e4d3f45c2697e4eb6e76b46187dfc9c1217757b3d3058af9319f9bb6b6910a17cd68abc29e7e2408b4c5966da308aa61150d77de93fa1ee5ab9a93de8
7
+ data.tar.gz: 85719e6d25ad91a891fd28478cf638a85ff7fd53600dc859f6f863451aef84f34424968ffe5064ea2c93e04eebac120ad96dfc27708378ab62906abccc22f1b4
data/Rakefile CHANGED
@@ -6,10 +6,15 @@ GEMSPEC = `git ls-files | grep gemspec`.chomp
6
6
  GEM = "usaidwat-#{USaidWat::VERSION}.gem"
7
7
 
8
8
  desc "Build usaidwat.gem"
9
- task :build do
9
+ task :build => :perms do
10
10
  system "gem", "build", GEMSPEC
11
11
  end
12
12
 
13
+ desc "Ensure correct permissions for usaidwat.gem"
14
+ task :perms do
15
+ system "chmod", "-R", "a+rX", *`git ls-files`.chomp.split("\n")
16
+ end
17
+
13
18
  desc "Install usaidwat.gem"
14
19
  task :install => :build do
15
20
  system "gem", "install", GEM
data/bin/usaidwat CHANGED
@@ -1,5 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'usaidwat'
4
+ require 'mercenary'
4
5
 
5
- USaidWat::Application.start(ARGV)
6
+ Mercenary.program(:usaidwat) do |p|
7
+ p.version USaidWat::VERSION
8
+ p.description 'Answers the age-old question, "Where does a Redditor comment the most?"'
9
+ p.syntax 'usaidwat <command> [options] <args>'
10
+
11
+ USaidWat::Application::Command.subclasses.each { |c| c.new(p) }
12
+
13
+ p.action do |args, options|
14
+ if args.empty?
15
+ puts p.to_s
16
+ exit 0
17
+ else
18
+ abort "Invalid command: #{args.first}"
19
+ end
20
+ end
21
+ end
@@ -18,6 +18,36 @@ Feature: Browse comments
18
18
  Yep. My first experience with a Heisenbug occurred in a C++ program, and disappeared when I tried to print a variable with printf (only to reappear when that call was removed).
19
19
 
20
20
 
21
+ nyc
22
+ http://www.reddit.com/r/nyc/comments/141zqc/z/c79dxg6
23
+ NYC taxi roof lights get overhaul - A light simply will mean the cab is availab
24
+ over 3 years ago
25
+
26
+ It has a fare when the lights are off.
27
+
28
+
29
+ worldnews
30
+ http://www.reddit.com/r/worldnews/comments/140mra/z/c797jq4
31
+ Palestinians win upgraded UN status by wide margin
32
+ over 3 years ago
33
+
34
+ The Judgment of Solomon Accords.
35
+ """
36
+
37
+ Scenario: List all comments with comment bodies unformatted
38
+ Given the Reddit service returns comments for the user "mipadi"
39
+ And time is frozen at Jun 24, 2015 11:05 AM
40
+ When I run `usaidwat log --raw mipadi`
41
+ Then it should pass with:
42
+ """
43
+ wikipedia
44
+ http://www.reddit.com/r/wikipedia/comments/142t4w/z/c79peed
45
+ Heisenbug: a software bug that seems to disappear or alter its behavior when one
46
+ over 3 years ago
47
+
48
+ Yep. My first experience with a Heisenbug occurred in a C++ program, and disappeared when I tried to print a variable with printf (only to reappear when that call was removed).
49
+
50
+
21
51
  nyc
22
52
  http://www.reddit.com/r/nyc/comments/141zqc/z/c79dxg6
23
53
  NYC taxi roof lights get overhaul - A light simply will mean the cab is availab
@@ -34,6 +64,54 @@ Feature: Browse comments
34
64
  The Judgment of Solomon Accords.
35
65
  """
36
66
 
67
+ Scenario: Output comments on line line
68
+ Given the Reddit service returns comments for the user "mipadi"
69
+ And time is frozen at Jun 24, 2015 11:05 AM
70
+ When I run `usaidwat log --oneline mipadi`
71
+ Then it should pass with:
72
+ """
73
+ wikipedia Heisenbug: a software bug that seems to disappear or alter its behavio
74
+ nyc NYC taxi roof lights get overhaul - A light simply will mean the cab is ava
75
+ worldnews Palestinians win upgraded UN status by wide margin
76
+ """
77
+
78
+ Scenario: Search for a specific comment
79
+ Given the Reddit service returns comments for the user "mipadi"
80
+ And time is frozen at Jun 24, 2015 11:05 AM
81
+ When I run `usaidwat log --grep='Heisenbug' mipadi`
82
+ Then it should pass with:
83
+ """
84
+ wikipedia
85
+ http://www.reddit.com/r/wikipedia/comments/142t4w/z/c79peed
86
+ Heisenbug: a software bug that seems to disappear or alter its behavior when one
87
+ over 3 years ago
88
+
89
+ Yep. My first experience with a Heisenbug occurred in a C++ program, and disappeared when I tried to print a variable with printf (only to reappear when that call was removed).
90
+ """
91
+
92
+ Scenario: Search for a specific comment with wrong case
93
+ Given the Reddit service returns comments for the user "mipadi"
94
+ And time is frozen at Jun 24, 2015 11:05 AM
95
+ When I run `usaidwat log --grep='heisenbug' mipadi`
96
+ Then it should pass with:
97
+ """
98
+ wikipedia
99
+ http://www.reddit.com/r/wikipedia/comments/142t4w/z/c79peed
100
+ Heisenbug: a software bug that seems to disappear or alter its behavior when one
101
+ over 3 years ago
102
+
103
+ Yep. My first experience with a Heisenbug occurred in a C++ program, and disappeared when I tried to print a variable with printf (only to reappear when that call was removed).
104
+ """
105
+
106
+ Scenario: Search for a specific comment with no matches
107
+ Given the Reddit service returns comments for the user "mipadi"
108
+ And time is frozen at Jun 24, 2015 11:05 AM
109
+ When I run `usaidwat log --grep='oogabooga' mipadi`
110
+ Then it should pass with:
111
+ """
112
+ mipadi has no comments matching /oogabooga/.
113
+ """
114
+
37
115
  Scenario: List all comments for a user that does not exist
38
116
  Given the Reddit service does not have a user "testuser"
39
117
  When I run `usaidwat log testuser`
@@ -50,6 +128,22 @@ Feature: Browse comments
50
128
  blank has no comments.
51
129
  """
52
130
 
131
+ Scenario: Search for a comment for a user that does not exist
132
+ Given the Reddit service does not have a user "testuser"
133
+ When I run `usaidwat log --grep='Heisenbug' testuser`
134
+ Then it should fail with:
135
+ """
136
+ No such user: testuser
137
+ """
138
+
139
+ Scenario: Search for a comment when user has no comments
140
+ Given the Reddit service returns comments for the user "blank"
141
+ When I run `usaidwat log --grep='Heisenbug' blank`
142
+ Then it should pass with:
143
+ """
144
+ blank has no comments matching /Heisenbug/.
145
+ """
146
+
53
147
  Scenario: Tally comments
54
148
  Given the Reddit service returns comments for the user "mipadi"
55
149
  When I run `usaidwat tally mipadi`
@@ -106,6 +200,22 @@ Feature: Browse comments
106
200
  blank has no comments.
107
201
  """
108
202
 
203
+ Scenario: Search for a comment when tallying
204
+ Given the Reddit service returns comments for the user "mipadi"
205
+ When I run `usaidwat tally --grep='Heisenbug' mipadi`
206
+ Then it should fail with:
207
+ """
208
+ invalid option: --grep=Heisenbug
209
+ """
210
+
211
+ Scenario: Search for a comment when sorting
212
+ Given the Reddit service returns comments for the user "mipadi"
213
+ When I run `usaidwat tally -c --grep='Heisenbug' mipadi`
214
+ Then it should fail with:
215
+ """
216
+ invalid option: --grep=Heisenbug
217
+ """
218
+
109
219
  Scenario: Sort comments when a user does not exist
110
220
  Given the Reddit service does not have a user "testuser"
111
221
  When I run `usaidwat tally testuser`
@@ -144,6 +254,34 @@ Feature: Browse comments
144
254
  You didn't slow down for very long though, did you?
145
255
  """
146
256
 
257
+ Scenario: Search in comments for a particular subreddit
258
+ Given the Reddit service returns comments for the user "mipadi"
259
+ And time is frozen at Jun 24, 2015 11:05 AM
260
+ When I run `usaidwat log --grep='New Jersey' mipadi AskReddit`
261
+ Then it should pass with:
262
+ """
263
+ AskReddit
264
+ http://www.reddit.com/r/AskReddit/comments/140t5c/z/c795nw3
265
+ I'm from Tennessee and most of our jokes are geared toward Mississippi and Alaba
266
+ over 3 years ago
267
+
268
+ You're from New Jersey? Which exit?
269
+ """
270
+
271
+ Scenario: Search in comments for a particular subreddit with wrong case
272
+ Given the Reddit service returns comments for the user "mipadi"
273
+ And time is frozen at Jun 24, 2015 11:05 AM
274
+ When I run `usaidwat log --grep='new jersey' mipadi AskReddit`
275
+ Then it should pass with:
276
+ """
277
+ AskReddit
278
+ http://www.reddit.com/r/AskReddit/comments/140t5c/z/c795nw3
279
+ I'm from Tennessee and most of our jokes are geared toward Mississippi and Alaba
280
+ over 3 years ago
281
+
282
+ You're from New Jersey? Which exit?
283
+ """
284
+
147
285
  Scenario: List comments for a particular subreddit specified with the wrong case
148
286
  Given the Reddit service returns comments for the user "mipadi"
149
287
  And time is frozen at Jun 24, 2015 11:05 AM
@@ -187,8 +325,7 @@ Feature: Browse comments
187
325
  When I run `usaidwat tally mipadi AskReddit`
188
326
  Then it should fail with:
189
327
  """
190
- ERROR: "usaidwat tally" was called with arguments ["mipadi", "AskReddit"]
191
- Usage: "usaidwat tally USERNAME"
328
+ You cannot specify a subreddit when tallying comments
192
329
  """
193
330
 
194
331
  Scenario: Sort comments with subreddit
@@ -196,16 +333,7 @@ Feature: Browse comments
196
333
  When I run `usaidwat tally -c mipadi AskReddit`
197
334
  Then it should fail with:
198
335
  """
199
- ERROR: "usaidwat tally" was called with arguments ["mipadi", "AskReddit"]
200
- Usage: "usaidwat tally USERNAME"
201
- """
202
-
203
- Scenario: Pass no arguments
204
- Given the Reddit service returns comments for the user "mipadi"
205
- When I run `usaidwat`
206
- Then it should pass with:
207
- """
208
- Commands:
336
+ You cannot specify a subreddit when tallying comments
209
337
  """
210
338
 
211
339
  Scenario: Pass no arguments when tallying
@@ -213,8 +341,7 @@ Feature: Browse comments
213
341
  When I run `usaidwat tally`
214
342
  Then it should fail with:
215
343
  """
216
- ERROR: "usaidwat tally" was called with no arguments
217
- Usage: "usaidwat tally USERNAME"
344
+ You must specify a username
218
345
  """
219
346
 
220
347
  Scenario: Pass no arguments when sorting
@@ -222,6 +349,13 @@ Feature: Browse comments
222
349
  When I run `usaidwat tally -c`
223
350
  Then it should fail with:
224
351
  """
225
- ERROR: "usaidwat tally" was called with no arguments
226
- Usage: "usaidwat tally USERNAME"
352
+ You must specify a username
353
+ """
354
+
355
+ Scenario: Pass no arguments when searching
356
+ Given the Reddit service returns comments for the user "mipadi"
357
+ When I run `usaidwat log --grep mipadi`
358
+ Then it should fail with:
359
+ """
360
+ You must specify a username
227
361
  """
@@ -4,17 +4,29 @@ Feature: Get help
4
4
  I want to be able to list help information for usaidwat
5
5
  In order to learn how to use it
6
6
 
7
+ Scenario: Pass no arguments
8
+ Given the Reddit service returns comments for the user "mipadi"
9
+ When I run `usaidwat`
10
+ Then it should pass with:
11
+ """
12
+ Usage:
13
+
14
+ usaidwat <command> [options] <args>
15
+ """
16
+
7
17
  Scenario: List usage details
8
18
  When I run `usaidwat --help`
9
19
  Then it should pass with:
10
20
  """
11
- Commands:
21
+ Usage:
22
+
23
+ usaidwat <command> [options] <args>
12
24
  """
13
25
 
14
26
  Scenario: Get version
15
27
  When I run `usaidwat --version`
16
28
  Then the exit status should be 0
17
- And the stdout should contain:
29
+ And the output should match:
18
30
  """
19
- usaidwat v
31
+ usaidwat [0-9]+\.[0-9]+\.[0-9]+
20
32
  """
@@ -1,84 +1,130 @@
1
- require 'sysexits'
2
- require 'thor'
1
+ require 'usaidwat/algo'
2
+ require 'usaidwat/client'
3
3
  require 'usaidwat/pager'
4
+ require 'sysexits'
4
5
 
5
6
  module USaidWat
6
- class Application < Thor
7
- include Pager
8
- include Sysexits
7
+ module Application
8
+ class Command
9
+ include Pager
10
+ include Sysexits
11
+
12
+ attr_reader :client
13
+
14
+ class << self
15
+ def subclasses
16
+ @subclasses ||= []
17
+ end
9
18
 
10
- class << self
11
- def client
12
- ENV['USAIDWAT_ENV'] == 'cucumber' ? USaidWat::Client::TestRedditor : USaidWat::Client::Redditor
19
+ def inherited(base)
20
+ subclasses << base
21
+ super
22
+ end
13
23
  end
14
24
 
15
- def exit_on_failure?
16
- true
25
+ def initialize(prog)
26
+ @client = cucumber? ? USaidWat::Client::TestRedditor : USaidWat::Client::Redditor
17
27
  end
18
- end
19
28
 
20
- map '--version' => :version
21
- map 't' => :tally
22
- map 'l' => :log
23
-
24
- desc 'tally USERNAME', 'Count comments by subreddit'
25
- option :count, :aliases => '-c', :type => :boolean, :desc => 'Sort output by number of comments'
26
- def tally(username)
27
- redditor = Application.client.new(username)
28
- algo_cls = options[:count] ? USaidWat::Algorithms::CountAlgorithm : USaidWat::Algorithms::LexicographicalAlgorithm
29
- quit "#{redditor.username} has no comments." if redditor.comments.empty?
30
- # Unfortunately Snooby cannot return comments for a specific
31
- # user in a specific subreddit, so for now we have to sort them
32
- # ourself.
33
- longest_subreddit = 0
34
- buckets = Hash.new { |hash, key| hash[key] = 0 }
35
- redditor.comments.each do |comment|
36
- subreddit = comment.subreddit
37
- longest_subreddit = subreddit.length if subreddit.length > longest_subreddit
38
- buckets[subreddit] += 1
29
+ protected
30
+
31
+ def cucumber?
32
+ ENV['USAIDWAT_ENV'] == 'cucumber'
39
33
  end
40
- algo = algo_cls.new(buckets)
41
- subreddits = buckets.keys.sort { |a,b| algo.sort(a, b) }
42
- subreddits.each do |subreddit|
43
- tally = buckets[subreddit]
44
- printf "%-*s %3d\n", longest_subreddit, subreddit, tally
34
+
35
+ def quit(message, code=:ok)
36
+ puts message
37
+ exit code
45
38
  end
46
- rescue USaidWat::Client::NoSuchUserError
47
- quit "No such user: #{username}", :no_such_user
48
39
  end
49
40
 
50
- desc 'log USERNAME [SUBREDDIT]', 'Show comments by a user'
51
- def log(username, subreddit = nil)
52
- redditor = Application.client.new(username)
53
- if subreddit
41
+ class Log < Command
42
+ def initialize(prog)
43
+ prog.command(:log) do |c|
44
+ c.alias :l
45
+ c.option 'grep', '--grep STRING', 'Show only comments matching STRING'
46
+ c.option 'oneline', '--oneline', 'Output log in a more comptact form'
47
+ c.option 'raw', '--raw', 'Print raw comment bodies'
48
+
49
+ c.action do |args, options|
50
+ process(options, args)
51
+ end
52
+ end
53
+ super
54
+ end
55
+
56
+ def process(options, args)
57
+ raise ArgumentError.new('You must specify a username') if args.empty?
58
+ username = args.shift
59
+ subreddit = args.shift
60
+
61
+ redditor = client.new(username)
54
62
  comments = redditor.comments
55
- comments = comments.group_by { |c| c.subreddit.downcase }
56
- comments = comments[subreddit.downcase]
57
- quit "No comments by #{redditor.username} for #{subreddit}." if comments.nil?
58
- list_comments(comments)
59
- else
60
- quit "#{redditor.username} has no comments." if redditor.comments.empty?
61
- list_comments(redditor.comments)
63
+ if subreddit
64
+ comments = comments.group_by { |c| c.subreddit.downcase }
65
+ comments = comments[subreddit.downcase]
66
+ quit "No comments by #{redditor.username} for #{subreddit}." if comments.nil?
67
+ end
68
+ comments = comments.select { |c| c.body =~ /#{options['grep']}/i } if options['grep']
69
+ if comments.empty?
70
+ msg = "#{redditor.username} has no comments"
71
+ msg = "#{msg} matching /#{options['grep']}/" if options['grep']
72
+ msg = "#{msg}."
73
+ quit msg
74
+ end
75
+ list_comments(comments, options['grep'], !options['oneline'].nil?, !options['raw'].nil?)
76
+ rescue USaidWat::Client::NoSuchUserError
77
+ quit "No such user: #{username}", :no_such_user
62
78
  end
63
- rescue USaidWat::Client::NoSuchUserError
64
- quit "No such user: #{username}", :no_such_user
65
- end
66
79
 
67
- desc 'version', 'Show version info and exit'
68
- def version
69
- puts "usaidwat v#{USaidWat::VERSION}"
70
- end
80
+ private
71
81
 
72
- no_commands do
73
- def list_comments(comments)
74
- formatter = USaidWat::CLI::CommentFormatter.new
82
+ def list_comments(comments, pattern = nil, oneline = false, raw = false)
83
+ formatter = (oneline ? USaidWat::CLI::CompactCommentFormatter : USaidWat::CLI::CommentFormatter).new(pattern, raw)
75
84
  page
76
85
  comments.each { |c| print formatter.format(c) }
77
86
  end
87
+ end
78
88
 
79
- def quit(message, code=:ok)
80
- puts message
81
- exit code
89
+ class Tally < Command
90
+ def initialize(prog)
91
+ prog.command(:tally) do |c|
92
+ c.alias :t
93
+ c.option 'count', '-c', '--count', 'Sort output by number of comments'
94
+
95
+ c.action do |args, options|
96
+ process(options, args)
97
+ end
98
+ end
99
+ super
100
+ end
101
+
102
+ def process(options, args)
103
+ raise ArgumentError.new('You must specify a username') if args.empty?
104
+ raise ArgumentError.new('You cannot specify a subreddit when tallying comments') if args.count > 1
105
+ username = args.first
106
+
107
+ redditor = client.new(username)
108
+ algo_cls = options['count'] ? USaidWat::Algorithms::CountAlgorithm : USaidWat::Algorithms::LexicographicalAlgorithm
109
+ quit "#{redditor.username} has no comments." if redditor.comments.empty?
110
+ # Unfortunately Snooby cannot return comments for a specific
111
+ # user in a specific subreddit, so for now we have to sort them
112
+ # ourself.
113
+ longest_subreddit = 0
114
+ buckets = Hash.new { |hash, key| hash[key] = 0 }
115
+ redditor.comments.each do |comment|
116
+ subreddit = comment.subreddit
117
+ longest_subreddit = subreddit.length if subreddit.length > longest_subreddit
118
+ buckets[subreddit] += 1
119
+ end
120
+ algo = algo_cls.new(buckets)
121
+ subreddits = buckets.keys.sort { |a,b| algo.sort(a, b) }
122
+ subreddits.each do |subreddit|
123
+ tally = buckets[subreddit]
124
+ printf "%-*s %3d\n", longest_subreddit, subreddit, tally
125
+ end
126
+ rescue USaidWat::Client::NoSuchUserError
127
+ quit "No such user: #{username}", :no_such_user
82
128
  end
83
129
  end
84
130
  end
@@ -1,12 +1,10 @@
1
+ require 'rainbow'
2
+
1
3
  class String
2
4
  def truncate(width)
3
5
  self[0, width]
4
6
  end
5
7
 
6
- def convert_entities
7
- self.gsub(/&gt;/, '>').gsub(/&lt;/, '<').gsub(/&amp;/, '&')
8
- end
9
-
10
8
  def pluralize(n, suffix = 's', singular_suffix = '')
11
9
  if n == 1
12
10
  self + singular_suffix
@@ -14,4 +12,8 @@ class String
14
12
  self + suffix
15
13
  end
16
14
  end
15
+
16
+ def highlight(pattern)
17
+ gsub(/#{pattern}/i) { |m| Rainbow(m).red }
18
+ end
17
19
  end
@@ -1,7 +1,9 @@
1
1
  require 'date'
2
+ require 'downterm'
2
3
  require 'highline'
3
- require 'stringio'
4
4
  require 'rainbow/ext/string'
5
+ require 'redcarpet'
6
+ require 'stringio'
5
7
  require 'usaidwat/ext/string'
6
8
  require 'usaidwat/ext/time'
7
9
 
@@ -9,27 +11,58 @@ Rainbow.enabled = true unless ENV['USAIDWAT_ENV'] == 'cucumber'
9
11
 
10
12
  module USaidWat
11
13
  module CLI
12
- class CommentFormatter
13
- def initialize
14
+ class BaseFormatter
15
+ attr_reader :pattern
16
+
17
+ def initialize(pattern = nil, raw = false)
18
+ @pattern = pattern
19
+ @raw = raw
14
20
  @count = 0
15
21
  end
16
-
22
+
23
+ def pattern?
24
+ !@pattern.nil?
25
+ end
26
+
27
+ def raw?
28
+ @raw
29
+ end
30
+ end
31
+
32
+ class CommentFormatter < BaseFormatter
33
+ def initialize(pattern = nil, raw = false)
34
+ @markdown = Redcarpet::Markdown.new(Downterm::Render::Terminal, :autolink => true,
35
+ :strikethrough => true,
36
+ :superscript => true)
37
+ super
38
+ end
39
+
17
40
  def format(comment)
18
41
  cols = HighLine::SystemExtensions.terminal_size[0]
19
42
  out = StringIO.new
20
43
  out.write("\n\n") unless @count == 0
21
44
  out.write("#{comment.subreddit}\n".color(:green))
22
45
  out.write("#{comment_link(comment)}\n".color(:yellow))
23
- out.write("#{comment.link_title.strip.truncate(cols)}\n".color(:red))
46
+ out.write("#{comment.link_title.strip.truncate(cols)}\n".color(:magenta))
24
47
  out.write("#{comment_date(comment)}\n".color(:blue))
25
48
  out.write("\n")
26
- out.write("#{comment.body.strip.convert_entities}\n")
49
+ out.write("#{comment_body(comment)}\n")
27
50
  @count += 1
28
51
  out.rewind
29
52
  out.read
30
53
  end
31
54
 
32
55
  private
56
+ def comment_body(comment)
57
+ body = comment.body
58
+ body = @markdown.render(body) unless raw?
59
+ if pattern?
60
+ body.highlight(pattern)
61
+ else
62
+ body
63
+ end
64
+ end
65
+
33
66
  def comment_link(comment)
34
67
  link = comment.link_id.split("_")[-1]
35
68
  "http://www.reddit.com/r/#{comment.subreddit}/comments/#{link}/z/#{comment.id}"
@@ -39,5 +72,18 @@ module USaidWat
39
72
  DateTime.strptime(comment.created_utc.to_s, "%s").to_time.localtime.ago
40
73
  end
41
74
  end
75
+
76
+ class CompactCommentFormatter < BaseFormatter
77
+ def format(comment)
78
+ cols = HighLine::SystemExtensions.terminal_size[0]
79
+ out = StringIO.new
80
+ subreddit = comment.subreddit
81
+ cols -= subreddit.length + 1
82
+ out.write("#{subreddit}".color(:green))
83
+ out.write(" #{comment.link_title.strip.truncate(cols)}\n")
84
+ out.rewind
85
+ out.read
86
+ end
87
+ end
42
88
  end
43
89
  end
@@ -1,3 +1,3 @@
1
1
  module USaidWat
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -72,5 +72,28 @@ EXPECTED
72
72
  end
73
73
  end
74
74
  end
75
+
76
+ describe CompactCommentFormatter do
77
+ let (:formatter) { CompactCommentFormatter.new }
78
+
79
+ before do
80
+ Timecop.freeze(Time.new(2015, 6, 16, 17, 8))
81
+ end
82
+
83
+ after do
84
+ Timecop.return
85
+ end
86
+
87
+ describe "#format" do
88
+ it "should return a string containing the formatted comment" do
89
+ comment = double("comment")
90
+ expect(comment).to receive(:subreddit).and_return("programming")
91
+ expect(comment).to receive(:link_title).and_return("Why Brit Ruby 2013 was cancelled and why this is not ok - Gist")
92
+ expected = "programming Why Brit Ruby 2013 was cancelled and why this is not ok - Gist\n"
93
+ actual = formatter.format(comment).delete_ansi_color_codes
94
+ expect(actual).to eq(expected)
95
+ end
96
+ end
97
+ end
75
98
  end
76
99
  end
@@ -1,38 +1,9 @@
1
+ require 'rainbow'
1
2
  require 'spec_helper'
2
3
 
3
4
  module USaidWat
4
5
  module Ext
5
6
  describe String do
6
- describe "#convert_entities" do
7
- it "converts &gt; to >" do
8
- s = "-&gt; look at this!"
9
- expected = "-> look at this!"
10
- actual = s.convert_entities
11
- expect(actual).to eq(expected)
12
- end
13
-
14
- it "converts &lt; to <" do
15
- s = "left &lt;&lt; shift!"
16
- expected = "left << shift!"
17
- actual = s.convert_entities
18
- expect(actual).to eq(expected)
19
- end
20
-
21
- it "converts both &gt; and &lt; to > and <" do
22
- s = "look -&gt; this string has both &lt;- awesome, huh?"
23
- expected = "look -> this string has both <- awesome, huh?"
24
- actual = s.convert_entities
25
- expect(actual).to eq(expected)
26
- end
27
-
28
- it "converts &amp; to &" do
29
- s = "i like cake &amp; ice cream"
30
- expected = "i like cake & ice cream"
31
- actual = s.convert_entities
32
- expect(actual).to eq(expected)
33
- end
34
- end
35
-
36
7
  describe "#truncate" do
37
8
  it "truncates strings longer than the given width to the width" do
38
9
  n = 80
@@ -74,6 +45,43 @@ module USaidWat
74
45
  expect(s.pluralize(1, "ies", "y")).to eq("poppy")
75
46
  end
76
47
  end
48
+
49
+ describe "#highlight" do
50
+ it "should highlight matching parts of strings" do
51
+ s = "apple pie is made from apples"
52
+ expected = "#{Rainbow("apple").red} pie is made from #{Rainbow("apple").red}s"
53
+ actual = s.highlight("apple")
54
+ expect(actual).to eq(expected)
55
+ end
56
+
57
+ it "should return an identical string if no matches are found" do
58
+ s = "apple pie is made from apples"
59
+ expected = s.dup
60
+ actual = s.highlight("cherry")
61
+ expect(actual).to eq(expected)
62
+ end
63
+
64
+ it "should match parts insensitive to case" do
65
+ s = "Apple pie is made from Apples"
66
+ expected = "#{Rainbow("Apple").red} pie is made from #{Rainbow("Apple").red}s"
67
+ actual = s.highlight("apple")
68
+ expect(actual).to eq(expected)
69
+ end
70
+
71
+ it "should highlight matching parts of strings using a regex-like string" do
72
+ s = "pears are tastier than bears"
73
+ expected = "#{Rainbow("pears").red} are tastier than #{Rainbow("bears").red}"
74
+ actual = s.highlight("[b|p]ears")
75
+ expect(actual).to eq(expected)
76
+ end
77
+
78
+ it "should highlight matching parts of strings using an actual regex" do
79
+ s = "pears are tastier than bears"
80
+ expected = "#{Rainbow("pears").red} are tastier than #{Rainbow("bears").red}"
81
+ actual = s.highlight(/[b|p]ears/)
82
+ expect(actual).to eq(expected)
83
+ end
84
+ end
77
85
  end
78
86
  end
79
87
  end
data/usaidwat.gemspec CHANGED
@@ -1,6 +1,8 @@
1
1
  # -*- encoding: utf-8 -*-
2
+
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
4
6
  require 'usaidwat/version'
5
7
 
6
8
  Gem::Specification.new do |gem|
@@ -13,20 +15,27 @@ Gem::Specification.new do |gem|
13
15
  gem.description = %q{View a user's last 100 Reddit comments, organized by subreddit.}
14
16
  gem.summary = %q{Answers the age-old question, "Where does a Redditor comment the most?"}
15
17
 
18
+ gem.metadata = {
19
+ 'build_date' => Time.now.strftime("%Y-%m-%d %H:%M:%S.%L %Z"),
20
+ }
21
+
16
22
  gem.files = `git ls-files`.split($/)
17
23
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
24
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
25
  gem.require_paths = ["lib"]
20
26
 
27
+ gem.required_ruby_version = '>= 1.9.3'
28
+
29
+ gem.add_runtime_dependency('downterm', '~> 0.1.0')
21
30
  gem.add_runtime_dependency('highline', '~> 1.7')
31
+ gem.add_runtime_dependency('mercenary', '~> 0.3.5')
22
32
  gem.add_runtime_dependency('rainbow', '~> 2.0')
23
33
  gem.add_runtime_dependency('snooby', '~> 0.1.5')
24
34
  gem.add_runtime_dependency('sysexits', '~> 1.2')
25
- gem.add_runtime_dependency('thor', '~> 0.19.1')
26
35
 
27
- gem.add_development_dependency('aruba', '~> 0.8.1')
36
+ gem.add_development_dependency('aruba', '~> 0.9.0')
28
37
  gem.add_development_dependency('cucumber', '~> 2.0')
29
38
  gem.add_development_dependency('rspec', '~> 3.2')
30
- gem.add_development_dependency('timecop', '~> 0.7.4')
39
+ gem.add_development_dependency('timecop', '~> 0.8.0')
31
40
  gem.add_development_dependency('webmock', '~> 1.21')
32
41
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: usaidwat
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Dippery
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-20 00:00:00.000000000 Z
11
+ date: 2015-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: downterm
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: highline
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -25,75 +39,75 @@ dependencies:
25
39
  - !ruby/object:Gem::Version
26
40
  version: '1.7'
27
41
  - !ruby/object:Gem::Dependency
28
- name: rainbow
42
+ name: mercenary
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '2.0'
47
+ version: 0.3.5
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '2.0'
54
+ version: 0.3.5
41
55
  - !ruby/object:Gem::Dependency
42
- name: snooby
56
+ name: rainbow
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: 0.1.5
61
+ version: '2.0'
48
62
  type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: 0.1.5
68
+ version: '2.0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: sysexits
70
+ name: snooby
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '1.2'
75
+ version: 0.1.5
62
76
  type: :runtime
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '1.2'
82
+ version: 0.1.5
69
83
  - !ruby/object:Gem::Dependency
70
- name: thor
84
+ name: sysexits
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: 0.19.1
89
+ version: '1.2'
76
90
  type: :runtime
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: 0.19.1
96
+ version: '1.2'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: aruba
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: 0.8.1
103
+ version: 0.9.0
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: 0.8.1
110
+ version: 0.9.0
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: cucumber
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +142,14 @@ dependencies:
128
142
  requirements:
129
143
  - - "~>"
130
144
  - !ruby/object:Gem::Version
131
- version: 0.7.4
145
+ version: 0.8.0
132
146
  type: :development
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
- version: 0.7.4
152
+ version: 0.8.0
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: webmock
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -194,7 +208,8 @@ files:
194
208
  homepage: https://github.com/mdippery/usaidwat
195
209
  licenses:
196
210
  - MIT
197
- metadata: {}
211
+ metadata:
212
+ build_date: 2015-08-27 18:54:51.726 PDT
198
213
  post_install_message:
199
214
  rdoc_options: []
200
215
  require_paths:
@@ -203,7 +218,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
203
218
  requirements:
204
219
  - - ">="
205
220
  - !ruby/object:Gem::Version
206
- version: '0'
221
+ version: 1.9.3
207
222
  required_rubygems_version: !ruby/object:Gem::Requirement
208
223
  requirements:
209
224
  - - ">="