doing 2.0.22 → 2.1.0pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +18 -15
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +36 -1
  6. data/Gemfile.lock +8 -1
  7. data/README.md +7 -1
  8. data/Rakefile +23 -4
  9. data/bin/doing +323 -173
  10. data/doc/Array.html +354 -1
  11. data/doc/Doing/Color.html +104 -92
  12. data/doc/Doing/Completion.html +216 -0
  13. data/doc/Doing/Configuration.html +340 -5
  14. data/doc/Doing/Content.html +229 -0
  15. data/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  16. data/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  17. data/doc/Doing/Errors/DoingStandardError.html +1 -1
  18. data/doc/Doing/Errors/EmptyInput.html +1 -1
  19. data/doc/Doing/Errors/NoResults.html +1 -1
  20. data/doc/Doing/Errors/PluginException.html +1 -1
  21. data/doc/Doing/Errors/UserCancelled.html +1 -1
  22. data/doc/Doing/Errors/WrongCommand.html +1 -1
  23. data/doc/Doing/Errors.html +1 -1
  24. data/doc/Doing/Hooks.html +1 -1
  25. data/doc/Doing/Item.html +337 -49
  26. data/doc/Doing/Items.html +444 -35
  27. data/doc/Doing/LogAdapter.html +139 -51
  28. data/doc/Doing/Note.html +253 -22
  29. data/doc/Doing/Pager.html +74 -36
  30. data/doc/Doing/Plugins.html +1 -1
  31. data/doc/Doing/Prompt.html +674 -0
  32. data/doc/Doing/Section.html +354 -0
  33. data/doc/Doing/Util.html +57 -1
  34. data/doc/Doing/WWID.html +477 -670
  35. data/doc/Doing/WWIDFile.html +398 -0
  36. data/doc/Doing.html +5 -5
  37. data/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  38. data/doc/GLI/Commands.html +1 -1
  39. data/doc/GLI.html +1 -1
  40. data/doc/Hash.html +97 -1
  41. data/doc/Status.html +37 -3
  42. data/doc/String.html +599 -23
  43. data/doc/Symbol.html +3 -3
  44. data/doc/Time.html +1 -1
  45. data/doc/_index.html +22 -1
  46. data/doc/class_list.html +1 -1
  47. data/doc/file.README.html +8 -2
  48. data/doc/index.html +8 -2
  49. data/doc/method_list.html +453 -173
  50. data/doc/top-level-namespace.html +1 -1
  51. data/doing.gemspec +3 -0
  52. data/doing.rdoc +79 -27
  53. data/example_plugin.rb +5 -5
  54. data/lib/completion/_doing.zsh +42 -42
  55. data/lib/completion/doing.bash +10 -10
  56. data/lib/completion/doing.fish +1 -280
  57. data/lib/doing/array.rb +36 -0
  58. data/lib/doing/colors.rb +70 -66
  59. data/lib/doing/completion/bash_completion.rb +1 -2
  60. data/lib/doing/completion/fish_completion.rb +1 -1
  61. data/lib/doing/completion/zsh_completion.rb +1 -1
  62. data/lib/doing/completion.rb +6 -0
  63. data/lib/doing/configuration.rb +134 -23
  64. data/lib/doing/hash.rb +37 -0
  65. data/lib/doing/item.rb +77 -12
  66. data/lib/doing/items.rb +125 -0
  67. data/lib/doing/log_adapter.rb +58 -4
  68. data/lib/doing/note.rb +53 -1
  69. data/lib/doing/pager.rb +49 -38
  70. data/lib/doing/plugins/export/markdown_export.rb +4 -4
  71. data/lib/doing/plugins/export/template_export.rb +2 -2
  72. data/lib/doing/plugins/import/calendar_import.rb +4 -4
  73. data/lib/doing/plugins/import/doing_import.rb +5 -7
  74. data/lib/doing/plugins/import/timing_import.rb +3 -3
  75. data/lib/doing/prompt.rb +206 -0
  76. data/lib/doing/section.rb +30 -0
  77. data/lib/doing/string.rb +123 -35
  78. data/lib/doing/util.rb +14 -6
  79. data/lib/doing/version.rb +1 -1
  80. data/lib/doing/wwid.rb +307 -614
  81. data/lib/doing.rb +6 -2
  82. data/lib/examples/plugins/capture_thing_import.rb +162 -0
  83. data/rdoc_to_mmd.rb +14 -8
  84. data/scripts/generate_bash_completions.rb +1 -1
  85. data/scripts/generate_fish_completions.rb +1 -1
  86. data/scripts/generate_zsh_completions.rb +1 -1
  87. metadata +73 -5
  88. data/lib/doing/wwidfile.rb +0 -117
data/bin/doing CHANGED
@@ -35,8 +35,10 @@ colors = Doing::Color
35
35
  wwid = Doing::WWID.new
36
36
 
37
37
  Doing.logger.log_level = :info
38
+ env_log_level = nil
38
39
 
39
40
  if ENV['DOING_LOG_LEVEL'] || ENV['DOING_DEBUG'] || ENV['DOING_QUIET'] || ENV['DOING_VERBOSE'] || ENV['DOING_PLUGIN_DEBUG']
41
+ env_log_level = true
40
42
  # Quiet always wins
41
43
  if ENV['DOING_QUIET'] && ENV['DOING_QUIET'].truthy?
42
44
  Doing.logger.log_level = :error
@@ -82,6 +84,12 @@ switch %i[p pager], default_value: settings['paginate']
82
84
  desc 'Answer yes/no menus with default option'
83
85
  switch [:default], default_value: false
84
86
 
87
+ desc 'Answer all yes/no menus with yes'
88
+ switch [:yes], negatable: false
89
+
90
+ desc 'Answer all yes/no menus with no'
91
+ switch [:no], negatable: false
92
+
85
93
  desc 'Exclude auto tags and default tags'
86
94
  switch %i[x noauto], default_value: false, negatable: false
87
95
 
@@ -121,9 +129,9 @@ command %i[now next] do |c|
121
129
  c.desc "Edit entry with #{Doing::Util.default_editor}"
122
130
  c.switch %i[e editor], negatable: false, default_value: false
123
131
 
