quirk 0.0.2
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.
- data/LICENSE.md +23 -0
- data/README.md +82 -0
- data/quirk +24 -0
- data/quirk.rb +239 -0
- data/quirk_test.rb +109 -0
- metadata +84 -0
data/LICENSE.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2012, Hugh Bien
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
Redistributions of source code must retain the above copyright notice, this list
|
8
|
+
of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
Redistributions in binary form must reproduce the above copyright notice, this
|
11
|
+
list of conditions and the following disclaimer in the documentation and/or
|
12
|
+
other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
15
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
16
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
18
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
19
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
20
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
21
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
22
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
23
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
Description
|
2
|
+
===========
|
3
|
+
|
4
|
+
Quirk is a command line utility for tracking good and bad habits.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
============
|
8
|
+
|
9
|
+
% gem install quirk
|
10
|
+
|
11
|
+
Then configure your habits in a plaintext file:
|
12
|
+
|
13
|
+
% quirk -e
|
14
|
+
mile-run: monday, wednesday, thursday
|
15
|
+
walk-dog: everyday
|
16
|
+
^quit-tv: friday
|
17
|
+
|
18
|
+
If a habit is prefixed with `^`, it means you're trying to break that habit.
|
19
|
+
In this case you're trying to quit TV on Fridays.
|
20
|
+
|
21
|
+
By default, all this does is edit the `~/.quirk` file. You can configure
|
22
|
+
which file to use by setting the environment variable `QUIRKFILE`.
|
23
|
+
|
24
|
+
Usage
|
25
|
+
=====
|
26
|
+
|
27
|
+
When you've done something, mark it with:
|
28
|
+
|
29
|
+
% quirk -m mile-run
|
30
|
+
|
31
|
+
To see a single habit (green days are good, red is bad):
|
32
|
+
|
33
|
+
% quirk -c mile-run
|
34
|
+
Jan 2012
|
35
|
+
Su Mo Tu We Th Fr Sa
|
36
|
+
1 2 3 4 5 6 7
|
37
|
+
8 9 10 11 12 13 14
|
38
|
+
15 16 17 18 19 20 21
|
39
|
+
22 23 24 25 26 27 28
|
40
|
+
29 30 31
|
41
|
+
|
42
|
+
Looking for a specific year?
|
43
|
+
|
44
|
+
% quirk mile-run -y 2011
|
45
|
+
|
46
|
+
See all of your current streaks:
|
47
|
+
|
48
|
+
% quirk -s
|
49
|
+
17 mile-run
|
50
|
+
3 walk-dog
|
51
|
+
-3 quit-tv
|
52
|
+
|
53
|
+
Habits are stored in plaintext in `~/.quirk`. You can use `quirk -e` to
|
54
|
+
add/remove entries. Note that habits start on the day of the first mark
|
55
|
+
by default. You can also specify the first day using `^`:
|
56
|
+
|
57
|
+
2012/01/01 walk-dog
|
58
|
+
2012/01/01 ^quit-tv
|
59
|
+
|
60
|
+
The first line means you walked the dog on `1/1`. The second line means you
|
61
|
+
started the habit of quitting TV. This is especailly handy for starting
|
62
|
+
quitting habits on a green day.
|
63
|
+
|
64
|
+
Zsh Tab Completion
|
65
|
+
==================
|
66
|
+
|
67
|
+
Here's an example zsh completion function:
|
68
|
+
|
69
|
+
#compdef quirk
|
70
|
+
compadd `quirk -l`
|
71
|
+
|
72
|
+
Put this into your `site-functions` directory (wherever `$fpath` points to):
|
73
|
+
|
74
|
+
% echo $fpath
|
75
|
+
/usr/share/zsh/site-functions /usr/share/zsh/4.3.11/functions
|
76
|
+
% sudo vim /usr/share/zsh/site-functions/_quirk
|
77
|
+
|
78
|
+
License
|
79
|
+
=======
|
80
|
+
|
81
|
+
Copyright 2012 Hugh Bien - http://hughbien.com.
|
82
|
+
Released under BSD License, see LICENSE.md for more info.
|
data/quirk
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require File.expand_path('quirk', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
ARGV.options do |o|
|
6
|
+
begin
|
7
|
+
app = Quirk::App.new
|
8
|
+
action = nil
|
9
|
+
o.set_summary_indent(' ')
|
10
|
+
o.banner = "Usage: #{File.basename($0)} [OPTION]"
|
11
|
+
o.define_head "Track good and bad habits (v#{Quirk::VERSION})"
|
12
|
+
o.on('-c', '--calendar habit', 'show calendar') { |h| action = [:calendar, h] }
|
13
|
+
o.on('-e', '--edit', 'edit habits') { action = [:edit] }
|
14
|
+
o.on('-l', '--list', 'list habits') { action = [:list] }
|
15
|
+
o.on('-m', '--mark habit', 'mark for today') { |h| action = [:mark, h] }
|
16
|
+
o.on('-s', '--streaks', 'list streaks') { action = [:streaks] }
|
17
|
+
o.on('-y', '--year year', 'set calendar year') { |y| app.year = y }
|
18
|
+
o.on('-h', '--help', 'show this help message') { puts o; exit }
|
19
|
+
o.parse!
|
20
|
+
action.nil? ? puts(o) : app.send(*action)
|
21
|
+
rescue RuntimeError => e
|
22
|
+
puts e.to_s
|
23
|
+
end
|
24
|
+
end
|
data/quirk.rb
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
module Quirk
|
5
|
+
VERSION = '0.0.2'
|
6
|
+
QUIRKFILE = ENV['QUIRKFILE'] || "#{ENV['HOME']}/.quirk"
|
7
|
+
EDITOR = ENV['EDITOR'] || 'vi'
|
8
|
+
|
9
|
+
def self.today
|
10
|
+
@today || Date.today
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.today=(date) # for testing
|
14
|
+
@today = date
|
15
|
+
end
|
16
|
+
|
17
|
+
class App
|
18
|
+
def initialize(quirkfile = QUIRKFILE)
|
19
|
+
@quirkfile = quirkfile
|
20
|
+
end
|
21
|
+
|
22
|
+
def calendar(habit_id)
|
23
|
+
puts cal.output(habit_id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def edit
|
27
|
+
`#{EDITOR} #{QUIRKFILE} < \`tty\` > \`tty\``
|
28
|
+
end
|
29
|
+
|
30
|
+
def list
|
31
|
+
puts cal.list
|
32
|
+
end
|
33
|
+
|
34
|
+
def mark(habit_id)
|
35
|
+
File.open(@quirkfile, 'a') do |file|
|
36
|
+
if cal.has_habit?(habit_id)
|
37
|
+
file.puts("#{Quirk.today.strftime('%Y/%m/%d')} #{habit_id}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def streaks
|
43
|
+
puts cal.streaks
|
44
|
+
end
|
45
|
+
|
46
|
+
def year=(year)
|
47
|
+
raise "Invalid year: #{year}" if year !~ /\d\d\d\d/
|
48
|
+
cal.year = year.to_i
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def cal
|
53
|
+
@cal ||= Calendar.parse(File.read(@quirkfile))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class Habit
|
58
|
+
attr_reader :id, :days, :marks
|
59
|
+
|
60
|
+
def initialize(id, days, quitting)
|
61
|
+
@id, @days, @quitting, @marks = id, days, quitting, []
|
62
|
+
end
|
63
|
+
|
64
|
+
def quitting?
|
65
|
+
!!@quitting
|
66
|
+
end
|
67
|
+
|
68
|
+
def mark!(date)
|
69
|
+
@marks << date
|
70
|
+
@marks.sort
|
71
|
+
end
|
72
|
+
|
73
|
+
def mark_first!(date)
|
74
|
+
@first_date = date
|
75
|
+
end
|
76
|
+
|
77
|
+
def first_date
|
78
|
+
@first_date || @marks.first
|
79
|
+
end
|
80
|
+
|
81
|
+
def color_on(date)
|
82
|
+
hit_color = quitting? ? :light_red : :light_green
|
83
|
+
miss_color = quitting? ? :light_green : :light_red
|
84
|
+
last_date = quitting? ? (Quirk.today + 1) : Quirk.today
|
85
|
+
if @marks.empty? ||
|
86
|
+
date < first_date ||
|
87
|
+
date > last_date ||
|
88
|
+
!days.include?(date.wday)
|
89
|
+
:white
|
90
|
+
elsif @marks.include?(date)
|
91
|
+
hit_color
|
92
|
+
else
|
93
|
+
date == last_date && !quitting? ? :white : miss_color
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def streak
|
98
|
+
return 0 if @marks.empty?
|
99
|
+
|
100
|
+
count = 0
|
101
|
+
deltas = {:light_red => -1, :light_green => 1, :white => 0}
|
102
|
+
date = Quirk.today
|
103
|
+
while date >= first_date && (color = color_on(date)) == :white
|
104
|
+
date -= 1
|
105
|
+
end
|
106
|
+
|
107
|
+
init_color = color
|
108
|
+
while date >= first_date
|
109
|
+
color = color_on(date)
|
110
|
+
break if color != init_color && days.include?(date.wday)
|
111
|
+
date -= 1
|
112
|
+
count += deltas[color]
|
113
|
+
end
|
114
|
+
count
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.parse(line)
|
118
|
+
line.strip!
|
119
|
+
line.gsub!(/\s+/, ' ')
|
120
|
+
|
121
|
+
quitting = line =~ /^\^/
|
122
|
+
line = line[1..-1] if quitting
|
123
|
+
id, days = line.split(':', 2).map(&:strip)
|
124
|
+
self.new(id, parse_days(days), quitting)
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.parse_days(text)
|
128
|
+
originals = text.split(',').map(&:strip)
|
129
|
+
days = []
|
130
|
+
if originals.include?('everyday')
|
131
|
+
(0..6).to_a
|
132
|
+
else
|
133
|
+
%w(sunday monday tuesday wednesday
|
134
|
+
thursday friday saturday).each_with_index do |day, index|
|
135
|
+
days << (index) if originals.include?(day)
|
136
|
+
end
|
137
|
+
days
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class Calendar
|
143
|
+
attr_writer :year
|
144
|
+
|
145
|
+
def initialize(habits)
|
146
|
+
@habits = habits.reduce({}) {|hash,habit| hash[habit.id] = habit; hash}
|
147
|
+
end
|
148
|
+
|
149
|
+
def year
|
150
|
+
@year || Quirk.today.year
|
151
|
+
end
|
152
|
+
|
153
|
+
def has_habit?(habit_id)
|
154
|
+
raise "No habit found: #{habit_id}" if !@habits.has_key?(habit_id)
|
155
|
+
true
|
156
|
+
end
|
157
|
+
|
158
|
+
def output(habit_id)
|
159
|
+
return if !has_habit?(habit_id)
|
160
|
+
habit = @habits[habit_id]
|
161
|
+
months = (1..12).map do |month|
|
162
|
+
first = Date.new(year, month, 1)
|
163
|
+
out = "#{first.strftime(' %b ')}\n"
|
164
|
+
out += "Su Mo Tu We Th Fr Sa\n"
|
165
|
+
out += (" " * first.wday)
|
166
|
+
while first.month == month
|
167
|
+
out += (first..(first + (6 - first.wday))).map do |date|
|
168
|
+
if date.year != year || date.month != month
|
169
|
+
' '
|
170
|
+
else
|
171
|
+
len = date.day.to_s.length
|
172
|
+
"#{' ' * (2 - len)}#{date.day.to_s.colorize(habit.color_on(date))}"
|
173
|
+
end
|
174
|
+
end.join(" ")
|
175
|
+
out += "\n"
|
176
|
+
first += 7 - first.wday
|
177
|
+
end
|
178
|
+
out.split("\n")
|
179
|
+
end
|
180
|
+
out = "#{(' ' * 32)}#{year}\n"
|
181
|
+
index = 0
|
182
|
+
while index < 12
|
183
|
+
line = 0
|
184
|
+
max_line = [months[index], months[index+1], months[index+2]].
|
185
|
+
map(&:length).max
|
186
|
+
while line <= max_line
|
187
|
+
out += "#{months[index][line] || (' ' * 20)} "
|
188
|
+
out += "#{months[index+1][line] || ( ' ' * 20)} "
|
189
|
+
out += "#{months[index+2][line]}\n"
|
190
|
+
line += 1
|
191
|
+
end
|
192
|
+
index += 3
|
193
|
+
end
|
194
|
+
out
|
195
|
+
end
|
196
|
+
|
197
|
+
def list
|
198
|
+
@habits.values.map(&:id).sort.join("\n")
|
199
|
+
end
|
200
|
+
|
201
|
+
def mark!(line)
|
202
|
+
date = Date.parse(line.strip.split(/\s+/)[0])
|
203
|
+
originals = line.strip.split(/\s+/, 2)[1].split(',').map(&:strip)
|
204
|
+
originals.each do |original|
|
205
|
+
if original =~ /^\^\s*/
|
206
|
+
original = original.sub(/^\^\s*/, '')
|
207
|
+
habit = @habits[original] if has_habit?(original)
|
208
|
+
habit.mark_first!(date)
|
209
|
+
elsif has_habit?(original)
|
210
|
+
@habits[original].mark!(date)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def streaks
|
216
|
+
pairs = @habits.values.map do |habit|
|
217
|
+
[habit.streak, habit.id]
|
218
|
+
end.sort_by(&:first)
|
219
|
+
len = pairs.map {|p| p.first.to_s.length}.max
|
220
|
+
pairs.map do |count, id|
|
221
|
+
"#{' ' * (len - count.to_s.length)}#{count} #{id}"
|
222
|
+
end.join("\n")
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.parse(text)
|
226
|
+
marks, habits = [], []
|
227
|
+
text.strip.each_line do |line|
|
228
|
+
if line =~ /^\d\d\d\d\/\d\d?\/\d\d?\s+/
|
229
|
+
marks << line
|
230
|
+
elsif line !~ /^\s*$/
|
231
|
+
habits << Habit.parse(line)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
cal = Calendar.new(habits)
|
235
|
+
marks.each { |mark| cal.mark!(mark) }
|
236
|
+
cal
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
data/quirk_test.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require "#{File.dirname(__FILE__)}/quirk"
|
3
|
+
require 'minitest/autorun'
|
4
|
+
|
5
|
+
Quirk.today = Date.new(2012, 1, 5) # 1 Su, 2 Mo, 3 Tu, 4 We, 5 Th
|
6
|
+
|
7
|
+
class QuirkAppTest < MiniTest::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
@app = Quirk::App.new(File.join(File.dirname(__FILE__), 'quirkfile'))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class QuirkHabitTest < MiniTest::Unit::TestCase
|
14
|
+
def test_parse
|
15
|
+
habit = Quirk::Habit.parse(' running: monday , tuesday, wednesday')
|
16
|
+
assert_equal('running', habit.id)
|
17
|
+
assert_equal([1, 2, 3], habit.days)
|
18
|
+
refute(habit.quitting?)
|
19
|
+
|
20
|
+
habit2 = Quirk::Habit.parse('walk-dog: everyday')
|
21
|
+
assert_equal('walk-dog', habit2.id)
|
22
|
+
assert_equal([0, 1, 2, 3, 4, 5, 6], habit2.days)
|
23
|
+
refute(habit2.quitting?)
|
24
|
+
|
25
|
+
habit3 = Quirk::Habit.parse('^quit-tv: everyday')
|
26
|
+
assert_equal('quit-tv', habit3.id)
|
27
|
+
assert_equal([0, 1, 2, 3, 4, 5, 6], habit3.days)
|
28
|
+
assert(habit3.quitting?)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_color_on
|
32
|
+
habit = Quirk::Habit.parse('running: sunday, monday, wednesday, thursday')
|
33
|
+
habit.mark!(Date.new(2012, 1, 2))
|
34
|
+
habit.mark!(Date.new(2012, 1, 3))
|
35
|
+
assert_equal(:white, habit.color_on(Date.new(2012, 1, 1)))
|
36
|
+
assert_equal(:green, habit.color_on(Date.new(2012, 1, 2)))
|
37
|
+
assert_equal(:white, habit.color_on(Date.new(2012, 1, 3)))
|
38
|
+
assert_equal(:red, habit.color_on(Date.new(2012, 1, 4)))
|
39
|
+
assert_equal(:white, habit.color_on(Date.new(2012, 1, 5)))
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_color_on_quit
|
43
|
+
quit = Quirk::Habit.parse('^quit-tv: sunday, monday, wednesday, thursday')
|
44
|
+
quit.mark!(Date.new(2012, 1, 2))
|
45
|
+
assert_equal(:white, quit.color_on(Date.new(2012, 1, 1)))
|
46
|
+
assert_equal(:red, quit.color_on(Date.new(2012, 1, 2)))
|
47
|
+
assert_equal(:white, quit.color_on(Date.new(2012, 1, 3)))
|
48
|
+
assert_equal(:green, quit.color_on(Date.new(2012, 1, 4)))
|
49
|
+
assert_equal(:green, quit.color_on(Date.new(2012, 1, 5)))
|
50
|
+
|
51
|
+
quit.mark_first!(Date.new(2012, 1, 1))
|
52
|
+
assert_equal(:green, quit.color_on(Date.new(2012, 1, 1)))
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_streak
|
56
|
+
missing = Quirk::Habit.parse('running: everyday')
|
57
|
+
assert_equal(0, missing.streak)
|
58
|
+
|
59
|
+
perfect = Quirk::Habit.parse('running: monday, wednesday')
|
60
|
+
perfect.mark!(Date.new(2012, 1, 2))
|
61
|
+
perfect.mark!(Date.new(2012, 1, 4))
|
62
|
+
assert_equal(2, perfect.streak)
|
63
|
+
|
64
|
+
bad = Quirk::Habit.parse('running: monday, tuesday, wednesday')
|
65
|
+
bad.mark!(Date.new(2012, 1, 1))
|
66
|
+
bad.mark!(Date.new(2012, 1, 2))
|
67
|
+
assert_equal(-2, bad.streak)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_streak_quit
|
71
|
+
missing = Quirk::Habit.parse('^quit-tv: everyday')
|
72
|
+
assert_equal(0, missing.streak)
|
73
|
+
|
74
|
+
perfect = Quirk::Habit.parse('^quit-tv: monday, tuesday')
|
75
|
+
perfect.mark!(Date.new(2011, 12, 31))
|
76
|
+
perfect.mark!(Date.new(2012, 1, 4))
|
77
|
+
assert_equal(2, perfect.streak)
|
78
|
+
|
79
|
+
bad = Quirk::Habit.parse('^quit-tv: sunday, thursday')
|
80
|
+
bad.mark!(Date.new(2012, 1, 1)) # sunday
|
81
|
+
bad.mark!(Date.new(2012, 1, 5)) # thursday
|
82
|
+
assert_equal(-2, bad.streak)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class QuirkCalendarTest < MiniTest::Unit::TestCase
|
87
|
+
def setup
|
88
|
+
@running = Quirk::Habit.parse('running: everyday')
|
89
|
+
@walking = Quirk::Habit.parse('walk-dog: sunday, saturday')
|
90
|
+
@smoking = Quirk::Habit.parse('^smoking: everyday')
|
91
|
+
@cal = Quirk::Calendar.new([@running, @walking, @smoking])
|
92
|
+
@cal.mark!('2012/01/01 ^smoking')
|
93
|
+
@cal.mark!('2012/01/01 running, walk-dog')
|
94
|
+
@cal.mark!('2012/01/02 running, walk-dog')
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_mark
|
98
|
+
assert_equal([Date.new(2012,1,1), Date.new(2012,1,2)], @running.marks)
|
99
|
+
assert_equal([Date.new(2012,1,1), Date.new(2012,1,2)], @walking.marks)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_mark_first
|
103
|
+
assert_equal(Date.new(2012, 1, 1), @smoking.first_date)
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_streaks
|
107
|
+
assert_equal("-2 running\n 0 smoking\n 1 walk-dog", @cal.streaks)
|
108
|
+
end
|
109
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: quirk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Hugh Bien
|
9
|
+
autorequire:
|
10
|
+
bindir: .
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: colorize
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Command line tool for tracking good/bad habits, data stored in plaintext.
|
47
|
+
email:
|
48
|
+
- hugh@hughbien.com
|
49
|
+
executables:
|
50
|
+
- quirk
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- quirk.rb
|
55
|
+
- quirk_test.rb
|
56
|
+
- README.md
|
57
|
+
- LICENSE.md
|
58
|
+
- quirk
|
59
|
+
- ./quirk
|
60
|
+
homepage: https://github.com/hughbien/quirk
|
61
|
+
licenses: []
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.3.6
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.8.23
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: Track good and bad habits
|
84
|
+
test_files: []
|