doing 0.2.5 → 1.0.0pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a4645c47a272a4fdf45174b2adff019820ed1537
4
- data.tar.gz: 444fa7c255629e9f9e5f1b357c28b0fd2ac3e8c3
3
+ metadata.gz: 74966c0e6ac08312d5b1ebb980795e47a19ae278
4
+ data.tar.gz: 746b50bfae984c7f95e3b64a7bb095a185d2208e
5
5
  SHA512:
6
- metadata.gz: 4b8872bc854b897c25737f79f50ab86ec91f48b5b64118cc121c463c0782738070150b06ef8a9e076b5a9bdf5922f94a5d45db35166f80af8cf0fc63f9e51519
7
- data.tar.gz: 4ed502a4de7165e67a5cc41d4737f069ececd82e64efa8af092d0c847b32ca1e99151ec7071945dace041277208411c0e0b36bdfc6a468330bb14a60b3660e87
6
+ metadata.gz: 7968dfa76f2c4b6aef6a8ae098f86df6286d5968330a1cebb471d1d13978c5ccfe1aa0bbda49e2bc74af83cadd7aae37197719f33b4336f51d25bc6f001c8ff1
7
+ data.tar.gz: 5fcf33fccaa418ba41c5f1c79515bb341024b9363a95adc07b7479163bd4eb5de96912d8c0b9994d4e6d6bdd0649ff8baf82628f996040ee993d90b8099b08bd
data/README.md CHANGED
@@ -263,11 +263,13 @@ Outputs:
263
263
  done - Add a completed item with @done(date). No argument finishes last entry.
264
264
  meanwhile - Finish any @meanwhile tasks and optionally create a new one
265
265
 
266
- The `doing now` command can accept `-s section_name` to send the new entry straight to a non-default section.
266
+ The `doing now` command can accept `-s section_name` to send the new entry straight to a non-default section. It also accepts `--back AMOUNT` to let you specify a start date in the past using "natural language." For example, `doing now --back 25m ENTRY` or `doing now --back "yesterday 3:30pm" ENTRY`.
267
+
268
+ You can finish the last unfinished task when starting a new one using `doing now` with the `-f` switch. It will look for the last task not marked `@done` and add the `@done` tag with the start time of the new task (either the current time or what you specified with `--back`).
267
269
 
268
270
  `doing done` is used to add an entry that you've already completed. Like `now`, you can specify a section with `-s section_name`. You can also skip straight to Archive with `-a`.
269
271
 
270
- You can also backdate entries using natural language with `--back 15m` or `--back "3/15 3pm"`. That will modify the timestamp of the entry. When used with `doing done`, this allows time intervals to be accurately counted when entering items after the fact.
272
+ You can also backdate entries using natural language with `--back 15m` or `--back "3/15 3pm"`. That will modify the starting timestamp of the entry. You can also use `--took 1h20m` or `--took 1:20` to set the finish date based on a "natural language" time interval. When used with `doing done`, this allows time intervals to be accurately counted when entering items after the fact. `--took` is also available for the `doing finish` command, but cannot be used in conjunction with `--back`. (In `finish` they both set the end date, and neither has priority. `--back` allows specific days/times, `--took` uses time intervals.)
271
273
 
272
274
  All of these commands accept a `-e` argument. This opens your command line editor as defined in the environment variable `$EDITOR`. Add your entry, save the temp file and close it, and the new entry will be added. Anything after the first line is included as a note on the entry.
273
275
 
@@ -277,15 +279,24 @@ All of these commands accept a `-e` argument. This opens your command line edito
277
279
 
278
280
  finish - Mark last X entries as @done
279
281
  tag - Tag last entry
282
+ note - Add a note to the last entry
280
283
 
281
284
  `doing finish` by itself is the same as `doing done` by itself. It adds `@done(timestamp)` to the last entry. It also accepts a numeric argument to complete X number of tasks back in history. Add `-a` to also archive the affected entries.
282
285
 
286
+ `doing finish` also provides an `--auto` flag, which you can use to set the end time of any entry to 1 minute before the start time of the next. Running a command such as `doing finish --auto 10` will go through the last 10 entries and sequentially update any without a `@done` tag with one set to the time just before the next entry in the list.
287
+
288
+ As mentioned above, `finish` also accepts `--back "2 hours"` (sets the date from time now minus interval) or `--took 30m` (sets the date from time started plus interval) so you can accurately add times to completed tasks, even if you don't do it in the moment.
289
+
283
290
  `tag` adds one or more tags to the last entry, or specify a count with `-c X`. Tags are specified as basic arguments, separated by spaces. For example:
284
291
 
285
292
  doing tag -c 3 client cancelled
286
293
 
287
294
  ... will mark the last three entries as "@client @cancelled." Add `-r` as a switch to remove the listed tags instead.
288
295
 
296
+ `note` lets you enter a note on the last entry. You can specify a section with `-s section_name`. `-e` will open your $EDITOR for typing the note, but you can just include it on the command line after any arguments. You can also pipe a note in on STDIN (`echo "fun stuff"|doing note`). The `-r` switch will remove/replace a note; if there's new note text passed when using the `-r` switch, it will replace any existing note. If the `-r` switch is used alone, any existing note will be removed.
297
+
298
+ You can also add notes at the time of entry by using the `-n` or `--note` flag with `doing now`, `doing later`, or `doing done`. If you pass in text to any of the creation commands that has multiple lines, everything after the first line break will become the note.
299
+
289
300
  #### Displaying entries:
290
301
 
291
302
  show - List all entries
@@ -293,6 +304,7 @@ All of these commands accept a `-e` argument. This opens your command line edito
293
304
  today - List entries from today
294
305
  yesterday - List entries from yesterday
295
306
  last - Show the last entry
307
+ grep - Show entries matching text or pattern
296
308
 
297
309
  `doing show` on its own will list all entries in the "Currently" section. Add a section name as an argument to display that section instead. Use "all" to display all entries from all sections.
298
310
 
@@ -413,19 +425,106 @@ That said, you can get support from other users (and occasionally me) on GitHub.
413
425
 
414
426
  Please try not to email me directly about GitHub projects.
415
427
 
