friends 0.29 → 0.30
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +2 -5
- data/CHANGELOG.md +15 -0
- data/PULL_REQUEST_TEMPLATE.md +2 -2
- data/README.md +41 -6
- data/bin/friends +7 -0
- data/friends.gemspec +3 -4
- data/lib/friends/commands/graph.rb +4 -2
- data/lib/friends/commands/list.rb +8 -27
- data/lib/friends/graph.rb +1 -0
- data/lib/friends/introvert.rb +67 -30
- data/lib/friends/serializable.rb +1 -1
- data/lib/friends/version.rb +1 -1
- data/test/commands/graph_spec.rb +34 -0
- data/test/commands/list/activities_spec.rb +36 -0
- data/test/commands/list/favorite/friends_spec.rb +84 -2
- data/test/commands/list/favorite/locations_spec.rb +88 -1
- data/test/commands/list/friends_spec.rb +25 -0
- data/test/helper.rb +14 -4
- metadata +14 -29
- data/.ruby-version +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81e378aa8d3e1a7285adcb3f92cc91977c22eca2
|
4
|
+
data.tar.gz: f48b3ccd7d4006679c7b072b06a980432c759a6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee11daf225f5c245b68a732267b0fafd7041d478d8cff7d68860f9b50a71f9a3db51de2edd4a7dac723a6db5c5c26045a697a21bc7215acc770bed3a2390ee10
|
7
|
+
data.tar.gz: e47d850e7cc62ea74a0c212f0315de2cc5bd1eb72f331526ccee67dd39d7599b091a546770d14ba2af7132f929ab8d9076f61b28cb8a68a36432ccda3d481f56
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -125,6 +125,9 @@ Lambda:
|
|
125
125
|
LambdaCall:
|
126
126
|
Enabled: false
|
127
127
|
|
128
|
+
Layout/IndentHeredoc:
|
129
|
+
Enabled: false
|
130
|
+
|
128
131
|
LineEndConcatenation:
|
129
132
|
Enabled: false
|
130
133
|
|
@@ -235,6 +238,9 @@ StringLiterals:
|
|
235
238
|
Style/MultilineBlockChain:
|
236
239
|
Enabled: false
|
237
240
|
|
241
|
+
Style/SymbolArray:
|
242
|
+
EnforcedStyle: brackets
|
243
|
+
|
238
244
|
VariableInterpolation:
|
239
245
|
Enabled: false
|
240
246
|
|
data/.travis.yml
CHANGED
@@ -5,10 +5,7 @@ rvm:
|
|
5
5
|
- 2.3.0
|
6
6
|
- 2.4.0
|
7
7
|
script:
|
8
|
-
|
9
|
-
|
10
|
-
addons:
|
11
|
-
code_climate:
|
12
|
-
repo_token: d744a74c96e3e5c763ed776709aff0662ac2f3e8274c01e439e09b38c8be4225
|
8
|
+
- bundle exec rake test
|
9
|
+
- bundle exec rubocop
|
13
10
|
notifications:
|
14
11
|
email: false
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v0.30](https://github.com/JacobEvelyn/friends/tree/v0.30) (2017-05-30)
|
4
|
+
[Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.29...v0.30)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- Code coverage in README is too low [\#163](https://github.com/JacobEvelyn/friends/issues/163)
|
9
|
+
- Improve display of favorites for ties [\#158](https://github.com/JacobEvelyn/friends/issues/158)
|
10
|
+
- Filter activities based on more than one friend/tag/etc. [\#88](https://github.com/JacobEvelyn/friends/issues/88)
|
11
|
+
|
12
|
+
**Merged pull requests:**
|
13
|
+
|
14
|
+
- Be able to filter output by more than one friend or tag [\#168](https://github.com/JacobEvelyn/friends/pull/168) ([JacobEvelyn](https://github.com/JacobEvelyn))
|
15
|
+
- Improve display of favorites for ties [\#165](https://github.com/JacobEvelyn/friends/pull/165) ([JacobEvelyn](https://github.com/JacobEvelyn))
|
16
|
+
- Correct code coverage calculations [\#164](https://github.com/JacobEvelyn/friends/pull/164) ([JacobEvelyn](https://github.com/JacobEvelyn))
|
17
|
+
|
3
18
|
## [v0.29](https://github.com/JacobEvelyn/friends/tree/v0.29) (2017-03-18)
|
4
19
|
[Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.28...v0.29)
|
5
20
|
|
data/PULL_REQUEST_TEMPLATE.md
CHANGED
@@ -6,8 +6,8 @@ merge this change:
|
|
6
6
|
- [ ] The code in these changes works correctly.
|
7
7
|
- [ ] Code has tests as appropriate.
|
8
8
|
- [ ] Code has been reviewed by @JacobEvelyn.
|
9
|
-
- [ ] All tests pass on
|
10
|
-
- [ ] Rubocop reports no issues on
|
9
|
+
- [ ] All tests pass on Travis CI.
|
10
|
+
- [ ] Rubocop reports no issues on Travis CI.
|
11
11
|
- [ ] The `README.md` file is updated as appropriate.
|
12
12
|
|
13
13
|
Don't worry—this list will get checked off in no time!
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
[![Gem Version](https://badge.fury.io/rb/friends.svg)](https://badge.fury.io/rb/friends) [![Dependency Status](https://gemnasium.com/badges/github.com/JacobEvelyn/friends.svg)](https://gemnasium.com/github.com/JacobEvelyn/friends)
|
2
|
-
[![
|
2
|
+
[![Coverage Status](https://coveralls.io/repos/github/JacobEvelyn/friends/badge.svg)](https://coveralls.io/github/JacobEvelyn/friends) [![Build Status](https://travis-ci.org/JacobEvelyn/friends.svg?branch=master)](https://travis-ci.org/JacobEvelyn/friends) [![Inline docs](http://inch-ci.org/github/JacobEvelyn/friends.png)](http://inch-ci.org/github/JacobEvelyn/friends) [![ghit.me](https://ghit.me/badge.svg?repo=JacobEvelyn/friends)](https://ghit.me/repo/JacobEvelyn/friends)
|
3
3
|
|
4
4
|
# `friends`
|
5
5
|
|
@@ -343,6 +343,13 @@ Jan 2015 |█████
|
|
343
343
|
Feb 2015 |███
|
344
344
|
```
|
345
345
|
|
346
|
+
Or a certain group of friends:
|
347
|
+
|
348
|
+
```bash
|
349
|
+
$ friends graph --with George --with Grace
|
350
|
+
Jan 2015 |█
|
351
|
+
```
|
352
|
+
|
346
353
|
Or graph only activities with a certain tag:
|
347
354
|
|
348
355
|
```bash
|
@@ -353,6 +360,13 @@ Jan 2015 |
|
|
353
360
|
Feb 2015 |███
|
354
361
|
```
|
355
362
|
|
363
|
+
Or with multiple tags:
|
364
|
+
|
365
|
+
```bash
|
366
|
+
$ friends graph --tagged @fun --tagged @work
|
367
|
+
Jul 2017 |█
|
368
|
+
```
|
369
|
+
|
356
370
|
Or graph only activities in a certain location:
|
357
371
|
|
358
372
|
```bash
|
@@ -443,6 +457,13 @@ $ friends list activities --with George
|
|
443
457
|
2014-11-15: Talked to George Washington Carver on the phone for an hour.
|
444
458
|
```
|
445
459
|
|
460
|
+
Or only filter activities done with a group of friends:
|
461
|
+
|
462
|
+
```bash
|
463
|
+
$ friends list activities --with George --with Grace
|
464
|
+
2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
|
465
|
+
```
|
466
|
+
|
446
467
|
Or filter your activities by location:
|
447
468
|
|
448
469
|
```bash
|
@@ -457,16 +478,23 @@ $ friends list activities --tagged food
|
|
457
478
|
2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
|
458
479
|
```
|
459
480
|
|
481
|
+
Or use more than one tag:
|
482
|
+
|
483
|
+
```bash
|
484
|
+
$ friends list activities --tagged @fun --tagged @work
|
485
|
+
2017-07-04: Summer picnic with @work colleagues. @fun
|
486
|
+
```
|
487
|
+
|
460
488
|
Or by date:
|
461
489
|
|
462
490
|
```bash
|
463
|
-
$ friends
|
491
|
+
$ friends list activities --since 'December 31st 2014'
|
464
492
|
2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
|
465
493
|
2014-12-31: Celebrated the new year with Marie Curie in New York City. @partying
|
466
494
|
```
|
467
495
|
|
468
496
|
```bash
|
469
|
-
$ friends
|
497
|
+
$ friends list activities --until 'December 31st 2014'
|
470
498
|
2014-12-31: Celebrated the new year with Marie Curie in New York City. @partying
|
471
499
|
2014-11-15: Talked to George Washington Carver on the phone for an hour.
|
472
500
|
```
|
@@ -474,7 +502,7 @@ $ friends graph --until 'December 31st 2014'
|
|
474
502
|
And you can mix and match these options to your heart's content:
|
475
503
|
|
476
504
|
```bash
|
477
|
-
$ friends list activities --tagged food --with Grace
|
505
|
+
$ friends list activities --tagged food --with Grace --with George
|
478
506
|
2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
|
479
507
|
```
|
480
508
|
|
@@ -487,7 +515,7 @@ $ friends list favorite friends
|
|
487
515
|
Your favorite friends:
|
488
516
|
1. George Washington Carver (2 activities)
|
489
517
|
2. Grace Hopper (1)
|
490
|
-
3. Marie Curie (
|
518
|
+
3. Marie Curie (0)
|
491
519
|
```
|
492
520
|
|
493
521
|
You can specify a number of favorites to show:
|
@@ -508,7 +536,7 @@ $ friends list favorite locations
|
|
508
536
|
Your favorite locations:
|
509
537
|
1. Atlantis (2 activities)
|
510
538
|
2. Paris (1)
|
511
|
-
3. London (
|
539
|
+
3. London (0)
|
512
540
|
```
|
513
541
|
|
514
542
|
You can specify a number of favorites to show:
|
@@ -555,6 +583,13 @@ Grace Hopper
|
|
555
583
|
Marie Curie
|
556
584
|
```
|
557
585
|
|
586
|
+
You can even use more than one tag to further narrow down the list:
|
587
|
+
|
588
|
+
```bash
|
589
|
+
$ friends list friends --tagged science --tagged navy
|
590
|
+
Grace Hopper
|
591
|
+
```
|
592
|
+
|
558
593
|
#### `list tags`
|
559
594
|
|
560
595
|
Lists all tags you've used, in alphabetical order:
|
data/bin/friends
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
if ENV["TRAVIS"] == "true"
|
5
|
+
require "simplecov"
|
6
|
+
SimpleCov.formatter = SimpleCov::Formatter::SimpleFormatter
|
7
|
+
SimpleCov.command_name Process.pid
|
8
|
+
SimpleCov.start
|
9
|
+
end
|
10
|
+
|
4
11
|
require "gli"
|
5
12
|
require "paint"
|
6
13
|
require "readline"
|
data/friends.gemspec
CHANGED
@@ -30,11 +30,10 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_dependency "semverse", "~> 1.2"
|
31
31
|
|
32
32
|
spec.add_development_dependency "bundler", "~> 1.6"
|
33
|
-
spec.add_development_dependency "
|
33
|
+
spec.add_development_dependency "coveralls", "~> 0.8"
|
34
34
|
spec.add_development_dependency "minitest", "~> 5.5"
|
35
|
-
spec.add_development_dependency "minitest-parallel_fork", "~> 1.0"
|
36
35
|
spec.add_development_dependency "minitest-proveit", "~> 1.0"
|
37
|
-
spec.add_development_dependency "overcommit", "~> 0.34"
|
38
36
|
spec.add_development_dependency "rake", "~> 11.2"
|
39
|
-
spec.add_development_dependency "rubocop", "~> 0.
|
37
|
+
spec.add_development_dependency "rubocop", "~> 0.49"
|
38
|
+
spec.add_development_dependency "simplecov", "~> 0.14"
|
40
39
|
end
|
@@ -5,7 +5,8 @@ command :graph do |graph|
|
|
5
5
|
graph.flag [:with],
|
6
6
|
arg_name: "NAME",
|
7
7
|
desc: "Graph activities with the given friend",
|
8
|
-
type: Stripped
|
8
|
+
type: Stripped,
|
9
|
+
multiple: true
|
9
10
|
|
10
11
|
graph.flag [:in],
|
11
12
|
arg_name: "LOCATION",
|
@@ -15,7 +16,8 @@ command :graph do |graph|
|
|
15
16
|
graph.flag [:tagged],
|
16
17
|
arg_name: "@TAG",
|
17
18
|
desc: "Graph activities with the given tag",
|
18
|
-
type: Tag
|
19
|
+
type: Tag,
|
20
|
+
multiple: true
|
19
21
|
|
20
22
|
graph.flag [:since],
|
21
23
|
arg_name: "DATE",
|
@@ -12,7 +12,8 @@ command :list do |list|
|
|
12
12
|
list_friends.flag [:tagged],
|
13
13
|
arg_name: "@TAG",
|
14
14
|
desc: "List only friends with the given tag",
|
15
|
-
type: Tag
|
15
|
+
type: Tag,
|
16
|
+
multiple: true
|
16
17
|
|
17
18
|
list_friends.switch [:verbose],
|
18
19
|
negatable: false,
|
@@ -38,7 +39,8 @@ command :list do |list|
|
|
38
39
|
list_activities.flag [:with],
|
39
40
|
arg_name: "NAME",
|
40
41
|
desc: "List only activities with the given friend",
|
41
|
-
type: Stripped
|
42
|
+
type: Stripped,
|
43
|
+
multiple: true
|
42
44
|
|
43
45
|
list_activities.flag [:in],
|
44
46
|
arg_name: "LOCATION",
|
@@ -48,7 +50,8 @@ command :list do |list|
|
|
48
50
|
list_activities.flag [:tagged],
|
49
51
|
arg_name: "@TAG",
|
50
52
|
desc: "List only activities with the given tag",
|
51
|
-
type: Tag
|
53
|
+
type: Tag,
|
54
|
+
multiple: true
|
52
55
|
|
53
56
|
list_activities.flag [:since],
|
54
57
|
arg_name: "DATE",
|
@@ -101,18 +104,7 @@ command :list do |list|
|
|
101
104
|
type: Integer
|
102
105
|
|
103
106
|
list_favorite_friends.action do |_, options|
|
104
|
-
|
105
|
-
|
106
|
-
if options[:limit] == 1
|
107
|
-
puts "Your best friend is #{favorites.first}"
|
108
|
-
else
|
109
|
-
puts "Your favorite friends:"
|
110
|
-
|
111
|
-
num_str_size = favorites.size.to_s.size + 1
|
112
|
-
favorites.each.with_index(1) do |name, rank|
|
113
|
-
puts "#{"#{rank}.".ljust(num_str_size)} #{name}"
|
114
|
-
end
|
115
|
-
end
|
107
|
+
@introvert.list_favorite_friends(limit: options[:limit])
|
116
108
|
end
|
117
109
|
end
|
118
110
|
|
@@ -125,18 +117,7 @@ command :list do |list|
|
|
125
117
|
type: Integer
|
126
118
|
|
127
119
|
list_favorite_locations.action do |_, options|
|
128
|
-
|
129
|
-
|
130
|
-
if options[:limit] == 1
|
131
|
-
puts "Your favorite location is #{favorites.first}"
|
132
|
-
else
|
133
|
-
puts "Your favorite locations:"
|
134
|
-
|
135
|
-
num_str_size = favorites.size.to_s.size + 1
|
136
|
-
favorites.each.with_index(1) do |name, rank|
|
137
|
-
puts "#{"#{rank}.".ljust(num_str_size)} #{name}"
|
138
|
-
end
|
139
|
-
end
|
120
|
+
@introvert.list_favorite_locations(limit: options[:limit])
|
140
121
|
end
|
141
122
|
end
|
142
123
|
end
|
data/lib/friends/graph.rb
CHANGED
data/lib/friends/introvert.rb
CHANGED
@@ -186,8 +186,8 @@ module Friends
|
|
186
186
|
# List all friend names in the friends file.
|
187
187
|
# @param location_name [String] the name of a location to filter by, or nil
|
188
188
|
# for unfiltered
|
189
|
-
# @param tagged [String] the
|
190
|
-
#
|
189
|
+
# @param tagged [Array<String>] the names of tags to filter by, or empty for
|
190
|
+
# unfiltered
|
191
191
|
# @param verbose [Boolean] true iff we should output friend names with
|
192
192
|
# nicknames, locations, and tags; false for names only
|
193
193
|
# @return [Array] a list of all friend names
|
@@ -200,8 +200,12 @@ module Friends
|
|
200
200
|
fs = fs.select { |friend| friend.location_name == location.name }
|
201
201
|
end
|
202
202
|
|
203
|
-
# Filter by tag if
|
204
|
-
|
203
|
+
# Filter by tag if param is passed.
|
204
|
+
unless tagged.empty?
|
205
|
+
fs = fs.select do |friend|
|
206
|
+
tagged.all? { |tag| friend.tags.include? tag }
|
207
|
+
end
|
208
|
+
end
|
205
209
|
|
206
210
|
verbose ? fs.map(&:to_s) : fs.map(&:name)
|
207
211
|
end
|
@@ -225,12 +229,12 @@ module Friends
|
|
225
229
|
# List all activity details.
|
226
230
|
# @param limit [Integer] the number of activities to return, or nil for no
|
227
231
|
# limit
|
228
|
-
# @param with [String] the
|
232
|
+
# @param with [Array<String>] the names of friends to filter by, or empty for
|
233
|
+
# unfiltered
|
234
|
+
# @param location_name [String] the name of a location to filter by, or
|
235
|
+
# nil for unfiltered
|
236
|
+
# @param tagged [Array<String>] the names of tags to filter by, or empty for
|
229
237
|
# unfiltered
|
230
|
-
# @param location_name [String] the name of a location to filter by, or nil
|
231
|
-
# for unfiltered
|
232
|
-
# @param tagged [String] the name of a tag to filter by (of the form:
|
233
|
-
# "@tag"), or nil for unfiltered
|
234
238
|
# @param since_date [Date] a date on or after which to find activities, or nil for unfiltered
|
235
239
|
# @param until_date [Date] a date before or on which to find activities, or nil for unfiltered
|
236
240
|
# @return [Array] a list of all activity text values
|
@@ -294,12 +298,12 @@ module Friends
|
|
294
298
|
# The keys of the hash are all of the months (inclusive) between the first
|
295
299
|
# and last month in which activities have been recorded.
|
296
300
|
#
|
297
|
-
# @param with [String] the
|
301
|
+
# @param with [Array<String>] the names of friends to filter by, or empty for
|
302
|
+
# unfiltered
|
303
|
+
# @param location_name [String] the name of a location to filter by, or
|
304
|
+
# nil for unfiltered
|
305
|
+
# @param tagged [Array<String>] the names of tags to filter by, or empty for
|
298
306
|
# unfiltered
|
299
|
-
# @param location_name [String] the name of a location to filter by, or nil
|
300
|
-
# for unfiltered
|
301
|
-
# @param tagged [String] the name of a tag to filter by (of the form:
|
302
|
-
# "@tag"), or nil for unfiltered
|
303
307
|
# @param since_date [Date] a date on or after which to find activities, or nil for unfiltered
|
304
308
|
# @param until_date [Date] a date before or on which to find activities, or nil for unfiltered
|
305
309
|
# @return [Hash{String => Integer}]
|
@@ -451,11 +455,11 @@ module Friends
|
|
451
455
|
private
|
452
456
|
|
453
457
|
# Filter activities by friend, location and tag
|
454
|
-
# @param with [String] the
|
458
|
+
# @param with [Array<String>] the names of friends to filter by, or empty for
|
455
459
|
# unfiltered
|
456
|
-
# @param location_name [String] the name of a location to filter by, or
|
457
|
-
# for unfiltered
|
458
|
-
# @param tagged [String] the
|
460
|
+
# @param location_name [String] the name of a location to filter by, or
|
461
|
+
# nil for unfiltered
|
462
|
+
# @param tagged [Array<String>] the names of tags to filter by, or empty for
|
459
463
|
# unfiltered
|
460
464
|
# @param since_date [Date] a date on or after which to find activities, or nil for unfiltered
|
461
465
|
# @param until_date [Date] a date before or on which to find activities, or nil for unfiltered
|
@@ -466,9 +470,11 @@ module Friends
|
|
466
470
|
acts = @activities
|
467
471
|
|
468
472
|
# Filter by friend name if argument is passed.
|
469
|
-
unless with.
|
470
|
-
|
471
|
-
acts = acts.select
|
473
|
+
unless with.empty?
|
474
|
+
friends = with.map { |name| thing_with_name_in(:friend, name) }
|
475
|
+
acts = acts.select do |act|
|
476
|
+
friends.all? { |friend| act.includes_friend?(friend) }
|
477
|
+
end
|
472
478
|
end
|
473
479
|
|
474
480
|
# Filter by location name if argument is passed.
|
@@ -478,7 +484,11 @@ module Friends
|
|
478
484
|
end
|
479
485
|
|
480
486
|
# Filter by tag if argument is passed.
|
481
|
-
|
487
|
+
unless tagged.empty?
|
488
|
+
acts = acts.select do |act|
|
489
|
+
tagged.all? { |tag| act.includes_tag?(tag) }
|
490
|
+
end
|
491
|
+
end
|
482
492
|
|
483
493
|
# Filter by date if arguments are passed.
|
484
494
|
acts = acts.select { |act| act.date >= since_date } unless since_date.nil?
|
@@ -504,15 +514,42 @@ module Friends
|
|
504
514
|
-thing.n_activities
|
505
515
|
end.take(limit) # Trim the list.
|
506
516
|
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
517
|
+
if results.size == 1
|
518
|
+
favorite = results.first
|
519
|
+
puts "Your favorite #{type} is "\
|
520
|
+
"#{favorite.name} "\
|
521
|
+
"(#{favorite.n_activities} "\
|
522
|
+
"#{favorite.n_activities == 1 ? 'activity' : 'activities'})"
|
523
|
+
else
|
524
|
+
puts "Your favorite #{type}s:"
|
525
|
+
|
526
|
+
max_str_size = results.map(&:name).map(&:size).max
|
527
|
+
|
528
|
+
grouped_results = results.group_by(&:n_activities)
|
529
|
+
|
530
|
+
rank = 1
|
531
|
+
first = true
|
532
|
+
data = grouped_results.each.with_object([]) do |(n_activities, things), arr|
|
533
|
+
things.each do |thing|
|
534
|
+
name = thing.name.ljust(max_str_size)
|
535
|
+
if first
|
536
|
+
label = n_activities == 1 ? " activity" : " activities"
|
537
|
+
first = false
|
538
|
+
end
|
539
|
+
str = "#{name} (#{n_activities}#{label})"
|
540
|
+
|
541
|
+
arr << [rank, str]
|
542
|
+
end
|
543
|
+
rank += things.size
|
544
|
+
end
|
545
|
+
|
546
|
+
# We need to use `data.last.first` instead of `rank` to determine the size
|
547
|
+
# of the numbering prefix because `rank` will simply be the size of all
|
548
|
+
# elements, which may be too large if the last element in the list is a tie.
|
549
|
+
num_str_size = data.last.first.to_s.size + 1 unless data.empty?
|
550
|
+
data.each do |ranking, str|
|
551
|
+
puts "#{"#{ranking}.".ljust(num_str_size)} #{str}"
|
513
552
|
end
|
514
|
-
parenthetical = "(#{n}#{label})"
|
515
|
-
"#{name} #{parenthetical}"
|
516
553
|
end
|
517
554
|
end
|
518
555
|
|
data/lib/friends/serializable.rb
CHANGED
data/lib/friends/version.rb
CHANGED
data/test/commands/graph_spec.rb
CHANGED
@@ -90,6 +90,16 @@ Jan 2015 |█
|
|
90
90
|
OUTPUT
|
91
91
|
end
|
92
92
|
end
|
93
|
+
|
94
|
+
describe "when more than one friend name is passed" do
|
95
|
+
subject { run_cmd("graph --with #{friend_name1} --with #{friend_name2}") }
|
96
|
+
let(:friend_name1) { "george" }
|
97
|
+
let(:friend_name2) { "grace" }
|
98
|
+
|
99
|
+
it "matches all friends case-insensitively" do
|
100
|
+
stdout_only "Jan 2015 |█"
|
101
|
+
end
|
102
|
+
end
|
93
103
|
end
|
94
104
|
|
95
105
|
describe "--tagged" do
|
@@ -110,6 +120,30 @@ Oct 2015 |
|
|
110
120
|
Nov 2015 |█
|
111
121
|
OUTPUT
|
112
122
|
end
|
123
|
+
|
124
|
+
describe "when more than one tag is passed" do
|
125
|
+
subject { run_cmd("graph --tagged #{tag1} --tagged #{tag2}") }
|
126
|
+
let(:tag1) { "food" }
|
127
|
+
let(:tag2) { "partying" }
|
128
|
+
let(:content) do
|
129
|
+
<<-FILE
|
130
|
+
### Activities:
|
131
|
+
- 2015-01-04: Got lunch with **Grace Hopper** and **George Washington Carver**. @food
|
132
|
+
- 2015-11-01: **Grace Hopper** and I went to _Marie's Diner_. George had to cancel at the last minute. @food
|
133
|
+
- 2014-11-15: Talked to **George Washington Carver** on the phone for an hour.
|
134
|
+
- 2014-12-31: Celebrated the new year in _Paris_ with **Marie Curie**. @partying @food
|
135
|
+
|
136
|
+
### Friends:
|
137
|
+
- George Washington Carver
|
138
|
+
- Marie Curie [Atlantis] @science
|
139
|
+
- Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
|
140
|
+
FILE
|
141
|
+
end
|
142
|
+
|
143
|
+
it "matches all tags case-sensitively" do
|
144
|
+
stdout_only "Dec 2014 |█"
|
145
|
+
end
|
146
|
+
end
|
113
147
|
end
|
114
148
|
|
115
149
|
describe "--since" do
|
@@ -97,6 +97,16 @@ clean_describe "list activities" do
|
|
97
97
|
stdout_only "2014-12-31: Celebrated the new year in Paris with Marie Curie. @partying"
|
98
98
|
end
|
99
99
|
end
|
100
|
+
|
101
|
+
describe "when more than one friend name is passed" do
|
102
|
+
subject { run_cmd("list activities --with #{friend_name1} --with #{friend_name2}") }
|
103
|
+
let(:friend_name1) { "george" }
|
104
|
+
let(:friend_name2) { "grace" }
|
105
|
+
|
106
|
+
it "matches all friends case-insensitively" do
|
107
|
+
stdout_only "2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food"
|
108
|
+
end
|
109
|
+
end
|
100
110
|
end
|
101
111
|
|
102
112
|
describe "--tagged" do
|
@@ -108,6 +118,32 @@ clean_describe "list activities" do
|
|
108
118
|
2015-11-01: Grace Hopper and I went to Marie's Diner. George had to cancel at the last minute. @food
|
109
119
|
OUTPUT
|
110
120
|
end
|
121
|
+
|
122
|
+
describe "when more than one tag is passed" do
|
123
|
+
subject { run_cmd("list activities --tagged #{tag1} --tagged #{tag2}") }
|
124
|
+
let(:tag1) { "food" }
|
125
|
+
let(:tag2) { "partying" }
|
126
|
+
let(:content) do
|
127
|
+
<<-FILE
|
128
|
+
### Activities:
|
129
|
+
- 2015-01-04: Got lunch with **Grace Hopper** and **George Washington Carver**. @food
|
130
|
+
- 2015-11-01: **Grace Hopper** and I went to _Marie's Diner_. George had to cancel at the last minute. @food
|
131
|
+
- 2014-11-15: Talked to **George Washington Carver** on the phone for an hour.
|
132
|
+
- 2014-12-31: Celebrated the new year in _Paris_ with **Marie Curie**. @partying @food
|
133
|
+
|
134
|
+
### Friends:
|
135
|
+
- George Washington Carver
|
136
|
+
- Marie Curie [Atlantis] @science
|
137
|
+
- Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
|
138
|
+
FILE
|
139
|
+
end
|
140
|
+
|
141
|
+
it "matches all tags case-sensitively" do
|
142
|
+
stdout_only(
|
143
|
+
"2014-12-31: Celebrated the new year in Paris with Marie Curie. @partying @food"
|
144
|
+
)
|
145
|
+
end
|
146
|
+
end
|
111
147
|
end
|
112
148
|
|
113
149
|
describe "--since" do
|
@@ -45,6 +45,69 @@ Your favorite friends:
|
|
45
45
|
OUTPUT
|
46
46
|
end
|
47
47
|
|
48
|
+
describe "when friends are tied for the same number of activities" do
|
49
|
+
let(:content) do
|
50
|
+
<<-FILE
|
51
|
+
### Activities:
|
52
|
+
- 2017-01-01: Did something with **Friend A**.
|
53
|
+
- 2017-01-01: Did something with **Friend A**.
|
54
|
+
- 2017-01-01: Did something with **Friend B**.
|
55
|
+
- 2017-01-01: Did something with **Friend B**.
|
56
|
+
- 2017-01-01: Did something with **Friend C**.
|
57
|
+
- 2017-01-01: Did something with **Friend D**.
|
58
|
+
- 2017-01-01: Did something with **Friend E**.
|
59
|
+
- 2017-01-01: Did something with **Friend F**.
|
60
|
+
- 2017-01-01: Did something with **Friend G**.
|
61
|
+
- 2017-01-01: Did something with **Friend H**.
|
62
|
+
- 2017-01-01: Did something with **Friend I**.
|
63
|
+
- 2017-01-01: Did something with **Friend J**.
|
64
|
+
|
65
|
+
### Friends:
|
66
|
+
- Friend A
|
67
|
+
- Friend B
|
68
|
+
- Friend C
|
69
|
+
- Friend D
|
70
|
+
- Friend E
|
71
|
+
- Friend F
|
72
|
+
- Friend G
|
73
|
+
- Friend H
|
74
|
+
- Friend I
|
75
|
+
- Friend J
|
76
|
+
FILE
|
77
|
+
end
|
78
|
+
|
79
|
+
it "uses tied ranks" do
|
80
|
+
subject[:stderr].must_equal ""
|
81
|
+
subject[:status].must_equal 0
|
82
|
+
|
83
|
+
lines = subject[:stdout].split("\n")
|
84
|
+
lines[1].must_match(/1\. Friend (A|B)/)
|
85
|
+
lines[2].must_match(/1\. Friend (A|B)/)
|
86
|
+
lines[3].must_include "3. Friend"
|
87
|
+
end
|
88
|
+
|
89
|
+
it "only uses the word 'activities' for the first item, even when a tie" do
|
90
|
+
subject[:stderr].must_equal ""
|
91
|
+
subject[:status].must_equal 0
|
92
|
+
|
93
|
+
lines = subject[:stdout].split("\n")
|
94
|
+
lines[1].must_include "activities"
|
95
|
+
lines[2].wont_include "activities"
|
96
|
+
end
|
97
|
+
|
98
|
+
it "indents based on the highest rank number, not the number of friends" do
|
99
|
+
subject[:stderr].must_equal ""
|
100
|
+
subject[:status].must_equal 0
|
101
|
+
|
102
|
+
# Since there are 10 friends, a naive implementation would pad our output
|
103
|
+
# assuming the (numerically) highest rank is "10." but since the highest
|
104
|
+
# rank is a tie, we never display a double-digit rank, so we don't need to
|
105
|
+
# pad our output for double digits.
|
106
|
+
lines = subject[:stdout].split("\n")
|
107
|
+
lines.last.must_include "3. Friend"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
48
111
|
describe "--limit" do
|
49
112
|
subject { run_cmd("list favorite friends --limit #{limit}") }
|
50
113
|
|
@@ -57,8 +120,27 @@ Your favorite friends:
|
|
57
120
|
|
58
121
|
describe "when limit is 1" do
|
59
122
|
let(:limit) { 1 }
|
60
|
-
|
61
|
-
|
123
|
+
|
124
|
+
it "uses correct friend pluralization" do
|
125
|
+
stdout_only "Your favorite friend is Grace Hopper (3 activities)"
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "when favorite friend only has one activity" do
|
129
|
+
let(:content) do
|
130
|
+
<<-FILE
|
131
|
+
### Activities:
|
132
|
+
- 2017-01-01: Did some math with **Grace Hopper**.
|
133
|
+
|
134
|
+
### Friends:
|
135
|
+
- George Washington Carver
|
136
|
+
- Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
|
137
|
+
- Marie Curie [Atlantis] @science
|
138
|
+
FILE
|
139
|
+
end
|
140
|
+
|
141
|
+
it "uses correct activity pluralization" do
|
142
|
+
stdout_only "Your favorite friend is Grace Hopper (1 activity)"
|
143
|
+
end
|
62
144
|
end
|
63
145
|
end
|
64
146
|
|
@@ -50,6 +50,69 @@ Your favorite locations:
|
|
50
50
|
OUTPUT
|
51
51
|
end
|
52
52
|
|
53
|
+
describe "when locations are tied for the same number of activities" do
|
54
|
+
let(:content) do
|
55
|
+
<<-FILE
|
56
|
+
### Activities:
|
57
|
+
- 2017-01-01: Did something in _Location A_.
|
58
|
+
- 2017-01-01: Did something in _Location A_.
|
59
|
+
- 2017-01-01: Did something in _Location B_.
|
60
|
+
- 2017-01-01: Did something in _Location B_.
|
61
|
+
- 2017-01-01: Did something in _Location C_.
|
62
|
+
- 2017-01-01: Did something in _Location D_.
|
63
|
+
- 2017-01-01: Did something in _Location E_.
|
64
|
+
- 2017-01-01: Did something in _Location F_.
|
65
|
+
- 2017-01-01: Did something in _Location G_.
|
66
|
+
- 2017-01-01: Did something in _Location H_.
|
67
|
+
- 2017-01-01: Did something in _Location I_.
|
68
|
+
- 2017-01-01: Did something in _Location J_.
|
69
|
+
|
70
|
+
### Locations:
|
71
|
+
- Location A
|
72
|
+
- Location B
|
73
|
+
- Location C
|
74
|
+
- Location D
|
75
|
+
- Location E
|
76
|
+
- Location F
|
77
|
+
- Location G
|
78
|
+
- Location H
|
79
|
+
- Location I
|
80
|
+
- Location J
|
81
|
+
FILE
|
82
|
+
end
|
83
|
+
|
84
|
+
it "uses tied ranks" do
|
85
|
+
subject[:stderr].must_equal ""
|
86
|
+
subject[:status].must_equal 0
|
87
|
+
|
88
|
+
lines = subject[:stdout].split("\n")
|
89
|
+
lines[1].must_match(/1\. Location (A|B)/)
|
90
|
+
lines[2].must_match(/1\. Location (A|B)/)
|
91
|
+
lines[3].must_include "3. Location"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "only uses the word 'activities' for the first item, even when a tie" do
|
95
|
+
subject[:stderr].must_equal ""
|
96
|
+
subject[:status].must_equal 0
|
97
|
+
|
98
|
+
lines = subject[:stdout].split("\n")
|
99
|
+
lines[1].must_include "activities"
|
100
|
+
lines[2].wont_include "activities"
|
101
|
+
end
|
102
|
+
|
103
|
+
it "indents based on the highest rank number, not the number of locations" do
|
104
|
+
subject[:stderr].must_equal ""
|
105
|
+
subject[:status].must_equal 0
|
106
|
+
|
107
|
+
# Since there are 10 friends, a naive implementation would pad our output
|
108
|
+
# assuming the (numerically) highest rank is "10." but since the highest
|
109
|
+
# rank is a tie, we never display a double-digit rank, so we don't need to
|
110
|
+
# pad our output for double digits.
|
111
|
+
lines = subject[:stdout].split("\n")
|
112
|
+
lines.last.must_include "3. Location"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
53
116
|
describe "--limit" do
|
54
117
|
subject { run_cmd("list favorite locations --limit #{limit}") }
|
55
118
|
|
@@ -62,9 +125,33 @@ Your favorite locations:
|
|
62
125
|
|
63
126
|
describe "when limit is 1" do
|
64
127
|
let(:limit) { 1 }
|
65
|
-
|
128
|
+
|
129
|
+
it "uses correct location pluralization" do
|
66
130
|
stdout_only "Your favorite location is Marie's Diner (2 activities)"
|
67
131
|
end
|
132
|
+
|
133
|
+
describe "when favorite location only has one activity" do
|
134
|
+
let(:content) do
|
135
|
+
<<-FILE
|
136
|
+
### Activities:
|
137
|
+
- 2017-01-01: Did some math with **Grace Hopper** at _Marie's Diner_.
|
138
|
+
|
139
|
+
### Friends:
|
140
|
+
- George Washington Carver
|
141
|
+
- Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
|
142
|
+
- Marie Curie [Atlantis] @science
|
143
|
+
|
144
|
+
### Locations:
|
145
|
+
- Atlantis
|
146
|
+
- Marie's Diner
|
147
|
+
- Paris
|
148
|
+
FILE
|
149
|
+
end
|
150
|
+
|
151
|
+
it "uses correct activity pluralization" do
|
152
|
+
stdout_only "Your favorite location is Marie's Diner (1 activity)"
|
153
|
+
end
|
154
|
+
end
|
68
155
|
end
|
69
156
|
|
70
157
|
describe "when limit is greater than 1" do
|
@@ -71,6 +71,31 @@ Marie Curie
|
|
71
71
|
Grace Hopper
|
72
72
|
OUTPUT
|
73
73
|
end
|
74
|
+
|
75
|
+
describe "when more than one tag is passed" do
|
76
|
+
subject { run_cmd("list friends --tagged #{tag1} --tagged #{tag2}") }
|
77
|
+
let(:tag1) { "science" }
|
78
|
+
let(:tag2) { "navy" }
|
79
|
+
let(:content) do
|
80
|
+
<<-FILE
|
81
|
+
### Activities:
|
82
|
+
|
83
|
+
### Friends:
|
84
|
+
- George Washington Carver
|
85
|
+
- Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
|
86
|
+
- Marie Curie [Atlantis] @science
|
87
|
+
- Neil Armstrong @navy @science
|
88
|
+
- John F. Kennedy @navy
|
89
|
+
FILE
|
90
|
+
end
|
91
|
+
|
92
|
+
it "matches all tags case-sensitively" do
|
93
|
+
stdout_only <<-OUTPUT
|
94
|
+
Grace Hopper
|
95
|
+
Neil Armstrong
|
96
|
+
OUTPUT
|
97
|
+
end
|
98
|
+
end
|
74
99
|
end
|
75
100
|
end
|
76
101
|
end
|
data/test/helper.rb
CHANGED
@@ -1,14 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
if ENV["TRAVIS"] == "true"
|
4
|
+
require "simplecov"
|
5
|
+
require "coveralls"
|
6
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
7
|
+
SimpleCov.start do
|
8
|
+
add_filter "/test/"
|
9
|
+
end
|
10
|
+
end
|
5
11
|
|
6
12
|
ENV["MT_HELL"] = "1" # Forces tests to have at least one assertion to pass.
|
7
13
|
|
8
14
|
require "minitest/autorun"
|
9
|
-
|
10
|
-
|
15
|
+
|
16
|
+
# Runs tests in parallel. Also, in combination with the MT_HELL environment var
|
17
|
+
# set above and the loading of the `minitest-proveit` gem, requires that tests
|
18
|
+
# have at least one assertion to pass.
|
11
19
|
require "minitest/hell"
|
20
|
+
|
21
|
+
require "minitest/pride"
|
12
22
|
require "open3"
|
13
23
|
require "securerandom"
|
14
24
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: friends
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.30'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Evelyn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chronic
|
@@ -95,19 +95,19 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '1.6'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: coveralls
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.8'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.8'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: minitest
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,20 +122,6 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '5.5'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: minitest-parallel_fork
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - "~>"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '1.0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '1.0'
|
139
125
|
- !ruby/object:Gem::Dependency
|
140
126
|
name: minitest-proveit
|
141
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,47 +137,47 @@ dependencies:
|
|
151
137
|
- !ruby/object:Gem::Version
|
152
138
|
version: '1.0'
|
153
139
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
140
|
+
name: rake
|
155
141
|
requirement: !ruby/object:Gem::Requirement
|
156
142
|
requirements:
|
157
143
|
- - "~>"
|
158
144
|
- !ruby/object:Gem::Version
|
159
|
-
version: '
|
145
|
+
version: '11.2'
|
160
146
|
type: :development
|
161
147
|
prerelease: false
|
162
148
|
version_requirements: !ruby/object:Gem::Requirement
|
163
149
|
requirements:
|
164
150
|
- - "~>"
|
165
151
|
- !ruby/object:Gem::Version
|
166
|
-
version: '
|
152
|
+
version: '11.2'
|
167
153
|
- !ruby/object:Gem::Dependency
|
168
|
-
name:
|
154
|
+
name: rubocop
|
169
155
|
requirement: !ruby/object:Gem::Requirement
|
170
156
|
requirements:
|
171
157
|
- - "~>"
|
172
158
|
- !ruby/object:Gem::Version
|
173
|
-
version: '
|
159
|
+
version: '0.49'
|
174
160
|
type: :development
|
175
161
|
prerelease: false
|
176
162
|
version_requirements: !ruby/object:Gem::Requirement
|
177
163
|
requirements:
|
178
164
|
- - "~>"
|
179
165
|
- !ruby/object:Gem::Version
|
180
|
-
version: '
|
166
|
+
version: '0.49'
|
181
167
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
168
|
+
name: simplecov
|
183
169
|
requirement: !ruby/object:Gem::Requirement
|
184
170
|
requirements:
|
185
171
|
- - "~>"
|
186
172
|
- !ruby/object:Gem::Version
|
187
|
-
version: '0.
|
173
|
+
version: '0.14'
|
188
174
|
type: :development
|
189
175
|
prerelease: false
|
190
176
|
version_requirements: !ruby/object:Gem::Requirement
|
191
177
|
requirements:
|
192
178
|
- - "~>"
|
193
179
|
- !ruby/object:Gem::Version
|
194
|
-
version: '0.
|
180
|
+
version: '0.14'
|
195
181
|
description: Spend time with the people you care about. Introvert-tested. Extrovert-approved.
|
196
182
|
email:
|
197
183
|
- jacobevelyn@gmail.com
|
@@ -203,7 +189,6 @@ files:
|
|
203
189
|
- ".gitignore"
|
204
190
|
- ".overcommit.yml"
|
205
191
|
- ".rubocop.yml"
|
206
|
-
- ".ruby-version"
|
207
192
|
- ".travis.yml"
|
208
193
|
- CHANGELOG.md
|
209
194
|
- CODE_OF_CONDUCT.md
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.4.0
|