friends 0.33 → 0.34
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/.rubocop.yml +16 -246
- data/.travis.yml +1 -0
- data/CHANGELOG.md +12 -1
- data/README.md +102 -80
- data/bin/friends +4 -6
- data/lib/friends/activity.rb +2 -2
- data/lib/friends/friend.rb +4 -8
- data/lib/friends/graph.rb +6 -5
- data/lib/friends/introvert.rb +12 -6
- data/lib/friends/location.rb +1 -1
- data/lib/friends/regex_builder.rb +8 -8
- data/lib/friends/version.rb +1 -1
- data/test/commands/add/activity_spec.rb +8 -3
- data/test/commands/help_spec.rb +1 -1
- data/test/helper.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c8288b02c441d46ce2481d4a39f8ea457519a6e7
|
|
4
|
+
data.tar.gz: 551632c785ec6d2447adf65d56ab4fa0aac16a49
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9fc27186b237b3a244d88e5c85cc019bfce8ae51a1b74becae9c103d33fa777429c247ae3070b3da288104299856475ab1e67e376a5b4bdb719f62f9550f6b8d
|
|
7
|
+
data.tar.gz: 3206d0662d64b42f8c8ce5e2fb5bc8ad9a95dda27b4d07541798fc27a177f0d7d5c343bfbf540357f891a6bf954e2b09acf38aa8a09d71988b84d480a92d8944
|
data/.rubocop.yml
CHANGED
|
@@ -1,280 +1,50 @@
|
|
|
1
|
-
AbcSize:
|
|
2
|
-
Enabled: false
|
|
3
|
-
|
|
4
|
-
AccessorMethodName:
|
|
5
|
-
Enabled: false
|
|
6
|
-
|
|
7
|
-
Alias:
|
|
8
|
-
Enabled: false
|
|
9
|
-
|
|
10
1
|
AllCops:
|
|
11
|
-
TargetRubyVersion: 2.
|
|
12
|
-
|
|
13
|
-
AmbiguousOperator:
|
|
14
|
-
Enabled: false
|
|
15
|
-
|
|
16
|
-
AmbiguousRegexpLiteral:
|
|
17
|
-
Enabled: false
|
|
18
|
-
|
|
19
|
-
ArrayJoin:
|
|
20
|
-
Enabled: false
|
|
21
|
-
|
|
22
|
-
AsciiComments:
|
|
23
|
-
Enabled: false
|
|
24
|
-
|
|
25
|
-
AsciiIdentifiers:
|
|
26
|
-
Enabled: false
|
|
27
|
-
|
|
28
|
-
AssignmentInCondition:
|
|
29
|
-
Enabled: true
|
|
30
|
-
|
|
31
|
-
Attr:
|
|
32
|
-
Enabled: false
|
|
33
|
-
|
|
34
|
-
BlockNesting:
|
|
35
|
-
Enabled: false
|
|
36
|
-
|
|
37
|
-
BracesAroundHashParameters:
|
|
38
|
-
Enabled: false
|
|
39
|
-
|
|
40
|
-
CaseEquality:
|
|
41
|
-
Enabled: false
|
|
42
|
-
|
|
43
|
-
CharacterLiteral:
|
|
44
|
-
Enabled: false
|
|
45
|
-
|
|
46
|
-
ClassLength:
|
|
47
|
-
Enabled: false
|
|
48
|
-
|
|
49
|
-
ClassVars:
|
|
50
|
-
Enabled: false
|
|
51
|
-
|
|
52
|
-
CollectionMethods:
|
|
53
|
-
PreferredMethods:
|
|
54
|
-
find: detect
|
|
55
|
-
reduce: inject
|
|
56
|
-
collect: map
|
|
57
|
-
find_all: select
|
|
58
|
-
|
|
59
|
-
ColonMethodCall:
|
|
60
|
-
Enabled: false
|
|
61
|
-
|
|
62
|
-
CommentAnnotation:
|
|
63
|
-
Enabled: false
|
|
2
|
+
TargetRubyVersion: 2.1
|
|
64
3
|
|
|
65
|
-
|
|
66
|
-
Enabled: false
|
|
67
|
-
|
|
68
|
-
CyclomaticComplexity:
|
|
69
|
-
Enabled: false
|
|
70
|
-
|
|
71
|
-
Delegate:
|
|
72
|
-
Enabled: false
|
|
73
|
-
|
|
74
|
-
DeprecatedClassMethods:
|
|
75
|
-
Enabled: false
|
|
76
|
-
|
|
77
|
-
Documentation:
|
|
78
|
-
Enabled: false
|
|
79
|
-
|
|
80
|
-
DotPosition:
|
|
4
|
+
Layout/DotPosition:
|
|
81
5
|
EnforcedStyle: trailing
|
|
82
6
|
|
|
83
|
-
DoubleNegation:
|
|
84
|
-
Enabled: false
|
|
85
|
-
|
|
86
|
-
ElseLayout:
|
|
87
|
-
Enabled: false
|
|
88
|
-
|
|
89
|
-
EmptyLiteral:
|
|
90
|
-
Enabled: false
|
|
91
|
-
|
|
92
|
-
Encoding:
|
|
93
|
-
Enabled: false
|
|
94
|
-
|
|
95
|
-
EvenOdd:
|
|
96
|
-
Enabled: false
|
|
97
|
-
|
|
98
|
-
FileName:
|
|
99
|
-
Enabled: false
|
|
100
|
-
|
|
101
|
-
FlipFlop:
|
|
102
|
-
Enabled: false
|
|
103
|
-
|
|
104
|
-
FormatString:
|
|
105
|
-
Enabled: false
|
|
106
|
-
|
|
107
|
-
GlobalVars:
|
|
108
|
-
Enabled: false
|
|
109
|
-
|
|
110
|
-
HandleExceptions:
|
|
111
|
-
Enabled: false
|
|
112
|
-
|
|
113
|
-
IfUnlessModifier:
|
|
114
|
-
Enabled: false
|
|
115
|
-
|
|
116
|
-
IfWithSemicolon:
|
|
117
|
-
Enabled: false
|
|
118
|
-
|
|
119
|
-
InvalidCharacterLiteral:
|
|
120
|
-
Enabled: false
|
|
121
|
-
|
|
122
|
-
Lambda:
|
|
123
|
-
Enabled: false
|
|
124
|
-
|
|
125
|
-
LambdaCall:
|
|
126
|
-
Enabled: false
|
|
127
|
-
|
|
128
7
|
Layout/IndentHeredoc:
|
|
129
8
|
Enabled: false
|
|
130
9
|
|
|
131
|
-
|
|
132
|
-
Enabled: false
|
|
133
|
-
|
|
134
|
-
LineLength:
|
|
135
|
-
Max: 100
|
|
136
|
-
|
|
137
|
-
LiteralInCondition:
|
|
138
|
-
Enabled: false
|
|
139
|
-
|
|
140
|
-
LiteralInInterpolation:
|
|
141
|
-
Enabled: false
|
|
142
|
-
|
|
143
|
-
Loop:
|
|
144
|
-
Enabled: false
|
|
145
|
-
|
|
146
|
-
MethodLength:
|
|
10
|
+
Metrics/AbcSize:
|
|
147
11
|
Enabled: false
|
|
148
12
|
|
|
149
13
|
Metrics/BlockLength:
|
|
150
14
|
Enabled: false
|
|
151
15
|
|
|
152
|
-
|
|
153
|
-
Enabled: false
|
|
154
|
-
|
|
155
|
-
MutableConstant:
|
|
156
|
-
Enabled: true
|
|
157
|
-
|
|
158
|
-
NegatedIf:
|
|
159
|
-
Enabled: false
|
|
160
|
-
|
|
161
|
-
NegatedWhile:
|
|
162
|
-
Enabled: false
|
|
163
|
-
|
|
164
|
-
Next:
|
|
165
|
-
Enabled: false
|
|
166
|
-
|
|
167
|
-
NilComparison:
|
|
168
|
-
Enabled: false
|
|
169
|
-
|
|
170
|
-
Not:
|
|
171
|
-
Enabled: false
|
|
172
|
-
|
|
173
|
-
NumericLiterals:
|
|
16
|
+
Metrics/ClassLength:
|
|
174
17
|
Enabled: false
|
|
175
18
|
|
|
176
|
-
|
|
19
|
+
Metrics/CyclomaticComplexity:
|
|
177
20
|
Enabled: false
|
|
178
21
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
ParameterLists:
|
|
183
|
-
Enabled: false
|
|
184
|
-
|
|
185
|
-
ParenthesesAsGroupedExpression:
|
|
186
|
-
Enabled: false
|
|
187
|
-
|
|
188
|
-
PerceivedComplexity:
|
|
189
|
-
Enabled: false
|
|
190
|
-
|
|
191
|
-
PercentLiteralDelimiters:
|
|
192
|
-
PreferredDelimiters:
|
|
193
|
-
'%': '{}'
|
|
194
|
-
|
|
195
|
-
PerlBackrefs:
|
|
196
|
-
Enabled: false
|
|
197
|
-
|
|
198
|
-
PredicateName:
|
|
199
|
-
NamePrefixBlacklist:
|
|
200
|
-
- is_
|
|
201
|
-
|
|
202
|
-
Proc:
|
|
203
|
-
Enabled: false
|
|
204
|
-
|
|
205
|
-
Rails:
|
|
206
|
-
Enabled: false
|
|
22
|
+
Metrics/LineLength:
|
|
23
|
+
Max: 100
|
|
207
24
|
|
|
208
|
-
|
|
25
|
+
Metrics/MethodLength:
|
|
209
26
|
Enabled: false
|
|
210
27
|
|
|
211
|
-
|
|
212
|
-
AllowMultipleReturnValues: true
|
|
213
|
-
|
|
214
|
-
RegexpLiteral:
|
|
28
|
+
Metrics/ParameterLists:
|
|
215
29
|
Enabled: false
|
|
216
30
|
|
|
217
|
-
|
|
31
|
+
Metrics/PerceivedComplexity:
|
|
218
32
|
Enabled: false
|
|
219
33
|
|
|
220
|
-
|
|
34
|
+
Naming/AccessorMethodName:
|
|
221
35
|
Enabled: false
|
|
222
36
|
|
|
223
|
-
|
|
224
|
-
EnforcedStyle: only_raise
|
|
225
|
-
|
|
226
|
-
SingleLineBlockParams:
|
|
37
|
+
Style/Documentation:
|
|
227
38
|
Enabled: false
|
|
228
39
|
|
|
229
|
-
|
|
40
|
+
Style/MultilineBlockChain:
|
|
230
41
|
Enabled: false
|
|
231
42
|
|
|
232
|
-
SpecialGlobalVars:
|
|
43
|
+
Style/SpecialGlobalVars:
|
|
233
44
|
Enabled: false
|
|
234
45
|
|
|
235
|
-
StringLiterals:
|
|
46
|
+
Style/StringLiterals:
|
|
236
47
|
EnforcedStyle: double_quotes
|
|
237
48
|
|
|
238
|
-
Style/MultilineBlockChain:
|
|
239
|
-
Enabled: false
|
|
240
|
-
|
|
241
49
|
Style/SymbolArray:
|
|
242
|
-
EnforcedStyle: brackets
|
|
243
|
-
|
|
244
|
-
VariableInterpolation:
|
|
245
|
-
Enabled: false
|
|
246
|
-
|
|
247
|
-
TrailingCommaInArguments:
|
|
248
|
-
Enabled: true
|
|
249
|
-
|
|
250
|
-
TrailingCommaInLiteral:
|
|
251
|
-
Enabled: true
|
|
252
|
-
|
|
253
|
-
TrivialAccessors:
|
|
254
|
-
Enabled: false
|
|
255
|
-
|
|
256
|
-
UnderscorePrefixedVariableName:
|
|
257
|
-
Enabled: false
|
|
258
|
-
|
|
259
|
-
VariableInterpolation:
|
|
260
|
-
Enabled: false
|
|
261
|
-
|
|
262
|
-
Void:
|
|
263
|
-
Enabled: false
|
|
264
|
-
|
|
265
|
-
WhenThen:
|
|
266
|
-
Enabled: false
|
|
267
|
-
|
|
268
|
-
WhileUntilModifier:
|
|
269
|
-
Enabled: false
|
|
270
|
-
|
|
271
|
-
WordArray:
|
|
272
|
-
Enabled: false
|
|
273
|
-
|
|
274
|
-
GuardClause:
|
|
275
|
-
Enabled: false
|
|
276
|
-
|
|
277
|
-
# Renaming `has_something?` to `something?` obfuscates whether it is a "is-a" or
|
|
278
|
-
# # a "has-a" relationship.
|
|
279
|
-
PredicateName:
|
|
280
|
-
Enabled: false
|
|
50
|
+
EnforcedStyle: brackets
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## [v0.34](https://github.com/JacobEvelyn/friends/tree/v0.34) (2018-01-10)
|
|
4
|
+
[Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.33...v0.34)
|
|
5
|
+
|
|
6
|
+
**Implemented enhancements:**
|
|
7
|
+
|
|
8
|
+
- Newer activities should always appear above older activities on the same date [\#184](https://github.com/JacobEvelyn/friends/issues/184)
|
|
9
|
+
|
|
10
|
+
**Merged pull requests:**
|
|
11
|
+
|
|
12
|
+
- Always sort activities stably within a date [\#185](https://github.com/JacobEvelyn/friends/pull/185) ([JacobEvelyn](https://github.com/JacobEvelyn))
|
|
13
|
+
|
|
3
14
|
## [v0.33](https://github.com/JacobEvelyn/friends/tree/v0.33) (2017-08-22)
|
|
4
15
|
[Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.32...v0.33)
|
|
5
16
|
|
|
6
|
-
**
|
|
17
|
+
**Implemented enhancements:**
|
|
7
18
|
|
|
8
19
|
- Prevent dates without years from being in the future [\#181](https://github.com/JacobEvelyn/friends/pull/181) ([JacobEvelyn](https://github.com/JacobEvelyn))
|
|
9
20
|
|
data/README.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
|
-
[](https://badge.fury.io/rb/friends)
|
|
2
|
-
|
|
1
|
+
[](https://badge.fury.io/rb/friends)
|
|
2
|
+
[](https://gemnasium.com/github.com/JacobEvelyn/friends)
|
|
3
|
+
[](https://coveralls.io/github/JacobEvelyn/friends)
|
|
4
|
+
[](https://travis-ci.org/JacobEvelyn/friends)
|
|
5
|
+
[](http://clayallsopp.github.io/readme-score?url=JacobEvelyn/friends)
|
|
6
|
+
[](http://inch-ci.org/github/JacobEvelyn/friends)
|
|
7
|
+
[](https://rubygems.org/gems/friends)
|
|
8
|
+
|
|
9
|
+
`friends` is a volunteer project. If you find it useful, please consider
|
|
10
|
+
making a small donation to show me you appreciate its continued development.
|
|
11
|
+
|
|
12
|
+
[](https://opencollective.com/friends)
|
|
13
|
+
[](https://www.patreon.com/jacobevelyn)
|
|
14
|
+
[](https://liberapay.com/jacobevelyn/donate)
|
|
15
|
+
[](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=jacobevelyn%40gmail%2ecom&lc=US&item_name=Development%20of%20JacobEvelyn%2ffriends%20%28GitHub%20repository%29&no_note=0¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHostedGuest)
|
|
16
|
+
[](https://flattr.com/submit/auto?user_id=jacobevelyn&url=https://github.com/JacobEvelyn/friends&title=friends&tags=github&category=software)
|
|
17
|
+
[](https://nrobinson2000.github.io/donate-bitcoin?address=1CFu6gWpmS89EnitPPdYssZhFMRWx5qhW4&amount=10&name=support-friends-development)
|
|
3
18
|
|
|
4
19
|
# `friends`
|
|
5
20
|
|
|
@@ -12,47 +27,47 @@ lots of help), and give feedback!**
|
|
|
12
27
|
|
|
13
28
|
## Table of Contents
|
|
14
29
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
30
|
+
* [Overview](#overview)
|
|
31
|
+
* [Installation](#installation)
|
|
32
|
+
* [Usage](#usage)
|
|
33
|
+
* [Core concepts](#core-concepts)
|
|
34
|
+
* [Global flags](#global-flags)
|
|
35
|
+
* [Syncing across multiple machines](#syncing-across-multiple-machines)
|
|
36
|
+
* [Setting reminders](#setting-reminders)
|
|
37
|
+
* [Command reference](#command-reference)
|
|
38
|
+
* `add`
|
|
39
|
+
* [`add activity`](#add-activity)
|
|
40
|
+
* [`add friend`](#add-friend)
|
|
41
|
+
* [`add tag`](#add-tag)
|
|
42
|
+
* [`add location`](#add-location)
|
|
43
|
+
* [`add nickname`](#add-nickname)
|
|
44
|
+
* [`clean`](#clean)
|
|
45
|
+
* [`graph`](#graph)
|
|
46
|
+
* [`help`](#help)
|
|
47
|
+
* `list`
|
|
48
|
+
* [`list activities`](#list-activities)
|
|
49
|
+
* `list favorite`
|
|
50
|
+
* [`list favorite friends`](#list-favorite-friends)
|
|
51
|
+
* [`list favorite locations`](#list-favorite-locations)
|
|
52
|
+
* [`list friends`](#list-friends)
|
|
53
|
+
* [`list tags`](#list-tags)
|
|
54
|
+
* [`list locations`](#list-locations)
|
|
55
|
+
* `remove`
|
|
56
|
+
* [`remove tag`](#remove-tag)
|
|
57
|
+
* [`remove nickname`](#remove-nickname)
|
|
58
|
+
* `rename`
|
|
59
|
+
* [`rename friend`](#rename-friend)
|
|
60
|
+
* [`rename location`](#rename-location)
|
|
61
|
+
* [`set location`](#set-location)
|
|
62
|
+
* [`stats`](#stats)
|
|
63
|
+
* [`suggest`](#suggest)
|
|
64
|
+
* [`update`](#update)
|
|
65
|
+
* [Other documentation](#other-documentation)
|
|
66
|
+
* [Contributing (it's encouraged!)](#contributing-its-encouraged)
|
|
67
|
+
* [Code of Conduct](#code-of-conduct)
|
|
68
|
+
* [License](#license)
|
|
69
|
+
|
|
70
|
+
---
|
|
56
71
|
|
|
57
72
|
## Overview
|
|
58
73
|
|
|
@@ -60,21 +75,22 @@ lots of help), and give feedback!**
|
|
|
60
75
|
people you care about.
|
|
61
76
|
|
|
62
77
|
`friends` gives you:
|
|
63
|
-
|
|
78
|
+
|
|
79
|
+
* More organization around staying in touch with friends and
|
|
64
80
|
family.
|
|
65
|
-
|
|
81
|
+
* A way to track the ebbs and flows of your relationships over
|
|
66
82
|
time.
|
|
67
|
-
|
|
83
|
+
* Suggestions for who to call or hang out with when you have free
|
|
68
84
|
time, whether it's fifteen minutes or an entire weekend.
|
|
69
|
-
|
|
85
|
+
* A low-cost way to record and remember big moments in your life.
|
|
70
86
|
|
|
71
87
|
Its philosophy emphasizes:
|
|
72
88
|
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
* **Simplicity**—it should be quick and easy to use.
|
|
90
|
+
* **Transparency**—all data is stored in a human-readable Markdown file. No
|
|
75
91
|
proprietary formats here! And in addition to being open-source, `friends` is
|
|
76
92
|
very much open to new ideas. Contribute!
|
|
77
|
-
|
|
93
|
+
* **Intelligence**—specify dates with English phrases like "yesterday." Specify
|
|
78
94
|
friends with their first names, even when you're friends with many *Joanne*s. `friends` will figure it out.
|
|
79
95
|
|
|
80
96
|
## Installation
|
|
@@ -91,44 +107,47 @@ Easy, huh?
|
|
|
91
107
|
|
|
92
108
|
`friends` is structured around several different types of things:
|
|
93
109
|
|
|
94
|
-
|
|
95
|
-
it. Activities may optionally contain any number of
|
|
96
|
-
and
|
|
97
|
-
|
|
110
|
+
* **Activities**: The things you do. Each activity has a date associated with
|
|
111
|
+
it. Activities may optionally contain any number of _friends_, _locations_,
|
|
112
|
+
and _tags_.
|
|
113
|
+
* **Friends**: The people you do _activities_ with. Each friend has a name and,
|
|
98
114
|
optionally, one or several nicknames. (Examples: `John`, `Grace Hopper`)
|
|
99
|
-
|
|
115
|
+
* **Locations**: The places in which _activities_ happen. (Examples: `Paris`,
|
|
100
116
|
`Marie's Diner`)
|
|
101
|
-
|
|
117
|
+
* **Tags**: A way to categorize your _activities_ with tags of your
|
|
102
118
|
choosing. (Examples: `@exercise`, `@school`)
|
|
103
119
|
|
|
104
120
|
The `friends.md` Markdown file that stores all of your data contains:
|
|
105
121
|
|
|
106
|
-
|
|
122
|
+
* an alphabetical list of all locations:
|
|
107
123
|
|
|
108
124
|
```markdown
|
|
109
125
|
### Locations:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
126
|
+
|
|
127
|
+
* Atlantis
|
|
128
|
+
* Marie's Diner
|
|
129
|
+
* Paris
|
|
113
130
|
```
|
|
114
131
|
|
|
115
|
-
|
|
132
|
+
* an alphabetical list of all friends and their nicknames and locations:
|
|
116
133
|
|
|
117
134
|
```markdown
|
|
118
135
|
### Friends:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
136
|
+
|
|
137
|
+
* George Washington Carver
|
|
138
|
+
* Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris]
|
|
139
|
+
* Marie Curie [Atlantis]
|
|
122
140
|
```
|
|
123
141
|
|
|
124
|
-
|
|
142
|
+
* and an ordered list of all activities:
|
|
125
143
|
|
|
126
144
|
```markdown
|
|
127
145
|
### Activities:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
146
|
+
|
|
147
|
+
* 2018-11-01: **Grace Hopper** and I went to _Marie's Diner_. George had to cancel at the last minute.
|
|
148
|
+
* 2018-01-04: Got lunch with **Grace Hopper** and **George Washington Carver**.
|
|
149
|
+
* 2017-12-31: Celebrated the new year in _Paris_ with **Marie Curie**.
|
|
150
|
+
* 2017-11-15: Talked to **George Washington Carver** on the phone for an hour.
|
|
132
151
|
```
|
|
133
152
|
|
|
134
153
|
See the example
|
|
@@ -142,16 +161,16 @@ specified before the name of the command, like: `friends [flags] [command]`.
|
|
|
142
161
|
|
|
143
162
|
These flags are:
|
|
144
163
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
164
|
+
* `--colorless`: Disable output colorization and other effects.
|
|
165
|
+
* `--debug`: Debug error messages with a full backtrace.
|
|
166
|
+
* `--filename`: Set the location of the friends file to use (default: ./friends.md).
|
|
148
167
|
|
|
149
168
|
```bash
|
|
150
169
|
$ friends --filename ./test/tmp/friends.md clean
|
|
151
170
|
File cleaned: "./test/tmp/friends.md"
|
|
152
171
|
```
|
|
153
172
|
|
|
154
|
-
|
|
173
|
+
* `--quiet`: Quiet output messages.
|
|
155
174
|
|
|
156
175
|
```bash
|
|
157
176
|
$ friends --quiet add activity Went rollerskating with George.
|
|
@@ -160,8 +179,8 @@ $ # No output!
|
|
|
160
179
|
|
|
161
180
|
In addition, these flags may be used without any command:
|
|
162
181
|
|
|
163
|
-
|
|
164
|
-
Help menus are available for all levels of commands:
|
|
182
|
+
* `--help`: Show the help menu. This is equivalent to `friends help`.
|
|
183
|
+
Help menus are available for all levels of commands:
|
|
165
184
|
|
|
166
185
|
```bash
|
|
167
186
|
$ friends --help
|
|
@@ -175,7 +194,7 @@ $ friends list --help
|
|
|
175
194
|
$ friends list activities --help
|
|
176
195
|
```
|
|
177
196
|
|
|
178
|
-
|
|
197
|
+
* `--version`: Show the `friends` program version.
|
|
179
198
|
|
|
180
199
|
### Syncing across multiple machines
|
|
181
200
|
|
|
@@ -212,9 +231,9 @@ hang out with every Saturday morning:
|
|
|
212
231
|
|
|
213
232
|
(If you use other tools, please share and we'll add to these examples!)
|
|
214
233
|
|
|
215
|
-
### Command reference
|
|
234
|
+
### Command reference\*
|
|
216
235
|
|
|
217
|
-
|
|
236
|
+
\*Note that the command-line output is colored, which this README cannot show.
|
|
218
237
|
|
|
219
238
|
#### `add activity`
|
|
220
239
|
|
|
@@ -223,7 +242,7 @@ $ friends add activity Got lunch with Grace and George.
|
|
|
223
242
|
Activity added: "2018-01-04: Got lunch with Grace Hopper and George Washington Carver."
|
|
224
243
|
```
|
|
225
244
|
|
|
226
|
-
`friends` will **automatically** figure out which "Grace" and "George" you're referring to,
|
|
245
|
+
`friends` will **automatically** figure out which "Grace" and "George" you're referring to, _even if you're friends with lots of different Graces and Georges_.
|
|
227
246
|
|
|
228
247
|
Nicknames will be used to match friends in activities,
|
|
229
248
|
just like formal names:
|
|
@@ -746,7 +765,7 @@ Updated to friends 0.17
|
|
|
746
765
|
|
|
747
766
|
## Other documentation
|
|
748
767
|
|
|
749
|
-
In case you're
|
|
768
|
+
In case you're _really_ interested, we have documentation on
|
|
750
769
|
[RubyDoc](http://www.rubydoc.info/github/JacobEvelyn/friends).
|
|
751
770
|
|
|
752
771
|
## Contributing (it's encouraged!)
|
|
@@ -760,6 +779,9 @@ quickly. And if you'd like to do the implementing yourself, see the
|
|
|
760
779
|
A big big thanks to all of this project's lovely
|
|
761
780
|
[contributors](https://github.com/JacobEvelyn/friends/graphs/contributors)!
|
|
762
781
|
|
|
782
|
+
Another way to contribute is to make a donation (see the buttons at the top
|
|
783
|
+
of this `README`!
|
|
784
|
+
|
|
763
785
|
## Code of Conduct
|
|
764
786
|
|
|
765
787
|
Note that this project follows a [Code of Conduct](https://github.com/JacobEvelyn/friends/blob/master/CODE_OF_CONDUCT.md).
|
data/bin/friends
CHANGED
|
@@ -16,7 +16,7 @@ require "semverse"
|
|
|
16
16
|
require "friends/introvert"
|
|
17
17
|
require "friends/version"
|
|
18
18
|
|
|
19
|
-
include GLI::App
|
|
19
|
+
include GLI::App # rubocop:disable Style/MixinUsage
|
|
20
20
|
|
|
21
21
|
program_desc "Spend time with the people you care about. Introvert-tested. "\
|
|
22
22
|
"Extrovert-approved."
|
|
@@ -104,11 +104,9 @@ end
|
|
|
104
104
|
|
|
105
105
|
# If an error is raised, print the message to STDERR and exit the program.
|
|
106
106
|
on_error do |error|
|
|
107
|
-
if @debug_mode
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
abort "Error: #{error}"
|
|
111
|
-
end
|
|
107
|
+
raise error if @debug_mode
|
|
108
|
+
|
|
109
|
+
abort "Error: #{error}"
|
|
112
110
|
end
|
|
113
111
|
|
|
114
112
|
# Run the program and return the exit code corresponding to its success.
|
data/lib/friends/activity.rb
CHANGED
|
@@ -12,8 +12,8 @@ module Friends
|
|
|
12
12
|
class Activity
|
|
13
13
|
extend Serializable
|
|
14
14
|
|
|
15
|
-
SERIALIZATION_PREFIX = "- "
|
|
16
|
-
DATE_PARTITION = ": "
|
|
15
|
+
SERIALIZATION_PREFIX = "- ".freeze
|
|
16
|
+
DATE_PARTITION = ": ".freeze
|
|
17
17
|
|
|
18
18
|
# @return [Regexp] the regex for capturing groups in deserialization
|
|
19
19
|
def self.deserialization_regex
|
data/lib/friends/friend.rb
CHANGED
|
@@ -10,8 +10,8 @@ module Friends
|
|
|
10
10
|
class Friend
|
|
11
11
|
extend Serializable
|
|
12
12
|
|
|
13
|
-
SERIALIZATION_PREFIX = "- "
|
|
14
|
-
NICKNAME_PREFIX = "a.k.a. "
|
|
13
|
+
SERIALIZATION_PREFIX = "- ".freeze
|
|
14
|
+
NICKNAME_PREFIX = "a.k.a. ".freeze
|
|
15
15
|
|
|
16
16
|
# @return [Regexp] the regex for capturing groups in deserialization
|
|
17
17
|
def self.deserialization_regex
|
|
@@ -60,9 +60,7 @@ module Friends
|
|
|
60
60
|
end.join(" ") + ")"
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
unless @location_name.nil?
|
|
64
|
-
location_str = " [#{Paint[@location_name, :bold, :yellow]}]"
|
|
65
|
-
end
|
|
63
|
+
location_str = " [#{Paint[@location_name, :bold, :yellow]}]" unless @location_name.nil?
|
|
66
64
|
|
|
67
65
|
tag_str = " #{Paint[@tags.join(' '), :bold, :cyan]}" unless @tags.empty?
|
|
68
66
|
|
|
@@ -78,9 +76,7 @@ module Friends
|
|
|
78
76
|
|
|
79
77
|
# @param tag [String] the tag to remove, of the format: "@tag"
|
|
80
78
|
def remove_tag(tag)
|
|
81
|
-
unless @tags.include? tag
|
|
82
|
-
raise FriendsError, "Tag \"#{tag}\" not found for \"#{name}\""
|
|
83
|
-
end
|
|
79
|
+
raise FriendsError, "Tag \"#{tag}\" not found for \"#{name}\"" unless @tags.include? tag
|
|
84
80
|
|
|
85
81
|
@tags.delete(tag)
|
|
86
82
|
end
|
data/lib/friends/graph.rb
CHANGED
|
@@ -4,16 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
module Friends
|
|
6
6
|
class Graph
|
|
7
|
-
DATE_FORMAT = "%b %Y"
|
|
7
|
+
DATE_FORMAT = "%b %Y".freeze # rubocop:disable Style/FormatStringToken
|
|
8
8
|
|
|
9
9
|
# @param activities [Array<Friends::Activity>] a list of activities to graph
|
|
10
10
|
def initialize(filtered_activities:, all_activities:)
|
|
11
11
|
@filtered_activities = filtered_activities
|
|
12
12
|
@all_activities = all_activities
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
|
|
14
|
+
return if @all_activities.empty?
|
|
15
|
+
|
|
16
|
+
@start_date = @all_activities.last.date
|
|
17
|
+
@end_date = @all_activities.first.date
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
# Prints the graph to STDOUT, with colors.
|
data/lib/friends/introvert.rb
CHANGED
|
@@ -14,10 +14,10 @@ require "friends/friends_error"
|
|
|
14
14
|
|
|
15
15
|
module Friends
|
|
16
16
|
class Introvert
|
|
17
|
-
DEFAULT_FILENAME = "./friends.md"
|
|
18
|
-
ACTIVITIES_HEADER = "### Activities:"
|
|
19
|
-
FRIENDS_HEADER = "### Friends:"
|
|
20
|
-
LOCATIONS_HEADER = "### Locations:"
|
|
17
|
+
DEFAULT_FILENAME = "./friends.md".freeze
|
|
18
|
+
ACTIVITIES_HEADER = "### Activities:".freeze
|
|
19
|
+
FRIENDS_HEADER = "### Friends:".freeze
|
|
20
|
+
LOCATIONS_HEADER = "### Locations:".freeze
|
|
21
21
|
|
|
22
22
|
# @param filename [String] the name of the friends Markdown file
|
|
23
23
|
def initialize(filename: DEFAULT_FILENAME)
|
|
@@ -32,7 +32,7 @@ module Friends
|
|
|
32
32
|
def clean
|
|
33
33
|
File.open(@filename, "w") do |file|
|
|
34
34
|
file.puts(ACTIVITIES_HEADER)
|
|
35
|
-
@activities.
|
|
35
|
+
stable_sort(@activities).each { |act| file.puts(act.serialize) }
|
|
36
36
|
file.puts # Blank line separating activities from friends.
|
|
37
37
|
file.puts(FRIENDS_HEADER)
|
|
38
38
|
@friends.sort.each { |friend| file.puts(friend.serialize) }
|
|
@@ -471,6 +471,12 @@ module Friends
|
|
|
471
471
|
|
|
472
472
|
private
|
|
473
473
|
|
|
474
|
+
# @param arr [Array] an unsorted array
|
|
475
|
+
# @return [Array] a stably-sorted array
|
|
476
|
+
def stable_sort(arr)
|
|
477
|
+
arr.sort_by.with_index { |x, idx| [x, idx] }
|
|
478
|
+
end
|
|
479
|
+
|
|
474
480
|
# Filter activities by friend, location and tag
|
|
475
481
|
# @param with [Array<String>] the names of friends to filter by, or empty for
|
|
476
482
|
# unfiltered
|
|
@@ -652,7 +658,7 @@ module Friends
|
|
|
652
658
|
|
|
653
659
|
begin
|
|
654
660
|
instance_variable_get("@#{stage.id}") << stage.klass.deserialize(line)
|
|
655
|
-
rescue => e
|
|
661
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
|
656
662
|
bad_line(e, line_num)
|
|
657
663
|
end
|
|
658
664
|
|
data/lib/friends/location.rb
CHANGED
|
@@ -6,26 +6,26 @@ module Friends
|
|
|
6
6
|
class RegexBuilder
|
|
7
7
|
# We don't want to match strings that are "escaped" with a leading
|
|
8
8
|
# backslash.
|
|
9
|
-
NO_LEADING_BACKSLASH = "(?<!\\\\)"
|
|
9
|
+
NO_LEADING_BACKSLASH = "(?<!\\\\)".freeze
|
|
10
10
|
|
|
11
11
|
# We don't want to match strings that are directly touching double asterisks
|
|
12
12
|
# as these are treated as sacred by our program.
|
|
13
|
-
NO_LEADING_ASTERISKS = "(?<!\\*\\*)"
|
|
14
|
-
NO_TRAILING_ASTERISKS = "(?!\\*\\*)"
|
|
13
|
+
NO_LEADING_ASTERISKS = "(?<!\\*\\*)".freeze
|
|
14
|
+
NO_TRAILING_ASTERISKS = "(?!\\*\\*)".freeze
|
|
15
15
|
|
|
16
16
|
# We don't want to match strings that are directly touching underscores
|
|
17
17
|
# as these are treated as sacred by our program.
|
|
18
|
-
NO_LEADING_UNDERSCORES = "(?<!_)"
|
|
19
|
-
NO_TRAILING_UNDERSCORES = "(?!_)"
|
|
18
|
+
NO_LEADING_UNDERSCORES = "(?<!_)".freeze
|
|
19
|
+
NO_TRAILING_UNDERSCORES = "(?!_)".freeze
|
|
20
20
|
|
|
21
21
|
# We don't want to match strings that are part of other words.
|
|
22
|
-
NO_LEADING_ALPHABETICALS = "(?<![A-z])"
|
|
23
|
-
NO_TRAILING_ALPHABETICALS = "(?![A-z])"
|
|
22
|
+
NO_LEADING_ALPHABETICALS = "(?<![A-z])".freeze
|
|
23
|
+
NO_TRAILING_ALPHABETICALS = "(?![A-z])".freeze
|
|
24
24
|
|
|
25
25
|
# We ignore case within the regex as opposed to globally to allow consumers
|
|
26
26
|
# of this API the ability to pass in strings that turn off this modifier
|
|
27
27
|
# with the "(?-i)" string.
|
|
28
|
-
IGNORE_CASE = "(?i)"
|
|
28
|
+
IGNORE_CASE = "(?i)".freeze
|
|
29
29
|
|
|
30
30
|
def self.regex(str)
|
|
31
31
|
Regexp.new(
|
data/lib/friends/version.rb
CHANGED
|
@@ -328,7 +328,9 @@ clean_describe "add activity" do
|
|
|
328
328
|
let(:content) do
|
|
329
329
|
<<-FILE
|
|
330
330
|
### Activities:
|
|
331
|
+
- 2018-01-01: Activity one year later.
|
|
331
332
|
- 2017-01-01: Activity 1.
|
|
333
|
+
- 2016-01-01: Activity one year earlier.
|
|
332
334
|
|
|
333
335
|
### Friends:
|
|
334
336
|
|
|
@@ -337,19 +339,22 @@ FILE
|
|
|
337
339
|
end
|
|
338
340
|
|
|
339
341
|
subject do
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
342
|
+
4.times do |i|
|
|
343
|
+
run_cmd("add activity 2017-01-01: Activity #{i + 2}.")
|
|
344
|
+
end
|
|
343
345
|
end
|
|
344
346
|
|
|
345
347
|
it "orders dates by insertion time" do
|
|
346
348
|
subject
|
|
347
349
|
File.read(filename).must_equal <<-FILE
|
|
348
350
|
### Activities:
|
|
351
|
+
- 2018-01-01: Activity one year later.
|
|
352
|
+
- 2017-01-01: Activity 5.
|
|
349
353
|
- 2017-01-01: Activity 4.
|
|
350
354
|
- 2017-01-01: Activity 3.
|
|
351
355
|
- 2017-01-01: Activity 2.
|
|
352
356
|
- 2017-01-01: Activity 1.
|
|
357
|
+
- 2016-01-01: Activity one year earlier.
|
|
353
358
|
|
|
354
359
|
### Friends:
|
|
355
360
|
|
data/test/commands/help_spec.rb
CHANGED
|
@@ -37,7 +37,7 @@ clean_describe "help" do
|
|
|
37
37
|
describe "with an invalid subcommand passed" do
|
|
38
38
|
subject { run_cmd("help garbage") }
|
|
39
39
|
|
|
40
|
-
# FIXME uncomment!!!
|
|
40
|
+
# FIXME: uncomment!!!
|
|
41
41
|
# Waiting for: https://github.com/davetron5000/gli/issues/255
|
|
42
42
|
# it "prints an error message" do
|
|
43
43
|
# stderr_only "error: Unknown command 'garbage'. Use 'friends help' for a list of commands."
|
data/test/helper.rb
CHANGED
|
@@ -24,7 +24,7 @@ require "securerandom"
|
|
|
24
24
|
|
|
25
25
|
require "friends"
|
|
26
26
|
|
|
27
|
-
CONTENT = <<-FILE
|
|
27
|
+
CONTENT = <<-FILE.freeze
|
|
28
28
|
### Activities:
|
|
29
29
|
- 2015-11-01: **Grace Hopper** and I went to _Marie's Diner_. George had to cancel at the last minute. @food
|
|
30
30
|
- 2015-01-04: Got lunch with **Grace Hopper** and **George Washington Carver**. @food
|
|
@@ -43,7 +43,7 @@ CONTENT = <<-FILE
|
|
|
43
43
|
FILE
|
|
44
44
|
|
|
45
45
|
# This is CONTENT but with activities, friends, and locations unsorted.
|
|
46
|
-
SCRAMBLED_CONTENT = <<-FILE
|
|
46
|
+
SCRAMBLED_CONTENT = <<-FILE.freeze
|
|
47
47
|
### Activities:
|
|
48
48
|
- 2015-01-04: Got lunch with **Grace Hopper** and **George Washington Carver**. @food
|
|
49
49
|
- 2015-11-01: **Grace Hopper** and I went to _Marie's Diner_. George had to cancel at the last minute. @food
|
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.34'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jacob Evelyn
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2018-01-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: chronic
|