428
+ ### Developer notes
429
+
430
+ I'll try to document some of the code structure as I flesh it out. I'm currently working on adding a CLI reporting structure and logging methods, as well as santizing and standardizing all the flags and switches for consistency. Feel free to [poke around](http://github.com/ttscoff/doing/), I'll try to add more comments in the future (and retroactively).
431
+
416
432
  ### Changelog
417
433
 
418
- #### 0.2.5 / 2014-03-21
419
-
420
- * Default to showing times #26, show totals even if no tags exist #27, fix indentation #29
421
- * Add section label to archived tasks automatically, excepting Currently section
422
- * Today outputs and backdate for finish
423
- * html styling and fix for 1.8.7 haml errors
424
- * Look, HTML output! (`--output html`)
425
- * Also, `--output csv`
426
- * let doing archive function on all sections
427
- * option to exclude date from `@done`,
428
- * output newlines in sections and views
429
- * Flagging (`doing mark`)
430
- * fix for view/section guess error
431
- * Adding tag filtering to archive command (`doing archive @done`)
434
+ #### 0.2.6pre
435
+
436
+ * --totals, --[no-]times, --output [csv,html] options for yesterday command.
437
+ * Add tests for Darwin to hide OS X-only features on other systems
438
+ * -f flag to `now` command for finishing last task when starting a new one (Looks back for the last unfinished task in the list)
439
+ * --took option for `done` and `finish` for specifying intervals from the start date for the completion date
440
+ * Basic command line reporting
441
+ * --auto flag for `finish` and `done` that will automatically set the completion time to 1 minute before the next start time in the list. You can use it retroactively to add times to sequential todos.
442
+ * `doing grep` for searching by text or regex
443
+
444
+ #### 0.2.5
445
+
446
+ * Default to showing times #26, show totals even if no tags exist #27, fix indentation #29
447
+ * Add section label to archived tasks automatically, excepting Currently section
448
+ * Today outputs and backdate for finish
449
+ * html styling and fix for 1.8.7 haml errors
450
+ * Look, HTML output! (`--output html`)
451
+ * Also, `--output csv`
452
+ * let doing archive function on all sections
453
+ * option to exclude date from `@done`,
454
+ * output newlines in sections and views
455
+ * Flagging (`doing mark`)
456
+ * fix for view/section guess error
457
+ * Adding tag filtering to archive command (`doing archive \@done`)
458
+ * `doing yesterday`
459
+ * `doing done -r` to remove last doing tag (optionally from `-s Section`)
460
+ * Add -f flag to specify alternate doing file
461
+ * Meanwhile command
462
+
463
+ #### 0.2.1
464
+
465
+ - CSV output for show command (`--csv`)
466
+ - HTML output for show command (`--output html`)
467
+ - fuzzy searching for all commands that specify a view.
468
+ - On the terminal you'll see "Assume you meant XXX" to show what match it found, but this is output to STDERR and won't show up if you're redirecting the output or using it in GeekTool, etc.
469
+ - tags_color in view config to highlight tags at the end of the lines. Can be set to any of the %colors.
470
+ - Basic time tracking.
471
+ - `-t` on `show` and `view` will turn on time calculations
472
+ - Intervals between timestamps and dated `@done` tags are calculated for each line, if the tag exists.
473
+ - You must include a %interval token in the appropriate template for it to show
474
+ - `@start(date)` tags can optionally be used to override the time stamp in the calculation
475
+ - Any other tags in the line have that line's total added to them
476
+ - Totals for tags can be displayed at the end of output with `--totals`
477
+
478
+
479
+ #### 0.2.0
480
+
481
+ - `doing done` without argument tags last entry done
482
+ - `-a` archives them
483
+ - `doing finish` or `doing finish X` marks last X entries done
484
+ - `-a` archives them
485
+ - `doing tag tag1 [tag2]` tags last entry or `-c X` entries
486
+ - `doing tag -r tag1 [tag2]` removes said tag(s)
487
+ - custom views additions
488
+ - custom views can include `tags` and `tags_bool`
489
+ - tags is a space separated list of tags to filter the results by
490
+ - tags_bool defines AND (all tags must exist), OR (any tag exists), or NONE (none of the tags exist)
491
+ - order key (asc or desc) defines output sort order by date
492
+ - section key can be set to "All" to combine sections
493
+ - `doing show` updates
494
+ - accepts "all" as a section
495
+ - arguments following section name are tags to filter by
496
+ - `-b` sets boolean (AND, OR, NONE) or (ALL, ANY, NONE) (default OR/ANY)
497
+ - use `-c X` to limit results
498
+ - use `-s` to set sort order (asc or desc)
499
+ - use `-a` to set age (newest or oldest)
500
+ - fuzzy section guessing when specified section isn't found
501
+ - fuzzy view guessing for `doing view` command
502
+
503
+ ----
504
+
505
+ #### 0.1.9
506
+
507
+ - colors in templated output
508
+ - open command
509
+ - opens in the default app for file type
510
+ - -a APPNAME (`doing open -a TaskPaper`)
511
+ - -b bundle_id (`doing open -b com.sublimetext.3`)
512
+ - -e switch for `now`, `later` and `done` commands
513
+ - save a tmp file and open it in an editor
514
+ - allows multi-line entries, anything after first line is considered a note
515
+ - assumed when no input is provided (`doing now`)
516
+ - `doing views` shows all available custom views
517
+ - `doing view` without a view name will let you choose a view from a menu
518
+ - `doing archive` fixed so that `-k X` works to keep X number of entries in the section
519
+
520
+ #### 0.1.7
521
+
522
+ - colors in templated output
523
+ - open command
524
+ - opens in the default app for file type
525
+ - -a APPNAME (`doing open -a TaskPaper`)
526
+ - -b bundle_id (`doing open -b com.sublimetext.3`)
527
+ - -e switch for `now`, `later` and `done` commands
528
+ - save a tmp file and open it in an editor
529
+ - allows multi-line entries, anything after first line is considered a note
530
+ - assumed when no input is provided (`doing now`)
data/bin/doing CHANGED
@@ -39,9 +39,18 @@ command :now do |c|
39
39
  c.desc "Edit entry with #{ENV['EDITOR']}"
40
40
  c.switch [:e,:editor]
41
41
 
42
- c.desc 'Backdate to "date_string" (natural language)'
42
+ c.desc 'Backdate start time [4pm|20m|2h|yesterday noon]'
43
43
  c.flag [:back]
44
44
 
45
+ c.desc 'Timed entry, marks last entry in section as @done'
46
+ c.default_value false
47
+ c.switch [:f,:finish_last], :negatable => false, :default_value => false
48
+
49
+ c.desc 'Note'
50
+ c.arg_name 'note_text'
51
+ c.default_value wwid.current_section
52
+ c.flag [:n,:note]
53
+
45
54
  # c.desc "Edit entry with specified app"
46
55
  # c.arg_name 'editor_app'
47
56
  # c.default_value wwid.config.has_key?('editor_app') && wwid.config['editor_app'] ? wwid.config['editor_app'] : false
@@ -65,7 +74,8 @@ command :now do |c|
65
74
  input = wwid.fork_editor(input)
66
75
  if input
67
76
  title, note = wwid.format_input(input)
68
- wwid.add_item(title.cap_first, section, {:note => note, :back => date})
77
+ note.push(options[:n]) if options[:n]
78
+ wwid.add_item(title.cap_first, section, {:note => note, :back => date, :timed => options[:f]})
69
79
  wwid.write(wwid.doing_file)
70
80
  else
71
81
  raise "No content"
@@ -73,11 +83,13 @@ command :now do |c|
73
83
  else
74
84
  if args.length > 0
75
85
  title, note = wwid.format_input(args.join(" "))
76
- wwid.add_item(title.cap_first, section, {:note => note, :back => date})
86
+ note.push(options[:n]) if options[:n]
87
+ wwid.add_item(title.cap_first, section, {:note => note, :back => date, :timed => options[:f]})
77
88
  wwid.write(wwid.doing_file)
78
89
  elsif STDIN.stat.size > 0
79
90
  title, note = wwid.format_input(STDIN.read)
80
- wwid.add_item(title.cap_first, section, {:note => note, :back => date})
91
+ note.push(options[:n]) if options[:n]
92
+ wwid.add_item(title.cap_first, section, {:note => note, :back => date, :timed => options[:f]})
81
93
  wwid.write(wwid.doing_file)
82
94
  else
83
95
  raise "You must provide content when creating a new entry"
@@ -86,6 +98,57 @@ command :now do |c|
86
98
  end
87
99
  end
88
100
 
101
+ desc 'Add a note to the last entry'
102
+ arg_name 'note_text'
103
+ command :note do |c|
104
+ c.desc 'Section'
105
+ c.arg_name 'section_name'
106
+ c.default_value wwid.current_section
107
+ c.flag [:s,:section], :default_value => wwid.current_section
108
+
109
+ c.desc "Edit entry with #{ENV['EDITOR']}"
110
+ c.switch [:e,:editor], :negatable => false, :default_value => false
111
+
112
+ c.desc "Replace/Remove last entry's note"
113
+ c.long_desc "If -r is provided with no other arguments, the last note is removed. If new content is specified through arguments or STDIN, any previous note will be replaced with the new one."
114
+ c.switch [:r,:remove], :negatable => false, :default_value => false
115
+
116
+ c.action do |global_options,options,args|
117
+ section = wwid.guess_section(options[:s]) || options[:s].cap_first
118
+
119
+ if options[:e] || (args.length == 0 && STDIN.stat.size == 0 && !options[:r])
120
+ raise "No EDITOR variable defined in environment" if ENV['EDITOR'].nil?
121
+ input = ""
122
+ input += args.join(" ") if args.length > 0
123
+ input = wwid.fork_editor(input)
124
+ if input
125
+ title, note = wwid.format_input(input)
126
+ note.insert(0, title)
127
+ wwid.note_last(section, note, options[:r])
128
+ else
129
+ raise "No content"
130
+ end
131
+ else
132
+ if args.length > 0
133
+ title, note = wwid.format_input(args.join(" "))
134
+ note.insert(0, title)
135
+ wwid.note_last(section, note, options[:r])
136
+ elsif STDIN.stat.size > 0
137
+ title, note = wwid.format_input(STDIN.read)
138
+ note.insert(0, title)
139
+ wwid.note_last(section, note, options[:r])
140
+ else
141
+ if options[:r]
142
+ wwid.note_last(section, [], true)
143
+ else
144
+ raise "You must provide content when adding a note"
145
+ end
146
+ end
147
+ end
148
+ wwid.write(wwid.doing_file)
149
+ end
150
+ end
151
+
89
152
  desc 'Finish any running @meanwhile tasks and optionally create a new one'
90
153
  arg_name 'entry'
91
154
  command :meanwhile do |c|
@@ -100,9 +163,14 @@ command :meanwhile do |c|
100
163
  c.desc "Archive previous @meanwhile entry"
101
164
  c.switch [:a,:archive], :default_value => false
102
165
 
103
- c.desc 'Backdate to "date_string" (natural language)'
166
+ c.desc 'Backdate start date for new entry to date string [4pm|20m|2h|yesterday noon]'
104
167
  c.flag [:back]
105
168
 
169
+ c.desc 'Note'
170
+ c.arg_name 'note_text'
171
+ c.default_value wwid.current_section
172
+ c.flag [:n,:note]
173
+
106
174
  c.action do |global_options,options,args|
107
175
  if options[:back]
108
176
  date = wwid.chronify(options[:back])
@@ -128,7 +196,8 @@ command :meanwhile do |c|
128
196
  end
129
197
  input = false unless input && input.length > 0
130
198
 
131
- wwid.stop_start("meanwhile",{:new_item => input, :back => date, :section => section, :archive => options[:a]})
199
+ note = options[:n] ? options[:n] : false
200
+ wwid.stop_start("meanwhile",{:new_item => input, :back => date, :section => section, :archive => options[:a], :note => note})
132
201
  wwid.write(wwid.doing_file)
133
202
  end
134
203
  end
@@ -144,9 +213,14 @@ command :later do |c|
144
213
  c.default_value wwid.config.has_key?('editor_app') && wwid.config['editor_app'] ? wwid.config['editor_app'] : false
145
214
  c.flag [:a,:app]
146
215
 
147
- c.desc 'Backdate to "date_string" (natural language)'
216
+ c.desc 'Backdate start time to date string [4pm|20m|2h|yesterday noon]'
148
217
  c.flag [:back]
149
218
 
219
+ c.desc 'Note'
220
+ c.arg_name 'note_text'
221
+ c.default_value wwid.current_section
222
+ c.flag [:n,:note]
223
+
150
224
  c.action do |global_options,options,args|
151
225
  if options[:back]
152
226
  date = wwid.chronify(options[:back])
@@ -162,6 +236,7 @@ command :later do |c|
162
236
  input = wwid.fork_editor(input)
163
237
  if input
164
238
  title, note = wwid.format_input(input)
239
+ note.push(options[:n]) if options[:n]
165
240
  wwid.add_item(title.cap_first, "Later", {:note => note, :back => date})
166
241
  wwid.write(wwid.doing_file)
167
242
  else
@@ -170,10 +245,12 @@ command :later do |c|
170
245
  else
171
246
  if args.length > 0
172
247
  title, note = wwid.format_input(args.join(" "))
248
+ note.push(options[:n]) if options[:n]
173
249
  wwid.add_item(title.cap_first, "Later", {:note => note, :back => date})
174
250
  wwid.write(wwid.doing_file)
175
251
  elsif STDIN.stat.size > 0
176
252
  title, note = wwid.format_input(STDIN.read)
253
+ note.push(options[:n]) if options[:n]
177
254
  wwid.add_item(title.cap_first, "Later", {:note => note, :back => date})
178
255
  wwid.write(wwid.doing_file)
179
256
  else
@@ -192,14 +269,17 @@ command :done do |c|
192
269
 
193
270
  c.desc 'Include date'
194
271
  c.default_value true
195
- c.switch [:d,:date], :default_value => true
272
+ c.switch [:d,:date], :negatable => true, :default_value => true
196
273
 
197
274
  c.desc 'Immediately archive the entry'
198
275
  c.default_value false
199
276
  c.switch [:a,:archive], :negatable => false, :default_value => false
200
277
 
201
- c.desc 'Backdate to "date_string" (natural language)'
202
- c.flag [:back]
278
+ c.desc 'Backdate start date to date string [4pm|20m|2h|yesterday noon]'
279
+ c.flag [:b,:back]
280
+
281
+ c.desc 'Set completion date to start date plus XX[mhd] or [HH:MM]'
282
+ c.flag [:t,:took]
203
283
 
204
284
  c.desc 'Section'
205
285
  c.default_value wwid.current_section
@@ -216,13 +296,21 @@ command :done do |c|
216
296
  c.action do |global_options,options,args|
217
297
  if options[:back]
218
298
  date = wwid.chronify(options[:back])
219
- raise "Unable to parse date string" if date.nil?
299
+ raise "Unable to parse date string for --back" if date.nil?
220
300
  else
221
301
  date = Time.now
222
302
  end
223
303
 
304
+ if options[:took]
305
+ minutes = wwid.chronify_qty(options[:took])
306
+ finish_date = date + minutes
307
+ raise "Unable to parse date string for --took" if date.nil?
308
+ else
309
+ finish_date = Time.now
310
+ end
311
+
224
312
  section = wwid.guess_section(options[:s]) || options[:s].cap_first
225
- donedate = options[:d] ? "(#{Time.now.strftime('%F %R')})" : ""
313
+ donedate = options[:d] ? "(#{finish_date.strftime('%F %R')})" : ""
226
314
 
227
315
  if options[:e]
228
316
  raise "No EDITOR variable defined in environment" if ENV['EDITOR'].nil?
@@ -242,11 +330,12 @@ command :done do |c|
242
330
  if options[:r]
243
331
  wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :remove => true })