124
- c.desc 'Backdate start time [4pm|20m|2h|yesterday noon]'
132
+ c.desc 'Backdate start time [4pm|20m|2h|"yesterday noon"]'
125
133
  c.arg_name 'DATE_STRING'
126
- c.flag %i[b back]
134
+ c.flag %i[b back started]
127
135
 
128
136
  c.desc 'Timed entry, marks last entry in section as @done'
129
137
  c.switch %i[f finish_last], negatable: false, default_value: false
@@ -151,29 +159,34 @@ command %i[now next] do |c|
151
159
  options[:section] = settings['current_section']
152
160
  end
153
161
 
154
- if options[:e] || (args.empty? && $stdin.stat.size.zero?)
162
+ if options[:editor] || (args.empty? && $stdin.stat.size.zero?)
155
163
  raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
156
164
 
157
- input = ''
165
+ input = date.strftime('%F %R | ')
158
166
  input += args.join(' ') unless args.empty?
159
167
  input = wwid.fork_editor(input).strip
160
168
 
161
169
  raise EmptyInput, 'No content' if input.empty?
162
170
 
163
- title, note = wwid.format_input(input)
164
- note.push(options[:n]) if options[:n]
165
- wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:f] })
171
+ date, title, note = wwid.format_input(input)
172
+ note.add(options[:note]) if options[:note]
173
+ wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
166
174
  wwid.write(wwid.doing_file)
167
175
  elsif args.length.positive?
168
- title, note = wwid.format_input(args.join(' '))
169
- note.push(options[:n]) if options[:n]
170
- wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:f] })
176
+ d, title, note = wwid.format_input(args.join(' '))
177
+ date = d.nil? ? date : d
178
+ note.add(options[:note]) if options[:note]
179
+ wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
171
180
  wwid.write(wwid.doing_file)
172
181
  elsif $stdin.stat.size.positive?
173
- input = $stdin.read
174
- title, note = wwid.format_input(input)
175
- note.push(options[:n]) if options[:n]
176
- wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:f] })
182
+ input = $stdin.read.strip
183
+ d, title, note = wwid.format_input(input)
184
+ unless d.nil?
185
+ Doing.logger.debug('Parser:', 'Date detected in input, overriding command line values')
186
+ date = d
187
+ end
188
+ note.add(options[:note]) if options[:note]
189
+ wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
177
190
  wwid.write(wwid.doing_file)
178
191
  else
179
192
  raise EmptyInput, 'You must provide content when creating a new entry'
@@ -238,14 +251,13 @@ command %i[reset begin] do |c|
238
251
  items = wwid.filter_items([], opt: options)
239
252
 
240
253
  if options[:interactive]
241
- last_entry = wwid.choose_from_items(items, {
254
+ last_entry = Doing::Prompt.choose_from_items(items, include_section: options[:section].nil?,
242
255
  menu: true,
243
256
  header: '',
244
257
  prompt: 'Select an entry to start/reset > ',
245
258
  multiple: false,
246
259
  sort: false,
247
- show_if_single: true
248
- }, include_section: options[:section].nil? )
260
+ show_if_single: true)
249
261
  else
250
262
  last_entry = items.last
251
263
  end
@@ -344,7 +356,7 @@ command :note do |c|
344
356
  last_note = last_entry.note || Doing::Note.new
345
357
  new_note = Doing::Note.new
346
358
 
347
- if options[:e] || (args.empty? && $stdin.stat.size.zero? && !options[:r])
359
+ if options[:editor] || (args.empty? && $stdin.stat.size.zero? && !options[:remove])
348
360
  raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
349
361
 
350
362
  input = !args.empty? ? args.join(' ') : ''
@@ -357,14 +369,14 @@ command :note do |c|
357
369
 
358
370
  input = prev_input.add(input)
359
371
 
360
- input = wwid.fork_editor([last_entry.title, '### Edit below this line', input.to_s].join("\n")).strip
361
- _title, note = wwid.format_input(input)
372
+ input = wwid.fork_editor(prev_input.strip_lines.join("\n"), message: nil).strip
373
+ note = input
362
374
  options[:remove] = true
363
375
  new_note.add(note)
364
376
  elsif !args.empty?
365
377
  new_note.add(args.join(' '))
366
378
  elsif $stdin.stat.size.positive?
367
- new_note.add($stdin.read)
379
+ new_note.add($stdin.read.strip)
368
380
  else
369
381
  raise EmptyInput, 'You must provide content when adding a note' unless options[:remove]
370
382
  end
@@ -423,31 +435,35 @@ command :meanwhile do |c|
423
435
  end
424
436
  input = ''
425
437
 
426
- if options[:e]
438
+ if options[:editor]
427
439
  raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
428
-
440
+ input += date.strftime('%F %R | ')
429
441
  input += args.join(' ') unless args.empty?
430
442
  input = wwid.fork_editor(input).strip
431
443
  elsif !args.empty?
432
444
  input = args.join(' ')
433
445
  elsif $stdin.stat.size.positive?
434
- input = $stdin.read
446
+ input = $stdin.read.strip
435
447
  end
436
448
 
437
449
  if input && !input.empty?
438
- input, note = wwid.format_input(input)
450
+ d, input, note = wwid.format_input(input)
451
+ unless d.nil?
452
+ Doing.logger.debug('Parser:', 'Date detected in input, overriding command line values')
453
+ date = d
454
+ end
439
455
  else
440
456
  input = nil
441
457
  note = []
442
458
  end
443
459
 
444
- if options[:n]
445
- note.push(options[:n])
460
+ if options[:note]
461
+ note.push(options[:note])
446
462
  elsif note.empty?
447
463
  note = nil
448
464
  end
449
465
 
450
- wwid.stop_start('meanwhile', { new_item: input, back: date, section: section, archive: options[:a], note: note })
466
+ wwid.stop_start('meanwhile', { new_item: input, back: date, section: section, archive: options[:archive], note: note })
451
467
  wwid.write(wwid.doing_file)
452
468
  end
453
469
  end
@@ -465,11 +481,11 @@ command :template do |c|
465
481
  c.switch %i[l list], negatable: false
466
482
 
467
483
  c.desc 'List in single column for completion'
468
- c.switch %i[c]
484
+ c.switch %i[c column]
469
485
 
470
486
  c.action do |_global_options, options, args|
