doing 2.1.11 → 2.1.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/.irbrc +1 -0
- data/.yardoc/checksums +15 -13
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +44 -1
- data/Gemfile.lock +9 -2
- data/README.md +56 -19
- data/bin/doing +215 -76
- data/docs/doc/Array.html +117 -3
- data/docs/doc/BooleanTermParser/Clause.html +1 -1
- data/docs/doc/BooleanTermParser/Operator.html +1 -1
- data/docs/doc/BooleanTermParser/Query.html +1 -1
- data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
- data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
- data/docs/doc/BooleanTermParser.html +1 -1
- data/docs/doc/Doing/Color.html +1 -1
- data/docs/doc/Doing/Completion.html +1 -1
- data/docs/doc/Doing/Configuration.html +7 -4
- data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
- data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
- data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
- data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
- data/docs/doc/Doing/Errors/NoResults.html +1 -1
- data/docs/doc/Doing/Errors/PluginException.html +1 -1
- data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
- data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
- data/docs/doc/Doing/Errors.html +1 -1
- data/docs/doc/Doing/Hooks.html +1 -1
- data/docs/doc/Doing/Item.html +337 -14
- data/docs/doc/Doing/Items.html +66 -2
- data/docs/doc/Doing/LogAdapter.html +1 -1
- data/docs/doc/Doing/Note.html +2 -2
- data/docs/doc/Doing/Pager.html +1 -1
- data/docs/doc/Doing/Plugins.html +1 -1
- data/docs/doc/Doing/Prompt.html +35 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/TemplateString.html +2 -2
- data/docs/doc/Doing/Util/Backup.html +84 -1
- data/docs/doc/Doing/Util.html +1 -1
- data/docs/doc/Doing/WWID.html +180 -35
- data/docs/doc/Doing.html +3 -3
- data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
- data/docs/doc/GLI/Commands.html +1 -1
- data/docs/doc/GLI.html +1 -1
- data/docs/doc/Hash.html +1 -1
- data/docs/doc/Numeric.html +279 -0
- data/docs/doc/PhraseParser/Operator.html +1 -1
- data/docs/doc/PhraseParser/PhraseClause.html +1 -1
- data/docs/doc/PhraseParser/Query.html +1 -1
- data/docs/doc/PhraseParser/QueryParser.html +1 -1
- data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
- data/docs/doc/PhraseParser/TermClause.html +1 -1
- data/docs/doc/PhraseParser.html +1 -1
- data/docs/doc/Status.html +1 -1
- data/docs/doc/String.html +767 -115
- data/docs/doc/Symbol.html +1 -1
- data/docs/doc/Time.html +1 -1
- data/docs/doc/_index.html +14 -9
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +41 -15
- data/docs/doc/index.html +41 -15
- data/docs/doc/method_list.html +407 -279
- data/docs/doc/top-level-namespace.html +2 -2
- data/docs/index.md +56 -19
- data/doing.gemspec +2 -0
- data/doing.rdoc +244 -45
- data/example_plugin.rb +2 -4
- data/lib/completion/_doing.zsh +31 -27
- data/lib/completion/doing.bash +50 -39
- data/lib/completion/doing.fish +35 -6
- data/lib/doing/array_chronify.rb +57 -0
- data/lib/doing/configuration.rb +4 -1
- data/lib/doing/item.rb +176 -0
- data/lib/doing/log_adapter.rb +1 -1
- data/lib/doing/numeric_chronify.rb +40 -0
- data/lib/doing/plugins/export/dayone_export.rb +1 -1
- data/lib/doing/plugins/export/json_export.rb +2 -2
- data/lib/doing/plugins/export/template_export.rb +47 -90
- data/lib/doing/plugins/import/calendar_import.rb +13 -1
- data/lib/doing/plugins/import/doing_import.rb +12 -1
- data/lib/doing/plugins/import/timing_import.rb +13 -1
- data/lib/doing/prompt.rb +13 -1
- data/lib/doing/string.rb +97 -33
- data/lib/doing/string_chronify.rb +83 -13
- data/lib/doing/time.rb +6 -6
- data/lib/doing/util_backup.rb +1 -1
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +88 -93
- data/lib/doing.rb +31 -27
- data/lib/examples/plugins/say_export.rb +1 -4
- metadata +46 -2
data/lib/doing/wwid.rb
CHANGED
|
@@ -185,34 +185,9 @@ module Doing
|
|
|
185
185
|
|
|
186
186
|
date = nil
|
|
187
187
|
iso_rx = /\d{4}-\d\d-\d\d \d\d:\d\d/
|
|
188
|
-
watch_tags = [
|
|
189
|
-
'start(?:ed)?',
|
|
190
|
-
'beg[ia]n',
|
|
191
|
-
'done',
|
|
192
|
-
'finished',
|
|
193
|
-
'completed?',
|
|
194
|
-
'waiting',
|
|
195
|
-
'defer(?:red)?'
|
|
196
|
-
]
|
|
197
|
-
if @config['date_tags']
|
|
198
|
-
date_tags = @config['date_tags']
|
|
199
|
-
date_tags = date_tags.split(/ *, */) if date_tags.is_a?(String)
|
|
200
|
-
date_tags.map! do |tag|
|
|
201
|
-
tag.sub(/^@/, '').gsub(/\((?!\?:)(.*?)\)/, '(?:\1)').strip
|
|
202
|
-
end
|
|
203
|
-
watch_tags.concat(date_tags).uniq!
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
done_rx = /(?<=^| )@(?<tag>#{watch_tags.join('|')})\((?<date>.*?)\)/i
|
|
207
188
|
date_rx = /^(?:\s*- )?(?<date>.*?) \| (?=\S)/
|
|
208
189
|
|
|
209
|
-
title.
|
|
210
|
-
m = Regexp.last_match
|
|
211
|
-
t = m['tag']
|
|
212
|
-
d = m['date']
|
|
213
|
-
parsed_date = d =~ date_rx ? Time.parse(d) : d.chronify(guess: :begin)
|
|
214
|
-
parsed_date.nil? ? m[0] : "@#{t}(#{parsed_date.strftime('%F %R')})"
|
|
215
|
-
end
|
|
190
|
+
title.expand_date_tags(@config['date_tags'])
|
|
216
191
|
|
|
217
192
|
if title =~ date_rx
|
|
218
193
|
m = title.match(date_rx)
|
|
@@ -369,7 +344,8 @@ module Doing
|
|
|
369
344
|
items.each_with_index do |i, x|
|
|
370
345
|
next if i.title =~ / @done/
|
|
371
346
|
|
|
372
|
-
|
|
347
|
+
finish_date = verify_duration(i.date, opt[:back], title: i.title)
|
|
348
|
+
items[x].tag('done', value: finish_date.strftime('%F %R'))
|
|
373
349
|
break
|
|
374
350
|
end
|
|
375
351
|
end
|
|
@@ -384,10 +360,13 @@ module Doing
|
|
|
384
360
|
end
|
|
385
361
|
|
|
386
362
|
##
|
|
387
|
-
## Remove items from
|
|
363
|
+
## Remove items from an array that already exist in
|
|
364
|
+
## @content based on start and end times
|
|
388
365
|
##
|
|
389
|
-
## @param items [Array] The items to
|
|
390
|
-
##
|
|
366
|
+
## @param items [Array] The items to
|
|
367
|
+
## deduplicate
|
|
368
|
+
## @param no_overlap [Boolean] Remove items with
|
|
369
|
+
## overlapping time spans
|
|
391
370
|
##
|
|
392
371
|
def dedup(items, no_overlap: false)
|
|
393
372
|
items.delete_if do |item|
|
|
@@ -640,6 +619,7 @@ module Doing
|
|
|
640
619
|
## @option opt [Boolean] :yesterday (false) limit to entries from yesterday
|
|
641
620
|
## @option opt [Number] :count (0) max entries to return
|
|
642
621
|
## @option opt [String] :age (new) 'old' or 'new'
|
|
622
|
+
## @option opt [Array] :val (nil) Array of tag value queries
|
|
643
623
|
##
|
|
644
624
|
def filter_items(items = Items.new, opt: {})
|
|
645
625
|
time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/
|
|
@@ -701,6 +681,16 @@ module Doing
|
|
|
701
681
|
keep = false if finished
|
|
702
682
|
end
|
|
703
683
|
|
|
684
|
+
if keep && opt[:val]&.count&.positive?
|
|
685
|
+
bool = opt[:bool].normalize_bool if opt[:bool]
|
|
686
|
+
bool ||= :and
|
|
687
|
+
bool = :and if bool == :pattern
|
|
688
|
+
|
|
689
|
+
val_match = opt[:val].nil? || opt[:val].empty? ? true : item.tag_values?(opt[:val], bool)
|
|
690
|
+
keep = false unless val_match
|
|
691
|
+
keep = opt[:not] ? !keep : keep
|
|
692
|
+
end
|
|
693
|
+
|
|
704
694
|
if keep && opt[:tag]
|
|
705
695
|
opt[:tag_bool] = opt[:bool].normalize_bool if opt[:bool]
|
|
706
696
|
opt[:tag_bool] ||= :and
|
|
@@ -883,11 +873,11 @@ module Doing
|
|
|
883
873
|
opt[:search] = search
|
|
884
874
|
end
|
|
885
875
|
|
|
886
|
-
opt[:query] = opt[:search] if opt[:search] && !opt[:query]
|
|
887
|
-
opt[:query] = "!#{opt[:query]}" if opt[:not]
|
|
876
|
+
# opt[:query] = opt[:search] if opt[:search] && !opt[:query]
|
|
877
|
+
opt[:query] = "!#{opt[:query]}" if opt[:query] && opt[:not]
|
|
888
878
|
opt[:multiple] = true
|
|
889
879
|
opt[:show_if_single] = true
|
|
890
|
-
filter_options = %i[after before case date_filter from fuzzy not search section].each_with_object({}) {
|
|
880
|
+
filter_options = %i[after before case date_filter from fuzzy not search section val].each_with_object({}) {
|
|
891
881
|
|k, hsh| hsh[k] = opt[k]
|
|
892
882
|
}
|
|
893
883
|
items = filter_items(Items.new, opt: filter_options)
|
|
@@ -987,7 +977,7 @@ module Doing
|
|
|
987
977
|
'--no-sort',
|
|
988
978
|
'--info=hidden'
|
|
989
979
|
])
|
|
990
|
-
next if
|
|
980
|
+
next if output_format =~ /^ *$/
|
|
991
981
|
|
|
992
982
|
raise UserCancelled unless output_format
|
|
993
983
|
|
|
@@ -1075,6 +1065,7 @@ module Doing
|
|
|
1075
1065
|
tag = opt[:tag]
|
|
1076
1066
|
items.map! do |i|
|
|
1077
1067
|
i.tag(tag, date: false, remove: opt[:remove], single: single)
|
|
1068
|
+
i.expand_date_tags(@config['date_tags'])
|
|
1078
1069
|
Hooks.trigger :post_entry_updated, self, i
|
|
1079
1070
|
end
|
|
1080
1071
|
end
|
|
@@ -1134,6 +1125,26 @@ module Doing
|
|
|
1134
1125
|
end
|
|
1135
1126
|
end
|
|
1136
1127
|
|
|
1128
|
+
def verify_duration(date, finish_date, title: nil)
|
|
1129
|
+
max_elapsed = @config.dig('interaction', 'confirm_longer_than') || 0
|
|
1130
|
+
max_elapsed = max_elapsed.chronify_qty if max_elapsed.is_a?(String)
|
|
1131
|
+
elapsed = finish_date - date
|
|
1132
|
+
|
|
1133
|
+
if max_elapsed.positive? && (elapsed > max_elapsed)
|
|
1134
|
+
puts boldwhite(title) if title
|
|
1135
|
+
human = elapsed.time_string(format: :natural)
|
|
1136
|
+
res = Prompt.yn(yellow("Did this entry actually take #{human}"), default_response: true)
|
|
1137
|
+
unless res
|
|
1138
|
+
new_elapsed = Prompt.enter_text('How long did it take?').chronify_qty
|
|
1139
|
+
raise InvalidTimeExpression, 'Unrecognized time span entry' unless new_elapsed.positive?
|
|
1140
|
+
|
|
1141
|
+
finish_date = date + new_elapsed if new_elapsed
|
|
1142
|
+
end
|
|
1143
|
+
end
|
|
1144
|
+
|
|
1145
|
+
finish_date
|
|
1146
|
+
end
|
|
1147
|
+
|
|
1137
1148
|
##
|
|
1138
1149
|
## Tag the last entry or X entries
|
|
1139
1150
|
##
|
|
@@ -1195,21 +1206,8 @@ module Doing
|
|
|
1195
1206
|
else
|
|
1196
1207
|
next_entry.date - 60
|
|
1197
1208
|
end
|
|
1198
|
-
elsif opt[:took]
|
|
1199
|
-
if item.date + opt[:took] > Time.now
|
|
1200
|
-
item.date = Time.now - opt[:took]
|
|
1201
|
-
done_date = Time.now
|
|
1202
|
-
else
|
|
1203
|
-
done_date = item.date + opt[:took]
|
|
1204
|
-
end
|
|
1205
|
-
elsif opt[:back]
|
|
1206
|
-
done_date = if opt[:back].is_a? Integer
|
|
1207
|
-
item.date + opt[:back]
|
|
1208
|
-
else
|
|
1209
|
-
item.date + (opt[:back] - item.date)
|
|
1210
|
-
end
|
|
1211
1209
|
else
|
|
1212
|
-
done_date =
|
|
1210
|
+
done_date = item.calculate_end_date(opt)
|
|
1213
1211
|
end
|
|
1214
1212
|
|
|
1215
1213
|
opt[:tags].each do |tag|
|
|
@@ -1220,15 +1218,39 @@ module Doing
|
|
|
1220
1218
|
next
|
|
1221
1219
|
end
|
|
1222
1220
|
|
|
1221
|
+
|
|
1223
1222
|
tag = tag.strip
|
|
1224
|
-
|
|
1223
|
+
|
|
1224
|
+
if tag =~ /^done$/
|
|
1225
|
+
max_elapsed = @config.dig('interaction', 'confirm_longer_than') || 0
|
|
1226
|
+
max_elapsed = max_elapsed.chronify_qty if max_elapsed.is_a?(String)
|
|
1227
|
+
elapsed = done_date - item.date
|
|
1228
|
+
|
|
1229
|
+
if max_elapsed.positive? && (elapsed > max_elapsed) && !opt[:took]
|
|
1230
|
+
puts boldwhite(item.title)
|
|
1231
|
+
human = elapsed.time_string(format: :natural)
|
|
1232
|
+
res = Prompt.yn(yellow("Did this actually take #{human}"), default_response: true)
|
|
1233
|
+
unless res
|
|
1234
|
+
new_elapsed = Prompt.enter_text('How long did it take?').chronify_qty
|
|
1235
|
+
raise InvalidTimeExpression, 'Unrecognized time span entry' unless new_elapsed > 0
|
|
1236
|
+
|
|
1237
|
+
opt[:took] = new_elapsed
|
|
1238
|
+
done_date = item.calculate_end_date(opt) if opt[:took]
|
|
1239
|
+
end
|
|
1240
|
+
end
|
|
1241
|
+
end
|
|
1242
|
+
|
|
1243
|
+
if opt[:remove] || opt[:rename] || opt[:value]
|
|
1225
1244
|
rename_to = nil
|
|
1226
|
-
if opt[:
|
|
1245
|
+
if opt[:value]
|
|
1246
|
+
rename_to = tag
|
|
1247
|
+
elsif opt[:rename]
|
|
1227
1248
|
rename_to = tag
|
|
1228
1249
|
tag = opt[:rename]
|
|
1229
1250
|
end
|
|
1230
1251
|
old_title = item.title.dup
|
|
1231
|
-
|
|
1252
|
+
force = opt[:value].nil? ? false : true
|
|
1253
|
+
item.title.tag!(tag, remove: opt[:remove], rename_to: rename_to, regex: opt[:regex], value: opt[:value], force: force)
|
|
1232
1254
|
if old_title != item.title
|
|
1233
1255
|
removed << tag
|
|
1234
1256
|
added << rename_to if rename_to
|
|
@@ -1255,6 +1277,7 @@ module Doing
|
|
|
1255
1277
|
logger.warn('Skipped:', 'Archiving is skipped when operating on all entries')
|
|
1256
1278
|
end
|
|
1257
1279
|
|
|
1280
|
+
item.expand_date_tags(@config['date_tags'])
|
|
1258
1281
|
Hooks.trigger :post_entry_updated, self, item
|
|
1259
1282
|
end
|
|
1260
1283
|
|
|
@@ -1823,7 +1846,8 @@ module Doing
|
|
|
1823
1846
|
case: options[:case],
|
|
1824
1847
|
not: options[:negate],
|
|
1825
1848
|
config_template: 'last',
|
|
1826
|
-
delete: options[:delete]
|
|
1849
|
+
delete: options[:delete],
|
|
1850
|
+
val: options[:val]
|
|
1827
1851
|
}
|
|
1828
1852
|
|
|
1829
1853
|
if options[:tag]
|
|
@@ -1987,7 +2011,7 @@ module Doing
|
|
|
1987
2011
|
EOS
|
|
1988
2012
|
sorted_tags_data.reverse.each do |k, v|
|
|
1989
2013
|
if v > 0
|
|
1990
|
-
output += "<tr><td style='text-align:left;'>#{k}</td><td style='text-align:left;'>#{
|
|
2014
|
+
output += "<tr><td style='text-align:left;'>#{k}</td><td style='text-align:left;'>#{v.time_string(format: :clock)}</td></tr>\n"
|
|
1991
2015
|
end
|
|
1992
2016
|
end
|
|
1993
2017
|
tail = <<EOS
|
|
@@ -1998,7 +2022,7 @@ EOS
|
|
|
1998
2022
|
<tfoot>
|
|
1999
2023
|
<tr>
|
|
2000
2024
|
<td style="text-align:left;"><strong>Total</strong></td>
|
|
2001
|
-
<td style="text-align:left;">#{
|
|
2025
|
+
<td style="text-align:left;">#{total.time_string(format: :clock)}</td>
|
|
2002
2026
|
</tr>
|
|
2003
2027
|
</tfoot>
|
|
2004
2028
|
</table>
|
|
@@ -2013,7 +2037,7 @@ EOS
|
|
|
2013
2037
|
EOS
|
|
2014
2038
|
sorted_tags_data.reverse.each do |k, v|
|
|
2015
2039
|
if v > 0
|
|
2016
|
-
output += "| #{' ' * (pad - k.length)}#{k} | #{
|
|
2040
|
+
output += "| #{' ' * (pad - k.length)}#{k} | #{v.time_string(format: :clock)} |\n"
|
|
2017
2041
|
end
|
|
2018
2042
|
end
|
|
2019
2043
|
tail = "[Tag Totals]"
|
|
@@ -2021,11 +2045,10 @@ EOS
|
|
|
2021
2045
|
when :json
|
|
2022
2046
|
output = []
|
|
2023
2047
|
sorted_tags_data.reverse.each do |k, v|
|
|
2024
|
-
d, h, m = format_time(v)
|
|
2025
2048
|
output << {
|
|
2026
2049
|
'tag' => k,
|
|
2027
2050
|
'seconds' => v,
|
|
2028
|
-
'formatted' => format
|
|
2051
|
+
'formatted' => v.time_string(format: :clock)
|
|
2029
2052
|
}
|
|
2030
2053
|
end
|
|
2031
2054
|
output
|
|
@@ -2036,8 +2059,7 @@ EOS
|
|
|
2036
2059
|
(max - k.length).times do
|
|
2037
2060
|
spacer += ' '
|
|
2038
2061
|
end
|
|
2039
|
-
|
|
2040
|
-
output.push("┃ #{spacer}#{k}:#{format('%<h> 4dh %<m>02dm', h: h, m: m)} ┃")
|
|
2062
|
+
output.push("┃ #{spacer}#{k}:#{v.time_string(format: :hm)} ┃")
|
|
2041
2063
|
end
|
|
2042
2064
|
|
|
2043
2065
|
header = '┏━━ Tag Totals '
|
|
@@ -2050,14 +2072,14 @@ EOS
|
|
|
2050
2072
|
(max + 12).times { divider += '━' }
|
|
2051
2073
|
divider += '┫'
|
|
2052
2074
|
output = output.empty? ? '' : "\n#{header}\n#{output.join("\n")}"
|
|
2053
|
-
d, h, m = format_time(total, human: true)
|
|
2054
2075
|
output += "\n#{divider}"
|
|
2055
2076
|
spacer = ''
|
|
2056
2077
|
(max - 6).times do
|
|
2057
2078
|
spacer += ' '
|
|
2058
2079
|
end
|
|
2080
|
+
total_time = total.time_string(format: :hm)
|
|
2059
2081
|
total = "┃ #{spacer}total: "
|
|
2060
|
-
total +=
|
|
2082
|
+
total += total_time
|
|
2061
2083
|
total += ' ┃'
|
|
2062
2084
|
output += "\n#{total}"
|
|
2063
2085
|
output += "\n#{footer}"
|
|
@@ -2069,13 +2091,11 @@ EOS
|
|
|
2069
2091
|
(max - k.length).times do
|
|
2070
2092
|
spacer += ' '
|
|
2071
2093
|
end
|
|
2072
|
-
|
|
2073
|
-
output.push("#{k}:#{spacer}#{format('%<d>02d:%<h>02d:%<m>02d', d: d, h: h, m: m)}")
|
|
2094
|
+
output.push("#{k}:#{spacer}#{v.time_string(format: :clock)}")
|
|
2074
2095
|
end
|
|
2075
2096
|
|
|
2076
2097
|
output = output.empty? ? '' : "\n--- Tag Totals ---\n#{output.join("\n")}"
|
|
2077
|
-
|
|
2078
|
-
output += "\n\nTotal tracked: #{format('%<d>02d:%<h>02d:%<m>02d', d: d, h: h, m: m)}\n"
|
|
2098
|
+
output += "\n\nTotal tracked: #{total.time_string(format: :clock)}\n"
|
|
2079
2099
|
output
|
|
2080
2100
|
end
|
|
2081
2101
|
end
|
|
@@ -2100,39 +2120,12 @@ EOS
|
|
|
2100
2120
|
record_tag_times(item, seconds) if record
|
|
2101
2121
|
return seconds.positive? ? seconds : false unless formatted
|
|
2102
2122
|
|
|
2103
|
-
return seconds.positive? ? format
|
|
2123
|
+
return seconds.positive? ? seconds.time_string(format: :clock) : false
|
|
2104
2124
|
end
|
|
2105
2125
|
|
|
2106
2126
|
false
|
|
2107
2127
|
end
|
|
2108
2128
|
|
|
2109
|
-
##
|
|
2110
|
-
## Format human readable time from seconds
|
|
2111
|
-
##
|
|
2112
|
-
## @param seconds [Integer] Seconds
|
|
2113
|
-
##
|
|
2114
|
-
def format_time(seconds, human: false)
|
|
2115
|
-
return [0, 0, 0] if seconds.nil?
|
|
2116
|
-
|
|
2117
|
-
if seconds.instance_of?(String) && seconds =~ /(\d+):(\d+):(\d+)/
|
|
2118
|
-
h = Regexp.last_match(1)
|
|
2119
|
-
m = Regexp.last_match(2)
|
|
2120
|
-
s = Regexp.last_match(3)
|
|
2121
|
-
seconds = (h.to_i * 60 * 60) + (m.to_i * 60) + s.to_i
|
|
2122
|
-
end
|
|
2123
|
-
minutes = (seconds / 60).to_i
|
|
2124
|
-
hours = (minutes / 60).to_i
|
|
2125
|
-
if human
|
|
2126
|
-
minutes = (minutes % 60).to_i
|
|
2127
|
-
[0, hours, minutes]
|
|
2128
|
-
else
|
|
2129
|
-
days = (hours / 24).to_i
|
|
2130
|
-
hours = (hours % 24).to_i
|
|
2131
|
-
minutes = (minutes % 60).to_i
|
|
2132
|
-
[days, hours, minutes]
|
|
2133
|
-
end
|
|
2134
|
-
end
|
|
2135
|
-
|
|
2136
2129
|
def configure(filename = nil)
|
|
2137
2130
|
if filename
|
|
2138
2131
|
Doing.config_with(filename, { ignore_local: true })
|
|
@@ -2212,6 +2205,8 @@ EOS
|
|
|
2212
2205
|
break
|
|
2213
2206
|
end
|
|
2214
2207
|
|
|
2208
|
+
logger.debug('Output:', "#{items.count} #{items.count == 1 ? 'item' : 'items'} shown")
|
|
2209
|
+
|
|
2215
2210
|
out
|
|
2216
2211
|
end
|
|
2217
2212
|
|
data/lib/doing.rb
CHANGED
|
@@ -9,42 +9,46 @@ require 'csv'
|
|
|
9
9
|
require 'tempfile'
|
|
10
10
|
require 'zlib'
|
|
11
11
|
require 'base64'
|
|
12
|
+
require 'plist'
|
|
12
13
|
|
|
13
14
|
require 'chronic'
|
|
14
15
|
require 'tty-link'
|
|
15
16
|
require 'tty-which'
|
|
16
17
|
require 'tty-markdown'
|
|
17
|
-
require '
|
|
18
|
-
|
|
18
|
+
require 'tty-reader'
|
|
19
|
+
require 'tty-screen'
|
|
19
20
|
require 'haml'
|
|
20
21
|
require 'json'
|
|
21
22
|
require 'logger'
|
|
22
23
|
require 'safe_yaml/load'
|
|
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
|
-
|
|
24
|
+
|
|
25
|
+
require_relative 'doing/hash'
|
|
26
|
+
require_relative 'doing/colors'
|
|
27
|
+
require_relative 'doing/template_string'
|
|
28
|
+
require_relative 'doing/string'
|
|
29
|
+
require_relative 'doing/time'
|
|
30
|
+
require_relative 'doing/array'
|
|
31
|
+
require_relative 'doing/symbol'
|
|
32
|
+
require_relative 'doing/util'
|
|
33
|
+
require_relative 'doing/util_backup'
|
|
34
|
+
require_relative 'doing/configuration'
|
|
35
|
+
require_relative 'doing/section'
|
|
36
|
+
require_relative 'doing/items'
|
|
37
|
+
require_relative 'doing/note'
|
|
38
|
+
require_relative 'doing/item'
|
|
39
|
+
require_relative 'doing/wwid'
|
|
40
|
+
require_relative 'doing/log_adapter'
|
|
41
|
+
require_relative 'doing/prompt'
|
|
42
|
+
require_relative 'doing/errors'
|
|
43
|
+
require_relative 'doing/hooks'
|
|
44
|
+
require_relative 'doing/plugin_manager'
|
|
45
|
+
require_relative 'doing/pager'
|
|
46
|
+
require_relative 'doing/completion'
|
|
47
|
+
require_relative 'doing/boolean_term_parser'
|
|
48
|
+
require_relative 'doing/phrase_parser'
|
|
49
|
+
require_relative 'doing/array_chronify'
|
|
50
|
+
require_relative 'doing/numeric_chronify'
|
|
51
|
+
require_relative 'doing/string_chronify'
|
|
48
52
|
# require 'doing/markdown_document_listener'
|
|
49
53
|
|
|
50
54
|
# Main doing module
|
|
@@ -149,11 +149,8 @@ module Doing
|
|
|
149
149
|
finished_at = i.end_date
|
|
150
150
|
took += finished_at.strftime('%A %B %e at %I:%M%p')
|
|
151
151
|
|
|
152
|
-
d, h, m = wwid.format_time(interval)
|
|
153
152
|
took += ' and it took'
|
|
154
|
-
took +=
|
|
155
|
-
took += " #{h.to_i} hours" if h.to_i.positive?
|
|
156
|
-
took += " #{m.to_i} minutes" if m.to_i.positive?
|
|
153
|
+
took += interval.time_string(format: :natural)
|
|
157
154
|
end
|
|
158
155
|
end
|
|
159
156
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: doing
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.1.
|
|
4
|
+
version: 2.1.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brett Terpstra
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-01-
|
|
11
|
+
date: 2022-01-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: safe_yaml
|
|
@@ -346,6 +346,46 @@ dependencies:
|
|
|
346
346
|
- - ">="
|
|
347
347
|
- !ruby/object:Gem::Version
|
|
348
348
|
version: 0.7.0
|
|
349
|
+
- !ruby/object:Gem::Dependency
|
|
350
|
+
name: tty-reader
|
|
351
|
+
requirement: !ruby/object:Gem::Requirement
|
|
352
|
+
requirements:
|
|
353
|
+
- - "~>"
|
|
354
|
+
- !ruby/object:Gem::Version
|
|
355
|
+
version: '0.9'
|
|
356
|
+
- - ">="
|
|
357
|
+
- !ruby/object:Gem::Version
|
|
358
|
+
version: 0.9.0
|
|
359
|
+
type: :runtime
|
|
360
|
+
prerelease: false
|
|
361
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
362
|
+
requirements:
|
|
363
|
+
- - "~>"
|
|
364
|
+
- !ruby/object:Gem::Version
|
|
365
|
+
version: '0.9'
|
|
366
|
+
- - ">="
|
|
367
|
+
- !ruby/object:Gem::Version
|
|
368
|
+
version: 0.9.0
|
|
369
|
+
- !ruby/object:Gem::Dependency
|
|
370
|
+
name: tty-screen
|
|
371
|
+
requirement: !ruby/object:Gem::Requirement
|
|
372
|
+
requirements:
|
|
373
|
+
- - "~>"
|
|
374
|
+
- !ruby/object:Gem::Version
|
|
375
|
+
version: '0.8'
|
|
376
|
+
- - ">="
|
|
377
|
+
- !ruby/object:Gem::Version
|
|
378
|
+
version: 0.8.1
|
|
379
|
+
type: :runtime
|
|
380
|
+
prerelease: false
|
|
381
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
382
|
+
requirements:
|
|
383
|
+
- - "~>"
|
|
384
|
+
- !ruby/object:Gem::Version
|
|
385
|
+
version: '0.8'
|
|
386
|
+
- - ">="
|
|
387
|
+
- !ruby/object:Gem::Version
|
|
388
|
+
version: 0.8.1
|
|
349
389
|
- !ruby/object:Gem::Dependency
|
|
350
390
|
name: parslet
|
|
351
391
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -396,6 +436,7 @@ extensions: []
|
|
|
396
436
|
extra_rdoc_files:
|
|
397
437
|
- README.md
|
|
398
438
|
files:
|
|
439
|
+
- ".irbrc"
|
|
399
440
|
- ".yardoc/checksums"
|
|
400
441
|
- ".yardoc/complete"
|
|
401
442
|
- ".yardoc/object_types"
|
|
@@ -457,6 +498,7 @@ files:
|
|
|
457
498
|
- docs/doc/GLI/Commands.html
|
|
458
499
|
- docs/doc/GLI/Commands/MarkdownDocumentListener.html
|
|
459
500
|
- docs/doc/Hash.html
|
|
501
|
+
- docs/doc/Numeric.html
|
|
460
502
|
- docs/doc/PhraseParser.html
|
|
461
503
|
- docs/doc/PhraseParser/Operator.html
|
|
462
504
|
- docs/doc/PhraseParser/PhraseClause.html
|
|
@@ -495,6 +537,7 @@ files:
|
|
|
495
537
|
- lib/completion/doing.fish
|
|
496
538
|
- lib/doing.rb
|
|
497
539
|
- lib/doing/array.rb
|
|
540
|
+
- lib/doing/array_chronify.rb
|
|
498
541
|
- lib/doing/boolean_term_parser.rb
|
|
499
542
|
- lib/doing/cli_status.rb
|
|
500
543
|
- lib/doing/colors.rb
|
|
@@ -512,6 +555,7 @@ files:
|
|
|
512
555
|
- lib/doing/log_adapter.rb
|
|
513
556
|
- lib/doing/markdown_document_listener.rb
|
|
514
557
|
- lib/doing/note.rb
|
|
558
|
+
- lib/doing/numeric_chronify.rb
|
|
515
559
|
- lib/doing/pager.rb
|
|
516
560
|
- lib/doing/phrase_parser.rb
|
|
517
561
|
- lib/doing/plugin_manager.rb
|