doing 1.0.6pre → 1.0.7pre

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: 31cbf5627a0818d3252c9f75265372652b7b22df
4
- data.tar.gz: 3c70bc7a7b81dd3ce0db6d0e291dd4d4cf45d29f
3
+ metadata.gz: 416eb3b0c0b4892d106c8e6431a5925b393e587c
4
+ data.tar.gz: 47b5a29f17ce836404630379612a0c82e0811a97
5
5
  SHA512:
6
- metadata.gz: 68287fcedc4d02dc46fa61e6587f4c3d7cf33f6727a9a03a9c155b9ecce63244deca08451be86be9d0c0260221d75b3478224c2c52edf538fc161a4bde191662
7
- data.tar.gz: a20c0b2ff59f6125e7d5f0046034a3bc1825546d3f8c01b0b72600285325a0ef719e97f4ead9beafb9954ec82e465263636caf152b08c9f93d6f22bd885fa588
6
+ metadata.gz: 4fb329e66f43e85a03a2c256d1ef0b68db8b8c917c974de5d39c5de805c71b9c2b7a0e4a5357cc4e5fe854ffdf2bfcb266ec60b1537e8426736023179b5dd541
7
+ data.tar.gz: a1057480b5758c883d6602a6e50b328b68972b9566888516a84a0b5d57a76c25e56031e725f6036bab35581a4bb9c37ead73b4a54cf0d7b59a800dd473587610
data/README.md CHANGED
@@ -127,6 +127,7 @@ The config also contains templates for various command outputs. Include placehol
127
127
  - `%[color]`: color can be black, red, green, blue, yellow, magenta, cyan or white
128
128
  - you can prefix "bg" to affect background colors (%bgyellow)
129
129
  - prefix "bold" and "boldbg" for strong colors (%boldgreen, %boldbgblue)
130
+ - there are some random special combo colors. Use `doing colors` to see the list
130
131
  - `%interval`: when used with the `-t` switch on the `show` command, it will display the time between a timestamp or `@start(date)` tag and the `@done(date)` tag, if it exists. Otherwise, it will remain empty.
131
132
 