244
332
  else
245
- wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :archive => options[:a], :back => date, :date => options[:d]})
333
+ wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :archive => options[:a], :back => finish_date, :date => options[:d]})
246
334
  end
247
335
  else
248
336
  if args.length > 0
249
337
  title, note = wwid.format_input(args.join(" "))
338
+ title.chomp!
250
339
  title += " @done#{donedate}"
251
340
  section = "Archive" if options[:a]
252
341
  wwid.add_item(title.cap_first, section.cap_first, {:note => note, :back => date})
@@ -265,14 +354,23 @@ command :done do |c|
265
354
  end
266
355
 
267
356
  desc 'Mark last X entries as @done'
357
+ long_desc 'Marks the last X entries with a @done tag and current date. Does not alter already completed entries.'
268
358
  arg_name 'count'
269
359
  command :finish do |c|
270
360
  c.desc 'Include date'
271
361
  c.default_value true
272
362
  c.switch [:d,:date], :default_value => true
273
363
 
274
- c.desc 'Backdate to "date_string" (natural language)'
275
- c.flag [:back]
364
+ c.desc 'Backdate completed date to date string [4pm|20m|2h|yesterday noon]'
365
+ c.flag [:b,:back]
366
+
367
+ c.desc 'Set the completed date to the start date plus XX[hmd]'
368
+ c.flag [:t,:took]
369
+
370
+ c.desc 'Auto-generate finish dates from next entry\'s start time'
371
+ c.long_desc 'Automatically generate completion dates 1 minute before next start date. --auto overrides the --date and --back parameters.'
372
+ c.default_value false
373
+ c.switch [:auto], :negatable => false, :default_value => false
276
374
 
277
375
  c.desc 'Archive entries'
278
376
  c.default_value false
@@ -286,19 +384,25 @@ command :finish do |c|
286
384
 
287
385
  section = wwid.guess_section(options[:s]) || options[:s].cap_first
288
386
 
289
- if options[:back]
290
- date = wwid.chronify(options[:back])
387
+ unless options[:auto]
388
+ raise "--back and --took cannot be used together" if options[:back] and options[:took]
291
389
 
292
- raise "Unable to parse date string" if date.nil?
293
- else
294
- date = Time.now
390
+ if options[:back]
391
+ date = wwid.chronify(options[:back])
392
+
393
+ raise "Unable to parse date string" if date.nil?
394
+ elsif options[:took]
395
+ date = wwid.chronify_qty(options[:took])
396
+ else
397
+ date = Time.now
398
+ end
295
399
  end
296
400
 
297
401
  if args.length > 1
298
402
  raise "Only one argument allowed"
299
403
  elsif args.length == 0 || args[0] =~ /\d+/
300
404
  count = args[0] ? args[0].to_i : 1
301
- wwid.tag_last({:tags => ["done"], :count => count, :section => section, :archive => options[:a], :date => options[:d], :back => date })
405
+ wwid.tag_last({:tags => ["done"], :count => count, :section => section, :archive => options[:a], :sequential => options[:auto], :date => options[:d], :back => date })
302
406
  else
303
407
  raise "Invalid argument (specify number of recent items to mark @done)"
304
408
  end
@@ -383,11 +487,11 @@ command :show do |c|
383
487
  c.default_value 'asc'
384
488
  c.flag [:s,:sort], :default_value => 'asc'
385
489
 
386
- c.desc 'Output to format'
490
+ c.desc 'Output to export format (csv|html)'
387
491
  c.flag [:o,:output]
388
492
 
389
493
  c.desc 'Show time intervals on @done tasks'
390
- c.default_value false
494
+ c.default_value true
391
495
  c.switch [:t,:times], :default_value => true
392
496
 
393
497
  c.desc 'Show intervals with totals at the end of output'
@@ -430,6 +534,37 @@ command :show do |c|
430
534
  end
431
535
  end
432
536
 
