doing 0.2.4 → 0.2.5pre

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: 9113d5736076e7608e42c328d3bc6a9f6edb517e
4
- data.tar.gz: 793034d75510f42fa2c9f2e3f75d26156fef4d51
3
+ metadata.gz: 8806f026f8106baa4c033a2d30675e0f3c30afea
4
+ data.tar.gz: 77139cb8ae62cc18311d5fcd7c27a725806375c9
5
5
  SHA512:
6
- metadata.gz: bd187715ead8168b92c2a70ebe53d68d95271a241524a1011c82c9358cae43ed0766dea0b1fe73c469d112435921342e2fb9811af2835f039d9ab1445519196f
7
- data.tar.gz: 11c41e6db6c47490ff82b922a262df3292808e6b5736babf3d12a28de96075f91322da61f882c73178a7b9240c82c8056f7f99180bee8c309d1dc852f7427ddc
6
+ metadata.gz: 6fb8b55cc46ceefe4c139af635417b2c318e90705ef7da3fb3aa2e2050bd7e7de89d4d9633e538ec0ca26e6d3582a81e3fa394ac3bf032684d463a36573f5cca
7
+ data.tar.gz: 659c26db54235f3ca7d13cc34bdc2f4cdd3e028cc6514c2c5f01c0c9216c7c0fcc693de629f3b965dd5b533e91b8390e09fdd29aebd010d5109ba947394ef16a
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  _If you're one of the rare people like me who find this useful, feel free to contribute to my [GitTip fund](https://www.gittip.com/ttscoff/) or just [buy me some coffee](http://brettterpstra.com/donate)._
6
6
 