132
133
  Date formats are based on Ruby [strftime](http://www.ruby-doc.org/stdlib-2.1.1/libdoc/date/rdoc/Date.html#method-i-strftime) formatting.
@@ -309,9 +310,9 @@ As mentioned above, `finish` also accepts `--back "2 hours"` (sets the finish da
309
310
 
310
311
  ... will mark the last three entries as "@client @cancelled." Add `-r` as a switch to remove the listed tags instead.
311
312
 
312
- `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.
313
+ `note` lets you append a note to the last entry. You can specify a section to grab the last entry from with `-s section_name`. `-e` will open your $EDITOR for typing the note, but you can also just include it on the command line after any flags. You can also pipe a note in on STDIN (`echo "fun stuff"|doing note`). If you don't use the `-r` switch, new notes will be appended to the existing notes, and using the `-e` switch will let you edit and add to an existing 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.
313
314
 
314
- 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.
315
+ 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 text to any of the creation commands which has multiple lines, everything after the first line break will become the note.
315
316
 
316
317
  #### Displaying entries:
317
318
 
@@ -451,10 +452,36 @@ I'll try to document some of the code structure as I flesh it out. I'm currently
451
452
 
452
453
  ### Changelog
453
454
 
455
+
456
+ #### 1.0.7 / 2014-09-23
457
+
458
+ * fix for -v option
459
+ * Slightly fuzzier searching in the grep command
460
+ * cleaner exits, only_timed key for view configs
461
+ * making the note command append new notes better, and load existing notes in the editor if -e is called
462
+ * handle multiple tag input in 'show' tag filter
463
+ * Global tag operations, better reporting
464
+
454
465
  #### 1.0.4pre
455
466
 
456
467
  * Improved HTML output
457
468
  * --only_timed option for view/show commands that only outputs items with elapsed timers (interval between start and done dates)
469
+ * add seconds for timed items in CSV output, run --only_timed before chopping off --count #
470
+ * fix for 1.8.7 Dir.home issue
471
+ * version bump
472
+ * don't show tag totals with zero times
473
+ * zsh completion for doing
474
+ * HTML styling
475
+ * --only_timed option
476
+ * added zsh completion file to README.md
477
+ * add zsh completion file
478
+
479
+ #### 1.0.3pre
480
+
481
+ * done command: making --took modify start time if --back isn't specified
482
+ * Cleaned up time totals, improved HTML output
483
+ * fixes for --back and --took parsing
484
+ * Adding more complete terminal reporting to archive command
458
485
 
459
486
  #### 1.0.0pre
460
487
 
data/bin/doing CHANGED
@@ -117,15 +117,22 @@ command :note do |c|
117
117
 
118
118
  if options[:e] || (args.length == 0 && STDIN.stat.size == 0 && !options[:r])
119
119
  raise "No EDITOR variable defined in environment" if ENV['EDITOR'].nil?
120
- input = ""
121
- input += args.join(" ") if args.length > 0
120
+
121
+ input = args.length > 0 ? args.join(" ") : ""
122
+
123
+ prev_input = wwid.last_note(section)
124
+ if prev_input.class == Array
125
+ prev_input = prev_input.join("\n")
126
+ end
127
+ input = prev_input + input
128
+
122
129
  input = wwid.fork_editor(input)
123
130
  if input
124
131
  title, note = wwid.format_input(input)
125
132
  note.insert(0, title)
126
- wwid.note_last(section, note, options[:r])
133
+ wwid.note_last(section, note, true)
127
134
  else
128
- raise "No content"
135
+ raise "No content, cancelled"
129
136
  end
130
137
  else
131
138
  if args.length > 0
@@ -423,7 +430,7 @@ command :tag do |c|
423
430
  c.default_value wwid.current_section
424
431
  c.flag [:s,:section], :default_value => wwid.current_section
425
432
 
426
- c.desc 'How many recent entries to tag'
433
+ c.desc 'How many recent entries to tag (0 for all)'
427
434
  c.default_value 1
428
435
  c.flag [:c,:count], :default_value => 1
429
436
 
@@ -442,7 +449,6 @@ command :tag do |c|
442
449
 
443
450
  section = wwid.guess_section(options[:s]) || options[:s].cap_first
444
451
 
445
- count = options[:c].to_i
446
452
  if args.join("") =~ /,/
447
453
  tags = args.join("").split(/,/)
448
454
  else
@@ -451,6 +457,22 @@ command :tag do |c|
451
457
 
452
458
  tags.map!{|tag| tag.sub(/^@/,'').strip }
453
459
 
460
+ count = options[:c].to_i
461
+
462
+ if count == 0
463
+ if options[:r]
464
+ print "Are you sure you want to remove #{tags.join(" and ")} from all records? (y/N) "
465
+ else
466
+ print "Are you sure you want to add #{tags.join(" and ")} to all records? (y/N) "
467
+ end
468
+
469
+ res = STDIN.gets
470
+
471
+ unless res.strip =~ /^y(es)?$/i
472
+ raise "Cancelled"
473
+ end
474
+ end
475
+
454
476
  wwid.tag_last({:tags => tags, :count => count, :section => section, :date => options[:d], :remove => options[:r]})
455
477
  end
456
478
  end
@@ -476,6 +498,7 @@ end
476
498
 
477
499
 
478
500
  desc 'List all entries'
501
+ long_desc 'The argument can be a section name, tag(s) or both. "pick" or "choose" as an argument will offer a section menu.'
479
502
  arg_name 'section [tags]'
480
503
  command :show do |c|
481
504
  c.desc 'Tag boolean (AND,OR,NONE)'
@@ -515,15 +538,27 @@ command :show do |c|
515
538
  if args.length > 0
516
539
  if args[0] =~ /^all$/i
517
540
  section = "All"
541
+ args.shift
542
+ elsif args[0] =~ /^(choose|pick)$/i
543
+ section = wwid.choose_section
544
+ args.shift
518
545
  elsif args[0] =~ /^@/
519
546
  section = "All"
520
- tags.push(args[0].sub(/^@/,''))
521
547
  else
522
548
  section = wwid.guess_section(args[0])
523
549
  raise "No such section: #{args[0]}" unless section
550
+ args.shift
524
551
  end
525
- if args.length > 1
526
- tags += args[1..-1].map{|tag| tag.sub(/^@/,'').strip}
552
+ if args.length > 0
553
+ args.each {|arg|
554
+ if arg =~ /,/
555
+ arg_tags = arg.split(/,/).each {|tag|
556
+ tags.push(tag.strip.sub(/^@/,''))
557
+ }
558
+ else
559
+ tags.push(arg.strip.sub(/^@/,''))
560
+ end
561
+ }
527
562
  end
528
563
  else
529
564
  section = wwid.current_section
@@ -572,7 +607,7 @@ command :grep do |c|
572
607
 
573
608
  options[:t] = true if options[:totals]
574
609
 
575
- puts wwid.list_section({:search => args.join, :section => section, :output => options[:output], :times => options[:t], :highlight => true, :totals => options[:totals], :only_timed => options[:only_timed]})
610
+ puts wwid.list_section({:search => args.join(' '), :section => section, :output => options[:output], :times => options[:t], :highlight => true, :totals => options[:totals], :only_timed => options[:only_timed]})
576
611
 
577
612
  end
578
613
  end
@@ -690,6 +725,24 @@ command :add_section do |c|
690
725
  end
691
726
  end
692
727
 
728
+ desc 'List available color variables for configuration templates and views'
729
+ command :colors do |c|
730
+ c.action do |global_options,options,args|
731
+ clrs = wwid.colors
732
+ bgs = []
733
+ fgs = []
734
+ clrs.each {|k,v|
735
+ if k =~ /bg/
736
+ bgs.push("#{v} #{clrs['default']} <-- #{k}")
737
+ else
738
+ fgs.push("#{v}XXXX#{clrs['default']} <-- #{k}")
739
+ end
740
+ }
741
+ puts fgs.join("\n")
742
+ puts bgs.join("\n")
743
+ end
744
+ end
745
+
693
746
  desc 'Display a user-created view'
694
747
  arg_name 'view_name'
695
748
  command :view do |c|
@@ -712,7 +765,7 @@ command :view do |c|
712
765
 
713
766
  c.desc 'Only show items with recorded time intervals'
714
767
  c.default_value false
715
- c.switch [:only_timed], :default_value => false, :negatable => false
768
+ c.switch [:only_timed], :default_value => false, :negatable => true
716
769
 
717
770
  c.action do |global_options,options,args|
718
771
  if args.empty?
@@ -727,6 +780,12 @@ command :view do |c|
727
780
 
728
781
  view = wwid.get_view(title)
729
782
  if view
783
+ if (view.has_key?('only_timed') && view['only_timed']) || options[:only_timed]
784
+ only_timed = true
785
+ else
786
+ only_timed = false
787
+ end
788
+
730
789
  template = view.has_key?('template') ? view['template'] : nil
731
790
  format = view.has_key?('date_format') ? view['date_format'] : nil
732
791
  tags_color = view.has_key?('tags_color') ? view['tags_color'] : nil
@@ -747,7 +806,7 @@ command :view do |c|
747
806
  order = view.has_key?('order') ? view['order'] : "asc"
748
807
  options[:t] = true if options[:totals]
749
808
  options[:output].downcase! if options[:output]
750
- 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, :totals => options[:totals], :only_timed => options[:only_timed] })
809
+ 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, :totals => options[:totals], :only_timed => only_timed })
751
810
  else
752
811
  raise "View #{title} not found in config"
753
812
  end
@@ -900,7 +959,7 @@ pre do |global,command,options,args|
900
959
  end
901
960
  wwid.config[:include_notes] = false unless global[:notes]
902
961
  if global[:version]
903
- puts "doing v" + Doing::VERSION
962
+ $stdout.puts "doing v" + Doing::VERSION
904
963
  end
905
964
 
906
965
  # Return true to proceed; false to abort and not call the
@@ -917,8 +976,7 @@ post do |global,command,options,args|
917
976
  end
918
977
 
919
978
  on_error do |exception|
920
- # Error logic here
921
- # return false to skip default error handling
979
+ # puts exception.message
922
980
  true
923
981
  end
924
982
 
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '1.0.6pre'
2
+ VERSION = '1.0.7pre'
3
3
  end
data/lib/doing/wwid.rb CHANGED
@@ -363,6 +363,17 @@ class WWID
363
363
  @results.push(%Q{Added "#{entry['title']}" to #{section}})
364
364
  end
365
365
 
366
+ def last_note(section=@current_section)
367
+ section = guess_section(section)
368
+ if @content.has_key?(section)
369
+ last_item = @content[section]['items'].dup.sort_by{|item| item['date'] }.reverse[0]
370
+ p last_item
371
+ return last_item['note']
372
+ else
373
+ raise "Section #{section} not found"
374
+ end
375
+ end
376
+
366
377
  def tag_last(opt={})
367
378
  opt[:section] ||= @current_section
368
379
  opt[:count] ||= 1
@@ -374,68 +385,85 @@ class WWID
374
385
  opt[:back] ||= Time.now
375
386
 
376
387
 
388
+ sec_arr = []
377
389
 
378
- opt[:section] = guess_section(opt[:section])
379
-
380
- if @content.has_key?(opt[:section])
381
- # sort_section(opt[:section])
382
- items = @content[opt[:section]]['items'].dup.sort_by{|item| item['date'] }.reverse
383
-
384
- index = 0
385
- done_date = Time.now
386
- next_start = Time.now
387
- items.map! {|item|
388
- break if index == opt[:count]
389
- if opt[:sequential]
390
- done_date = next_start - 1
391
- next_start = item['date']
392
- elsif opt[:back].instance_of? Fixnum
393
- done_date = item['date'] + opt[:back]
394
- else
395
- done_date = opt[:back]
396
- end
390
+ if opt[:section].nil?
391
+ sec_arr = [@current_section]
392
+ elsif opt[:section].class == String
393
+ if opt[:section] =~ /^all$/i
394
+ sec_arr = sections
395
+ else
396
+ sec_arr = [guess_section(opt[:section])]
397
+ end
398
+ end
397
399
 
398
- title = item['title']
399
- opt[:tags].each {|tag|
400
- if opt[:remove]
401
- title.gsub!(/(^| )@#{tag.strip}(\([^\)]*\))?/,'')
402
- @results.push("Updated: #{title}")
400
+ sec_arr.each {|section|
401
+ if @content.has_key?(section)
402
+
403
+ items = @content[section]['items'].dup.sort_by{|item| item['date'] }.reverse
404
+
405
+ index = 0
406
+ done_date = Time.now
407
+ next_start = Time.now
408
+ count = opt[:count] == 0 ? items.length : opt[:count]
409
+ items.map! {|item|
410
+ break if index == count
411
+ if opt[:sequential]
412
+ done_date = next_start - 1
413
+ next_start = item['date']
414
+ elsif opt[:back].instance_of? Fixnum
415
+ done_date = item['date'] + opt[:back]
403
416
  else
404
- unless title =~ /@#{tag}/
405
- title.chomp!
406
- if opt[:date]
407
- title += " @#{tag}(#{done_date.strftime('%F %R')})"
408
- else
409
- title += " @#{tag}"
417
+ done_date = opt[:back]
418
+ end
419
+
420
+ title = item['title']
421
+ opt[:tags].each {|tag|
422
+ tag.strip!
423
+ if opt[:remove]
424
+ if title =~ /@#{tag}/
425
+ title.gsub!(/(^| )@#{tag}(\([^\)]*\))?/,'')
426
+ @results.push("Removed @#{tag}: #{title}")
427
+ end
428
+ else
429
+ unless title =~ /@#{tag}/
430
+ title.chomp!
431
+ if opt[:date]
432
+ title += " @#{tag}(#{done_date.strftime('%F %R')})"
433
+ else
434
+ title += " @#{tag}"
435
+ end
436
+ @results.push("Added @#{tag}: #{title}")
410
437
  end
411
- @results.push("Updated: #{title}")
412
438
  end
413
- end
414
- }
439
+ }
415
440
 
416
- item['title'] = title
417
- index += 1
418
- item
419
- }
441
+ item['title'] = title
442
+ index += 1
443
+ item
444
+ }
420
445
 
421
- @content[opt[:section]]['items'] = items
422
-
423
- if opt[:archive] && opt[:section] != "Archive"
424
- # concat [count] items from [section] and archive section
425
- archived = @content[opt[:section]]['items'][0..opt[:count]-1].concat(@content['Archive']['items'])
426
- # chop [count] items off of [section] items
427
- @content[opt[:section]]['items'] = @content[opt[:section]]['items'][opt[:count]..-1]
428
- # overwrite archive section with concatenated array
429
- @content['Archive']['items'] = archived
430
- # log it
431
- result = opt[:count] == 1 ? "1 entry" : "#{opt[:count]} entries"
432
- @results.push("Archived #{result}")
446
+ @content[section]['items'] = items
447
+
448
+ if opt[:archive] && section != "Archive" && opt[:count] > 0
449
+ # concat [count] items from [section] and archive section
450
+ archived = @content[section]['items'][0..opt[:count]-1].concat(@content['Archive']['items'])
451
+ # chop [count] items off of [section] items
452
+ @content[opt[:section]]['items'] = @content[opt[:section]]['items'][opt[:count]..-1]
453
+ # overwrite archive section with concatenated array
454
+ @content['Archive']['items'] = archived
455
+ # log it
456
+ result = opt[:count] == 1 ? "1 entry" : "#{opt[:count]} entries"
457
+ @results.push("Archived #{result}")
458
+ elsif opt[:archive] && opt[:count] == 0
459
+ @results.push("Archiving is skipped when operating on all entries") if opt[:count] == 0
460
+ end
461
+ else
462
+ raise "Section not found: #{section}"
433
463
  end
464
+ }
434
465
 
435
- write(@doing_file)
436
- else
437
- raise "Section not found"
438
- end
466
+ write(@doing_file)
439
467
  end
440
468
 
441
469
  def note_last(section, note, replace=false)
@@ -488,12 +516,15 @@ class WWID
488
516
 
489
517
  tag.sub!(/^@/,'')
490
518
 
519
+ found_items = 0
520
+
491
521
  @content[opt[:section]]['items'].each_with_index {|item, i|
492
522
  if item['title'] =~ /@#{tag}/
493
523
  title = item['title'].gsub(/(^| )@(#{tag}|done)(\([^\)]*\))?/,'')
494
524
  title += " @done(#{opt[:back].strftime('%F %R')})"
495
525
 
496
526
  @content[opt[:section]]['items'][i]['title'] = title
527
+ found_items += 1
497
528
 
498
529
  if opt[:archive] && opt[:section] != "Archive"
499
530
  @results.push(%Q{Completed and archived "#{@content[opt[:section]]['items'][i]['title']}"})
@@ -505,6 +536,8 @@ class WWID
505
536
  end
506
537
  }
507
538
 
539
+ @results.push("No active @#{tag} tasks found.") if found_items == 0
540
+
508
541
  if opt[:new_item]
509
542
  title, note = format_input(opt[:new_item])
510
543
  note.push(opt[:note]) if opt[:note]
@@ -530,7 +563,9 @@ class WWID
530
563
  $stdout.puts output
531
564
  else
532
565
  if File.exists?(File.expand_path(file))
566
+ # Create a backup copy for the undo command
533
567
  FileUtils.cp(file,file+"~")
568
+
534
569
  File.open(File.expand_path(file),'w+') do |f|
535
570
  f.puts output
536
571
  end
@@ -647,13 +682,14 @@ class WWID
647
682
  if opt[:search]
648
683
  items.keep_if {|item|
649
684
  text = item['note'] ? item['title'] + item['note'].join(" ") : item['title']
650
- text =~ /#{opt[:search]}/i
685
+ pattern = opt[:search].split('').join('.{0,3}')
686
+ text =~ /#{pattern}/i
651
687
  }
652
688
  end
653
689
 
654
690
  if opt[:only_timed]
655
691
  items.delete_if {|item|
656
- get_interval(item) == "00:00:00"
692
+ get_interval(item) == false
657
693
  }
658
694
  end
659
695
 
@@ -963,6 +999,12 @@ EOT
963
999
  color['boldbgmagenta'] = "\033[1;45m"
964
1000
  color['boldbgcyan'] = "\033[1;46m"
965
1001
  color['boldbgwhite'] = "\033[1;47m"
1002
+ color['softpurple'] = "\033[0;35;40m"
1003
+ color['hotpants'] = "\033[7;34;40m"
1004
+ color['knightrider'] = "\033[7;30;40m"
1005
+ color['flamingo'] = "\033[7;31;47m"
1006
+ color['yeller'] = "\033[1;37;43m"
1007
+ color['whiteboard'] = "\033[1;30;47m"
966
1008
  color['default']="\033[0;39m"
967
1009
  color
968
1010
  end
@@ -1090,7 +1132,7 @@ EOS
1090
1132
 
1091
1133
  return seconds unless formatted
1092
1134
 
1093
- "%02d:%02d:%02d" % fmt_time(seconds)
1135
+ seconds > 0 ? "%02d:%02d:%02d" % fmt_time(seconds) : false
1094
1136
  end
1095
1137
 
1096
1138
  def fmt_time(seconds)
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: 1.0.6pre
4
+ version: 1.0.7pre
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-09-23 00:00:00.000000000 Z
11
+ date: 2014-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake