todorb 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/todorb.rb CHANGED
@@ -4,7 +4,8 @@
4
4
  * Description: a command line todo list manager
5
5
  * Author: rkumar
6
6
  * Date: 2010-06-10 20:10
7
- * License: GPL
7
+ * License: Ruby License
8
+ * Now requires subcommand gem as of 2010-06-22 16:16
8
9
 
9
10
  =end
10
11
  require 'rubygems'
@@ -12,15 +13,17 @@ require 'rubygems'
12
13
  require 'common/colorconstants'
13
14
  require 'common/sed'
14
15
  require 'common/cmdapp'
16
+ require 'subcommand'
15
17
  include ColorConstants
16
18
  include Sed
17
19
  include Cmdapp
20
+ include Subcommands
18
21
 
19
22
  PRI_A = YELLOW + BOLD
20
23
  PRI_B = WHITE + BOLD
21
24
  PRI_C = GREEN + BOLD
22
25
  PRI_D = CYAN + BOLD
23
- VERSION = "2.0"
26
+ VERSION = "1.0.0"
24
27
  DATE = "2010-06-10"
25
28
  APPNAME = File.basename($0)
26
29
  AUTHOR = "rkumar"
@@ -59,7 +62,6 @@ class Todo
59
62
  def initialize options, argv
60
63
 
61
64
  @options = options
62
- @aliases = {}
63
65
  @argv = argv
64
66
  @file = options[:file]
65
67
  ## data is a 2 dim array: rows and fields. It contains each row of the file
@@ -86,29 +88,28 @@ class Todo
86
88
  $valid_array = false
87
89
  # menu MENU
88
90
  #@actions = %w[ list add pri priority depri tag del delete status redo note archive help]
89
- @actions = {}
90
- @actions["list"] = "List all tasks.\n\t --hide-numbering --renumber"
91
- @actions["listsub"] = "List all tasks.\n\t --hide-numbering --renumber"
92
- @actions["add"] = "Add a task. \n\t #{$APPNAME} add <TEXT>\n\t --component C --project P --priority X add <TEXT>"
93
- @actions["pri"] = "Add priority to task. \n\t #{$APPNAME} pri <ITEM> [A-Z]"
94
- @actions["priority"] = "Same as pri"
95
- @actions["depri"] = "Remove priority of task. \n\t #{$APPNAME} depri <ITEM>"
96
- @actions["delete"] = "Delete a task. \n\t #{$APPNAME} delete <ITEM>"
97
- @actions["del"] = "Same as delete"
98
- @actions["status"] = "Change the status of a task. \n\t #{$APPNAME} status <STAT> <ITEM>\n\t<STAT> are open closed started pending hold next"
99
- @actions["redo"] = "Renumbers the todo file starting 1"
100
- @actions["note"] = "Add a note to an item. \n\t #{$APPNAME} note <ITEM> <TEXT>"
101
- @actions["tag"] = "Add a tag to an item/s. \n\t #{$APPNAME} tag <ITEMS> <TEXT>"
102
- @actions["archive"] = "archive closed tasks to archive.txt"
103
- @actions["copyunder"] = "Move first item under second (as a subtask). aka cu"
104
-
105
- @actions["help"] = "Display help"
106
- @actions["addsub"] = "Add a task under another . \n\t #{$APPNAME} add <TEXT>\n\t --component C --project P --priority X add <TEXT>"
91
+ #@actions = {}
92
+ #@actions["list"] = "List all tasks.\n\t --hide-numbering --renumber"
93
+ #@actions["listsub"] = "List all tasks.\n\t --hide-numbering --renumber"
94
+ #@actions["add"] = "Add a task. \n\t #{$APPNAME} add <TEXT>\n\t --component C --project P --priority X add <TEXT>"
95
+ #@actions["pri"] = "Add priority to task. \n\t #{$APPNAME} pri <TASK> [A-Z]"
96
+ #@actions["priority"] = "Same as pri"
97
+ #@actions["depri"] = "Remove priority of task. \n\t #{$APPNAME} depri <TASK>"
98
+ #@actions["delete"] = "Delete a task. \n\t #{$APPNAME} delete <TASK>"
99
+ #@actions["del"] = "Same as delete"
100
+ #@actions["status"] = "Change the status of a task. \n\t #{$APPNAME} status <STAT> <TASK>\n\t<STAT> are open closed started pending hold next"
101
+ #@actions["redo"] = "Renumbers the todo file starting 1"
102
+ #@actions["note"] = "Add a note to an item. \n\t #{$APPNAME} note <TASK> <TEXT>"
103
+ #@actions["tag"] = "Add a tag to an item/s. \n\t #{$APPNAME} tag <TASK> <TEXT>"
104
+ #@actions["archive"] = "archive closed tasks to archive.txt"
105
+ #@actions["copyunder"] = "Move first item under second (as a subtask). aka cu"
106
+ #
107
+ #@actions["help"] = "Display help"
108
+ #@actions["addsub"] = "Add a task under another . \n\t #{$APPNAME} add <TEXT>\n\t --component C --project P --priority X add <TEXT>"
107
109
 