7
+ [Changelog](#changelog)
8
+
7
9
  ## What and why
8
10
 
9
11
  `doing` is a basic CLI for adding and listing "what was I doing" reminders in a [TaskPaper-formatted](http://www.hogbaysoftware.com/products/taskpaper) text file. It allows for multiple sections/categories and flexible output formatting.
@@ -313,17 +315,63 @@ Display any of the custom views you make in `~/.doingrc` with the `view` command
313
315
 
314
316
  #### Utilities
315
317
 
316
- archive - Move all but the most recent 5 entries to the Archive section
318
+ archive - Move entries between sections
317
319
  open - Open the "doing" file in an editor (OS X)
318
320
  config - Edit the default configuration
319
321
 
322
+ #### Archiving
323
+
324
+ COMMAND OPTIONS
325
+ -k, --keep=arg - Count to keep (ignored if archiving by tag) (default: 5)
326
+ -t, --to=arg - Move entries to (default: Archive)
327
+ -b, --bool=arg - Tag boolean (default: AND)
328
+
329
+ The `archive` command will move entries from one section (default: Currently) to another section (default: Archive).
330
+
331
+ `doing archive` on its own will move all but the most recent 5 entries from currently into the archive.
332
+
333
+ `doing archive other_section` will archive from "other_section" to Archive.
334
+
335
+ `doing archive other_section -t alternate` will move from "other_section" to "alternate." You can use the `-k` flag on any of these to change the number of items to leave behind. To move everything, use `-k 0`.
336
+
337
+ You can also use tags to archive. You define the section first, and anything following it is treated as tags. If your first argument starts with "@", it will assume all sections and assume any following arguments are tags.
338
+
339
+ By default tag archiving uses an "AND" boolean, meaning all the tags listed must exist on the entry for it to be moved. You can change this behavior with `-b OR` or `-b NONE` ("ALL" and "ANY" also work).
340
+
341
+ Example: Archive all Currently items for @client that are marked @done
342
+
343
+ doing archive @client @done
344
+
320
345
  ---
321
346
 
322
347
  ## Extras
323
348
 
324
349
  ### Bash completion
325
350
 
326
- Add basic command line completion for Bash with [this gist](https://gist.github.com/fcrespo82/9609318).
351
+ See the file `doing.completion.bash` in the git repository for full bash completion. Thanks to [fcrespo82](https://github.com/fcrespo82) for getting it [started](https://gist.github.com/fcrespo82/9609318).
352
+
353
+ ### Launchbar
354
+
355
+ The previous incarnation of `doing` had a [LaunchBar](http://obdev.at/launchbar/) action that I used frequently. The Day One popup has mostly replaced that for me, but only because I have a system that connects it to my WWID file. However, I've still found a place for adding WWID entries without including them in my journal, and LaunchBar is the perfect way to do that for me.
356
+
357
+ All you need is an AppleScript saved at "~/Library/Application Support/LaunchBar/Actions/Doing.scpt". It should look like this:
358
+
359
+
360
+ on handle_string(message)
361
+ -- get the input from LaunchBar
362
+ if message is "?" then
363
+ -- if the input is just "?" display the last three entries
364
+ set _doing to do shell script "/usr/bin/doing recent 3"
365
+ tell application "LaunchBar" to display in large type _doing
366
+ else
367
+ -- otherwise, create a new entry using the input
368
+ do shell script "/usr/bin/doing now " & quoted form of message
369
+ end if
370
+
371
+ end handle_string
372
+
373
+
374
+ Evan Lovely has [converted this to an Alfred workflow as well](http://www.evanlovely.com/blog/technology/alfred-for-terpstras-doing/).
327
375
 
328
376
  ## Troubleshooting
329
377
 
@@ -358,3 +406,20 @@ I'm not making any money on `doing`, and I don't plan to spend a lot of time fix
358
406
  That said, you can get support from other users (and occasionally me) on GitHub. If you run into a replicatable issue in your environment, please [post an issue](https://github.com/ttscoff/doing/issues) and include your platform, OS version, and the result of `ruby -v`, along with a copy/paste of the error message.
359
407
 
360
408
  Please try not to email me directly about GitHub projects.
409
+
410
+ ### Changelog
411
+
412
+ #### 0.2.5 / 2014-03-21
413
+
414
+ * Default to showing times #26, show totals even if no tags exist #27, fix indentation #29
415
+ * Add section label to archived tasks automatically, excepting Currently section
416
+ * Today outputs and backdate for finish
417
+ * html styling and fix for 1.8.7 haml errors
418
+ * Look, HTML output! (`--output html`)
419
+ * Also, `--output csv`
420
+ * let doing archive function on all sections
421
+ * option to exclude date from `@done`,
422
+ * output newlines in sections and views
423
+ * Flagging (`doing mark`)
424
+ * fix for view/section guess error
425
+ * Adding tag filtering to archive command (`doing archive @done`)
data/bin/doing CHANGED
@@ -47,6 +47,7 @@ command :now do |c|
47
47
  c.action do |global_options,options,args|
48
48
  if options[:back]
49
49
  date = wwid.chronify(options[:back])
50
+
50
51
  raise "Unable to parse date string" if date.nil?
51
52
  else
52
53
  date = Time.now
@@ -135,6 +136,10 @@ end
135
136
  desc 'Add a completed item with @done(date). No argument finishes last entry.'
136
137
  arg_name 'entry'
137
138
  command :done do |c|
139
+ c.desc 'Include date'
140
+ c.default_value true
141
+ c.switch [:d,:date], :default_value => true
142
+
138
143
  c.desc 'Immediately archive the entry'
139
144
  c.default_value false
140
145
  c.switch [:a,:archive], :negatable => false, :default_value => false
@@ -163,6 +168,7 @@ command :done do |c|
163
168
  end
164
169
 
165
170
  section = wwid.guess_section(options[:s]) || options[:s].cap_first
171
+ donedate = options[:d] ? "(#{Time.now.strftime('%F %R')})" : ""
166
172
 
167
173
  if options[:e]
168
174
  raise "No EDITOR variable defined in environment" if ENV['EDITOR'].nil?
@@ -171,7 +177,7 @@ command :done do |c|
171
177
  input = wwid.fork_editor(input)
172
178
  if input
173
179
  title, note = wwid.format_input(input)
174
- title += " @done(#{Time.now.strftime('%F %R')})"
180
+ title += " @done#{donedate}"
175
181
  section = "Archive" if options[:a]
176
182
  wwid.add_item(title.cap_first, section.cap_first, {:note => note, :back => date})
177
183
  wwid.write(wwid.doing_file)
@@ -179,17 +185,17 @@ command :done do |c|
179
185
  raise "No content"
180
186
  end
181
187
  elsif args.length == 0 && STDIN.stat.size == 0
182
- wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :archive => options[:a], :back => date})
188
+ wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :archive => options[:a], :back => date, :date => options[:d]})
183
189
  else
184
190
  if args.length > 0
185
191
  title, note = wwid.format_input(args.join(" "))
186
- title += " @done(#{Time.now.strftime('%F %R')})"
192
+ title += " @done#{donedate}"
187
193
  section = "Archive" if options[:a]
188
194
  wwid.add_item(title.cap_first, section.cap_first, {:note => note, :back => date})
189
195
  wwid.write(wwid.doing_file)
190
196
  elsif STDIN.stat.size > 0
191
197
  title, note = wwid.format_input(STDIN.read)
192
- title += " @done(#{Time.now.strftime('%F %R')})"
198
+ title += " @done#{donedate}"
193
199
  section = options[:a] ? "Archive" : section
194
200
  wwid.add_item(title.cap_first, section.cap_first, {:note => note, :back => date})
195
201
  wwid.write(wwid.doing_file)
@@ -203,6 +209,13 @@ end
203
209
  desc 'Mark last X entries as @done'
204
210
  arg_name 'count'
205
211
  command :finish do |c|
212
+ c.desc 'Include date'
213
+ c.default_value true
214
+ c.switch [:d,:date], :default_value => true
215
+
216
+ c.desc 'Backdate to "date_string" (natural language)'
217
+ c.flag [:back]
218
+
206
219
  c.desc 'Archive entries'
207
220
  c.default_value false
208
221
  c.switch [:a,:archive], :negatable => false, :default_value => false
@@ -215,11 +228,19 @@ command :finish do |c|
215
228
 
216
229
  section = wwid.guess_section(options[:s]) || options[:s].cap_first
217
230
 
231
+ if options[:back]
232
+ date = wwid.chronify(options[:back])
233
+
234
+ raise "Unable to parse date string" if date.nil?
235
+ else
236
+ date = Time.now
237
+ end
238
+
218
239
  if args.length > 1
219
240
  raise "Only one argument allowed"
220
241
  elsif args.length == 0 || args[0] =~ /\d+/
221
242
  count = args[0] ? args[0].to_i : 1
222
- wwid.tag_last({:tags => ["done"], :count => count, :section => section, :archive => options[:a]})
243
+ wwid.tag_last({:tags => ["done"], :count => count, :section => section, :archive => options[:a], :date => options[:d], :back => date })
223
244
  else
224
245
  raise "Invalid argument (specify number of recent items to mark @done)"
225
246
  end
@@ -266,6 +287,24 @@ command :tag do |c|
266
287
  end
267
288
  end
268
289
 
290
+ desc 'Mark last entry as highlighted'
291
+ command :mark do |c|
292
+ c.desc 'Section'
293
+ c.default_value wwid.current_section
294
+ c.flag [:s,:section], :default_value => wwid.current_section
295
+
296
+ c.desc 'Remove mark'
297
+ c.default_value false
298
+ c.switch [:r,:remove], :negatable => false, :default_value => false
299
+
300
+
301
+ c.action do |global_options,options,args|
302
+ mark = wwid.config['marker_tag'] || "flagged"
303
+ wwid.tag_last({:tags => [mark], :section => options[:s], :remove => options[:r]})
304
+ end
305
+ end
306
+
307
+
269
308
 
270
309
  desc 'List all entries'
271
310
  arg_name 'section [tags]'
@@ -286,13 +325,12 @@ command :show do |c|
286
325
  c.default_value 'asc'
287
326
  c.flag [:s,:sort], :default_value => 'asc'
288
327
 
289
- c.desc 'Output to csv'
290
- c.default_value false
291
- c.switch [:csv], :default_value => false, :negatable => false
328
+ c.desc 'Output to format'
329
+ c.flag [:o,:output]
292
330
 
293
331
  c.desc 'Show time intervals on @done tasks'
294
332
  c.default_value false
295
- c.switch [:t,:times], :default_value => false
333
+ c.switch [:t,:times], :default_value => true
296
334
 
297
335
  c.desc 'Show intervals with totals at the end of output'
298
336
  c.default_value false
@@ -327,7 +365,7 @@ command :show do |c|
327
365
 
328
366
  options[:t] = true if options[:totals]
329
367
 
330
- puts wwid.list_section({:section => section, :count => options[:c].to_i, :tag_filter => tag_filter, :age => options[:a], :order => options[:s], :csv => options[:csv], :times => options[:t]})
368
+ puts wwid.list_section({:section => section, :count => options[:c].to_i, :tag_filter => tag_filter, :age => options[:a], :order => options[:s], :output => options[:output], :times => options[:t], :highlight => true})
331
369
 
332
370
  puts wwid.tag_times if options[:totals]
333
371
 
@@ -341,6 +379,15 @@ command :recent do |c|
341
379
  c.desc 'Section'
342
380
  c.default_value wwid.current_section
343
381
  c.flag [:s,:section], :default_value => wwid.current_section
382
+
383
+ c.desc 'Show time intervals on @done tasks'
384
+ c.default_value false
385
+ c.switch [:t,:times], :default_value => true
386
+
387
+ c.desc 'Show intervals with totals at the end of output'
388
+ c.default_value false
389
+ c.switch [:totals], :default_value => false, :negatable => true
390
+
344
391
  c.action do |global_options,options,args|
345
392
 
346
393
  section = wwid.guess_section(options[:s]) || options[:s].cap_first
@@ -351,7 +398,11 @@ command :recent do |c|
351
398
  else
352
399
  count = 10
353
400
  end
354
- puts wwid.recent(count,section.cap_first)
401
+ options[:t] = true if options[:totals]
402
+
403
+ puts wwid.recent(count,section.cap_first,{ :times => options[:t] })
404
+
405
+ puts wwid.tag_times if options[:totals]
355
406
  end
356
407
  end
357
408
  end
@@ -360,17 +411,20 @@ desc 'List entries from today'
360
411
  command :today do |c|
361
412
  c.desc 'Show time intervals on @done tasks'
362
413
  c.default_value false
363
- c.switch [:t,:times], :default_value => false
414
+ c.switch [:t,:times], :default_value => true
364
415
 
365
416
  c.desc 'Show time totals at the end of output'
366
417
  c.default_value false
367
418
  c.switch [:totals], :default_value => false, :negatable => true
368
419
 
420
+ c.desc 'Output to format'
421
+ c.flag [:o,:output]
422
+
369
423
  c.action do |global_options,options,args|
370
424
 
371
425
  options[:t] = true if options[:totals]
372
426
 
373
- puts wwid.today(options[:t]).strip
427
+ puts wwid.today(options[:t],options[:output]).chomp
374
428
 
375
429
  puts wwid.tag_times if options[:totals]
376
430
  end
@@ -386,7 +440,7 @@ end
386
440
  desc 'List sections'
387
441
  command :sections do |c|
388
442
  c.action do |global_options,options,args|
389
- puts wwid.sections.join(", ")
443
+ puts wwid.sections.join("\t")
390
444
  end
391
445
  end
392
446
 
@@ -420,13 +474,12 @@ command :view do |c|
420
474
  c.desc 'Count to display (override view settings)'
421
475
  c.flag [:c,:count], :must_match => /^\d+$/, :type => Integer
422
476
 
423
- c.desc 'Output to csv'
424
- c.default_value 'false'
425
- c.switch [:csv], :default_value => false, :negatable => false
477
+ c.desc 'Output to format'
478
+ c.flag [:o,:output]
426
479
 
427
480
  c.desc 'Show time intervals on @done tasks'
428
481
  c.default_value false
429
- c.switch [:t,:times], :default_value => false
482
+ c.switch [:t,:times], :default_value => true
430
483
 
431
484
  c.desc 'Show intervals with totals at the end of output'
432
485
  c.default_value false
@@ -455,7 +508,7 @@ command :view do |c|
455
508
  if view['tags'].class == Array
456
509
  tag_filter['tags'] = view['tags'].map{|tag| tag.strip }
457
510
  else
458
- tag_filter['tags'] = view['tags'].split(" ").map{|tag| tag.strip }
511
+ tag_filter['tags'] = view['tags'].gsub(/[, ]+/," ").split(" ").map{|tag| tag.strip }
459
512
  end
460
513
  tag_filter['bool'] = view.has_key?('tags_bool') && !view['tags_bool'].nil? ? view['tags_bool'].upcase : "OR"
461
514
  end
@@ -464,8 +517,8 @@ command :view do |c|
464
517
  section = options[:s] ? section : view.has_key?('section') ? view['section'] : wwid.current_section
465
518
  order = view.has_key?('order') ? view['order'] : "asc"
466
519
  options[:t] = true if options[:totals]
467
-
468
- puts wwid.list_section({:section => section, :count => count, :template => template, :format => format, :order => order, :tag_filter => tag_filter, :csv => options[:csv], :tags_color => tags_color, :times => options[:t] })
520
+ options[:output].downcase! if options[:output]
521
+ puts wwid.list_section({:section => section, :count => count, :template => template, :format => format, :order => order, :tag_filter => tag_filter, :output => options[:output], :tags_color => tags_color, :times => options[:t], :highlight => true })
469
522
 
470
523
  puts wwid.tag_times if options[:totals]
471
524
  else
@@ -477,25 +530,40 @@ end
477
530
  desc 'List available custom views'
478
531
  command :views do |c|
479
532
  c.action do |global_options,options,args|
480
- puts wwid.views.join(", ")
533
+ puts wwid.views.join("\t")
481
534
  end
482
535
  end
483
536
 
484
- desc 'Move all but the most recent 5 entries in a section to Archive'
537
+ desc 'Move entries in between sections'
485
538
  arg_name 'section'
486
539
  default_value wwid.current_section
487
540
  command :archive do |c|
488
- c.desc 'Count to keep'
541
+ c.desc 'Count to keep (ignored if archiving by tag)'
489
542
  c.default_value 5
490
543
  c.flag [:k,:keep], :default_value => 5, :must_match => /^\d+$/, :type => Integer
491
544
 
545
+ c.desc 'Move entries to'
546
+ c.default_value "Archive"
547
+ c.flag [:t,:to], :default_value => "Archive"
548
+
549
+ c.desc 'Tag boolean'
550
+ c.default_value "AND"
551
+ c.flag [:b,:bool], :default_value => "AND"
552
+
492
553
  c.action do |global_options,options,args|
493
554
  if args.length > 0
494
- section = args.join(" ").cap_first
555
+ if args[0] =~ /^@\S+/
556
+ section = "all"
557
+ tags = args.map {|t| t.sub(/^@/,'').strip }
558
+ else
559
+ section = args[0].cap_first
560
+ tags = args.length > 1 ? args[1..-1].map {|t| t.sub(/^@/,'').strip } : nil
561
+ end
495
562
  else
496
563
  section = wwid.current_section
564
+ tags = nil
497
565
  end
498
- wwid.archive(section,options[:k])
566
+ wwid.archive(section,options[:k],options[:t],tags,options[:b])
499
567
  end
500
568
  end
501
569
 
@@ -6,6 +6,7 @@ require 'pp'
6
6
  require 'csv'
7
7
  require 'tempfile'
8
8
  require 'chronic'
9
+ require 'haml'
9
10
  require 'doing/wwid.rb'
10
11
 
11
12
  DOING_CONFIG = "~/.doingrc"
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '0.2.4'
2
+ VERSION = '0.2.5pre'
3
3
  end
@@ -5,6 +5,7 @@ class String
5
5
  m.upcase
6
6
  end
7
7
  end
8
+
8
9
  end
9
10
 
10
11
  class WWID
@@ -60,6 +61,8 @@ class WWID
60
61
  'order' => "asc"
61
62
  }
62
63
  }
64
+ @config['marker_tag'] ||= 'flagged'
65
+ @config['marker_color'] ||= 'red'
63
66
 
64
67
  @doing_file = File.expand_path(config['doing_file'])
65
68
  @current_section = config['current_section']
@@ -213,8 +216,9 @@ class WWID
213
216
  @content[title.cap_first] = {'original' => "#{title}:", 'items' => []}
214
217
  end
215
218
 
216
- def guess_section(frag)
217
- sections.each {|section| return section if frag.downcase == section.downcase}
219
+ def guess_section(frag,guessed=false)
220
+ return "All" if frag =~ /all/i
221
+ sections.each {|section| return section.cap_first if frag.downcase == section.downcase }
218
222
  section = false
219
223
  re = frag.split('').join(".*?")
220
224
  sections.each {|sect|
@@ -224,18 +228,25 @@ class WWID
224
228
  break
225
229
  end
226
230
  }
227
- unless section
228
- alt = guess_view(frag)
231
+ unless section || guessed
232
+ alt = guess_view(frag,true)
229
233
  if alt
230
234
  raise "Did you mean `doing view #{alt}`?"
231
235
  else
232
- raise "Invalid section: #{frag}"
236
+ print "Create a new section called #{frag.cap_first} (y/N)?"
237
+ input = STDIN.gets
238
+ if input =~ /^y/i
239
+ add_section(frag.cap_first)
240
+ write(doing_file)
241
+ return frag.cap_first
242
+ end
243
+ raise "Unknown section: #{frag}"
233
244
  end
234
245
  end
235
- section.cap_first
246
+ section ? section.cap_first : section
236
247
  end
237
248
 
238
- def guess_view(frag)
249
+ def guess_view(frag,guessed=false)
239
250
  views.each {|view| return view if frag.downcase == view.downcase}
240
251
  view = false
241
252
  re = frag.split('').join(".*?")
@@ -246,12 +257,12 @@ class WWID
246
257
  break
247
258
  end
248
259
  }
