Class: Todo

Inherits:
Object
  • Object
show all
Defined in:
lib/todorb.rb

Instance Method Summary (collapse)

Constructor Details

- (Todo) initialize(options, argv)

This class is responsible for all todo task related functionality.

Create a file

Adding a task is the first operation.

    $ todorb add "Create a project in rubyforge"
    $ todorb add "Update Rakefile with project name"

The above creates a TODO2.txt file and a serial_number file.

List tasks

To list open/unstarted tasks:

    $ todorb

To list closed tasks also:

    $ todorb --show-all

If you are located elsewhere, give directory name:

    $ todorb -d ~/

Close a task (mark as done)

    $ todorb status close 1

Add priority

    $ todorb pri A 2

For more:

    $ todorb --help
    $ todorb --show-actions

TODO:



61
62
63
64
65
66
67
68
69
70
# File 'lib/todorb.rb', line 61

def initialize options, argv
 
  @options = options
  @argv = argv
  @file = options[:file]
  ## data is a 2 dim array: rows and fields. It contains each row of the file
  # as an array of strings. The item number is space padded.
  @data = []
  init_vars
end

Instance Method Details

- (Object) _paditem(item)

for historical reasons, I pad item to 3 spaces in text file. It used to help me in printing straight off without any formatting in unix shell



223
224
225
# File 'lib/todorb.rb', line 223

def _paditem item
  return sprintf("%3s", item)
end

- (Object) _separate(args, pattern = nil)

separates args into tag or subcommand and items This allows user to pass e.g. a priority first and then item list or item list first and then priority. This can only be used if the tag or pri or status is non-numeric and the item is numeric.



516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
# File 'lib/todorb.rb', line 516

def _separate args, pattern=nil #/^[a-zA-Z]/ 
  tag = nil
  items = []
  args.each do |arg| 
    if arg =~ /^[0-9\.]+$/
      items << arg
    else
      tag = arg
      if pattern
        die "#{@action}: #{arg} appears invalid." if arg !~ pattern
      end
    end
  end
  items = nil if items.empty?
  return tag, items
end

- (Object) active_tasks



294
295
296
297
298
299
300
301
302
# File 'lib/todorb.rb', line 294

def active_tasks
  @ctr = 0
  @data.each { |row|  
    unless row[1] =~ /^\[x\]/ 
      yield row
      @ctr += 1
    end
  }
end

- (Object) add(args)

TODO: config we need to read up from config file and update



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/todorb.rb', line 117

def add args
  if args.empty?
    print "Enter todo: "
    STDOUT.flush
    text = gets.chomp
    if text.empty?
      exit ERRCODE
    end
    Kernel.print("You gave me '#{text}'") if @verbose
  else
    text = args.join " "
    Kernel.print("I got '#{text}'") if @verbose
  end
  # convert actual newline to C-a. slash n's are escapes so echo -e does not muck up.
  text.tr! "\n", ''
  Kernel.print("Got '#{text}'\n") if @verbose
  item = _get_serial_number
  die "Could not get a new item number" if item.nil?
  paditem = _paditem(item)
  verbose "item no is:#{paditem}:\n" 
  priority = @options[:priority] ? " (#{@options[:priority]})" : ""
  project  = @options[:project]  ? " +#{@options[:project]}"   : ""
  component  = @options[:component]  ? " @#{@options[:component]}"   : ""
  newtext="#{paditem}#{@todo_delim}[ ]#{priority}#{project}#{component} #{text} (#{@today})"
  File.open(@app_file_path, "a") { | file| file.puts newtext }
  puts "Adding:"
  puts newtext

  0
end

- (0, 1) addsub(args)

add a subtask

Examples:

addsub 1 "A task"   
   => will get added as 1.1 or 1.2 etc
addsub 1.3 "a task"
   => will get added as 1.3.x

Parameters:

  • (Array) 1.

    item under which to place, 2. text

Returns:

  • (0, 1)

    success or fail



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/todorb.rb', line 157