537
+ desc 'Search for entries'
538
+ long_desc 'Search all sections (or limit to a single section) for entries matching text or regular expression.'
539
+ arg_name 'search_pattern'
540
+ command :grep do |c|
541
+ c.desc 'Section'
542
+ c.default_value "all"
543
+ c.flag [:s,:section], :default_value => "All"
544
+
545
+ c.desc 'Output to export format (csv|html)'
546
+ c.flag [:o,:output]
547
+
548
+ c.desc 'Show time intervals on @done tasks'
549
+ c.default_value true
550
+ c.switch [:t,:times], :default_value => true
551
+
552
+ c.desc 'Show intervals with totals at the end of output'
553
+ c.default_value false
554
+ c.switch [:totals], :default_value => false, :negatable => true
555
+
556
+ c.action do |global_options,options,args|
557
+
558
+ section = wwid.guess_section(options[:s]) if options[:s]
559
+
560
+ options[:t] = true if options[:totals]
561
+
562
+ puts wwid.list_section({:search => args.join, :section => section, :output => options[:output], :times => options[:t], :highlight => true})
563
+
564
+ puts wwid.tag_times if options[:totals]
565
+ end
566
+ end
567
+
433
568
  desc 'List recent entries'
434
569
  default_value 10
435
570
  arg_name 'count'
@@ -439,7 +574,7 @@ command :recent do |c|
439
574
  c.flag [:s,:section], :default_value => wwid.current_section
440
575
 
441
576
  c.desc 'Show time intervals on @done tasks'
442
- c.default_value false
577
+ c.default_value true
443
578
  c.switch [:t,:times], :default_value => true
444
579
 
445
580
  c.desc 'Show intervals with totals at the end of output'
@@ -468,14 +603,14 @@ end
468
603
  desc 'List entries from today'
469
604
  command :today do |c|
470
605
  c.desc 'Show time intervals on @done tasks'
471
- c.default_value false
606
+ c.default_value true
472
607
  c.switch [:t,:times], :default_value => true
473
608
 
474
609
  c.desc 'Show time totals at the end of output'
475
610
  c.default_value false
476
611
  c.switch [:totals], :default_value => false, :negatable => true
477
612
 
478
- c.desc 'Output to format'
613
+ c.desc 'Output to export format (csv|html)'
479
614
  c.flag [:o,:output]
480
615
 
481
616
  c.action do |global_options,options,args|
@@ -492,9 +627,22 @@ desc 'List entries from yesterday'
492
627
  default_value wwid.current_section
493
628
  arg_name 'section'
494
629
  command :yesterday do |c|
630
+ c.desc 'Output to export format (csv|html)'
631
+ c.flag [:o,:output]
632
+
633
+ c.desc 'Show time intervals on @done tasks'
634
+ c.default_value true
635
+ c.switch [:t,:times], :default_value => true
636
+
637
+ c.desc 'Show time totals at the end of output'
638
+ c.default_value false
639
+ c.switch [:totals], :default_value => false, :negatable => true
640
+
495
641
  c.action do |global_options, options,args|
496
642
  section = args.length > 0 ? args.join(" ") : wwid.current_section
497
- puts wwid.yesterday(section).strip
643
+ puts wwid.yesterday(section,options[:t],options[:o]).chomp
644
+
645
+ puts wwid.tag_times if options[:totals]
498
646
  end
499
647
  end
500
648
 
@@ -542,11 +690,11 @@ command :view do |c|
542
690
  c.desc 'Count to display (override view settings)'
543
691
  c.flag [:c,:count], :must_match => /^\d+$/, :type => Integer
544
692
 
545
- c.desc 'Output to format'
693
+ c.desc 'Output to export format (csv|html)'
546
694
  c.flag [:o,:output]
547
695
 
548
696
  c.desc 'Show time intervals on @done tasks'
549
- c.default_value false
697
+ c.default_value true
550
698
  c.switch [:t,:times], :default_value => true
551
699
 
552
700
  c.desc 'Show intervals with totals at the end of output'
@@ -635,8 +783,9 @@ command :archive do |c|
635
783
  end
636
784
  end
637
785
 
638
- desc 'Open the "doing" file in an editor (OS X)'
786
+ desc 'Open the "doing" file in an editor'
639
787
  command :open do |c|
788
+ if `uname` =~ /Darwin/
640
789
  c.desc 'open with app name'
641
790
  c.arg_name 'app_name'
642
791
  c.flag [:a]
@@ -644,7 +793,7 @@ command :open do |c|
644
793
  c.desc 'open with app bundle id'
645
794
  c.arg_name 'bundle_id'
646
795
  c.flag [:b]
647
-
796
+ end
648
797
  c.desc 'open with $EDITOR'
649
798
  c.switch [:e], :negatable => false
650
799
 
@@ -653,7 +802,7 @@ command :open do |c|
653
802
  params.delete_if { |k,v|
654
803
  k.class == String || v.nil? || v == false
655
804
  }
656
-
805
+ if `uname` =~ /Darwin/
657
806
  if params.length < 2
658
807
  if options[:a]
659
808
  system %Q{open -a "#{options[:a]}" "#{File.expand_path(wwid.doing_file)}"}
@@ -672,41 +821,66 @@ command :open do |c|
672
821
  else
673
822
  raise "The open command takes a single parameter. #{params.length} specified."
674
823
  end
824
+ else
825
+ raise "No EDITOR variable defined in environment" if ENV['EDITOR'].nil?
826
+ system %Q{$EDITOR "#{File.expand_path(wwid.doing_file)}"}
827
+ end
675
828
  end
676
829
  end
677
830
 
831
+
678
832
  desc 'Edit the configuration file'
679
833
  command :config do |c|
680
834
  c.desc 'Editor to use'
681
835
  c.default_value ENV['EDITOR']
682
836
  c.flag [:e,:editor], :default_value => nil
683
837
 
684
- c.desc 'Application to use (OS X only)'
685
- c.flag [:a]
686
-
687
- c.desc "Use the editor_app defined in ~/.doingrc (#{wwid.config['editor_app']})"
688
- c.switch [:x]
838
+ if `uname` =~ /Darwins/
839
+ c.desc 'Application to use'
840
+ c.flag [:a]
689
841
 
690
- c.desc 'Application bundle id to use (OS X only)'
691
- c.flag [:b]
842
+ c.desc "Use the editor_app defined in ~/.doingrc (#{wwid.config['editor_app']})"
843
+ c.switch [:x]
692
844
 
845
+ c.desc 'Application bundle id to use'
846
+ c.flag [:b]
847
+ end
693
848
  c.action do |global_options,options,args|