471
- if options[:list] || options[:c]
472
- if options[:c]
487
+ if options[:list] || options[:column]
488
+ if options[:column]
473
489
  $stdout.print Doing::Plugins.plugin_templates.join("\n")
474
490
  else
475
491
  $stdout.puts "Available templates: #{Doing::Plugins.plugin_templates.join(', ')}"
@@ -478,7 +494,7 @@ command :template do |c|
478
494
  end
479
495
 
480
496
  if args.empty?
481
- type = wwid.choose_from(Doing::Plugins.plugin_templates, sorted: false, prompt: 'Select template type > ')
497
+ type = Doing::Prompt.choose_from(Doing::Plugins.plugin_templates, sorted: false, prompt: 'Select template type > ')
482
498
  else
483
499
  type = args[0]
484
500
  end
@@ -613,22 +629,29 @@ command :later do |c|
613
629
  if options[:editor] || (args.empty? && $stdin.stat.size.zero?)
614
630
  raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
615
631
 
616
- input = args.empty? ? '' : args.join(' ')
632
+ input += date.strftime('%F %R | ')
633
+ input += args.empty? ? '' : args.join(' ')
617
634
  input = wwid.fork_editor(input).strip
618
635
  raise EmptyInput, 'No content' unless input && !input.empty?
619
636
 
620
- title, note = wwid.format_input(input)
621
- note.push(options[:n]) if options[:n]
637
+ d, title, note = wwid.format_input(input)
638
+ date = d.nil? ? date : d
639
+ note.add(options[:note]) if options[:note]
622
640
  wwid.add_item(title.cap_first, 'Later', { note: note, back: date })
623
641
  wwid.write(wwid.doing_file)
624
642
  elsif !args.empty?
625
- title, note = wwid.format_input(args.join(' '))
626
- note.push(options[:n]) if options[:n]
643
+ d, title, note = wwid.format_input(args.join(' '))
644
+ date = d.nil? ? date : d
645
+ note.add(options[:note]) if options[:note]
627
646
  wwid.add_item(title.cap_first, 'Later', { note: note, back: date })
628
647
  wwid.write(wwid.doing_file)
629
648
  elsif $stdin.stat.size.positive?
630
- title, note = wwid.format_input($stdin.read)
631
- note.push(options[:n]) if options[:n]
649
+ d, title, note = wwid.format_input($stdin.read)
650
+ unless d.nil?
651
+ Doing.logger.debug('Parser:', 'Date detected in input, overriding command line values')
652
+ date = d
653
+ end
654
+ note.add(options[:note]) if options[:note]
632
655
  wwid.add_item(title.cap_first, 'Later', { note: note, back: date })
633
656
  wwid.write(wwid.doing_file)
634
657
  else
@@ -659,9 +682,9 @@ command %i[done did] do |c|
659
682
  c.arg_name 'DATE_STRING'
660
683
  c.flag [:at]
661
684
 
662
- c.desc 'Backdate start date by interval [4pm|20m|2h|yesterday noon]'
685
+ c.desc 'Backdate start date by interval or set to time [4pm|20m|2h|"yesterday noon"]'
663
686
  c.arg_name 'DATE_STRING'
664
- c.flag %i[b back]
687
+ c.flag %i[b back started]
665
688
 