def addsub args
  under = args.shift
  text = args.join " "
  exit unless text
  #puts "under #{under} text: #{text} "
  lastlinect = nil
  lastlinetext = nil
  # look for last item below given task (if there is)
  Sed::egrep( [@app_file_path], Regexp.new("#{under}\.[0-9]+	")) do |fn,ln,line|
    lastlinect = ln
    lastlinetext = line
    puts line if @verbose 
  end
  if lastlinect
    verbose "Last line found #{lastlinetext} " 
    m = lastlinetext.match(/\.([0-9]+)	/)
    lastindex = m[1].to_i
    # check if it has subitems, find last one only for linecount
    Sed::egrep( [@app_file_path], Regexp.new("#{under}\.#{lastindex}\.[0-9]+	")) do |fn,ln,line|
      lastlinect = ln
    end
    lastindex += 1
    item = "#{under}.#{lastindex}"
  else
    # no subitem found, so this is first
    item = "#{under}.1"
    # get line of parent
    found = nil
    Sed::egrep( [@app_file_path], Regexp.new("#{under}	")) do |fn,ln,line|
      lastlinect = ln
      found = true
    end
    die "Task #{under} not found" unless found
  end
  die "Could not determine which line to insert under" unless lastlinect
  verbose "item is #{item} ::: line #{lastlinect} " 

  # convert actual newline to C-a. slash n's are escapes so echo -e does not muck up.
  text.tr! "\n", ''
  Kernel.print("Got '#{text}'\n") if @verbose
  paditem = _paditem(item)
  print "item no is:#{paditem}:\n" if @verbose
  priority = @options[:priority] ? " (#{@options[:priority]})" : ""
  project  = @options[:project]  ? " +#{@options[:project]}"   : ""
  component  = @options[:component]  ? " @#{@options[:component]}"   : ""
  level = (item.split '.').length
  indent = " " * (TABSTOP * (level-1))
  newtext=nil
  if @copying
    newtext="#{indent}#{item}#{@todo_delim}#{text}"
  else
    newtext="#{indent}#{paditem}#{@todo_delim}[ ]#{priority}#{project}#{component} #{text} (#{@today})"
  end
  raise "Cannot insert blank text. Programmer error!" unless newtext
  #_backup
  puts "Adding:"
  puts newtext
  Sed::insert_row(@app_file_path, lastlinect, newtext)
  return 0
end

- (Object) archive(args = nil)



578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
# File 'lib/todorb.rb', line 578

def archive(args=nil)
  filename = @archive_path
  file = File.open(filename, "a") 
  ctr = 0
  Sed::delete_row @app_file_path do |line|
    if line =~ /\[x\]/
      file.puts line
      ctr += 1
      puts line if @verbose
      true
    end
  end
  file.close
  puts "Archived #{ctr} tasks."
end

- (Object) change_items(items, pattern = nil, replacement = nil)



683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
# File 'lib/todorb.rb', line 683

def change_items items, pattern=nil, replacement=nil
  ctr = errors = 0
  #tag, items = _separate args
  # or items = args
  die "#{@action}: items expected" unless items
  total = items.count
  load_array
  items.each do |item| 
    row = get_item(item)
    if row
      if pattern
        puts " #{row[0]} : #{row[1]} " if @verbose 
        ret = row[1].sub!(pattern, replacement)
        if ret
          puts " #{GREEN}#{row[0]} : #{row[1]} #{CLEAR}"
          ctr += 1
        else
          # this is since there could be a programmer error.
          die "Possible error in sub() - No replacement: #{row[0]} : #{row[1]}.\nNothing saved. "
        end
      else
        puts " #{row[0]} : #{row[1]} " if @verbose 
        ret = yield item, row
        if ret
          ctr += 1 
          puts " #{GREEN}#{row[0]} : #{row[1]} #{CLEAR}"
        end
      end
    else
      errors += 1
      warning "#{item} not found."
    end
  end
  message "#{errors} error/s" if errors > 0
  if ctr > 0
    puts "Changed #{ctr} task/s"
    save_array 
    return 0 
  end
  return ERRCODE
end

- (Object) check_file(filename = @app_file_path)



217
218
219
# File 'lib/todorb.rb', line 217

def check_file filename=@app_file_path
  File.exists?(filename) or die "#{filename} does not exist in this dir. Use 'add' to create an item first."
end

- (Object) colorize

colorize each line, if required. However, we should put the colors in some Map, so it can be changed at configuration level.



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/todorb.rb', line 307

def colorize
  colorme = @options[:colorize]
  @data.each do |r| 
    if @options[:hide_numbering]
      string = "#{r[1]} "
    else
      string = " #{r[0]} #{r[1]} "
    end
    if colorme
      m=string.match(/\(([A-Z])\)/)
      if m 
        case m[1]
        when "A", "B", "C", "D"
          pri = self.class.const_get("PRI_#{m[1]}")
          #string = "#{YELLOW}#{BOLD}#{string}#{CLEAR}"
          string = "#{pri}#{string}#{CLEAR}"
        else
          string = "#{NORMAL}#{GREEN}#{string}#{CLEAR}"
          #string = "#{BLUE}\e[6m#{string}#{CLEAR}"
          #string = "#{BLUE}#{string}#{CLEAR}"
        end 
      else
        string = "#{NORMAL}#{string}#{CLEAR}"
      end
    end # colorme
    ## since we've added notes, we convert C-a to newline with spaces
    # so it prints in next line with some neat indentation.
    string.gsub!('', "\n        ")
    #string.tr! '', "\n"
    puts string
  end
end

- (Object) copyunder(args)



598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
# File 'lib/todorb.rb', line 598

def copyunder(args)
  if args.nil? or args.count != 2
    die "copyunder expects only 2 args: from and to item, both existing"
  end
  from = args[0]
  to = args[1]
  # extract item from
  lastlinetext = nil
  rx = regexp_item from
  Sed::egrep( [@app_file_path], rx) do |fn,ln,line|
    lastlinect = ln
    lastlinetext = line
    puts line
  end
  # removing everything from start to status inclusive
  lastlinetext.sub!(/^.*\[/,'[').chomp!
  puts lastlinetext
  @copying = true
  addsub [to, lastlinetext]
  # remove item number and status ? 
  # give to addsub to add.
  # delete from
  delete_item from
  # take care of data in addsub (if existing, and also /
end

- (Object) delete(args)



429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
# File 'lib/todorb.rb', line 429

def delete(args)
  ctr = errors = 0
  items = args
  die "#{@action}: items expected" unless items
  total = items.count
  totalitems = []
  load_array
  items.each do |item| 
    if @options[:recursive]
      a = get_item_subs item
      if a
        a.each { |e| 
          totalitems << e; #e[0].strip
        }
      else
        errors += 1
        warning "#{item} not found."
      end
    else
      row = get_item(item)
      if row
        totalitems << row
      else
        errors += 1
        warning "#{item} not found."
      end
    end
  end
  totalitems.each { |item| 
    puts "#{item[0]} #{item[1]}"
    print "Do you wish to delete (Y/N): "
    STDOUT.flush
    ans = STDIN.gets.chomp
    if ans =~ /[Yy]/
      @data.delete item
      # put deleted row into deleted file, so one can undo
      File.open(@deleted_path, "a") { | file| file.puts "#{item[0]}#{@todo_delim}#{item[1]}" }
      ctr += 1
    else
      puts "Delete canceled #{item[0]}"
    end
  }
  message "#{errors} error/s" if errors > 0
  if ctr > 0
    puts "Deleted #{ctr} task/s"
    save_array 
    return 0 
  end
  return ERRCODE
end

- (Object) delete_item(item)

does a straight delete of an item, no questions asked internal use only.



726
727
728
729
730
731
# File 'lib/todorb.rb', line 726

def delete_item item
  filename=@app_file_path
  d = Sed::_read filename
  d.delete_if { |row| line_contains_item?(row, item) }
  Sed::_write filename, d
end

- (Object) depri(args)

Remove the priority of a task

Parameters:

  • (Array) items

    to deprioritize

Returns:



405
406
407
# File 'lib/todorb.rb', line 405

def depri(args)
  change_items args, /\([A-Z]\) /,""
end

- (Object) each



289
290
291
292
293
# File 'lib/todorb.rb', line 289

def each
  @data.each { |row|  
      yield row
  }
end

- (Object) extract_item(line)

unused - wrote so i could use it refactoring - i should be using this TODO:



745
746
747
748
749
# File 'lib/todorb.rb', line 745

def extract_item line
    item = line.match(/^ *([0-9\.]+)/)
    return nil if item.nil?
    return item[1]
end

- (Object) filter

filters output based on project and or component and or priority



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/todorb.rb', line 252

def filter
  project = @options[:project]
  component = @options[:component]
  priority = @options[:priority]
  if project
    r = Regexp.new "\\+#{project}"
    @data = @data.select { |row| row[1] =~ r }
  end
  if component
    r = Regexp.new "@#{component}"
    @data = @data.select { |row| row[1] =~ r }
  end
  if priority
    r = Regexp.new "\\(#{priority}\\)"
    @data = @data.select { |row| row[1] =~ r }
  end
end

- (Object) get_item(item)



630
631
632
633
634
635
636
637
638
639
640
641
# File 'lib/todorb.rb', line 630

def get_item(item)
  raise "Please load array first!" if @data.empty?
  puts "get_item got #{item}." if @verbose
  #rx = regexp_item(item)
  rx = Regexp.new("^ +#{item}$")
  @data.each { |row|
    puts "    get_item read #{row[0]}." if @verbose 
    return row if row[0] =~ rx
  }
  # not found
  return nil
end

- (Array?) get_item_subs(item)

get item and its subtasks (in an attempt to make recursive changes cleaner)

Parameters:

  • (taken from command line) item

Returns:

  • (Array, nil)

    row[] objects



658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
# File 'lib/todorb.rb', line 658

def get_item_subs(item)
  raise "Please load array first!" if @data.empty?
  verbose "get_item got #{item}."
  #rx = regexp_item(item)
  rx = Regexp.new("^ +#{item}$")
  rx2 = Regexp.new("^ +#{item}\.")
  rows = []
  @data.each { |row|
    verbose "    get_item read #{row[0]}."
    if row[0] =~ rx
      rows << row 
      rx = rx2
    end
  }
  return nil if rows.empty?
  return rows
end

- (Object) grep



342
343
344
345
346
# File 'lib/todorb.rb', line 342

def grep
  r = Regexp.new @options[:grep]
  #@data = @data.grep r
  @data = @data.find_all {|i| i[1] =~ r }
end

- (Object) init_vars



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/todorb.rb', line 71

def init_vars
  @app_default_action = "list"
  @app_file_path = @options[:file] || "TODO2.txt"
  #@app_serial_path = File.expand_path("~/serial_numbers")
  @app_serial_path = "serial_numbers"
  @archive_path = "todo_archive.txt" 
  @deleted_path = "todo_deleted.txt"
  @todo_delim = "\t"
  @appname = File.basename( Dir.getwd ) #+ ".#{$0}"
  # in order to support the testing framework
  t = Time.now
  ut = ENV["TODO_TEST_TIME"]
  t = Time.at(ut.to_i) if ut
  @now = t.strftime("%Y-%m-%d %H:%M:%S")
  @today = t.strftime("%Y-%m-%d")
  @verbose = @options[:verbose]
  $valid_array = false
  # menu MENU
  #@actions = %w[ list add pri priority depri tag del delete status redo note archive help]
  #@actions = {}
  #@actions["list"] = "List all tasks.\n\t --hide-numbering --renumber"
  #@actions["listsub"] = "List all tasks.\n\t --hide-numbering --renumber"
  #@actions["add"] = "Add a task. \n\t #{$APPNAME} add <TEXT>\n\t --component C --project P --priority X add <TEXT>"
  #@actions["pri"] = "Add priority to task. \n\t #{$APPNAME} pri <ITEM> [A-Z]"
  #@actions["priority"] = "Same as pri"
  #@actions["depri"] = "Remove priority of task. \n\t #{$APPNAME} depri <ITEM>"
  #@actions["delete"] = "Delete a task. \n\t #{$APPNAME} delete <ITEM>"
  #@actions["del"] = "Same as delete"
  #@actions["status"] = "Change the status of a task. \n\t #{$APPNAME} status <STAT> <ITEM>\n\t<STAT> are open closed started pending hold next"
  #@actions["redo"] = "Renumbers the todo file starting 1"
  #@actions["note"] = "Add a note to an item. \n\t #{$APPNAME} note <ITEM> <TEXT>"
  #@actions["tag"] = "Add a tag to an item/s. \n\t #{$APPNAME} tag <ITEMS> <TEXT>"
  #@actions["archive"] = "archive closed tasks to archive.txt"
  #@actions["copyunder"] = "Move first item under second (as a subtask). aka cu"
#
  #@actions["help"] = "Display help"
  #@actions["addsub"] = "Add a task under another . \n\t #{$APPNAME} add <TEXT>\n\t --component C --project P --priority X add <TEXT>"

  # adding some sort of aliases so shortcuts can be defined
  #@aliases["open"] = ["status","open"]
  #@aliases["close"] = ["status","closed"]

  @copying = false # used by copyunder when it calls addsub
  # TODO: config
  # we need to read up from config file and update
end

- (Boolean) line_contains_item?(line, item)

Returns:

  • (Boolean)


732
733
734
735
# File 'lib/todorb.rb', line 732

def line_contains_item? line, item
  rx = regexp_item item
  return line.match rx
end

- (Object) list(args)



269
270
271
272
273
274
275
276
277
278
279
# File 'lib/todorb.rb', line 269

def list args
  populate
  grep if @options[:grep]
  filter if @options[:filter]
  sort if @options[:sort]
  renumber if @options[:renumber]
  colorize # << currently this is where I print !! Since i colorize the whole line
  puts " " 
  puts " #{@data.length} of #{@total} rows displayed from #{@app_file_path} "
  return 0
end

- (Object) listsub(args)

list task and its subtasks

 just testing this out


645
646
647
648
649
650
651
652
653
# File 'lib/todorb.rb', line 645

def listsub(args)
  load_array
  args.each { |item|  
    a = get_item_subs item
    puts "for #{item} "
    a.each { |e| puts " #{e[0]} #{e[1]} " }
  }
  0
end

- (Object) note(args)



562
563
564
565
566
567
568
569
570
571
# File 'lib/todorb.rb', line 562

def note(args)
  _backup
  text = args.pop
  change_items args do |item, row|
    m = row[0].match(/^ */)
    indent = m[0]
    ret = row[1].sub!(/ (\([0-9]{4})/," #{indent}* #{text} "+'\1')
    ret
  end
end

- (Object) populate

populates array with open tasks (or all if --show-all) DO NOT USE in conjunction with save_array since this is only open tasks Use load_array with save_array



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/todorb.rb', line 230

def populate
  $valid_array = false # this array object should not be saved
  check_file
  @ctr = 0
  @total = 0
  #CSV.foreach(@file,:col_sep => "\t") do |row|    # 1.9 2009-10-05 11:12 
  File.open(@file).each do |line|
    row = line.chomp.split "\t"
    @total += 1
    if @options[:show_all]
      @data << row
      @ctr += 1
    else
      unless row[1] =~ /^\[x\]/ 
        @data << row
        @ctr += 1
      end
    end
  end
end

- (Object) pri(args)

2010-06-19 15:21 total rewrite, so we fetch item from array and warn if absent.



359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/todorb.rb', line 359

def pri args
  errors = 0
  ctr = 0
  #populate # populate removed closed task so later saving will lose tasks
  load_array
  ## if the first arg is priority then following items all have that priority
  ## if the first arg is item/s then wait for priority and use that
  prior, items = _separate args, /^[A-Z]$/ 
  total = items.count
  die "#{@action}: priority expected [A-Z]" unless prior
  die "#{@action}: items expected" unless items
  verbose "args 0 is #{args[0]}. pri #{prior} items #{items} "
  items.each do |item| 
    row = get_item(item)
    if row
      puts " #{row[0]} : #{row[1]} "
      # remove existing priority if there
      if row[1] =~ /\] (\([A-Z]\) )/
        row[1].sub!(/\([A-Z]\) /,"")
      end
      ret = row[1].sub!(/\] /,"] (#{prior}) ")
      if ret
        puts " #{GREEN}#{row[0]} : #{row[1]} #{CLEAR}"
        ctr += 1
      else
        die "Error in sub(): #{row}.\nNothing saved. "
      end
    else
      errors += 1
      warning "#{item} not found."
    end
  end

  message "#{errors} error/s" if errors > 0
  if ctr > 0
    puts "Changed priority of #{ctr} task/s"
    save_array 
    return 0 
  end
  return ERRCODE
end


280
281
282
283
284
285
286
287
288
# File 'lib/todorb.rb', line 280

def print_todo
  @ctr = 0
  @data.each { |row|  
    unless row[1] =~ /^\[x\]/ 
      puts " #{row[0]} | #{row[1]} " #unless row[1] =~ /^\[x\]/
      @ctr += 1
    end
  }
end

- (Object) redo(args)

Redoes the numbering in the file. Useful if the numbers have gone high and you want to start over.



753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
# File 'lib/todorb.rb', line 753

def redo args
  #require 'fileutils'
  #FileUtils.cp @app_file_path, "#{@app_file_path}.org"
  _backup
  puts "Saved #{@app_file_path} as #{@app_file_path}.org"
  #ctr = 1
  #change_file @app_file_path do |line|
    #paditem = _paditem ctr
    #line.sub!(/^ *[0-9]+/, paditem)
    #ctr += 1
  #end
  ctr = 0
  Sed::change_file @app_file_path do |line|
    if line =~ /^ *[0-9]+\t/
      ctr += 1
      paditem = _paditem ctr
      line.sub!(/^ *[0-9]+\t/, "#{paditem}#{@todo_delim}")
    else
      # assume its a subtask, just change the outer number
      line.sub!(/[0-9]+\./, "#{ctr}.")
    end
  end
  _set_serial_number ctr
  puts "Redone numbering"
end

- (Object) regexp_item(item)

return a regexp for an item to do matches on - WARNING INCLUDES TAB



741
742
743
# File 'lib/todorb.rb', line 741

def regexp_item item
  Regexp.new("^ +#{item}#{@todo_delim}")
end

- (Boolean) row_contains_item?(row, item)

Returns:

  • (Boolean)


736
737
738
739
# File 'lib/todorb.rb', line 736

def row_contains_item? row, item
  rx = Regexp.new("^ +#{item}")
  return row[0].match rx
end

- (Object) sort



339
340
341
# File 'lib/todorb.rb', line 339

def sort
  @data.sort! { |a,b| b[1] <=> a[1] }
end

- (Object) status(args)



485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
# File 'lib/todorb.rb', line 485

def status(args)
  stat, items = _separate args #, /^[a-zA-Z]/ 
  verbose "Items: #{items} : stat #{stat} "
  status, newstatus = _resolve_status stat
  if status.nil?
    die "Status #{stat} is invalid!"
  end
  # this worked fine for single items, but not for recursive changes 
  #ctr = change_items(items, /(\[.\])/, "[#{newstatus}]")
  totalitems = []
  #ret = line.sub!(/(\[.\])/, "[#{newstatus}]")
  load_array
  items.each { |item| 
    a = get_item_subs item
    if a
      a.each { |e| 
        totalitems << e[0].strip
      }
    else
      # perhaps I should pass item into total and let c_i handle error message
      warning "No tasks found for #{item}"
    end
  }
  change_items(totalitems, /(\[.\])/, "[#{newstatus}]")
  0
end

- (Object) tag(args)

Appends a tag to task FIXME: check with subtasks

Parameters:

  • (Array) items

    and tag, or tag and items

Returns:



414
415
416
417
418
419
420
421
# File 'lib/todorb.rb', line 414

def tag(args)
  tag, items = _separate args
  #change_items items do |item, row|
    #ret = row[1].sub!(/ (\([0-9]{4})/, " @#{tag} "+'\1')
    #ret
  #end
  change_items(items, / (\([0-9]{4})/, " @#{tag} "+'\1')
end