friends 0.28 → 0.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -4
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +2 -0
  5. data/CHANGELOG.md +13 -0
  6. data/README.md +35 -5
  7. data/Rakefile +1 -1
  8. data/bin/friends +7 -379
  9. data/friends.gemspec +3 -1
  10. data/lib/friends/activity.rb +4 -4
  11. data/lib/friends/commands/add.rb +64 -0
  12. data/lib/friends/commands/clean.rb +9 -0
  13. data/lib/friends/commands/edit.rb +12 -0
  14. data/lib/friends/commands/graph.rb +56 -0
  15. data/lib/friends/commands/list.rb +143 -0
  16. data/lib/friends/commands/remove.rb +27 -0
  17. data/lib/friends/commands/rename.rb +30 -0
  18. data/lib/friends/commands/set.rb +14 -0
  19. data/lib/friends/commands/stats.rb +11 -0
  20. data/lib/friends/commands/suggest.rb +20 -0
  21. data/lib/friends/commands/update.rb +29 -0
  22. data/lib/friends/graph.rb +7 -7
  23. data/lib/friends/introvert.rb +23 -18
  24. data/lib/friends/version.rb +1 -1
  25. data/test/commands/add/activity_spec.rb +379 -0
  26. data/test/commands/add/friend_spec.rb +30 -0
  27. data/test/commands/add/location_spec.rb +30 -0
  28. data/test/commands/add/nickname_spec.rb +50 -0
  29. data/test/commands/add/tag_spec.rb +65 -0
  30. data/test/commands/clean_spec.rb +39 -0
  31. data/test/commands/graph_spec.rb +147 -0
  32. data/test/commands/help_spec.rb +45 -0
  33. data/test/commands/list/activities_spec.rb +136 -0
  34. data/test/commands/list/favorite/friends_spec.rb +77 -0
  35. data/test/commands/list/favorite/locations_spec.rb +82 -0
  36. data/test/commands/list/friends_spec.rb +76 -0
  37. data/test/commands/list/locations_spec.rb +35 -0
  38. data/test/commands/list/tags_spec.rb +58 -0
  39. data/test/commands/remove/nickname_spec.rb +63 -0
  40. data/test/commands/remove/tag_spec.rb +64 -0
  41. data/test/commands/rename/friend_spec.rb +55 -0
  42. data/test/commands/rename/location_spec.rb +43 -0
  43. data/test/commands/set/location_spec.rb +54 -0
  44. data/test/commands/stats_spec.rb +41 -0
  45. data/test/commands/suggest_spec.rb +86 -0
  46. data/test/commands/update_spec.rb +13 -0
  47. data/test/helper.rb +114 -0
  48. metadata +89 -15
  49. data/test/activity_spec.rb +0 -597
  50. data/test/friend_spec.rb +0 -241
  51. data/test/graph_spec.rb +0 -92
  52. data/test/introvert_spec.rb +0 -969
  53. data/test/location_spec.rb +0 -60
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 31ada45e644c5d8473d57a70508d64f360dd3541
4
- data.tar.gz: dc6d98844de09d8bfd8110dbe1fd0b2b468a6711
3
+ metadata.gz: 266cfedd5b0654ca5ebd434c11ead3d8c21d4e9e
4
+ data.tar.gz: 76d290e42cc9babe0dcfe3dd9419dded6ca4825d
5
5
  SHA512:
6
- metadata.gz: fd6409785d7d579a2ba0106757572970a28b5e23eb52c2e7c1dd227fbeeed92f7107c75f8780c3d6f397332b3ce41d23d0af3394f812d993e17147724814ed87
7
- data.tar.gz: 3a9d5fa932b44adc0a27d4d73044d5eefb060cd6a363e4934d19d0274668d171eaab2f08914732bbcbd9da467ab1b31d65a3e82ac551e532191dc8e832f5ca4b
6
+ metadata.gz: 41e311c6cd3f8dc4a0c9e86d5268badad683731307626f6f50ef33eaf15edfc930754adce617f2934262b6915caa87b3167b138741b3e6b99025d0c4cc542a06
7
+ data.tar.gz: e838474558ec1a065cd7d72a828fb6073adafac32a6aec23b4bc6e930063f5838e55129d9a6d82d01bf0236a79777db936a31a32b15104fce83cdd3c146e1c5c
data/.rubocop.yml CHANGED
@@ -74,9 +74,6 @@ Delegate:
74
74
  DeprecatedClassMethods:
75
75
  Enabled: false
76
76
 
77
- DeprecatedHashMethods:
78
- Enabled: false
79
-
80
77
  Documentation:
81
78
  Enabled: false
82
79
 
@@ -132,7 +129,7 @@ LineEndConcatenation:
132
129
  Enabled: false
133
130
 
134
131
  LineLength:
135
- Max: 80
132
+ Max: 100
136
133
 
137
134
  LiteralInCondition:
138
135
  Enabled: false
@@ -146,6 +143,9 @@ Loop:
146
143
  MethodLength:
147
144
  Enabled: false
148
145
 
146
+ Metrics/BlockLength:
147
+ Enabled: false
148
+
149
149
  ModuleFunction:
150
150
  Enabled: false
151
151
 
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.0
1
+ 2.4.0
data/.travis.yml CHANGED
@@ -1,7 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.1.0
4
+ - 2.2.0
4
5
  - 2.3.0
6
+ - 2.4.0
5
7
  script:
6
8
  - bundle exec rake test
7
9
  - bundle exec rubocop
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Change Log
2
2
 
3
+ ## [v0.29](https://github.com/JacobEvelyn/friends/tree/v0.29) (2017-03-18)
4
+ [Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.28...v0.29)
5
+
6
+ **Implemented enhancements:**
7
+
8
+ - Add `--since \<date\>` and `--until \<date\>` flags, and remove extraneous months from `graph` [\#153](https://github.com/JacobEvelyn/friends/issues/153)
9
+ - Add integration tests for bin/friends? [\#127](https://github.com/JacobEvelyn/friends/issues/127)
10
+
11
+ **Merged pull requests:**
12
+
13
+ - Add --since and --until flags to `graph` and `list activities` [\#157](https://github.com/JacobEvelyn/friends/pull/157) ([JacobEvelyn](https://github.com/JacobEvelyn))
14
+ - Restructuring [\#155](https://github.com/JacobEvelyn/friends/pull/155) ([JacobEvelyn](https://github.com/JacobEvelyn))
15
+
3
16
  ## [v0.28](https://github.com/JacobEvelyn/friends/tree/v0.28) (2016-06-25)
4
17
  [Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.27...v0.28)
5
18
 
data/README.md CHANGED
@@ -42,7 +42,7 @@ lots of help), and give feedback!**
42
42
  - `rename`
43
43
  - [`rename friend`](#rename-friend)
44
44
  - [`rename location`](#rename-location)
45
- - [`set location`](#set)
45
+ - [`set location`](#set-location)
46
46
  - [`stats`](#stats)
47
47
  - [`suggest`](#suggest)
48
48
  - [`update`](#update)
@@ -55,9 +55,8 @@ lots of help), and give feedback!**
55
55
 
56
56
  ## Overview
57
57
 
58
- `friends` is both a Ruby library and a command-line interface that
59
- allows you to keep track of your relationships with the people you
60
- care about.
58
+ `friends` is a command-line program that helps you to keep track of your relationships with the
59
+ people you care about.
61
60
 
62
61
  `friends` gives you:
63
62
  - More organization around staying in touch with friends and
@@ -364,10 +363,27 @@ Jan 2015 |
364
363
  Feb 2015 |█
365
364
  ```
366
365
 
366
+ Or graph only activities on or after a certain date:
367
+
368
+ ```bash
369
+ $ friends graph --since 'January 1st 2015'
370
+ Jan 2015 |███████
371
+ Feb 2015 |█████
372
+ ```
373
+
374
+ Or graph only activities before or on a certain date:
375
+
376
+ ```bash
377
+ $ friends graph --until 'January 1st 2015'
378
+ Nov 2014 |███
379
+ Dec 2014 |██
380
+ Jan 2015 |███████
381
+ ```
382
+
367
383
  And you can use multiple of these flags together:
368
384
 
369
385
  ```bash
370
- $ friends graph --in Paris --tagged food --with George
386
+ $ friends graph --in Paris --tagged food --with George --after 'September 2014'
371
387
  Nov 2014 |█
372
388
  ```
373
389
 
@@ -441,6 +457,20 @@ $ friends list activities --tagged food
441
457
  2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
442
458
  ```
443
459
 
460
+ Or by date:
461
+
462
+ ```bash
463
+ $ friends graph --since 'December 31st 2014'
464
+ 2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
465
+ 2014-12-31: Celebrated the new year with Marie Curie in New York City. @partying
466
+ ```
467
+
468
+ ```bash
469
+ $ friends graph --until 'December 31st 2014'
470
+ 2014-12-31: Celebrated the new year with Marie Curie in New York City. @partying
471
+ 2014-11-15: Talked to George Washington Carver on the phone for an hour.
472
+ ```
473
+
444
474
  And you can mix and match these options to your heart's content:
445
475
 
446
476
  ```bash
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require "bundler/gem_tasks"
4
4
  require "rake/testtask"
5
5
 
6
6
  Rake::TestTask.new do |t|
7
- t.test_files = FileList["test/*_spec.rb"]
7
+ t.test_files = FileList["test/**/*_spec.rb"]
8
8
  end
9
9
 
10
10
  task default: :test
data/bin/friends CHANGED
@@ -39,6 +39,12 @@ end
39
39
  class Stripped; end
40
40
  accept(Stripped, &:strip)
41
41
 
42
+ class InputDate; end
43
+ accept(InputDate) do |value|
44
+ time = Chronic.parse(value)
45
+ time && time.to_date
46
+ end
47
+
42
48
  switch [:quiet],
43
49
  negatable: false,
44
50
  desc: "Quiet output messages"
@@ -56,385 +62,7 @@ switch [:colorless],
56
62
  negatable: false,
57
63
  desc: "Disable output colorization and other effects"
58
64
 
59
- desc "Updates the `friends` program"
60
- command :update do |update|
61
- update.action do
62
- # rubocop:disable Lint/AssignmentInCondition
63
- if match = `gem search friends`.match(/^friends\s\(([^\)]+)\)$/)
64
- # rubocop:enable Lint/AssignmentInCondition
65
- remote_version = match[1]
66
- if Semverse::Version.coerce(remote_version) >
67
- Semverse::Version.coerce(Friends::VERSION)
68
- `gem update friends && gem cleanup friends`
69
- if $?.success?
70
- @message = Paint[
71
- "Updated to friends #{remote_version}", :bold, :green
72
- ]
73
- else
74
- @message = Paint[
75
- "Error updating to friends version #{remote_version}", :bold, :red
76
- ]
77
- end
78
- else
79
- @message = Paint[
80
- "Already up-to-date (#{Friends::VERSION})", :bold, :green
81
- ]
82
- end
83
- end
84
- end
85
- end
86
-
87
- desc "Opens the `friends.md` file in $EDITOR for manual editing"
88
- command :edit do |edit|
89
- edit.action do |global_options|
90
- editor = ENV["EDITOR"] || "vim"
91
- filename = global_options[:filename]
92
-
93
- puts "Opening \"#{filename}\" in #{editor}" unless global_options[:quiet]
94
- Kernel.exec "#{editor} #{filename}"
95
- end
96
- end
97
-
98
- desc "Lists friends, activities, and locations"
99
- command :list do |list|
100
- list.desc "List all friends"
101
- list.command :friends do |list_friends|
102
- list_friends.flag [:in],
103
- arg_name: "LOCATION",
104
- desc: "List only friends in the given location",
105
- type: Stripped
106
-
107
- list_friends.flag [:tagged],
108
- arg_name: "@TAG",
109
- desc: "List only friends with the given tag",
110
- type: Tag
111
-
112
- list_friends.switch [:verbose],
113
- negatable: false,
114
- desc: "Output friend nicknames, locations, and tags"
115
-
116
- list_friends.action do |_, options|
117
- puts @introvert.list_friends(
118
- location_name: options[:in],
119
- tagged: options[:tagged],
120
- verbose: options[:verbose]
121
- )
122
- end
123
- end
124
-
125
- list.desc "Lists all activities"
126
- list.command :activities do |list_activities|
127
- list_activities.flag [:limit],
128
- arg_name: "NUMBER",
129
- desc: "The number of activities to return",
130
- default_value: 10,
131
- type: Integer
132
-
133
- list_activities.flag [:with],
134
- arg_name: "NAME",
135
- desc: "List only activities with the given friend",
136
- type: Stripped
137
-
138
- list_activities.flag [:in],
139
- arg_name: "LOCATION",
140
- desc: "List only activities in the given location",
141
- type: Stripped
142
-
143
- list_activities.flag [:tagged],
144
- arg_name: "@TAG",
145
- desc: "List only activities with the given tag",
146
- type: Tag
147
-
148
- list_activities.action do |_, options|
149
- puts @introvert.list_activities(
150
- limit: options[:limit],
151
- with: options[:with],
152
- location_name: options[:in],
153
- tagged: options[:tagged]
154
- )
155
- end
156
- end
157
-
158
- list.desc "List all locations"
159
- list.command :locations do |list_locations|
160
- list_locations.action do
161
- puts @introvert.list_locations
162
- end
163
- end
164
-
165
- list.desc "List all tags used"
166
- list.command :tags do |list_tags|
167
- list_tags.flag [:from],
168
- arg_name: '"activities" or "friends" (default: both)',
169
- desc: "List only tags from activities or friends instead of"\
170
- "both"
171
- list_tags.action do |_, options|
172
- puts @introvert.list_tags(from: options[:from])
173
- end
174
- end
175
-
176
- list.desc "List favorite friends and locations"
177
- list.command :favorite do |list_favorite|
178
- list_favorite.desc "List favorite friends"
179
- list_favorite.command :friends do |list_favorite_friends|
180
- list_favorite_friends.flag [:limit],
181
- arg_name: "NUMBER",
182
- desc: "The number of friends to return",
183
- default_value: 10,
184
- type: Integer
185
-
186
- list_favorite_friends.action do |_, options|
187
- favorites = @introvert.list_favorite_friends(limit: options[:limit])
188
-
189
- if options[:limit] == 1
190
- puts "Your best friend is #{favorites.first}"
191
- else
192
- puts "Your favorite friends:"
193
-
194
- num_str_size = favorites.size.to_s.size + 1
195
- favorites.each.with_index(1) do |name, rank|
196
- puts "#{"#{rank}.".ljust(num_str_size)} #{name}"
197
- end
198
- end
199
- end
200
- end
201
-
202
- list_favorite.desc "List favorite locations"
203
- list_favorite.command :locations do |list_favorite_locations|
204
- list_favorite_locations.flag [:limit],
205
- arg_name: "NUMBER",
206
- desc: "The number of locations to return",
207
- default_value: 10,
208
- type: Integer
209
-
210
- list_favorite_locations.action do |_, options|
211
- favorites = @introvert.list_favorite_locations(limit: options[:limit])
212
-
213
- if options[:limit] == 1
214
- puts "Your favorite location is #{favorites.first}"
215
- else
216
- puts "Your favorite locations:"
217
-
218
- num_str_size = favorites.size.to_s.size + 1
219
- favorites.each.with_index(1) do |name, rank|
220
- puts "#{"#{rank}.".ljust(num_str_size)} #{name}"
221
- end
222
- end
223
- end
224
- end
225
- end
226
- end
227
-
228
- desc "Adds a friend (or nickname), activity, or location"
229
- command :add do |add|
230
- add.desc "Adds a friend"
231
- add.arg_name "NAME"
232
- add.command :friend do |add_friend|
233
- add_friend.action do |_, _, args|
234
- friend = @introvert.add_friend(name: args.join(" "))
235
- @message = "Friend added: \"#{friend.name}\""
236
- @dirty = true # Mark the file for cleaning.
237
- end
238
- end
239
-
240
- add.desc "Adds an activity"
241
- add.arg_name "DESCRIPTION"
242
- add.command :activity do |add_activity|
243
- add_activity.action do |_, _, args|
244
- activity = @introvert.add_activity(serialization: args.join(" "))
245
-
246
- # If there's no description, prompt the user for one.
247
- if activity.description.nil? || activity.description.empty?
248
- activity.description = Readline.readline(activity.to_s)
249
- activity.highlight_description(introvert: @introvert)
250
- end
251
-
252
- @message = "Activity added: \"#{activity}\""
253
- @dirty = true # Mark the file for cleaning.
254
- end
255
- end
256
-
257
- add.desc "Adds a location"
258
- add.arg_name "LOCATION"
259
- add.command :location do |add_location|
260
- add_location.action do |_, _, args|
261
- location = @introvert.add_location(name: args.join(" "))
262
- @message = "Location added: \"#{location.name}\""
263
- @dirty = true # Mark the file for cleaning.
264
- end
265
- end
266
-
267
- add.desc "Adds a nickname to a friend"
268
- add.arg_name "NAME NICKNAME"
269
- add.command :nickname do |add_nickname|
270
- add_nickname.action do |_, _, args|
271
- friend = @introvert.add_nickname(name: args.first, nickname: args[1])
272
- @message = "Nickname added: \"#{friend}\""
273
- @dirty = true # Mark the file for cleaning.
274
- end
275
- end
276
-
277
- add.desc "Adds a tag to a friend"
278
- add.arg_name "NAME @TAG"
279
- add.command :tag do |add_tag|
280
- add_tag.action do |_, _, args|
281
- friend = @introvert.add_tag(
282
- name: args[0..-2].join(" "),
283
- tag: Tag.convert_to_tag(args.last)
284
- )
285
- @message = "Tag added to friend: \"#{friend}\""
286
- @dirty = true # Mark the file for cleaning.
287
- end
288
- end
289
- end
290
-
291
- desc "Set data about friends"
292
- command :set do |set|
293
- set.desc "Set a friend's location"
294
- set.arg_name "NAME LOCATION"
295
- set.command :location do |set_location|
296
- set_location.action do |_, _, args|
297
- friend = @introvert.set_location(name: args.first, location_name: args[1])
298
- @message = "#{friend.name}'s location set to: #{friend.location_name}"
299
- @dirty = true # Mark the file for cleaning.
300
- end
301
- end
302
- end
303
-
304
- desc "Remove a nickname"
305
- command :remove do |remove|
306
- remove.desc "Removes a nickname from a friend"
307
- remove.arg_name "NAME NICKNAME"
308
- remove.command :nickname do |remove_nickname|
309
- remove_nickname.action do |_, _, args|
310
- friend = @introvert.remove_nickname(name: args.first, nickname: args[1])
311
- @message = "Nickname removed: \"#{friend}\""
312
- @dirty = true # Mark the file for cleaning.
313
- end
314
- end
315
-
316
- remove.desc "Removes a tag from a friend"
317
- remove.arg_name "NAME @TAG"
318
- remove.command :tag do |remove_tag|
319
- remove_tag.action do |_, _, args|
320
- friend = @introvert.remove_tag(
321
- name: args[0..-2].join(" "),
322
- tag: Tag.convert_to_tag(args.last)
323
- )
324
- @message = "Tag removed from friend: \"#{friend}\""
325
- @dirty = true # Mark the file for cleaning.
326
- end
327
- end
328
- end
329
-
330
- desc "Graph activities over time"
331
- command :graph do |graph|
332
- graph.flag [:with],
333
- arg_name: "NAME",
334
- desc: "Graph activities with the given friend",
335
- type: Stripped
336
-
337
- graph.flag [:in],
338
- arg_name: "LOCATION",
339
- desc: "Graph activities in the given location",
340
- type: Stripped
341
-
342
- graph.flag [:tagged],
343
- arg_name: "@TAG",
344
- desc: "Graph activities with the given tag",
345
- type: Tag
346
-
347
- graph.action do |_, options|
348
- # This math is taken from Minitest's Pride plugin (the PrideLOL class).
349
- PI_3 = Math::PI / 3
350
-
351
- colors = (0...(6 * 7)).map do |n|
352
- n *= 1.0 / 6
353
- r = (3 * Math.sin(n) + 3).to_i
354
- g = (3 * Math.sin(n + 2 * PI_3) + 3).to_i
355
- b = (3 * Math.sin(n + 4 * PI_3) + 3).to_i
356
-
357
- [r, g, b].map { |c| c * 51 }
358
- end
359
-
360
- data = @introvert.graph(
361
- with: options[:with],
362
- location_name: options[:in],
363
- tagged: options[:tagged]
364
- )
365
-
366
- data.each do |month, count|
367
- print "#{month} |"
368
- puts colors.take(count).map { |rgb| Paint["█", rgb] }.join
369
- end
370
- end
371
- end
372
-
373
- desc "Suggest friends to do activities with"
374
- command :suggest do |suggest|
375
- suggest.flag [:in],
376
- arg_name: "LOCATION",
377
- desc: "Suggest only friends in the given location",
378
- type: Stripped
379
-
380
- suggest.action do |_, options|
381
- suggestions = @introvert.suggest(location_name: options[:in])
382
-
383
- puts "Distant friend: "\
384
- "#{Paint[suggestions[:distant].sample || 'None found', :bold, :magenta]}"
385
- puts "Moderate friend: "\
386
- "#{Paint[suggestions[:moderate].sample || 'None found', :bold, :magenta]}"
387
- puts "Close friend: "\
388
- "#{Paint[suggestions[:close].sample || 'None found', :bold, :magenta]}"
389
- end
390
- end
391
-
392
- desc "Cleans your friends.md file"
393
- command :clean do |clean|
394
- clean.action do
395
- @clean_command = true
396
- @dirty = true # Mark the file for cleaning.
397
- end
398
- end
399
-
400
- desc "List all stats"
401
- command :stats do |stats|
402
- stats.action do
403
- puts "Total activities: #{@introvert.total_activities}"
404
- puts "Total friends: #{@introvert.total_friends}"
405
- days = @introvert.elapsed_days
406
- puts "Total time elapsed: #{days} day#{'s' if days != 1}"
407
- end
408
- end
409
-
410
- desc "Renames a friend or location"
411
- command :rename do |rename|
412
- rename.desc "Renames a friend"
413
- rename.arg_name "NAME NEW_NAME"
414
- rename.command :friend do |rename_friend|
415
- rename_friend.action do |_, _, args|
416
- friend = @introvert.rename_friend(
417
- old_name: args.first,
418
- new_name: args[1]
419
- )
420
- @message = "Name changed: \"#{friend}\""
421
- @dirty = true # Mark the file for cleaning.
422
- end
423
- end
424
-
425
- rename.desc "Renames a location"
426
- rename.arg_name "NAME NEW_NAME"
427
- rename.command :location do |rename_location|
428
- rename_location.action do |_, _, args|
429
- location = @introvert.rename_location(
430
- old_name: args.first,
431
- new_name: args[1]
432
- )
433
- @message = "Location renamed: \"#{location.name}\""
434
- @dirty = true # Mark the file for cleaning.
435
- end
436
- end
437
- end
65
+ commands_from "friends/commands"
438
66
 
439
67
  # Before each command, clean up all arguments and create the global Introvert.
440
68
  pre do |global_options, cmd, options|