249
- unless view
250
- alt = guess_section(frag)
260
+ unless view || guessed
261
+ alt = guess_section(frag,true)
251
262
  if alt
252
263
  raise "Did you mean `doing show #{alt}`?"
253
264
  else
254
- raise "Invalid view: #{frag}"
265
+ raise "Unknown view: #{frag}"
255
266
  end
256
267
  end
257
268
  view
@@ -278,6 +289,7 @@ class WWID
278
289
  opt[:tags] ||= ["done"]
279
290
  opt[:date] ||= false
280
291
  opt[:remove] ||= false
292
+ opt[:back] ||= Time.now
281
293
 
282
294
  opt[:section] = guess_section(opt[:section])
283
295
 
@@ -290,11 +302,11 @@ class WWID
290
302
  title = item['title']
291
303
  opt[:tags].each {|tag|
292
304
  if opt[:remove]
293
- title.gsub!(/ @#{tag}/,'')
305
+ title.gsub!(/(^| )@#{tag}/,'')
294
306
  else
295
307
  unless title =~ /@#{tag}/
296
- if tag == "done" || opt[:date]
297
- title += " @#{tag}(#{Time.now.strftime('%F %R')})"
308
+ if (tag == "done" && opt[:date]) || opt[:date]
309
+ title += " @#{tag}(#{opt[:back].strftime('%F %R')})"
298
310
  else
299
311
  title += " @#{tag}"
300
312
  end
@@ -305,9 +317,9 @@ class WWID
305
317
  }
306
318
 
307
319
  if opt[:archive] && opt[:section] != "Archive"
308
- archived = @content[opt[:section]]['items'][0..opt[:count]-1]
320
+ archived = @content[opt[:section]]['items'][0..opt[:count]-1].concat(@content['Archive']['items'])
309
321
  @content[opt[:section]]['items'] = @content[opt[:section]]['items'][opt[:count]..-1]
310
- @content['Archive']['items'] = archived + @content['Archive']['items']
322
+ @content['Archive']['items'] = archived
311
323
  end
312
324
 
313
325
  write(@doing_file)
@@ -324,7 +336,7 @@ class WWID
324
336
  end
325
337
  @content.each {|title, section|
326
338
  output += section['original'] + "\n"
327
- output += list_section({:section => title, :template => "\t- %date | %title%note"})
339
+ output += list_section({:section => title, :template => "\t- %date | %title%note", :highlight => false})
328
340
  }
329
341
  output += @other_content_bottom.join("\n")
330
342
  if file.nil?
@@ -381,18 +393,22 @@ class WWID
381
393
  opt[:tag_filter] ||= false
382
394
  opt[:tags_color] ||= false
383
395
  opt[:times] ||= false
384
-
396
+ # opt[:highlight] ||= true
397
+ section = ""
385
398
  if opt[:section].nil?
386
- opt[:section] = @content[choose_section]
399
+ section = choose_section
400
+ opt[:section] = @content[section]
387
401
  elsif opt[:section].class == String
388
402
  if opt[:section] =~ /^all$/i
389
403
  combined = {'items' => []}
390
404
  @content.each {|k,v|
391
405
  combined['items'] += v['items']
392
406
  }
407
+ section = opt[:tag_filter] ? opt[:tag_filter]['tags'].map {|tag| "@#{tag}"}.join(" + ") : "doing"
393
408
  opt[:section] = combined
394
409
  else
395
- opt[:section] = @content[guess_section(opt[:section])]
410
+ section = guess_section(opt[:section])
411
+ opt[:section] = @content[section]
396
412
  end
397
413
  end
398
414
 
@@ -431,6 +447,7 @@ class WWID
431
447
  items.delete_if {|item|
432
448
  item['date'] < Date.today.to_time
433
449
  }.reverse!
450
+ section = Time.now.strftime('%A, %B %d')
434
451
  else
435
452
  if opt[:age] =~ /oldest/i
436
453
  items = items[0..count]
@@ -445,20 +462,71 @@ class WWID
445
462
 
446
463
  out = ""
447
464
 
448
- if opt[:csv]
449
- output = [['date','title','note'].to_csv]
465
+ if opt[:output]
466
+ raise "Unknown output format" unless opt[:output] =~ /(html|csv)/
467
+ end
468
+
469
+ if opt[:output] == "csv"
470
+ output = [CSV.generate_line(['date','title','note'])]
450
471
  items.each {|i|
451
472
  note = ""
452
473
  if i['note']
453
474
  arr = i['note'].map{|line| line.strip}.delete_if{|e| e =~ /^\s*$/}
454
475
  note = arr.join("\n") unless arr.nil?
455
476
  end
456
- output.push([i['date'],i['title'],note].to_csv)
477
+ output.push(CSV.generate_line([i['date'],i['title'],note]))
457
478
  }
458
- out = output.join()
459
- else
479
+ out = output.join("")
480
+ elsif opt[:output] == "html"
481
+ page_title = section
482
+ items_out = []
483
+ items.each {|i|
484
+ # if i.has_key?('note')
485
+ # note = '<span class="note">' + i['note'].map{|n| n.strip }.join('<br>') + '</span>'
486
+ # else
487
+ # note = ''
488
+ # end
489
+ items_out << {
490
+ :date => i['date'].strftime('%a %-I:%M%p'),
491
+ :title => i['title'].gsub(/(@[^ \(]+(\(.*?\))?)/is,'<span class="tag">\1</span>').strip, #+ " #{note}"
492
+ :note => i['note']
493
+ }
494
+ }
495
+ style = "body{background:#faf9f5;color:#333;font-family:Palatino,Georgia,serif;font-size:16px;line-height:120%;text-align:justify;padding:20px}h1{text-align:left;position:relative;left:220px;margin-bottom:1em}ul{list-style-position:outside;position:relative;left:170px;margin-right:170px;text-align:left}ul li{list-style-type:none;border-left:solid 1px #ccc;padding-left:10px;line-height:1.75}ul li .date{font-size:14px;position:absolute;left:-82px;color:#7d9ca2;text-align:right;width:110px;line-height:2}ul li .tag{color:#999}ul li .note{display:block;color:#666;padding:0 0 0 22px;line-height:1.4;font-size:15px}ul li .note:before{content:'\\25BA';font-weight:300;position:absolute;left:40px;font-size:8px;color:#aaa;line-height:3}ul li:hover .note{display:block}"
496
+ template =<<EOT
497
+ !!!
498
+ %html
499
+ %head
500
+ %meta{"charset" => "utf-8"}/
501
+ %meta{"content" => "IE=edge,chrome=1", "http-equiv" => "X-UA-Compatible"}/
502
+ %title what are you doing?
503
+ %style= @style
504
+ %body
505
+ %header
506
+ %h1= @page_title
507
+ %article
508
+ %ul
509
+ - @items.each do |i|
510
+ %li
511
+ %span.date= i[:date]
512
+ = i[:title]
513
+ - if i[:note]
514
+ %span.note= i[:note].map{|n| n.strip }.join('<br>')
515
+ EOT
516
+ engine = Haml::Engine.new(template)
517
+ puts engine.render(Object.new, { :@items => items_out, :@page_title => page_title, :@style => style })
460
518
 
519
+ else
461
520
  items.each {|item|
521
+
522
+ if opt[:highlight] && item['title'] =~ /@#{@config['marker_tag']}\b/i
523
+ flag = colors[@config['marker_color']]
524
+ reset = colors['default']
525
+ else
526
+ flag = ""
527
+ reset = ""
528
+ end
529
+
462
530
  if (item.has_key?('note') && !item['note'].empty?) && @config[:include_notes]
463
531
  note_lines = item['note'].delete_if{|line| line =~ /^\s*$/ }.map{|line| "\t\t" + line.sub(/^\t\t/,'') }
464
532
  if opt[:wrap_width] && opt[:wrap_width] > 0
@@ -500,11 +568,12 @@ class WWID
500
568
  item['date'].strftime('%b %d %Y, %-I:%M%P')
501
569
  end
502
570
  }
571
+
503
572
  output.sub!(/%title/) {|m|
504
573
  if opt[:wrap_width] && opt[:wrap_width] > 0
505
- item['title'].gsub(/(.{1,#{opt[:wrap_width]}})(\s+|\Z)/, "\\1\n\t ").strip
574
+ flag+item['title'].gsub(/(.{1,#{opt[:wrap_width]}})(\s+|\Z)/, "\\1\n\t ").chomp+reset
506
575
  else
507
- item['title'].strip
576
+ flag+item['title'].chomp+reset
508
577
  end
509
578
  }
510
579
  if opt[:tags_color]
@@ -528,20 +597,94 @@ class WWID
528
597
  return out
529
598
  end
530
599
 
531
- def archive(section=nil,count=10)
600
+ def archive(section="Currently",count=5,destination=nil,tags=nil,bool=nil,export=nil)
601
+
532
602
  section = choose_section if section.nil? || section =~ /choose/i
533
- section = guess_section(section)
534
- if sections.include?(section)
535
- items = @content[section]['items']
536
- return if items.length < count
537
- @content[section]['items'] = items[0..count-1]
538
- add_section('Archive') unless sections.include?('Archive')
539
- @content['Archive']['items'] += items[count..-1]
540
- write(@doing_file)
603
+ archive_all = section =~ /all/i # && !(tags.nil? || tags.empty?)
604
+ section = guess_section(section) unless archive_all
605
+
606
+ if destination =~ /archive/i && !sections.include?("Archive")
607
+ add_section("Archive")
608
+ end
609
+
610
+ destination = guess_section(destination)
611
+
612
+ if sections.include?(destination) && (sections.include?(section) || archive_all)
613
+ if archive_all
614
+ to_archive = sections.dup
615
+ to_archive.delete(destination)
616
+ to_archive.each {|source,v|
617
+ do_archive(source, destination, { :count => count, :tags => tags, :bool => bool, :label => true })
618
+ }
619
+ else
620
+ do_archive(section, destination, { :count => count, :tags => tags, :bool => bool, :label => true })
621
+ end
622
+
623
+ write(doing_file)
624
+ else
625
+ raise "Either source or destination does not exist"
541
626
  end
542
627
  end
543
628
 
629
+ def do_archive(section, destination, opt={})
630
+ count = opt[:count] || 5
631
+ tags = opt[:tags] || []
632
+ bool = opt[:bool] || "AND"
633
+ label = opt[:label] || false
544
634
 
635
+ items = @content[section]['items']
636
+ moved_items = []
637
+
638
+ if tags && !tags.empty?
639
+ items.delete_if {|item|
640
+ if bool =~ /(AND|ALL)/
641
+ score = 0
642
+ tags.each {|tag|
643
+ score += 1 if item['title'] =~ /@#{tag}/i
644
+ }
645
+ res = score < tags.length
646
+ moved_items.push(item) if res
647
+ res
648
+ elsif bool =~ /NONE/
649
+ del = false
650
+ tags.each {|tag|
651
+ del = true if item['title'] =~ /@#{tag}/i
652
+ }
653
+ moved_items.push(item) if del
654
+ del
655
+ elsif bool =~ /(OR|ANY)/
656
+ del = true
657
+ tags.each {|tag|
658
+ del = false if item['title'] =~ /@#{tag}/i
659
+ }
660
+ moved_items.push(item) if del
661
+ del
662
+ end
663
+ }
664
+ moved_items.each {|item|
665
+ if label
666
+ item['title'] += " @from(#{section})" unless section == "Currently" || item['title'] =~ /@from\(/
667
+ end
668
+ }
669
+ @content[section]['items'] = moved_items
670
+ @content[destination]['items'] += items
671
+ else
672
+
673
+ return if items.length < count
674
+ if count == 0
675
+ @content[section]['items'] = []
676
+ else
677
+ @content[section]['items'] = items[0..count-1]
678
+ end
679
+
680
+ items.each{|item|
681
+ if label
682
+ item['title'] += " @from(#{section})" unless section == "Currently"
683
+ end
684
+ }
685
+ @content[destination]['items'] += items[count..-1]
686
+ end
687
+ end
545
688
 
546
689
  def colors
547
690
  color = {}
@@ -588,26 +731,28 @@ class WWID
588
731
  list_section({:section => @current_section, :wrap_width => cfg['wrap_width'], :count => 0, :format => cfg['date_format'], :template => cfg['template'], :order => order})
589
732
  end
590
733
 
591
- def today(times=false)
734
+ def today(times=true,output=nil)
592
735
  cfg = @config['templates']['today']
593
- 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})
736
+ 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})
594
737
  end
595
738
 
596
- def recent(count=10,section=nil)
739
+ def recent(count=10,section=nil,opt={})
740
+ times = opt[:t] || true
597
741
  cfg = @config['templates']['recent']
598
742
  section ||= @current_section
599
743
  section = guess_section(section)
600
- list_section({:section => section, :wrap_width => cfg['wrap_width'], :count => count, :format => cfg['date_format'], :template => cfg['template'], :order => "asc"})
744
+ list_section({:section => section, :wrap_width => cfg['wrap_width'], :count => count, :format => cfg['date_format'], :template => cfg['template'], :order => "asc", :times => times })
601
745
  end
602
746
 
603
- def last
747
+ def last(times=true)
604
748
  cfg = @config['templates']['last']
605
- list_section({:section => @current_section, :wrap_width => cfg['wrap_width'], :count => 1, :format => cfg['date_format'], :template => cfg['template']})
749
+ list_section({:section => @current_section, :wrap_width => cfg['wrap_width'], :count => 1, :format => cfg['date_format'], :template => cfg['template'], :times => times})
606
750
  end
607
751
 
608
752
  def tag_times
609
753
  output = []
610
- return "" if @timers.length == 0
754
+ # return "" if @timers.length == 0
755
+
611
756
  max = @timers.keys.sort_by {|k| k.length }.reverse[0].length + 1
612
757
 
613
758
  total = @timers.delete("All")
@@ -619,7 +764,10 @@ class WWID
619
764
  end
620
765
  output.push("#{k}:#{spacer}#{"%02d:%02d:%02d" % fmt_time(v)}")
621
766
  }
622
- output.empty? ? "" : "\n--- Tag Totals ---\n" + output.join("\n") + "\n\nTotal tracked: #{"%02d:%02d:%02d" % fmt_time(total)}\n"
767
+
768
+ output = output.empty? ? "" : "\n--- Tag Totals ---\n" + output.join("\n")
769
+ output += "\n\nTotal tracked: #{"%02d:%02d:%02d" % fmt_time(total)}\n"
770
+ output
623
771
  end
624
772
 
625
773
  private
@@ -666,7 +814,6 @@ end
666
814
 
667
815
 
668
816
 
669
-
670
817
  # infile = "~/Dropbox/nvALT2.2/?? What was I doing.md"
671
818
 
672
819
  # wwid = WWID.new(infile)
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.4
4
+ version: 0.2.5pre
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-03-19 00:00:00.000000000 Z
11
+ date: 2014-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -72,6 +72,20 @@ dependencies:
72
72
  - - '='
73
73
  - !ruby/object:Gem::Version
74
74
  version: 2.9.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: haml
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '='
80
+ - !ruby/object:Gem::Version
81
+ version: 4.0.3
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '='
87
+ - !ruby/object:Gem::Version
88
+ version: 4.0.3
75
89
  - !ruby/object:Gem::Dependency
76
90
  name: chronic
77
91
  requirement: !ruby/object:Gem::Requirement
@@ -130,9 +144,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
144
  version: '0'
131
145
  required_rubygems_version: !ruby/object:Gem::Requirement
132
146
  requirements:
133
- - - '>='
147
+ - - '>'
134
148
  - !ruby/object:Gem::Version
135
- version: '0'
149
+ version: 1.3.1
136
150
  requirements: []
137
151
  rubyforge_project:
138
152
  rubygems_version: 2.2.2