694
- if options[:x]
695
- %x{open -a "#{wwid.config['editor_app']}" "#{File.expand_path(DOING_CONFIG)}"}
696
- elsif options[:a] || options[:b]
697
- if options[:a]
698
- %x{open -a "#{options[:a]}" "#{File.expand_path(DOING_CONFIG)}"}
699
- elsif options[:b]
700
- %x{open -b #{options[:b]} "#{File.expand_path(DOING_CONFIG)}"}
849
+ if `uname` =~ /Darwins/
850
+ if options[:x]
851
+ %x{open -a "#{wwid.config['editor_app']}" "#{File.join(Dir.home, DOING_CONFIG_NAME)}"}
852
+ elsif options[:a] || options[:b]
853
+ if options[:a]
854
+ %x{open -a "#{options[:a]}" "#{File.join(Dir.home, DOING_CONFIG_NAME)}"}
855
+ elsif options[:b]
856
+ %x{open -b #{options[:b]} "#{File.join(Dir.home, DOING_CONFIG_NAME)}"}
857
+ end
858
+ else
859
+ raise "No EDITOR variable defined in environment" if options[:e].nil? && ENV['EDITOR'].nil?
860
+ editor = options[:e].nil? ? ENV['EDITOR'] : options[:e]
861
+ system %Q{#{editor} "#{File.expand_path(DOING_CONFIG)}"}
701
862
  end
702
863
  else
703
864
  raise "No EDITOR variable defined in environment" if options[:e].nil? && ENV['EDITOR'].nil?
704
865
  editor = options[:e].nil? ? ENV['EDITOR'] : options[:e]
705
- system %Q{#{editor} "#{File.expand_path(DOING_CONFIG)}"}
866
+ system %Q{#{editor} "#{File.join(Dir.home, DOING_CONFIG_NAME)}"}
706
867
  end
707
868
  end
708
869
  end
709
870
 
871
+ desc 'Undo the last change to the doing_file'
872
+ command :undo do |c|
873
+ c.desc 'Specify alternate doing file'
874
+ c.default_value wwid.doing_file
875
+ c.flag [:f,:file], :default_value => wwid.doing_file
876
+
877
+ c.action do |global_options,options,args|
878
+ file = options[:f] || wwid.doing_file
879
+ wwid.restore_backup(file)
880
+ end
881
+ end
882
+
883
+
710
884
  pre do |global,command,options,args|
711
885
  if global[:doing_file]
712
886
  wwid.init_doing_file(input=global[:doing_file])
@@ -728,6 +902,7 @@ end
728
902
  post do |global,command,options,args|
729
903
  # Use skips_post before a command to skip this
730
904
  # block on that command only
905
+ puts wwid.results.join("\n")
731
906
  end
732
907
 
733
908
  on_error do |exception|
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '0.2.5'
2
+ VERSION = '1.0.0pre'
3
3
  end
data/lib/doing/wwid.rb CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/ruby
2
+
3
+ require 'deep_merge'
4
+
2
5
  class String
3
6
  def cap_first
4
7
  self.sub(/^\w/) do |m|
@@ -9,13 +12,14 @@ class String
9
12
  end
10
13
 
11
14
  class WWID
12
- attr_accessor :content, :sections, :current_section, :doing_file, :config
15
+ attr_accessor :content, :sections, :current_section, :doing_file, :config, :results
13
16
 
14
17
 
15
18
  def initialize
16
19
  @content = {}
17
20
  @timers = {}
18
21
  @config = read_config
22
+ @results = []
19
23
 
20
24
  @config['doing_file'] ||= "~/what_was_i_doing.md"
21
25
  @config['current_section'] ||= 'Currently'
@@ -63,6 +67,7 @@ class WWID
63
67
  }
64
68
  @config['marker_tag'] ||= 'flagged'
65
69
  @config['marker_color'] ||= 'red'
70
+ @config['default_tags'] ||= []
66
71
 
67
72
  @current_section = config['current_section']
68
73
  @default_template = config['templates']['default']['template']
@@ -70,7 +75,7 @@ class WWID
70
75
 
71
76
  @config[:include_notes] ||= true
72
77
 
73
- File.open(File.expand_path(DOING_CONFIG), 'w') { |yf| YAML::dump(config, yf) }
78
+ File.open(home_config, 'w') { |yf| YAML::dump(config, yf) }
74
79
  end
75
80
 
76
81
  def init_doing_file(input=nil)
@@ -141,12 +146,23 @@ class WWID
141
146
  end
142
147
  end
143
148
 
149
+ def home_config
150
+ File.join(Dir.home, DOING_CONFIG_NAME)
151
+ end
152
+
144
153
  def read_config
145
- if File.exists? File.expand_path(DOING_CONFIG)
146
- return YAML.load_file(File.expand_path(DOING_CONFIG))
147
- else
148
- return {}
154
+ config = {}
155
+ dir = Dir.pwd
156
+ while(dir != '/')
157
+ if File.exists? File.join(dir, DOING_CONFIG_NAME)
158
+ config = YAML.load_file(File.join(dir, DOING_CONFIG_NAME)).deep_merge!(config)
159
+ end
160
+ dir = File.dirname(dir)
161
+ end
162
+ if config.empty? && File.exists?(home_config)
163
+ config = YAML.load_file(home_config)
149
164
  end
165
+ config
150
166
  end
151
167
 
152
168
  def fork_editor(input="")
@@ -182,7 +198,10 @@ class WWID
182
198
  end
183
199
 
184
200
  # This takes a multi-line string and formats it as an entry
185
- # returns an array of [title(String), note(Array)]
201
+ # Params:
202
+ # +input+:: String
203
+ # Returns:
204
+ # [title(String), note(Array)]
186
205
  def format_input(input)
187
206
  raise "No content in entry" if input.nil? || input.strip.length == 0
188
207
  input_lines = input.split(/[\n\r]+/)
@@ -197,16 +216,21 @@ class WWID
197
216
  [title, note]
198
217
  end
199
218
 
219
+ # Converts simple strings into seconds that can be added to a Time object
220
+ # Params:
221
+ # +qty+:: HH:MM or XX[dhm][[XXhm][XXm]] (1d2h30m, 45m, 1.5d, 1h20m, etc.)
222
+ # Returns:
223
+ # seconds(Integer)
200
224
  def chronify(input)
201
- if input =~ /^(\d+)([mhd])?$/i
225
+ if input =~ /^(\d+)\s*([mhd])?/i
202
226
  amt = $1
203
227
  type = $2.nil? ? "m" : $2
204
228
  input = case type.downcase
205
- when "m"
229
+ when 'm'
206
230
  amt + " minutes ago"
207
- when "h"
231
+ when 'h'
208
232
  amt + " hours ago"
209
- when "d"
233
+ when 'd'
210
234
  amt + " days ago"
211
235
  else
212
236
  input
@@ -216,6 +240,32 @@ class WWID
216
240
  Chronic.parse(input, {:context => :past, :ambiguous_time_range => 8})
217
241
  end
218
242
 
243
+
244
+ # Converts simple strings into seconds that can be added to a Time object
245
+ # Params:
246
+ # +qty+:: HH:MM or XX[dhm][[XXhm][XXm]] (1d2h30m, 45m, 1.5d, 1h20m, etc.)
247
+ # Returns seconds (Integer)
248
+ def chronify_qty(qty)
249
+ minutes = 0
250
+ if qty.strip =~ /^(\d+):(\d\d)$/
251
+ minutes += $1.to_i * 60
252
+ minutes += $2.to_i
253
+ elsif qty.strip =~ /\d+\s*[hmd]/
254
+ matches = qty.scan(/([\d\.]+)\s*([hmd])/)
255
+ matches.each {|m|
256
+ case m[1]
257
+ when "m"
258
+ minutes += m[0].to_i
259
+ when "h"
260
+ minutes += (m[0].to_f * 60).round
261
+ when "d"
262
+ minutes += (m[0].to_f * 60 * 24).round
263
+ end
264
+ }
265
+ end
266
+ minutes * 60
267
+ end
268
+
219
269
  def sections
220
270
  @content.keys
221
271
  end
@@ -282,12 +332,29 @@ class WWID
282
332
  opt[:date] ||= Time.now
283
333
  opt[:note] ||= []
284
334
  opt[:back] ||= Time.now
335
+ opt[:timed] ||= false
285
336
 
286
- entry = {'title' => title.strip.cap_first, 'date' => opt[:back]}
337
+ title = [title.strip.cap_first] + @config['default_tags'].map{|t| '@' + t.sub(/^ *@/,'').chomp}
338
+ entry = {'title' => title.join(' '), 'date' => opt[:back]}
287
339
  unless opt[:note] =~ /^\s*$/s
288
340
  entry['note'] = opt[:note]
289
341
  end
290
- @content[section]['items'].push(entry)
342
+ items = @content[section]['items']
343
+ if opt[:timed]
344
+ items.reverse!
345
+ items.each_with_index {|i,x|
346
+ if i['title'] =~ / @done/
347
+ next
348
+ else
349
+ items[x]['title'] = "#{i['title']} @done(#{opt[:back].strftime('%F %R')})"
350
+ break
351
+ end
352
+ }
353
+ items.reverse!
354
+ end
355
+ items.push(entry)
356
+ @content[section]['items'] = items
357
+ @results.push(%Q{Added "#{entry['title']}" to #{section}})
291
358
  end
292
359
 
293
360
  def tag_last(opt={})
@@ -295,39 +362,68 @@ class WWID
295
362
  opt[:count] ||= 1
296
363
  opt[:archive] ||= false
297
364
  opt[:tags] ||= ["done"]
365
+ opt[:sequential] ||= false
298
366
  opt[:date] ||= false
299
367
  opt[:remove] ||= false
300
368
  opt[:back] ||= Time.now
301
369
 
370
+
371
+
302
372
  opt[:section] = guess_section(opt[:section])
303
373
 
304
374
  if @content.has_key?(opt[:section])
305
375
  # sort_section(opt[:section])
306
- # items = @content[opt[:section]]['items'].sort_by{|item| item['date'] }.reverse
376
+ items = @content[opt[:section]]['items'].dup.sort_by{|item| item['date'] }.reverse
377
+
378
+ index = 0
379
+ done_date = Time.now
380
+ next_start = Time.now
381
+ items.map! {|item|
382
+ break if index == opt[:count]
383
+ if opt[:sequential]
384
+ done_date = next_start - 1
385
+ next_start = item['date']
386
+ elsif opt[:back].instance_of? Fixnum
387
+ done_date = item['date'] + opt[:back]
388
+ else
389
+ done_date = opt[:back]
390
+ end
307
391
 
308
- @content[opt[:section]]['items'].each_with_index {|item, i|
309
- break if i == opt[:count]
310
392
  title = item['title']
311
393
  opt[:tags].each {|tag|
312
394
  if opt[:remove]
313
395
  title.gsub!(/(^| )@#{tag.strip}(\([^\)]*\))?/,'')
396
+ @results.push("Updated: #{title}")
314
397
  else
315
398
  unless title =~ /@#{tag}/
316
- if (tag == "done" && opt[:date]) || opt[:date]
317
- title += " @#{tag}(#{opt[:back].strftime('%F %R')})"
399
+ title.chomp!
400
+ if opt[:date]
401
+ title += " @#{tag}(#{done_date.strftime('%F %R')})"
318
402
  else
319
403
  title += " @#{tag}"
320
404
  end
405
+ @results.push("Updated: #{title}")
321
406
  end
322
407
  end
323
408
  }
324
- @content[opt[:section]]['items'][i]['title'] = title
409
+
410
+ item['title'] = title
411
+ index += 1
412
+ item
325
413
  }
326
414
 
415
+ @content[opt[:section]]['items'] = items
416
+
327
417
  if opt[:archive] && opt[:section] != "Archive"
418
+ # concat [count] items from [section] and archive section
328
419
  archived = @content[opt[:section]]['items'][0..opt[:count]-1].concat(@content['Archive']['items'])
420
+ # chop [count] items off of [section] items
329
421
  @content[opt[:section]]['items'] = @content[opt[:section]]['items'][opt[:count]..-1]
422
+ # overwrite archive section with concatenated array
330
423
  @content['Archive']['items'] = archived
424
+ # log it
425
+ result = opt[:count] == 1 ? "1 entry" : "#{opt[:count]} entries"
426
+ @results.push("Archived #{result}")
331
427
  end
332
428
 
333
429
  write(@doing_file)
@@ -336,6 +432,41 @@ class WWID
336
432
  end
337
433
  end
338
434
 
435
+ def note_last(section, note, replace=false)
436
+ section = guess_section(section)
437
+
438
+ if @content.has_key?(section)
439
+ # sort_section(opt[:section])
440
+ items = @content[section]['items'].dup.sort_by{|item| item['date'] }.reverse
441
+
442
+ current_note = items[0]['note']
443
+ current_note = [] if current_note.nil?
444
+ title = items[0]['title']
445
+ if replace
446
+ items[0]['note'] = note
447
+ if note.empty? && !current_note.empty?
448
+ @results.push(%Q{Removed note from "#{title}"})
449
+ elsif current_note.length > 0 && note.length > 0
450
+ @results.push(%Q{Replaced note from "#{title}"})
451
+ elsif note.length > 0
452
+ @results.push(%Q{Added note to #{title}})
453
+ else
454
+ @results.push(%Q{Entry "#{title}" has no note})
455
+ end
456
+ elsif current_note.class == Array
457
+ items[0]['note'] = current_note.concat(note)
458
+ @results.push(%Q{Added note to "#{title}"}) if note.length > 0
459
+ else
460
+ items[0]['note'] = note
461
+ @results.push(%Q{Added note to "#{title}"}) if note.length > 0
462
+ end
463
+
464
+ @content[section]['items'] = items
465
+ else
466
+ raise "Section not found"
467
+ end
468
+ end
469
+
339
470
  # accepts one tag and the raw text of a new item
340
471
  # if the passed tag is on any item, it's replaced with @done
341
472
  # if new_item is not nil, it's tagged with the passed tag and inserted
@@ -345,6 +476,7 @@ class WWID
345
476
  opt[:archive] ||= false
346
477
  opt[:back] ||= Time.now
347
478
  opt[:new_item] ||= false
479
+ opt[:note] ||= false
348
480
 
349
481
  opt[:section] = guess_section(opt[:section])
350
482
 
@@ -358,14 +490,18 @@ class WWID
358
490
  @content[opt[:section]]['items'][i]['title'] = title
359
491
 
360
492
  if opt[:archive] && opt[:section] != "Archive"
493
+ @results.push(%Q{Completed and archived "#{@content[opt[:section]]['items'][i]['title']}"})
361
494
  @content['Archive']['items'].push(@content[opt[:section]]['items'][i])
362
495
  @content[opt[:section]]['items'].delete_at(i)
496
+ else
497
+ @results.push(%Q{Completed "#{@content[opt[:section]]['items'][i]['title']}"})
363
498
  end
364
499
  end
365
500
  }
366
501
 
367
502
  if opt[:new_item]
368
503
  title, note = format_input(opt[:new_item])
504
+ note.push(opt[:note]) if opt[:note]
369
505
  title += " @#{tag}"
370
506
  add_item(title.cap_first, opt[:section], {:note => note, :back => opt[:back]})
371
507
  end
@@ -374,7 +510,7 @@ class WWID
374
510
  end
375
511
 
376
512
  def write(file=nil)
377
- if @other_content_top.empty?
513
+ unless @other_content_top
378
514
  output = ""
379
515
  else
380
516
  output = @other_content_top.join("\n") + "\n"
@@ -383,11 +519,12 @@ class WWID
383
519
  output += section['original'] + "\n"
384
520
  output += list_section({:section => title, :template => "\t- %date | %title%note", :highlight => false})
385
521
  }
386
- output += @other_content_bottom.join("\n")
522
+ output += @other_content_bottom.join("\n") unless @other_content_bottom.nil?
387
523
  if file.nil?
388
524
  $stdout.puts output
389
525
  else
390
526
  if File.exists?(File.expand_path(file))
527
+ FileUtils.cp(file,file+"~")
391
528
  File.open(File.expand_path(file),'w+') do |f|
392
529
  f.puts output
393
530
  end
@@ -395,6 +532,15 @@ class WWID
395
532
  end
396
533
  end
397
534
 
535
+ def restore_backup(file)
536
+ if File.exists?(file+"~")
537
+ puts file+"~"
538
+ FileUtils.cp(file+"~",file)
539
+ @results.push("Restored #{file}")
540
+ end
541
+ end
542
+
543
+
398
544
  def choose_section
399
545
  sections.each_with_index {|section, i|
400
546
  puts "% 3d: %s" % [i+1, section]
@@ -438,6 +584,8 @@ class WWID
438
584
  opt[:tag_filter] ||= false
439
585
  opt[:tags_color] ||= false
440
586
  opt[:times] ||= false
587
+ opt[:search] ||= false
588
+
441
589
  # opt[:highlight] ||= true
442
590
  section = ""
443
591
  if opt[:section].nil?
@@ -488,6 +636,13 @@ class WWID
488
636
  }
489
637
  end
490
638
 
639
+ if opt[:search]
640
+ items.keep_if {|item|
641
+ text = item['note'] ? item['title'] + item['note'].join(" ") : item['title']
642
+ text =~ /#{opt[:search]}/i
643
+ }
644
+ end
645
+
491
646
  if opt[:today]
492
647
  items.delete_if {|item|
493
648
  item['date'] < Date.today.to_time
@@ -792,9 +947,9 @@ EOT
792
947
  list_section({:section => @current_section, :wrap_width => cfg['wrap_width'], :count => 0, :format => cfg['date_format'], :template => cfg['template'], :order => "asc", :today => true, :times => times, :output => output})
793
948
  end
794
949
 
795
- def yesterday(section)
950
+ def yesterday(section,times=nil,output=nil)
796
951
  section = guess_section(section)
797
- list_section({:section => section, :count => 0, :order => "asc", :yesterday => true})
952
+ list_section({:section => section, :count => 0, :order => "asc", :yesterday => true, :times => times, :output => output })
798
953
  end
799
954
 
800
955
  def recent(count=10,section=nil,opt={})
data/lib/doing.rb CHANGED
@@ -9,4 +9,4 @@ require 'chronic'
9
9
  require 'haml'
10
10
  require 'doing/wwid.rb'
11
11
 
12
- DOING_CONFIG = "~/.doingrc"
12
+ DOING_CONFIG_NAME = ".doingrc"
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: 0.2.5
4
+ version: 1.0.0pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-12 00:00:00.000000000 Z
11
+ date: 2014-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -106,6 +106,20 @@ dependencies:
106
106
  - - '>='
107
107
  - !ruby/object:Gem::Version
108
108
  version: 0.10.2
109
+ - !ruby/object:Gem::Dependency
110
+ name: deep_merge
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ type: :runtime
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
109
123
  description: A tool for managing a TaskPaper-like file of recent activites. Perfect
110
124
  for the late-night hacker on too much caffeine to remember what they accomplished
111
125
  at 2 in the morning.
@@ -144,9 +158,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
158
  version: '0'
145
159
  required_rubygems_version: !ruby/object:Gem::Requirement
146
160
  requirements:
147
- - - '>='
161
+ - - '>'
148
162
  - !ruby/object:Gem::Version
149
- version: '0'
163
+ version: 1.3.1
150
164
  requirements: []
151
165
  rubyforge_project:
152
166
  rubygems_version: 2.2.2