friends 0.13 → 0.15
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -1
- data/README.md +6 -1
- data/bin/friends +1 -1
- data/friends.gemspec +1 -0
- data/lib/friends/activity.rb +19 -9
- data/lib/friends/version.rb +1 -1
- data/test/activity_spec.rb +55 -20
- data/test/introvert_spec.rb +5 -11
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fd5cb3c9a9b913b0772d731f872709820e5fa12
|
4
|
+
data.tar.gz: 99b28c2a79ae11aea5b49e75f328ed03433f94dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8aba3f30dfc6de57c2d98a79b8fa3e131458b199c25e3bfff960ec0011069040844a90580848b10e255fb869ab2843e0ab941daa85c390e69e3ba74dbe650ce
|
7
|
+
data.tar.gz: f9491efb85eed54694805e080c2e00ab5893687d60d78bc643cdccae64cc3081139ea5333e8a9d5d99ba0861e9c3b5586a59156f81b6766d2facbc1ca9eeee65
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v0.15](https://github.com/JacobEvelyn/friends/tree/v0.15) (2016-03-11)
|
4
|
+
[Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.14...v0.15)
|
5
|
+
|
6
|
+
## [v0.14](https://github.com/JacobEvelyn/friends/tree/v0.14) (2016-03-11)
|
7
|
+
[Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.13...v0.14)
|
8
|
+
|
9
|
+
**Implemented enhancements:**
|
10
|
+
|
11
|
+
- Allow dates in natural-language formats [\#65](https://github.com/JacobEvelyn/friends/issues/65)
|
12
|
+
|
13
|
+
**Merged pull requests:**
|
14
|
+
|
15
|
+
- Allow natural-language dates [\#82](https://github.com/JacobEvelyn/friends/pull/82) ([JacobEvelyn](https://github.com/JacobEvelyn))
|
16
|
+
|
3
17
|
## [v0.13](https://github.com/JacobEvelyn/friends/tree/v0.13) (2016-01-21)
|
4
18
|
[Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.12...v0.13)
|
5
19
|
|
@@ -208,4 +222,4 @@
|
|
208
222
|
## [v0.0.1](https://github.com/JacobEvelyn/friends/tree/v0.0.1) (2014-12-11)
|
209
223
|
|
210
224
|
|
211
|
-
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
225
|
+
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
data/README.md
CHANGED
@@ -51,7 +51,7 @@ Activity added: "2015-01-04: Got lunch with Grace Hopper and George Washington C
|
|
51
51
|
|
52
52
|
You can of course specify a date for the activity:
|
53
53
|
```
|
54
|
-
$ friends add activity "
|
54
|
+
$ friends add activity "Yesterday: Celebrated the new year with Marie."
|
55
55
|
Activity added: "2014-12-31: Celebrated the new year with Marie Curie."
|
56
56
|
```
|
57
57
|
Or get an **interactive prompt** by just typing `friends add activity`, with or without a date specified:
|
@@ -59,6 +59,11 @@ Or get an **interactive prompt** by just typing `friends add activity`, with or
|
|
59
59
|
$ friends add activity 2015-11-01
|
60
60
|
2015-11-01: <type description here>
|
61
61
|
```
|
62
|
+
**Natural-language dates** work just fine:
|
63
|
+
```
|
64
|
+
$ friends add activity 'last Monday'
|
65
|
+
2016-03-07: <type description here>
|
66
|
+
```
|
62
67
|
You can escape the names of friends you don't want `friends` to match with a backslash:
|
63
68
|
```
|
64
69
|
$ friends add activity "2015-11-01: Grace and I went to \Marie's Diner. \George had to cancel at the last minute."
|
data/bin/friends
CHANGED
@@ -131,7 +131,7 @@ command :add do |add|
|
|
131
131
|
activity = @introvert.add_activity(serialization: args.first)
|
132
132
|
|
133
133
|
# If there's no description, prompt the user for one.
|
134
|
-
if
|
134
|
+
if activity.description.nil? || activity.description.empty?
|
135
135
|
activity.description = Readline.readline(activity.display_text)
|
136
136
|
activity.highlight_friends(introvert: @introvert)
|
137
137
|
end
|
data/friends.gemspec
CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
# We need Ruby 2.0's keyword arguments and default UTF-8 encoding.
|
23
23
|
spec.required_ruby_version = ">= 2.1"
|
24
24
|
|
25
|
+
spec.add_dependency "chronic", "~> 0.10"
|
25
26
|
spec.add_dependency "gli", "~> 2.12"
|
26
27
|
spec.add_dependency "memoist", "~> 0.11"
|
27
28
|
spec.add_dependency "paint", "~> 1.0"
|
data/lib/friends/activity.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
# Activity represents an activity you've done with one or more Friends.
|
3
3
|
|
4
|
+
require "chronic"
|
4
5
|
require "memoist"
|
5
6
|
require "paint"
|
6
7
|
|
@@ -12,13 +13,11 @@ module Friends
|
|
12
13
|
extend Memoist
|
13
14
|
|
14
15
|
SERIALIZATION_PREFIX = "- ".freeze
|
16
|
+
DATE_PARTITION = ": ".freeze
|
15
17
|
|
16
18
|
# @return [Regexp] the regex for capturing groups in deserialization
|
17
19
|
def self.deserialization_regex
|
18
|
-
#
|
19
|
-
# rubocop:disable Metrics/LineLength
|
20
|
-
/(#{SERIALIZATION_PREFIX})?((?<date_s>\d{4}-\d\d-\d\d)(:\s)?)?(?<description>.+)?/
|
21
|
-
# rubocop:enable Metrics/LineLength
|
20
|
+
/(#{SERIALIZATION_PREFIX})?(?<str>.+)?/
|
22
21
|
end
|
23
22
|
|
24
23
|
# @return [Regexp] the string of what we expected during deserialization
|
@@ -26,12 +25,23 @@ module Friends
|
|
26
25
|
"[YYYY-MM-DD]: [Activity]"
|
27
26
|
end
|
28
27
|
|
29
|
-
# @param
|
30
|
-
#
|
28
|
+
# @param str [String] the text of the activity, of one of the formats:
|
29
|
+
# "<date>: <description>"
|
30
|
+
# "<date>" (Program will prompt for description.)
|
31
|
+
# "<description>" (The current date will be used by default.)
|
31
32
|
# @return [Activity] the new activity
|
32
|
-
def initialize(
|
33
|
-
|
34
|
-
|
33
|
+
def initialize(str: "")
|
34
|
+
# Partition lets us parse "Today" and "Today: I awoke." identically.
|
35
|
+
date_s, _, description = str.partition(DATE_PARTITION)
|
36
|
+
|
37
|
+
if time = Chronic.parse(date_s)
|
38
|
+
@date = time.to_date
|
39
|
+
@description = description
|
40
|
+
else
|
41
|
+
# If the user didn't input a date, we fall back to the current date.
|
42
|
+
@date = Date.today
|
43
|
+
@description = str # Use str in case DATE_PARTITION occurred naturally.
|
44
|
+
end
|
35
45
|
end
|
36
46
|
|
37
47
|
attr_reader :date
|
data/lib/friends/version.rb
CHANGED
data/test/activity_spec.rb
CHANGED
@@ -1,18 +1,37 @@
|
|
1
1
|
require "./test/helper"
|
2
2
|
|
3
3
|
describe Friends::Activity do
|
4
|
-
let(:date) { Date.today }
|
4
|
+
let(:date) { Date.today - 1 }
|
5
5
|
let(:date_s) { date.to_s }
|
6
6
|
let(:friend1) { Friends::Friend.new(name: "Elizabeth Cady Stanton") }
|
7
7
|
let(:friend2) { Friends::Friend.new(name: "John Cage") }
|
8
8
|
let(:description) { "Lunch with **#{friend1.name}** and **#{friend2.name}**" }
|
9
|
+
let(:partition) { Friends::Activity::DATE_PARTITION }
|
9
10
|
let(:activity) do
|
10
|
-
Friends::Activity.new(
|
11
|
+
Friends::Activity.new(str: "#{date_s}#{partition}#{description}")
|
11
12
|
end
|
12
13
|
|
13
14
|
describe ".deserialize" do
|
14
15
|
subject { Friends::Activity.deserialize(serialized_str) }
|
15
16
|
|
17
|
+
describe "when serialized string is empty" do
|
18
|
+
let(:serialized_str) { "" }
|
19
|
+
|
20
|
+
it "defaults date to today and sets no description" do
|
21
|
+
today = Date.today - 7
|
22
|
+
|
23
|
+
# We stub out Date.today to guarantee that it is always the same even
|
24
|
+
# when the date changes in the middle of the test's execution. To ensure
|
25
|
+
# this technique actually works, we move our reference time backward by
|
26
|
+
# a week.
|
27
|
+
Date.stub(:today, today) do
|
28
|
+
new_activity = subject
|
29
|
+
new_activity.date.must_equal today
|
30
|
+
new_activity.description.must_equal ""
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
16
35
|
describe "when string is well-formed" do
|
17
36
|
let(:serialized_str) { "#{date_s}: #{description}" }
|
18
37
|
|
@@ -23,23 +42,45 @@ describe Friends::Activity do
|
|
23
42
|
end
|
24
43
|
end
|
25
44
|
|
45
|
+
describe "when date is written in natural language" do
|
46
|
+
let(:serialized_str) { "Yesterday: #{description}" }
|
47
|
+
|
48
|
+
it "creates an activity with the correct date and description" do
|
49
|
+
now = Time.now + 604800
|
50
|
+
|
51
|
+
# Chronic uses Time.now for parsing, so we stub this to prevent racy
|
52
|
+
# behavior when the date changes in the middle of test execution. To
|
53
|
+
# ensure this technique actually works, we move our reference time
|
54
|
+
# backward by a week.
|
55
|
+
Time.stub(:now, now) do
|
56
|
+
new_activity = subject
|
57
|
+
new_activity.date.must_equal (now.to_date - 1)
|
58
|
+
new_activity.description.must_equal description
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
26
63
|
describe "when no date is present" do
|
27
64
|
let(:serialized_str) { description }
|
28
65
|
|
29
66
|
it "defaults to today" do
|
30
|
-
today = Date.today
|
67
|
+
today = Date.today - 7
|
31
68
|
|
32
69
|
# We stub out Date.today to guarantee that it is always the same even
|
33
|
-
# when the date changes in the middle of the test's execution.
|
70
|
+
# when the date changes in the middle of the test's execution. To ensure
|
71
|
+
# this technique actually works, we move our reference time backward by
|
72
|
+
# a week.
|
34
73
|
Date.stub(:today, today) { subject.date.must_equal today }
|
35
74
|
end
|
36
75
|
end
|
37
76
|
|
38
77
|
describe "when no description is present" do
|
39
|
-
let(:serialized_str) {
|
78
|
+
let(:serialized_str) { date_s }
|
40
79
|
|
41
|
-
it "
|
42
|
-
subject
|
80
|
+
it "leaves description blank" do
|
81
|
+
new_activity = subject
|
82
|
+
new_activity.date.must_equal date
|
83
|
+
new_activity.description.must_equal ""
|
43
84
|
end
|
44
85
|
end
|
45
86
|
end
|
@@ -249,17 +290,14 @@ describe Friends::Activity do
|
|
249
290
|
# better friend than Elizabeth Cady Stanton.
|
250
291
|
old_activities = [
|
251
292
|
Friends::Activity.new(
|
252
|
-
|
253
|
-
|
254
|
-
"**John Cage**."
|
293
|
+
str: "#{date_s}#{partition}Picnic with "\
|
294
|
+
"**Elizabeth Cady Stanton** and **John Cage**."
|
255
295
|
),
|
256
296
|
Friends::Activity.new(
|
257
|
-
|
258
|
-
description: "Got lunch with with **Elizabeth II**."
|
297
|
+
str: "#{date_s}#{partition}Got lunch with **Elizabeth II**."
|
259
298
|
),
|
260
299
|
Friends::Activity.new(
|
261
|
-
|
262
|
-
description: "Ice skated with **Elizabeth II**."
|
300
|
+
str: "#{date_s}#{partition}Ice skated with **Elizabeth II**."
|
263
301
|
)
|
264
302
|
]
|
265
303
|
|
@@ -282,8 +320,7 @@ describe Friends::Activity do
|
|
282
320
|
|
283
321
|
# Give a past activity to Elizabeth II.
|
284
322
|
old_activity = Friends::Activity.new(
|
285
|
-
|
286
|
-
description: "Do something with **Elizabeth II**."
|
323
|
+
str: "#{date_s}#{partition}Do something with **Elizabeth II**."
|
287
324
|
)
|
288
325
|
|
289
326
|
stub_activities([old_activity]) { subject }
|
@@ -339,10 +376,8 @@ describe Friends::Activity do
|
|
339
376
|
|
340
377
|
describe "#<=>" do
|
341
378
|
it "sorts by reverse-date" do
|
342
|
-
|
343
|
-
|
344
|
-
past_act = Friends::Activity.new(date_s: yesterday, description: "Dummy")
|
345
|
-
future_act = Friends::Activity.new(date_s: tomorrow, description: "Dummy")
|
379
|
+
past_act = Friends::Activity.new(str: "Yesterday: Dummy")
|
380
|
+
future_act = Friends::Activity.new(str: "Tomorrow: Dummy")
|
346
381
|
[past_act, future_act].sort.must_equal [future_act, past_act]
|
347
382
|
end
|
348
383
|
end
|
data/test/introvert_spec.rb
CHANGED
@@ -31,13 +31,10 @@ describe Friends::Introvert do
|
|
31
31
|
let(:activities) do
|
32
32
|
[
|
33
33
|
Friends::Activity.new(
|
34
|
-
|
35
|
-
description: "Lunch with **#{friend_names.first}** and "\
|
36
|
-
"**#{friend_names.last}**."
|
34
|
+
str: "Lunch w/ **#{friend_names.first}** and **#{friend_names.last}**."
|
37
35
|
),
|
38
36
|
Friends::Activity.new(
|
39
|
-
|
40
|
-
description: "Called **#{friend_names.last}**."
|
37
|
+
str: "Yesterday: Called **#{friend_names.last}**."
|
41
38
|
)
|
42
39
|
]
|
43
40
|
end
|
@@ -413,22 +410,19 @@ describe Friends::Introvert do
|
|
413
410
|
let(:activities) do
|
414
411
|
[
|
415
412
|
Friends::Activity.new(
|
416
|
-
|
417
|
-
description: "Lunch with **George Washington Carver**."
|
413
|
+
str: "Lunch with **George Washington Carver**."
|
418
414
|
),
|
419
415
|
|
420
416
|
# Create another activity with a gap of over a month between it and
|
421
417
|
# the next activity, so we can test that we correctly return data for
|
422
418
|
# months in the range with no activities.
|
423
419
|
Friends::Activity.new(
|
424
|
-
|
425
|
-
description: "Called **George Washington Carver**."
|
420
|
+
str: "70 days ago: Called **George Washington Carver**."
|
426
421
|
),
|
427
422
|
|
428
423
|
# Create an activity that doesn't involve our friend name.
|
429
424
|
Friends::Activity.new(
|
430
|
-
|
431
|
-
description: "Called **Betsy Ross** on the phone."
|
425
|
+
str: "150 days ago: Called **Betsy Ross** on the phone."
|
432
426
|
)
|
433
427
|
]
|
434
428
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: friends
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.15'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Evelyn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: chronic
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.10'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.10'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: gli
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|