108
110
  # adding some sort of aliases so shortcuts can be defined
109
- @aliases["open"] = ["status","open"]
110
- @aliases["close"] = ["status","closed"]
111
- @aliases["cu"] = ["copyunder"]
111
+ #@aliases["open"] = ["status","open"]
112
+ #@aliases["close"] = ["status","closed"]
112
113
 
113
114
  @copying = false # used by copyunder when it calls addsub
114
115
  # TODO: config
@@ -147,8 +148,9 @@ class Todo
147
148
  ##
148
149
  # add a subtask
149
150
  # @param [Array] 1. item under which to place, 2. text
150
- # @return
151
- # @example:
151
+ # @return [0,1] success or fail
152
+ #
153
+ # @example
152
154
  # addsub 1 "A task"
153
155
  # => will get added as 1.1 or 1.2 etc
154
156
  # addsub 1.3 "a task"
@@ -232,16 +234,20 @@ class Todo
232
234
  @ctr = 0
233
235
  @total = 0
234
236
  #CSV.foreach(@file,:col_sep => "\t") do |row| # 1.9 2009-10-05 11:12
235
- File.open(@file).each do |line|
236
- row = line.chomp.split "\t"
237
- @total += 1
238
- if @options[:show_all]
239
- @data << row
240
- @ctr += 1
241
- else
242
- unless row[1] =~ /^\[x\]/
237
+ filelist = [@file]
238
+ filelist << @archive_path if @options[:show_arch]
239
+ filelist.each do |file|
240
+ File.open(file).each do |line|
241
+ row = line.chomp.split "\t"
242
+ @total += 1
243
+ if @options[:show_all]
243
244
  @data << row
244
245
  @ctr += 1
246
+ else
247
+ unless row[1] =~ /^\[x\]/
248
+ @data << row
249
+ @ctr += 1
250
+ end
245
251
  end
246
252
  end
247
253
  end
@@ -325,7 +331,8 @@ class Todo
325
331
  #string = "#{BLUE}#{string}#{CLEAR}"
326
332
  end
327
333
  else
328
- string = "#{NORMAL}#{string}#{CLEAR}"
334
+ #string = "#{NORMAL}#{string}#{CLEAR}"
335
+ # no need to put clear, let it be au natural
329
336
  end
330
337
  end # colorme
331
338
  ## since we've added notes, we convert C-a to newline with spaces
@@ -335,8 +342,15 @@ class Todo
335
342
  puts string
336
343
  end
337
344
  end
345
+ # internal method for sorting on reverse of line (status, priority)
338
346
  def sort
339
- @data.sort! { |a,b| b[1] <=> a[1] }
347
+ fold_subtasks
348
+ if @options[:reverse]
349
+ @data.sort! { |a,b| a[1] <=> b[1] }
350
+ else
351
+ @data.sort! { |a,b| b[1] <=> a[1] }
352
+ end
353
+ unfold_subtasks
340
354
  end
341
355
  def grep
342
356
  r = Regexp.new @options[:grep]
@@ -347,8 +361,8 @@ class Todo
347
361
  # Adds or changes priority for a task
348
362
  #
349
363
  # @param [Array] priority, single char A-Z, item or items
350
- # @return
351
- # @example:
364
+ # @return [0,1] success or fail
365
+ # @example
352
366
  # pri A 5 6 7
353
367
  # pri 5 6 7 A
354
368
  # -- NO LONGER this complicated system pri A 5 6 7 B 1 2 3
@@ -400,7 +414,7 @@ class Todo
400
414
  # Remove the priority of a task
401
415
  #
402
416
  # @param [Array] items to deprioritize
403
- # @return
417
+ # @return [0,1] success or fail
404
418
  def depri(args)
405
419
  change_items args, /\([A-Z]\) /,""
406
420
  end
@@ -409,7 +423,7 @@ class Todo
409
423
  # FIXME: check with subtasks
410
424
  #
411
425
  # @param [Array] items and tag, or tag and items
412
- # @return
426
+ # @return [0,1] success or fail
413
427
  def tag(args)
414
428
  tag, items = _separate args
415
429
  #change_items items do |item, row|
@@ -422,8 +436,7 @@ class Todo
422
436
  # deletes one or more items
423
437
  #
424
438
  # @param [Array, #include?] items to delete
425
- # @return
426
- # FIXME: if invalid item passed I have no way of giving error
439
+ # @return [0,1] success or fail
427
440
  public
428
441
  def delete(args)
429
442
  ctr = errors = 0
@@ -454,10 +467,24 @@ class Todo
454
467
  end
455
468
  end
456
469
  totalitems.each { |item|
470
+ # FIXME: TODO: if --force used then don'y prompt
457
471
  puts "#{item[0]} #{item[1]}"
458
- print "Do you wish to delete (Y/N): "
459
- STDOUT.flush
460
- ans = STDIN.gets.chomp
472
+ ans = nil
473
+ if @options[:force]
474
+ ans = "Y"
475
+ else
476
+ $stderr.print "Do you wish to delete (Y/N/A/q): "
477
+ STDOUT.flush
478
+ ans = STDIN.gets.chomp
479
+ # A means user specified ALL, don't keep asking
480
+ if ans =~ /[Aa]/
481
+ ans = "Y"
482
+ @options[:force] = true
483
+ elsif ans =~ /[qQ]/
484
+ $stderr.puts "Operation canceled. No tasks deleted."
485
+ exit 1
486
+ end
487
+ end
461
488
  if ans =~ /[Yy]/
462
489
  @data.delete item
463
490
  # put deleted row into deleted file, so one can undo
@@ -479,7 +506,7 @@ class Todo
479
506
  # Change status of given items
480
507
  #
481
508
  # @param [Array, #include?] items to change status of
482
- # @return [true, false] success or fail
509
+ # @return [0,1] success or fail
483
510
  public
484
511
  def status(args)
485
512
  stat, items = _separate args #, /^[a-zA-Z]/
@@ -530,7 +557,7 @@ class Todo
530
557
  end
531
558
  ##
532
559
  # Renumber while displaying
533
- # @return [true, false] success or fail
560
+ # @return [0,1] success or fail
534
561
  private
535
562
  def renumber
536
563
  ## this did not account for subtasks
@@ -556,7 +583,7 @@ class Todo
556
583
  # For given items, add a note
557
584
  #
558
585
  # @param [Array, #include?] items to add note to, note
559
- # @return [true, false] success or fail
586
+ # @return [0, 1] success or fail
560
587
  public
561
588
  def note(args)
562
589
  _backup
@@ -567,12 +594,13 @@ class Todo
567
594
  ret = row[1].sub!(/ (\([0-9]{4})/," #{indent}* #{text} "+'\1')
568
595
  ret
569
596
  end
597
+ 0
570
598
  end
571
599
  ##
572
- # Archive all items
600
+ # Archive all closed items
573
601
  #
574
602
  # @param none (ignored)
575
- # @return [true, false] success or fail
603
+ # @return [0, 1] success or fail
576
604
  public
577
605
  def archive(args=nil)
578
606
  filename = @archive_path
@@ -588,11 +616,12 @@ class Todo
588
616
  end
589
617
  file.close
590
618
  puts "Archived #{ctr} tasks."
619
+ 0
591
620
  end
592
621
  # Copy given item under second item
593
622
  #
594
623
  # @param [Array] 2 items, move first under second
595
- # @return [Boolean] success or fail
624
+ # @return [0,1] success or fail
596
625
  public
597
626
  def copyunder(args)
598
627
  if args.nil? or args.count != 2
@@ -616,8 +645,8 @@ class Todo
616
645
  # remove item number and status ?
617
646
  # give to addsub to add.
618
647
  # delete from
619
- delete_item from
620
- # take care of data in addsub (if existing, and also /
648
+ # The earlier todoapp.sh was not deleting, so we don't. We just copy
649
+ delete_item(from) if @options[:delete_old]
621
650
  end
622
651
  ##
623
652
  # Get row for given item or nil.
@@ -740,7 +769,7 @@ class Todo
740
769
  def regexp_item item
741
770
  Regexp.new("^ +#{item}#{@todo_delim}")
742
771
  end
743
- # @unused - wrote so i could use it refactoring - i should be using this TODO:
772
+ # unused - wrote so i could use it refactoring - i should be using this TODO:
744
773
  def extract_item line
745
774
  item = line.match(/^ *([0-9\.]+)/)
746
775
  return nil if item.nil?
@@ -749,6 +778,7 @@ class Todo
749
778
  ##
750
779
  # Redoes the numbering in the file.
751
780
  # Useful if the numbers have gone high and you want to start over.
781
+ # @return [0,1] success or fail
752
782
  def redo args
753
783
  #require 'fileutils'
754
784
  #FileUtils.cp @app_file_path, "#{@app_file_path}.org"
@@ -771,8 +801,9 @@ class Todo
771
801
  line.sub!(/[0-9]+\./, "#{ctr}.")
772
802
  end
773
803
  end
774
- _set_serial_number ctr
804
+ _set_serial_number ctr+1
775
805
  puts "Redone numbering"
806
+ 0
776
807
  end
777
808
  ##
778
809
  private
@@ -818,6 +849,46 @@ class Todo
818
849
  end
819
850
  ## [1, 2, 3, 3.1, 3.1.1, 3.2, 3.3 ... ], " 3.1.1\t[ ] some task"
820
851
 
852
+ def fold_subtasks
853
+ #load_array
854
+ prev = ""
855
+ newarray = []
856
+ # get the main item, avoid subitem
857
+ #item = line.match(/^ *([0-9\.]+)/)
858
+ rx = Regexp.new "^ *([0-9]+)"
859
+ @data.each { |row|
860
+ it = row[0].match(rx)
861
+ item = it[1]
862
+ if item == prev # append to prev line
863
+ #puts "item matches prev #{item} #{prev} "
864
+ x=newarray.last
865
+ x[1] << "#{row[0]}\t#{row[1]}"
866
+ else
867
+ #puts "no match item matches prev #{row[0]}: #{prev} "
868
+ newarray << row
869
+ end
870
+ prev = item
871
+ }
872
+ #newarray.each { |row| puts "#{row[0]} #{row[1]}" }
873
+ @data = newarray
874
+ end
875
+ def unfold_subtasks
876
+ newarray = []
877
+ # get the main item, avoid subitem
878
+ #item = line.match(/^ *([0-9\.]+)/)
879
+ @data.each { |row|
880
+ if row[1] =~ //
881
+ #puts "row #{row[0]} contains ^B"
882
+ line = row.join "\t"
883
+ lines = line.split //
884
+ #puts " #{lines.count} lines "
885
+ lines.each { |e| newarray << e.split("\t") }
886
+ else
887
+ newarray << row
888
+ end
889
+ }
890
+ @data = newarray
891
+ end
821
892
  def self.main args
822
893
  ret = nil
823
894
  begin
@@ -836,103 +907,197 @@ class Todo
836
907
  options[:colorize] = (plain == "0") ? false:true
837
908
  end
838
909
 
839
- OptionParser.new do |opts|
840
- opts.banner = "Usage: #{$APPNAME} [options] action"
841
-
842
- opts.separator ""
843
- opts.separator "Options for list and add:"
844
-
845
- opts.on("-P", "--project PROJECTNAME", "name of project for add or list") { |v|
846
- options[:project] = v
847
- options[:filter] = true
848
- }
849
- opts.on("-p", "--priority A-Z", "priority code for add or list") { |v|
850
- options[:priority] = v
851
- options[:filter] = true
852
- }
853
- opts.on("-C", "--component COMPONENT", "component name for add or list") { |v|
854
- options[:component] = v
855
- options[:filter] = true
856
- }
857
- opts.separator ""
858
- opts.separator "Specific options:"
859
- opts.on("--force", "force delete or add without prompting") do |v|
860
- options[:force] = v
861
- end
862
- opts.on("--recursive", "operate on subtasks also for delete, status") do |v|
863
- options[:recursive] = v
864
- end
865
- opts.separator ""
866
- opts.separator "List options:"
867
-
868
- opts.on("--[no-]color", "--[no-]colors", "colorize listing") do |v|
869
- options[:colorize] = v
870
- options[:color_scheme] = 1
871
- end
872
- opts.on("-s", "--sort", "sort list on priority") do |v|
873
- options[:sort] = v
874
- end
875
- opts.on("-g", "--grep REGEXP", "filter list on pattern") do |v|
876
- options[:grep] = v
877
- end
878
- opts.on("--renumber", "renumber while listing") do |v|
879
- options[:renumber] = v
880
- end
881
- opts.on("--hide-numbering", "hide-numbering while listing ") do |v|
882
- options[:hide_numbering] = v
883
- end
884
- opts.on("--[no-]show-all", "show all tasks (incl closed)") do |v|
885
- options[:show_all] = v
886
- end
887
-
888
- opts.separator ""
889
- opts.separator "Common options:"
890
-
891
- opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
892
- options[:verbose] = v
893
- end
894
- opts.on("-f", "--file FILENAME", "CSV filename") do |v|
895
- options[:file] = v
896
- end
897
- opts.on("-d DIR", "--dir DIR", "Use TODO file in this directory") do |v|
898
- require 'FileUtils'
899
- dir = File.expand_path v
900
- if File.directory? dir
901
- options[:dir] = dir
902
- # changing dir is important so that serial_number file is the current one.
903
- FileUtils.cd dir
904
- else
905
- die "#{RED}#{v}: no such directory #{CLEAR}"
906
- end
907
- end
908
- # No argument, shows at tail. This will print an options summary.
909
- # Try it and see!
910
- opts.on("-h", "--help", "Show this message") do
911
- puts opts
912
- exit 0
913
- end
914
-
915
- opts.on("--show-actions", "show actions ") do |v|
916
- todo = Todo.new(options, ARGV)
917
- todo.help nil
918
- exit 0
919
- end
910
+ Subcommands::global_options do |opts|
911
+ opts.banner = "Usage: #{$APPNAME} [options] [subcommand [options]]"
912
+ opts.description = "Todo list manager"
913
+ #opts.separator ""
914
+ #opts.separator "Global options are:"
915
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
916
+ options[:verbose] = v
917
+ end
918
+ opts.on("-f", "--file FILENAME", "CSV filename") do |v|
919
+ options[:file] = v
920
+ end
921
+ opts.on("-d DIR", "--dir DIR", "Use TODO file in this directory") do |v|
922
+ require 'FileUtils'
923
+ dir = File.expand_path v
924
+ if File.directory? dir
925
+ options[:dir] = dir
926
+ # changing dir is important so that serial_number file is the current one.
927
+ FileUtils.cd dir
928
+ else
929
+ die "#{RED}#{v}: no such directory #{CLEAR}"
930
+ end
931
+ end
932
+ opts.on("--show-actions", "show actions ") do |v|
933
+ todo = Todo.new(options, ARGV)
934
+ todo.help nil
935
+ exit 0
936
+ end
920
937
 
921
- opts.on("--version", "Show version") do
922
- puts "#{APPNAME} version #{VERSION}, #{DATE}"
923
- puts "by #{AUTHOR}. This software is under the GPL License."
924
- exit 0
925
- end
938
+ opts.on("--version", "Show version") do
939
+ version = Cmdapp::version_info || VERSION
940
+ puts "#{APPNAME} version #{version}, #{DATE}"
941
+ puts "by #{AUTHOR}. This software is under the GPL License."
942
+ exit 0
943
+ end
944
+ # No argument, shows at tail. This will print an options summary.
945
+ # Try it and see!
946
+ opts.on("-h", "--help", "Show this message") do
947
+ puts opts
948
+ exit 0
949
+ end
926
950
  opts.separator ""
927
951
  opts.separator "Common Usage:"
928
952
  opts.separator <<TEXT
953
+ #{APPNAME} add "Text ...."
929
954
  #{APPNAME} list
930
- #{APPNAME} add "TEXT ...."
931
955
  #{APPNAME} pri 1 A
932
956
  #{APPNAME} close 1
933
957
  TEXT
934
-
935
- end.parse!(args)
958
+ end
959
+
960
+ Subcommands::command :list do |opts|
961
+ opts.banner = "Usage: list [options]"
962
+ opts.description = "List tasks.\t --show-all and others"
963
+ opts.on("-P", "--project PROJECTNAME", "name of project for add or list") { |v|
964
+ options[:project] = v
965
+ options[:filter] = true
966
+ }
967
+ opts.on("-p", "--priority A-Z", "priority code for add or list") { |v|
968
+ options[:priority] = v
969
+ options[:filter] = true
970
+ }
971
+ opts.on("-C", "--component COMPONENT", "component name for add or list") { |v|
972
+ options[:component] = v
973
+ options[:filter] = true
974
+ }
975
+ opts.on("--[no-]color", "--[no-]colors", "colorize listing") do |v|
976
+ options[:colorize] = v
977
+ options[:color_scheme] = 1
978
+ end
979
+ opts.on("-s", "--sort", "sort list on status,priority") do |v|
980
+ options[:sort] = v
981
+ end
982
+ opts.on("--reverse", "sort list on status,priority reversed") do |v|
983
+ options[:reverse] = v
984
+ end
985
+ opts.on("-g", "--grep REGEXP", "filter list on pattern") do |v|
986
+ options[:grep] = v
987
+ end
988
+ opts.on("--renumber", "renumber while listing") do |v|
989
+ options[:renumber] = v
990
+ end
991
+ opts.on("--hide-numbering", "hide-numbering while listing ") do |v|
992
+ options[:hide_numbering] = v
993
+ end
994
+ opts.on("--[no-]show-all", "show all tasks (incl closed)") do |v|
995
+ options[:show_all] = v
996
+ end
997
+ opts.on("--show-arch", "show all tasks adding archived ones too") do |v|
998
+ options[:show_arch] = v
999
+ options[:show_all] = v # when adding archived, we set show-all so closed are visible
1000
+ end
1001
+ end
1002
+
1003
+ Subcommands::command :add, :a do |opts|
1004
+ opts.banner = "Usage: add [options] TEXT"
1005
+ opts.description = "Add a task."
1006
+ opts.on("-f", "--[no-]force", "force verbosely") do |v|
1007
+ options[:force] = v
1008
+ end
1009
+ opts.on("-P", "--project PROJECTNAME", "name of project for add or list") { |v|
1010
+ options[:project] = v
1011
+ options[:filter] = true
1012
+ }
1013
+ opts.on("-p", "--priority A-Z", "priority code for add or list") { |v|
1014
+ options[:priority] = v
1015
+ options[:filter] = true
1016
+ }
1017
+ opts.on("-C", "--component COMPONENT", "component name for add or list") { |v|
1018
+ options[:component] = v
1019
+ options[:filter] = true
1020
+ }
1021
+ end
1022
+ # XXX order of these 2 matters !! reverse and see what happens
1023
+ Subcommands::command :pri, :p do |opts|
1024
+ opts.banner = "Usage: pri [options] [A-Z] <TASK/s>"
1025
+ opts.description = "Add priority to task. "
1026
+ opts.on("-f", "--[no-]force", "force verbosely") do |v|
1027
+ options[:force] = v
1028
+ end
1029
+ end
1030
+ Subcommands::command :depri do |opts|
1031
+ opts.banner = "Usage: depri [options] <TASK/s>"
1032
+ opts.description = "Remove priority of task. \n\t todorb depri <TASK>"
1033
+ opts.on("-f", "--[no-]force", "force verbosely") do |v|
1034
+ options[:force] = v
1035
+ end
1036
+ end
1037
+ Subcommands::command :delete, :del do |opts|
1038
+ opts.banner = "Usage: delete [options] <TASK/s>"
1039
+ opts.description = "Delete a task. \n\t todorb delete <TASK>"
1040
+ opts.on("-f", "--[no-]force", "force - don't prompt") do |v|
1041
+ options[:force] = v
1042
+ end
1043
+ opts.on("--recursive", "operate on subtasks also") { |v|
1044
+ options[:recursive] = v
1045
+ }
1046
+ end
1047
+ Subcommands::command :status do |opts|
1048
+ opts.banner = "Usage: status [options] <STATUS> <TASKS>"
1049
+ opts.description = "Change the status of a task. \t<STATUS> are open closed started pending hold next"
1050
+ opts.on("--recursive", "operate on subtasks also") { |v|
1051
+ options[:recursive] = v
1052
+ }
1053
+ end
1054
+ Subcommands::command :redo do |opts|
1055
+ opts.banner = "Usage: redo"
1056
+ opts.description = "Renumbers the todo file starting 1"
1057
+ end
1058
+ Subcommands::command :note do |opts|
1059
+ opts.banner = "Usage: note <TASK> <TEXT>"
1060
+ opts.description = "Add a note to a task."
1061
+ end
1062
+ Subcommands::command :tag do |opts|
1063
+ opts.banner = "Usage: tag <TAG> <TASKS>"
1064
+ opts.description = "Add a tag to an item/s. "
1065
+ end
1066
+ Subcommands::command :archive do |opts|
1067
+ opts.banner = "Usage: archive"
1068
+ opts.description = "archive closed tasks to archive.txt"
1069
+ end
1070
+ Subcommands::command :copyunder, :cu do |opts|
1071
+ opts.banner = "Usage: copyunder"
1072
+ opts.description = "Move first task under second (as a subtask). aka cu"
1073
+ opts.on("-d", "--delete", "Delete old after copying") do |v|
1074
+ options[:delete_old] = v
1075
+ end
1076
+ end
1077
+ Subcommands::command :addsub do |opts|
1078
+ opts.banner = "Usage: addsub [options]"
1079
+ opts.description = "Add a task under another."
1080
+ opts.on("-P", "--project PROJECTNAME", "name of project for add or list") { |v|
1081
+ options[:project] = v
1082
+ #options[:filter] = true
1083
+ }
1084
+ opts.on("-p", "--priority A-Z", "priority code for add or list") { |v|
1085
+ options[:priority] = v
1086
+ #options[:filter] = true
1087
+ }
1088
+ opts.on("-C", "--component COMPONENT", "component name for add or list") { |v|
1089
+ options[:component] = v
1090
+ #options[:filter] = true
1091
+ }
1092
+ end
1093
+ #Subcommands::command :testy do |opts|
1094
+ #opts.banner = "Usage: test"
1095
+ #opts.description = "test out some functionality"
1096
+ #end
1097
+ Subcommands::alias_command :open , "status","open"
1098
+ Subcommands::alias_command :close , "status","closed"
1099
+ cmd = Subcommands::opt_parse()
1100
+ args.unshift cmd if cmd
936
1101
 
937
1102
  options[:file] ||= "TODO2.txt"
938
1103
  if options[:verbose]
data/tests/data.1 ADDED
@@ -0,0 +1,14 @@
1
+ 1 [x] if no TODO file give proper message to add task (2010-06-14)
2
+ 2 [x] what if no serial_number file? (2010-06-14)
3
+ 3 [x] Add a close for status close (2010-06-14)
4
+ 3.1 [ ] hello there new a u 3 (2010-06-15)
5
+ 3.1.1 [ ] hello there new a u 3 (2010-06-15)
6
+ 3.1.2 [ ] hello there new a u 3 (2010-06-15)
7
+ 3.1.3 [ ] hello there new a u 3 (2010-06-15)
8
+ 3.2 [ ] hello there new a u 3.2 (2010-06-15)
9
+ 3.2.1 [ ] hello there new a u 3.2.1 (2010-06-15)
10
+ 3.2.1.1 [ ] hello there new a u 3.2.1.1 (2010-06-15)
11
+ 4 [ ] start rubyforge project for todorb (2010-06-14)
12
+ 5 [ ] list: if dir given then show full path of TODO2.txt at end (2010-06-14)
13
+ 6 [ ] allow for ENV VARS such as verbose, plain, force (2010-06-15)
14
+ 7 [ ] list: search terms with - + and = (2010-06-15)
data/tests/data.2 ADDED
@@ -0,0 +1,7 @@
1
+ 1 [ ] if no TODO file give proper message to add task (2010-06-14)
2
+ 2 [ ] what if no serial_number file? (2010-06-14)
3
+ 3 [ ] Add a close for status close (2010-06-14)
4
+ 4 [ ] start rubyforge project for todorb (2010-06-14)
5
+ 5 [ ] list: if dir given then show full path of TODO2.txt at end (2010-06-14)
6
+ 6 [ ] allow for ENV VARS such as verbose, plain, force (2010-06-15)
7
+ 7 [ ] list: search terms with - + and = (2010-06-15)