666
689
  c.desc %(Set completion date to start date plus interval (XX[mhd] or HH:MM).
667
690
  If used without the --back option, the start date will be moved back to allow
@@ -710,8 +733,6 @@ command %i[done did] do |c|
710
733
  date = options[:took] ? finish_date - took : finish_date
711
734
  elsif options[:took]
712
735
  finish_date = date + took
713
- elsif options[:back]
714
- finish_date = date
715
736
  else
716
737
  finish_date = Time.now
717
738
  end
@@ -743,16 +764,17 @@ command %i[done did] do |c|
743
764
 
744
765
  old_entry = last_entry.dup
745
766
  last_entry.note.add(note)
746
- input = [last_entry.title, last_entry.note.to_s].join("\n")
767
+ input = ["#{last_entry.date.strftime('%F %R | ')}#{last_entry.title}", last_entry.note.strip_lines.join("\n")].join("\n")
747
768
  else
748
769
  is_new = true
749
- input = [args.join(' '), note.to_s].join("\n")
770
+ input = ["#{date.strftime('%F %R | ')}#{args.join(' ')}", note.strip_lines.join("\n")].join("\n")
750
771
  end
751
772
 
752
773
  input = wwid.fork_editor(input).strip
753
774
  raise EmptyInput, 'No content' unless input && !input.empty?
754
775
 
755
- title, note = wwid.format_input(input)
776
+ d, title, note = wwid.format_input(input)
777
+ date = d.nil? ? date : d
756
778
  new_entry = Doing::Item.new(date, title, section, note)
757
779
  if new_entry.should_finish?
758
780
  if new_entry.should_time?
@@ -763,23 +785,23 @@ command %i[done did] do |c|
763
785
  end
764
786
 
765
787
  if (is_new)
766
- wwid.content[section][:items].push(new_entry)
788
+ wwid.content.push(new_entry)
767
789
  else
768
- wwid.update_item(old_entry, new_entry)
790
+ wwid.content.update_item(old_entry, new_entry)
769
791
  end
770
792
 
771
- if options[:a]
793
+ if options[:archive]
772
794
  wwid.move_item(new_entry, 'Archive', label: true)
773
795
  end
774
796
 
775
797
  wwid.write(wwid.doing_file)
776
798
  elsif args.empty? && $stdin.stat.size.zero?
777
- if options[:r]
799
+ if options[:remove]
778
800
  wwid.tag_last({ tags: ['done'], count: 1, section: section, remove: true })
779
801
  else
780
802
  note = options[:note] ? Doing::Note.new(options[:note]) : nil
781
803
  opt = {
782
- archive: options[:a],
804
+ archive: options[:archive],
783
805
  back: finish_date,
784
806
  count: 1,
785
807
  date: options[:date],
@@ -793,9 +815,10 @@ command %i[done did] do |c|
793
815
  end
794
816
  elsif !args.empty?
795
817
  note = Doing::Note.new(options[:note])
796
- title, new_note = wwid.format_input([args.join(' '), note.to_s].join("\n"))
818
+ d, title, new_note = wwid.format_input([args.join(' '), note.strip_lines.join("\n")].join("\n"))
819
+ date = d.nil? ? date : d
797
820
  title.chomp!
798
- section = 'Archive' if options[:a]
821
+ section = 'Archive' if options[:archive]
799
822
  new_entry = Doing::Item.new(date, title, section, new_note)
800
823
  if new_entry.should_finish?
801
824
  if new_entry.should_time?
@@ -804,13 +827,17 @@ command %i[done did] do |c|
804
827
  new_entry.tag('done')
805
828
  end
806
829
  end
807
- wwid.content[section][:items].push(new_entry)
830
+ wwid.content.push(new_entry)
808
831
  wwid.write(wwid.doing_file)
809
832
  Doing.logger.info('Entry Added:', new_entry.title)
810
833
  elsif $stdin.stat.size.positive?
811
- title, note = wwid.format_input($stdin.read)
834
+ d, title, note = wwid.format_input($stdin.read.strip)
835
+ unless d.nil?
836
+ Doing.logger.debug('Parser:', 'Date detected in input, overriding command line values')
837
+ date = d
838
+ end
812
839
  note.add(options[:note]) if options[:note]
813
- section = options[:a] ? 'Archive' : section
840
+ section = options[:archive] ? 'Archive' : section
814
841
  new_entry = Doing::Item.new(date, title, section, note)
815
842
 
816
843
  if new_entry.should_finish?
@@ -821,7 +848,7 @@ command %i[done did] do |c|
821
848
  end
822
849
  end
823
850
 
824
- wwid.content[section][:items].push(new_entry)
851
+ wwid.content.push(new_entry)
825
852
  wwid.write(wwid.doing_file)
826
853
  Doing.logger.info('Entry Added:', new_entry.title)
827
854
  else
@@ -907,7 +934,7 @@ command :cancel do |c|
907
934
  end
908
935
 
909
936
  opts = {
910
- archive: options[:a],
937
+ archive: options[:archive],
911
938
  case: options[:case].normalize_case,
912
939
  count: count,
913
940
  date: false,
@@ -1188,7 +1215,7 @@ command :tag do |c|
1188
1215
  c.desc 'Tag last entry (or entries) not marked @done'
1189
1216
  c.switch %i[u unfinished], negatable: false, default_value: false
1190
1217
 
1191
- c.desc 'Autotag entries based on autotag configuration in ~/.doingrc'
1218
+ c.desc 'Autotag entries based on autotag configuration in ~/.config/doing/config.yml'
1192
1219
  c.switch %i[a autotag], negatable: false, default_value: false
1193
1220
 
1194
1221
  c.desc 'Tag the last X entries containing TAG.
@@ -1279,15 +1306,15 @@ command :tag do |c|
1279
1306
  end
1280
1307
 
1281
1308
 
1282
- question = if options[:a]
1309
+ question = if options[:aarchive]
1283
1310
  "Are you sure you want to autotag all records#{section_q}"
1284
- elsif options[:r]
1311
+ elsif options[:remove]
1285
1312
  "Are you sure you want to remove #{tags.join(' and ')} from all records#{section_q}"
1286
1313
  else
1287
1314
  "Are you sure you want to add #{tags.join(' and ')} to all records#{section_q}"
1288
1315
  end
1289
1316
 
1290
- res = wwid.yn(question, default_response: false)
1317
+ res = Doing::Prompt.yn(question, default_response: false)
1291
1318
 
1292
1319
  raise UserCancelled unless res
1293
1320
  end
@@ -1408,7 +1435,7 @@ command [:mark, :flag] do |c|
1408
1435
  "Are you sure you want to flag all records#{section_q}"
1409
1436
  end
1410
1437
 
1411
- res = wwid.yn(question, default_response: false)
1438
+ res = Doing::Prompt.yn(question, default_response: false)
1412
1439
 
1413
1440
  exit_now! 'Cancelled' unless res
1414
1441
  end
@@ -1598,7 +1625,6 @@ command :show do |c|
1598
1625
  end
1599
1626
 
1600
1627
  opt = options.dup
1601
-
1602
1628
  opt[:sort_tags] = options[:tag_sort] =~ /^n/i
1603
1629
  opt[:count] = options[:count].to_i
1604
1630
  opt[:date_filter] = dates
@@ -1729,7 +1755,7 @@ command :recent do |c|
1729
1755
  c.switch %i[i interactive], negatable: false, default_value: false
1730
1756
 
1731
1757
  c.action do |global_options, options, args|
1732
- section = wwid.guess_section(options[:s]) || options[:s].cap_first
1758
+ section = wwid.guess_section(options[:section]) || options[:section].cap_first
1733
1759
 
1734
1760
  unless global_options[:version]
1735
1761
  if settings['templates']['recent'].key?('count')
@@ -1744,7 +1770,7 @@ command :recent do |c|
1744
1770
  count = args.empty? ? config_count : args[0].to_i
1745
1771
  end
1746
1772
 
1747
- options[:t] = true if options[:totals]
1773
+ options[:times] = true if options[:totals]
1748
1774
  options[:sort_tags] = options[:tag_sort] =~ /^n/i
1749
1775
 
1750
1776
  template = settings['templates']['recent'].deep_merge(settings['templates']['default'])
@@ -1753,7 +1779,7 @@ command :recent do |c|
1753
1779
  opts = {
1754
1780
  sort_tags: options[:sort_tags],
1755
1781
  tags_color: tags_color,
1756
- times: options[:t],
1782
+ times: options[:times],
1757
1783
  totals: options[:totals],
1758
1784
  interactive: options[:interactive]
1759
1785
  }
@@ -1802,7 +1828,7 @@ command :today do |c|
1802
1828
  c.action do |_global_options, options, _args|
1803
1829
  raise DoingRuntimeError, %(Invalid output type "#{options[:output]}") if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
1804
1830
 
1805
- options[:t] = true if options[:totals]
1831
+ options[:times] = true if options[:totals]
1806
1832
  options[:sort_tags] = options[:tag_sort] =~ /^n/i
1807
1833
  opt = {
1808
1834
  after: options[:after],
@@ -1863,14 +1889,14 @@ command :on do |c|
1863
1889
 
1864
1890
  raise InvalidTimeExpression, 'Unrecognized date string' unless start
1865
1891
 
1866
- message = "Date interpreted as #{start}"
1892
+ message = "date interpreted as #{start}"
1867
1893
  message += " to #{finish}" if finish
1868
- Doing.logger.debug(message)
1894
+ Doing.logger.debug('Interpreter:', message)
1869
1895
 
1870
- options[:t] = true if options[:totals]
1896
+ options[:times] = true if options[:totals]
1871
1897
  options[:sort_tags] = options[:tag_sort] =~ /^n/i
1872
1898
 
1873
- Doing::Pager.page wwid.list_date([start, finish], options[:s], options[:t], options[:output],
1899
+ Doing::Pager.page wwid.list_date([start, finish], options[:section], options[:times], options[:output],
1874
1900
  { totals: options[:totals], sort_tags: options[:sort_tags] }).chomp
1875
1901
  end
1876
1902
  end
@@ -1918,12 +1944,12 @@ command :since do |c|
1918
1944
 
1919
1945
  raise InvalidTimeExpression, 'Unrecognized date string' unless start
1920
1946
 
1921
- Doing.logger.debug("Date interpreted as #{start} through the current time")
1947
+ Doing.logger.debug('Interpreter:', "date interpreted as #{start} through the current time")
1922
1948
 
1923
- options[:t] = true if options[:totals]
1949
+ options[:times] = true if options[:totals]
1924
1950
  options[:sort_tags] = options[:tag_sort] =~ /^n/i
1925
1951
 
1926
- Doing::Pager.page wwid.list_date([start, finish], options[:s], options[:t], options[:output],
1952
+ Doing::Pager.page wwid.list_date([start, finish], options[:section], options[:times], options[:output],
1927
1953
  { totals: options[:totals], sort_tags: options[:sort_tags] }).chomp
1928
1954
  end
1929
1955
  end
@@ -2053,9 +2079,9 @@ command :last do |c|
2053
2079
  end
2054
2080
 
2055
2081
  if options[:editor]
2056
- wwid.edit_last(section: options[:s], options: { search: search, fuzzy: options[:fuzzy], case: options[:case], tag: tags, tag_bool: options[:bool], not: options[:not] })
2082
+ wwid.edit_last(section: options[:section], options: { search: search, fuzzy: options[:fuzzy], case: options[:case], tag: tags, tag_bool: options[:bool], not: options[:not] })
2057
2083
  else
2058
- Doing::Pager::page wwid.last(times: true, section: options[:s],
2084
+ Doing::Pager::page wwid.last(times: true, section: options[:section],
2059
2085
  options: { search: search, fuzzy: options[:fuzzy], case: options[:case], negate: options[:not], tag: tags, tag_bool: options[:bool] }).strip
2060
2086
  end
2061
2087
  end
@@ -2067,8 +2093,8 @@ command :sections do |c|
2067
2093
  c.switch %i[c column], negatable: false, default_value: false
2068
2094
 
2069
2095
  c.action do |_global_options, options, _args|
2070
- joiner = options[:c] ? "\n" : "\t"
2071
- print wwid.sections.join(joiner)
2096
+ joiner = options[:column] ? "\n" : "\t"
2097
+ print wwid.content.section_titles.join(joiner)
2072
2098
  end
2073
2099
  end
2074
2100
 
@@ -2089,7 +2115,7 @@ command :add_section do |c|
2089
2115
  c.action do |_global_options, _options, args|
2090
2116
  raise InvalidArgument, "Section #{args[0]} already exists" if wwid.sections.include?(args[0])
2091
2117
 
2092
- wwid.add_section(args.join(' ').cap_first)
2118
+ wwid.content.add_section(args.join(' ').cap_first, log: true)
2093
2119
  wwid.write(wwid.doing_file)
2094
2120
  end
2095
2121
  end
@@ -2247,6 +2273,7 @@ command :view do |c|
2247
2273
  rescue WrongCommand => exception
2248
2274
  cmd = commands[:show]
2249
2275
  options[:sort] = 'asc'
2276
+ options[:tag_order] = 'asc'
2250
2277
  action = cmd.send(:get_action, nil)
2251
2278
  return action.call(global_options, options, args)
2252
2279
  end
@@ -2289,12 +2316,9 @@ command :view do |c|
2289
2316
  # If the -o/--output flag was specified, override any default in the view template
2290
2317
  options[:output] ||= view.key?('output_format') ? view['output_format'] : 'template'
2291
2318
 
2292
- count = if options[:c]
2293
- options[:c]
2294
- else
2295
- view.key?('count') ? view['count'] : 10
2296
- end
2297
- section = if options[:s]
2319
+ count = options[:count] ? options[:count] : view.key?('count') ? view['count'] : 10
2320
+
2321
+ section = if options[:section]
2298
2322
  section
2299
2323
  else
2300
2324
  view.key?('section') ? view['section'] : settings['current_section']
@@ -2312,7 +2336,7 @@ command :view do |c|
2312
2336
  view.key?('tag_order') ? view['tag_order'].normalize_order : 'asc'
2313
2337
  end
2314
2338
 
2315
- options[:t] = true if totals
2339
+ options[:times] = true if totals
2316
2340
  output_format = options[:output]&.downcase || 'template'
2317
2341
 
2318
2342
  options[:sort_tags] = if options[:tag_sort]
@@ -2386,7 +2410,7 @@ command :views do |c|
2386
2410
  c.switch %i[c column], default_value: false
2387
2411
 
2388
2412
  c.action do |_global_options, options, _args|
2389
- joiner = options[:c] ? "\n" : "\t"
2413
+ joiner = options[:column] ? "\n" : "\t"
2390
2414
  print wwid.views.join(joiner)
2391
2415
  end
2392
2416
  end
@@ -2552,6 +2576,10 @@ end
2552
2576
  desc 'Open the "doing" file in an editor'
2553
2577
  long_desc "`doing open` defaults to using the editor_app setting in #{config.config_file} (#{settings.key?('editor_app') ? settings['editor_app'] : 'not set'})."
2554
2578
  command :open do |c|
2579
+ c.desc 'Open with editor command (e.g. vim, mate)'
2580
+ c.arg_name 'COMMAND'
2581
+ c.flag %i[e editor]
2582
+
2555
2583
  if `uname` =~ /Darwin/
2556
2584
  c.desc 'Open with app name'
2557
2585
  c.arg_name 'APP_NAME'
@@ -2567,11 +2595,17 @@ command :open do |c|
2567
2595
  params.delete_if do |k, v|
2568
2596
  k.instance_of?(String) || v.nil? || v == false
2569
2597
  end
2570
- if `uname` =~ /Darwin/
2598
+
2599
+ if options[:editor]
2600
+ raise MissingEditor, "Editor #{options[:editor]} not found" unless Doing::Util.exec_available(options[:editor])
2601
+
2602
+ editor = TTY::Which.which(options[:editor])
2603
+ system %(#{editor} "#{File.expand_path(wwid.doing_file)}")
2604
+ elsif `uname` =~ /Darwin/
2571
2605
  if options[:app]
2572
- system %(open -a "#{options[:a]}" "#{File.expand_path(wwid.doing_file)}")
2606
+ system %(open -a "#{options[:app]}" "#{File.expand_path(wwid.doing_file)}")
2573
2607
  elsif options[:bundle_id]
2574
- system %(open -b "#{options[:b]}" "#{File.expand_path(wwid.doing_file)}")
2608
+ system %(open -b "#{options[:bundle_id]}" "#{File.expand_path(wwid.doing_file)}")
2575
2609
  elsif Doing::Util.find_default_editor('doing_file')
2576
2610
  editor = Doing::Util.find_default_editor('doing_file')
2577
2611
  if Doing::Util.exec_available(editor)
@@ -2591,132 +2625,240 @@ command :open do |c|
2591
2625
  end
2592
2626
 
2593
2627
  desc 'Edit the configuration file or output a value from it'
2594
- long_desc %(Run without arguments, `doing config` opens your `.doingrc` in an editor.
2628
+ long_desc %(Run without arguments, `doing config` opens your `config.yml` in an editor.
2595
2629
  If local configurations are found in the path between the current directory
2596
- and `~/.doingrc`, a menu will allow you to select which to open in the editor.
2630
+ and the root (/), a menu will allow you to select which to open in the editor.
2597
2631
 
2598
2632
  It will use the editor defined in `config_editor_app`, or one specified with `--editor`.
2599
2633
 
2600
- Use `doing config -d` to output the configuration to the terminal, and
2634
+ Use `doing config get` to output the configuration to the terminal, and
2601
2635
  provide a dot-separated key path to get a specific value. Shows the current value
2602
2636
  including keys/overrides set by local configs.)
2603
- arg_name 'KEY_PATH'
2604
2637
  command :config do |c|
2605
2638
  c.example 'doing config', desc: "Open an active configuration in #{Doing::Util.find_default_editor('config')}"
2606
- c.example 'doing config -d doing_file', desc: 'Output the value of a config key as YAML'
2607
- c.example 'doing config -d plugins.say.say_voice -o json', desc: 'Output the value of a key path as JSON'
2639
+ c.example 'doing config get doing_file', desc: 'Output the value of a config key as YAML'
2640
+ c.example 'doing config get plugins.plugin_path -o json', desc: 'Output the value of a key path as JSON'
2641
+ c.example 'doing config set plugins.say.say_voice Alex', desc: 'Set the value of a key path and update config file'
2642
+ c.example 'doing config set plug.say.voice Zarvox', desc: 'Key paths for get and set are fuzzy matched'
2608
2643
 
2609
- c.desc 'Editor to use'
2610
- c.arg_name 'EDITOR'
2611
- c.flag %i[e editor], default_value: nil
2644
+ c.default_command :edit
2612
2645
 
2613
- c.desc 'Show a config key value based on arguments. Separate key paths with colons or dots, e.g. "export_templates.html". Empty arguments outputs the entire config.'
2614
- c.switch %i[d dump], negatable: false
2646
+ c.desc 'DEPRECATED'
2647
+ c.switch %i[d dump]
2615
2648
 
2616
- c.desc 'Format for --dump (json|yaml|raw)'
2617
- c.arg_name 'FORMAT'
2618
- c.flag %i[o output], default_value: 'yaml', must_match: /^(?:y(?:aml)?|j(?:son)?|r(?:aw)?)$/
2649
+ c.desc 'DEPRECATED'
2650
+ c.switch %i[u update]
2619
2651
 
2620
- c.desc 'Update config file with missing configuration options'
2621
- c.switch %i[u update], default_value: false, negatable: false
2652
+ c.desc 'List configuration paths, including .doingrc files in the current and parent directories'
2653
+ c.long_desc 'Config files are listed in order of precedence (if there are multiple configs detected).
2654
+ Values defined in the top item in the list will override values in configutations below it.'
2655
+ c.command :list do |list|
2656
+ list.action do |global, options, args|
2657
+ puts config.additional_configs.join("\n")
2658
+ puts config.config_file
2659
+ end
2660
+ end
2622
2661
 
2623
- if `uname` =~ /Darwin/
2624
- c.desc 'Application to use'
2625
- c.arg_name 'APP_NAME'
2626
- c.flag [:a]
2662
+ c.desc 'Open config file in editor'
2663
+ c.command :edit do |edit|
2664
+ edit.example 'doing config edit', desc: 'Open a config file in the default editor'
2665
+ edit.example 'doing config edit --editor vim', desc: 'Open config in specific editor'
2627
2666
 
2628
- c.desc 'Application bundle id to use'
2629
- c.arg_name 'BUNDLE_ID'
2630
- c.flag [:b]
2667
+ edit.desc 'Editor to use'
2668
+ edit.arg_name 'EDITOR'
2669
+ edit.flag %i[e editor], default_value: nil
2670
+
2671
+ if `uname` =~ /Darwin/
2672
+ edit.desc 'Application to use'
2673
+ edit.arg_name 'APP_NAME'
2674
+ edit.flag %i[a app]
2675
+
2676
+ edit.desc 'Application bundle id to use'
2677
+ edit.arg_name 'BUNDLE_ID'
2678
+ edit.flag %i[b bundle_id]
2679
+
2680
+ edit.desc "Use the config_editor_app defined in ~/.config/doing/config.yml (#{settings.key?('config_editor_app') ? settings['config_editor_app'] : 'config_editor_app not set'})"
2681
+ edit.switch %i[x default]
2682
+ end
2683
+
2684
+ edit.action do |global, options, args|
2685
+ if options[:update] || options[:dump]
2686
+ cmd = commands[:config]
2687
+ if options[:update]
2688
+ cmd = cmd.commands[:update]
2689
+ elsif options[:dump]
2690
+ cmd = cmd.commands[:get]
2691
+ end
2692
+ action = cmd.send(:get_action, nil)
2693
+ action.call(global, options, args)
2694
+ Doing.logger.warn('Deprecated:', '--dump and --update are deprecated,
2695
+ use `doing config get` and `doing config update`')
2696
+ Doing.logger.output_results
2697
+ return
2698
+ end
2699
+
2700
+ config_file = config.choose_config
2701
+
2702
+ if `uname` =~ /Darwin/
2703
+ if options[:default]
2704
+ editor = Doing::Util.find_default_editor('config')
2705
+ if editor
2706
+ if Doing::Util.exec_available(editor)
2707
+ system %(#{editor} "#{config_file}")
2708
+ else
2709
+ `open -a "#{editor}" "#{config_file}"`
2710
+ end
2711
+ else
2712
+ raise InvalidArgument, 'No viable editor found in config or environment.'
2713
+ end
2714
+ elsif options[:app] || options[:bundle_id]
2715
+ if options[:app]
2716
+ `open -a "#{options[:app]}" "#{config_file}"`
2717
+ elsif options[:bundle_id]
2718
+ `open -b #{options[:bundle_id]} "#{config_file}"`
2719
+ end
2720
+ else
2721
+ editor = options[:editor] || Doing::Util.find_default_editor('config')
2722
+
2723
+ raise MissingEditor, 'No viable editor defined in config or environment' unless editor
2631
2724
 
2632
- c.desc "Use the config_editor_app defined in ~/.doingrc (#{settings.key?('config_editor_app') ? settings['config_editor_app'] : 'config_editor_app not set'})"
2633
- c.switch [:x]
2725
+ if Doing::Util.exec_available(editor)
2726
+ system %(#{editor} "#{config_file}")
2727
+ else
2728
+ `open -a "#{editor}" "#{config_file}"`
2729
+ end
2730
+ end
2731
+ else
2732
+ editor = options[:editor] || Doing::Util.default_editor
2733
+ raise MissingEditor, 'No EDITOR variable defined in environment' unless editor && Doing::Util.exec_available(editor)
2734
+
2735
+ system %(#{editor} "#{config_file}")
2736
+ end
2737
+ end
2634
2738
  end
2635
2739
 
2636
- c.action do |_global_options, options, args|
2637
- if options[:update]
2740
+ c.desc 'Update default config file, adding any missing keys'
2741
+ c.command %i[update refresh] do |update|
2742
+ update.action do |_global, options, args|
2638
2743
  config.configure({rewrite: true, ignore_local: true})
2639
- return
2744
+ Doing.logger.warn('Config:', 'config refreshed')
2640
2745
  end
2746
+ end
2747
+
2748
+ c.desc 'Undo the last change to a config file'
2749
+ c.command :undo do |undo|
2750
+ undo.action do |_global, options, args|
2751
+ config_file = config.choose_config
2752
+ wwid.restore_backup(config_file)
2753
+ end
2754
+ end
2755
+
2756
+ c.desc 'Output a key\'s value'
2757
+ c.arg 'KEY_PATH'
2758
+ c.command %i[get dump] do |dump|
2759
+ dump.example 'doing config get', desc: 'Output the entire configuration'
2760
+ dump.example 'doing config get timer_format --output raw', desc: 'Output the value of timer_format as a plain string'
2761
+ dump.example 'doing config get doing_file', desc: 'Output the value of the doing_file setting, respecting local configurations'
2762
+ dump.example 'doing config get -o json plug.plugpath', desc: 'Key path is fuzzy matched: output the value of plugins->plugin_path as JSON'
2763
+
2764
+ dump.desc 'Format for output (json|yaml|raw)'
2765
+ dump.arg_name 'FORMAT'
2766
+ dump.flag %i[o output], default_value: 'yaml', must_match: /^(?:y(?:aml)?|j(?:son)?|r(?:aw)?)$/
2767
+
2768
+ dump.action do |_global, options, args|
2641
2769
 
2642
- if options[:dump]
2643
2770
  keypath = args.join('.')
2644
2771
  cfg = config.value_for_key(keypath)
2772
+ real_path = config.resolve_key_path(keypath)
2645
2773
 
2646
2774
  if cfg
2647
- $stdout.puts case options[:output]
2648
- when /^j/
2649
- JSON.pretty_generate(cfg)
2650
- when /^r/
2651
- cfg.map {|k, v| v.to_s }
2652
- else
2653
- YAML.dump(cfg)
2654
- end
2775
+ val = cfg.map {|k, v| v }[0]
2776
+ if real_path.count.positive?
2777
+ nested_cfg = {}
2778
+ nested_cfg.deep_set(real_path, val)
2779
+ else
2780
+ nested_cfg = val
2781
+ end
2782
+
2783
+ if options[:output] =~ /^r/
2784
+ if val.is_a?(Hash)
2785
+ $stdout.puts YAML.dump(val)
2786
+ elsif val.is_a?(Array)
2787
+ $stdout.puts val.join(', ')
2788
+ else
2789
+ $stdout.puts val.to_s
2790
+ end
2791
+ else
2792
+ $stdout.puts case options[:output]
2793
+ when /^j/
2794
+ JSON.pretty_generate(val)
2795
+ else
2796
+ YAML.dump(nested_cfg)
2797
+ end
2798
+ end
2655
2799
  else
2656
2800
  Doing.logger.log_now(:error, 'Config:', "Key #{keypath} not found")
2657
2801
  end
2658
2802
  Doing.logger.output_results
2659
2803
  return
2660
2804
  end
2805
+ end
2661
2806
 
2662
- if config.additional_configs.count.positive?
2663
- choices = [config.config_file]
2664
- choices.concat(config.additional_configs)
2665
- res = wwid.choose_from(choices.uniq.sort.reverse, sorted: false, prompt: 'Local configs found, select which to edit > ')
2807
+ c.desc 'Set a key\'s value in the config file'
2808
+ c.arg 'KEY VALUE'
2809
+ c.command :set do |set|
2810
+ set.example 'doing config set timer_format human', desc: 'Set the value of timer_format to "human"'
2811
+ set.example 'doing config set plug.plugpath ~/my_plugins', desc: 'Key path is fuzzy matched: set the value of plugins->plugin_path'
2666
2812
 
2667
- raise UserCancelled, 'Cancelled' unless res
2813
+ set.desc 'Delete specified key'
2814
+ set.switch %i[r remove], default_value: false, negatable: false
2668
2815
 
2669
- config_file = res.strip || config.config_file
2670
- else
2671
- config_file = config.config_file
2672
- end
2816
+ set.action do |_global, options, args|
2817
+ if args.count < 2 && !options[:remove]
2818
+ raise InvalidArgument, 'config set requires at least two arguments, key path and value'
2673
2819
 
2674
- if `uname` =~ /Darwin/
2675
- if options[:x]
2676
- editor = Doing::Util.find_default_editor('config')
2677
- if editor
2678
- if Doing::Util.exec_available(editor)
2679
- system %(#{editor} "#{config_file}")
2680
- else
2681
- `open -a "#{editor}" "#{config_file}"`
2682
- end
2683
- else
2684
- raise InvalidArgument, 'No viable editor found in config or environment.'
2685
- end
2686
- elsif options[:a] || options[:b]
2687
- if options[:a]
2688
- `open -a "#{options[:a]}" "#{config_file}"`
2689
- elsif options[:b]
2690
- `open -b #{options[:b]} "#{config_file}"`
2691
- end
2692
- else
2693
- editor = options[:e] || Doing::Util.find_default_editor('config')
2820
+ end
2694
2821
 
2695
- raise MissingEditor, 'No viable editor defined in config or environment' unless editor
2822
+ value = options[:remove] ? nil : args.pop
2823
+ keypath = args.join('.')
2824
+ old_value = config.value_for_key(keypath).map { |k, v| v.to_s }
2825
+ real_path = config.resolve_key_path(keypath)
2826
+ raise InvalidArgument, 'Invalid key path' if real_path.empty?
2696
2827
 
2697
- if Doing::Util.exec_available(editor)
2698
- system %(#{editor} "#{config_file}")
2699
- else
2700
- `open -a "#{editor}" "#{config_file}"`
2701
- end
2828
+ config_file = config.choose_config
2829
+ cfg = YAML.safe_load_file(config_file) || {}
2830
+
2831
+ $stderr.puts "Updating #{config_file}".yellow
2832
+
2833
+ if options[:remove]
2834
+ cfg.deep_set(real_path, nil)
2835
+ $stderr.puts "#{'Deleting key:'.yellow} #{real_path.join('->').boldwhite}"
2836
+ else
2837
+ old_value = cfg.dig(*real_path) || 'empty'
2838
+ cfg.deep_set(real_path, value.set_type)
2839
+ $stderr.puts "#{'Key path:'.yellow} #{real_path.join('->').boldwhite}"
2840
+ $stderr.puts "#{'Previous:'.yellow} #{old_value.to_s.boldwhite}"
2841
+ $stderr.puts "#{' New:'.yellow} #{value.set_type.to_s.boldwhite}"
2702
2842
  end
2703
- else
2704
- editor = options[:e] || Doing::Util.default_editor
2705
- raise MissingEditor, 'No EDITOR variable defined in environment' unless editor && Doing::Util.exec_available(editor)
2706
2843
 
2707
- system %(#{editor} "#{config_file}")
2844
+ res = Doing::Prompt.yn('Update selected config', default_response: true)
2845
+
2846
+ raise UserCancelled, 'Cancelled' unless res
2847
+
2848
+ Doing::Util.write_to_file(config_file, YAML.dump(cfg), backup: true)
2849
+ Doing.logger.warn('Config:', "#{config_file} updated")
2708
2850
  end
2709
2851
  end
2710
2852
  end
2711
2853
 
2712
- desc 'Undo the last change to the doing_file'
2854
+ desc 'Undo the last change to the Doing file'
2713
2855
  command :undo do |c|
2714
2856
  c.desc 'Specify alternate doing file'
2715
2857
  c.arg_name 'PATH'
2716
2858
  c.flag %i[f file], default_value: wwid.doing_file
2717
2859
 
2718
2860
  c.action do |_global_options, options, _args|
2719
- file = options[:f] || wwid.doing_file
2861
+ file = options[:file] || wwid.doing_file
2720
2862
  wwid.restore_backup(file)
2721
2863
  end
2722
2864
  end
@@ -2823,9 +2965,9 @@ pre do |global, _command, _options, _args|
2823
2965
 
2824
2966
  $stdout.puts "doing v#{Doing::VERSION}" if global[:version]
2825
2967
  unless STDOUT.isatty
2826
- Doing::Color::coloring = global[:pager] ? global[:color] : false
2968
+ Doing::Color.coloring = global[:pager] ? global[:color] : false
2827
2969
  else
2828
- Doing::Color::coloring = global[:color]
2970
+ Doing::Color.coloring = global[:color]
2829
2971
  end
2830
2972
 
2831
2973
  # Return true to proceed; false to abort and not call the
@@ -2853,13 +2995,21 @@ end
2853
2995
 
2854
2996
  around do |global, command, options, arguments, code|
2855
2997
  # Doing.logger.debug('Pager:', "Global: #{global[:pager]}, Config: #{settings['paginate']}, Pager: #{Doing::Pager.paginate}")
2856
- Doing.logger.adjust_verbosity(global)
2998
+ if env_log_level.nil?
2999
+ Doing.logger.adjust_verbosity(global)
3000
+ end
2857
3001
 
2858
3002
  if global[:stdout]
2859
3003
  Doing.logger.logdev = $stdout
2860
3004
  end
2861
3005
 
2862
- wwid.default_option = global[:default]
3006
+ if global[:yes]
3007
+ Doing::Prompt.force_answer = true
3008
+ elsif global[:no]
3009
+ Doing::Prompt.force_answer = false
3010
+ else
3011
+ Doing::Prompt.default_answer = global[:default]
3012
+ end
2863
3013
 
2864
3014
  if global[:config_file] && global[:config_file] != config.config_file
2865
3015
  Doing.logger.warn(format('%sWARNING:%s %sThe use of --config_file is deprecated, please set the environment variable DOING_CONFIG instead.', colors.flamingo, colors.default, colors.boldred))