friends 0.13 → 0.15
Sign up to get free protection for your applications and to get access to all the features.
- 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
|