doing 2.1.30 → 2.1.31pre

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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.irbrc +1 -0
  3. data/.yardoc/checksums +9 -8
  4. data/.yardoc/object_types +0 -0
  5. data/.yardoc/objects/root.dat +0 -0
  6. data/CHANGELOG.md +4923 -0
  7. data/Gemfile.lock +1 -1
  8. data/README.md +1 -1
  9. data/bin/commands/again.rb +1 -1
  10. data/bin/commands/archive.rb +3 -3
  11. data/bin/commands/cancel.rb +1 -1
  12. data/bin/commands/commands.rb +8 -8
  13. data/bin/commands/completion.rb +61 -19
  14. data/bin/commands/config.rb +9 -9
  15. data/bin/commands/done.rb +1 -1
  16. data/bin/commands/flag.rb +1 -1
  17. data/bin/commands/grep.rb +5 -5
  18. data/bin/commands/last.rb +1 -1
  19. data/bin/commands/meanwhile.rb +1 -1
  20. data/bin/commands/now.rb +1 -1
  21. data/bin/commands/on.rb +1 -1
  22. data/bin/commands/open.rb +1 -1
  23. data/bin/commands/recent.rb +4 -4
  24. data/bin/commands/show.rb +8 -8
  25. data/bin/commands/since.rb +1 -1
  26. data/bin/commands/today.rb +1 -1
  27. data/bin/commands/view.rb +3 -3
  28. data/bin/commands/yesterday.rb +2 -2
  29. data/bin/doing +22 -133
  30. data/docs/doc/Array.html +1 -1
  31. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  32. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  33. data/docs/doc/BooleanTermParser/Query.html +1 -1
  34. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  35. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  36. data/docs/doc/BooleanTermParser.html +1 -1
  37. data/docs/doc/Doing/Color.html +1 -1
  38. data/docs/doc/Doing/Completion.html +324 -4
  39. data/docs/doc/Doing/Configuration.html +1 -1
  40. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  41. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  42. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  43. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  44. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  45. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  46. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  47. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  48. data/docs/doc/Doing/Errors.html +1 -1
  49. data/docs/doc/Doing/Hooks.html +1 -1
  50. data/docs/doc/Doing/Item.html +125 -1
  51. data/docs/doc/Doing/Items.html +1 -1
  52. data/docs/doc/Doing/LogAdapter.html +1 -1
  53. data/docs/doc/Doing/Note.html +109 -3
  54. data/docs/doc/Doing/Pager.html +1 -1
  55. data/docs/doc/Doing/Plugins.html +1 -1
  56. data/docs/doc/Doing/Prompt.html +1 -1
  57. data/docs/doc/Doing/Section.html +1 -1
  58. data/docs/doc/Doing/TemplateString.html +1 -1
  59. data/docs/doc/Doing/Types.html +1 -1
  60. data/docs/doc/Doing/Util/Backup.html +1 -1
  61. data/docs/doc/Doing/Util.html +1 -1
  62. data/docs/doc/Doing/WWID.html +6 -6
  63. data/docs/doc/Doing.html +2 -2
  64. data/docs/doc/FalseClass.html +1 -1
  65. data/docs/doc/GLI/Commands/Help.html +1 -1
  66. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  67. data/docs/doc/GLI/Commands.html +1 -1
  68. data/docs/doc/GLI.html +1 -1
  69. data/docs/doc/Hash.html +1 -1
  70. data/docs/doc/Object.html +1 -1
  71. data/docs/doc/PhraseParser/Operator.html +1 -1
  72. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  73. data/docs/doc/PhraseParser/Query.html +1 -1
  74. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  75. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  76. data/docs/doc/PhraseParser/TermClause.html +1 -1
  77. data/docs/doc/PhraseParser.html +1 -1
  78. data/docs/doc/Status.html +1 -1
  79. data/docs/doc/String.html +1 -1
  80. data/docs/doc/Symbol.html +1 -1
  81. data/docs/doc/Time.html +1 -1
  82. data/docs/doc/TrueClass.html +1 -1
  83. data/docs/doc/_index.html +3 -1
  84. data/docs/doc/file.README.html +2 -2
  85. data/docs/doc/index.html +2 -2
  86. data/docs/doc/method_list.html +337 -241
  87. data/docs/doc/top-level-namespace.html +105 -1
  88. data/doing.rdoc +25 -9
  89. data/example_plugin.rb +7 -5
  90. data/lib/completion/_doing.zsh +2 -2
  91. data/lib/completion/doing.bash +2 -2
  92. data/lib/completion/doing.fish +2 -3
  93. data/lib/doing/add_options.rb +117 -0
  94. data/lib/doing/array/array.rb +16 -0
  95. data/lib/doing/completion/bash_completion.rb +12 -51
  96. data/lib/doing/completion/fish_completion.rb +16 -52
  97. data/lib/doing/completion/zsh_completion.rb +12 -56
  98. data/lib/doing/completion.rb +203 -17
  99. data/lib/doing/item.rb +21 -3
  100. data/lib/doing/items.rb +5 -5
  101. data/lib/doing/note.rb +24 -8
  102. data/lib/doing/plugins/export/dayone_export.rb +8 -6
  103. data/lib/doing/plugins/export/html_export.rb +4 -4
  104. data/lib/doing/plugins/export/json_export.rb +19 -20
  105. data/lib/doing/plugins/export/markdown_export.rb +2 -2
  106. data/lib/doing/plugins/export/template_export.rb +4 -4
  107. data/lib/doing/plugins/import/calendar_import.rb +1 -1
  108. data/lib/doing/plugins/import/doing_import.rb +1 -1
  109. data/lib/doing/plugins/import/timing_import.rb +1 -1
  110. data/lib/doing/string/highlight.rb +3 -4
  111. data/lib/doing/string/string.rb +8 -0
  112. data/lib/doing/util.rb +1 -1
  113. data/lib/doing/util_backup.rb +12 -12
  114. data/lib/doing/version.rb +1 -1
  115. data/lib/doing/wwid.rb +76 -77
  116. data/lib/doing.rb +57 -0
  117. data/lib/examples/commands/wiki.rb +27 -19
  118. data/scripts/setting_replace.rb +11 -0
  119. metadata +6 -4
@@ -24,8 +24,8 @@ module Doing
24
24
 
25
25
  out = ''
26
26
  items.each do |item|
27
- if opt[:highlight] && item.title =~ /@#{wwid.config['marker_tag']}\b/i
28
- flag = Doing::Color.send(wwid.config['marker_color'])
27
+ if opt[:highlight] && item.title =~ /@#{Doing.setting('marker_tag')}\b/i
28
+ flag = Doing::Color.send(Doing.setting('marker_color'))
29
29
  reset = Doing::Color.reset + Doing::Color.default
30
30
  else
31
31
  flag = ''
@@ -34,7 +34,7 @@ module Doing
34
34
 
35
35
  placeholders = {}
36
36
 
37
- if !item.note.empty? && wwid.config['include_notes']
37
+ if !item.note.empty? && Doing.setting('include_notes')
38
38
  note = item.note.map(&:strip).delete_if(&:empty?)
39
39
  note.map! { |line| "#{line.sub(/^\t*/, '')} " }
40
40
 
@@ -133,7 +133,7 @@ module Doing
133
133
 
134
134
  # Doing.logger.debug('Template Export:', "#{items.count} items output to template #{opt[:template]}")
135
135
  if opt[:totals]
136
- out += wwid.tag_times(format: wwid.config['timer_format'].to_sym,
136
+ out += wwid.tag_times(format: Doing.setting('timer_format').to_sym,
137
137
  sort_by: opt[:sort_tags],
138
138
  sort_order: opt[:tag_order])
139
139
  end
@@ -23,7 +23,7 @@ module Doing
23
23
  limit_start = options[:start].to_i
24
24
  limit_end = options[:end].to_i
25
25
 
26
- section = options[:section] || wwid.config['current_section']
26
+ section = options[:section] || Doing.setting('current_section')
27
27
  options[:no_overlap] ||= false
28
28
  options[:autotag] ||= wwid.auto_tag
29
29
 
@@ -63,7 +63,7 @@ module Doing
63
63
  title.gsub!(/ +/, ' ')
64
64
  title.strip!
65
65
  section = options[:section] || item.section
66
- section ||= wwid.config['current_section']
66
+ section ||= Doing.setting('current_section')
67
67
 
68
68
  new_item = Item.new(item.date, title, section)
69
69
  new_item.note = item.note
@@ -24,7 +24,7 @@ module Doing
24
24
  ##
25
25
  def self.import(wwid, path, options: {})
26
26
  exit_now! 'Path to JSON report required' if path.nil?
27
- section = options[:section] || wwid.config['current_section']
27
+ section = options[:section] || Doing.setting('current_section')
28
28
  options[:no_overlap] ||= false
29
29
  options[:autotag] ||= wwid.auto_tag
30
30
  wwid.content.add_section(section) unless wwid.content.section?(section)
@@ -35,10 +35,9 @@ module Doing
35
35
 
36
36
  def highlight_search(search, distance: nil, negate: false, case_type: nil)
37
37
  out = dup
38
- prefs = Doing.config.settings['search'] || {}
39
- matching = prefs.fetch('matching', 'pattern').normalize_matching
40
- distance ||= prefs.fetch('distance', 3).to_i
41
- case_type ||= prefs.fetch('case', 'smart').normalize_case
38
+ matching = Doing.setting('search.matching', 'pattern').normalize_matching
39
+ distance ||= Doing.setting('search.distance', 3).to_i
40
+ case_type ||= Doing.setting('search.case', 'smart').normalize_case
42
41
 
43
42
  if search.rx? || matching == :fuzzy
44
43
  rx = search.to_rx(distance: distance, case_type: case_type)
@@ -2,6 +2,14 @@
2
2
 
3
3
  class ::String
4
4
  include Doing::Color
5
+
6
+ def utf8
7
+ if String.method_defined? :force_encoding
8
+ dup.force_encoding('utf-8')
9
+ else
10
+ self
11
+ end
12
+ end
5
13
  end
6
14
 
7
15
  require_relative 'highlight'
data/lib/doing/util.rb CHANGED
@@ -159,7 +159,7 @@ module Doing
159
159
 
160
160
  return ENV['EDITOR'] if ENV['DOING_EDITOR_TEST']
161
161
 
162
- editor_config = Doing.config.settings['editors']
162
+ editor_config = Doing.setting('editors')
163
163
 
164
164
  if editor_config.is_a?(String)
165
165
  msg = "Please update your configuration, 'editors' should be a mapping."
@@ -30,7 +30,7 @@ module Doing
30
30
  ## @param limit Maximum number of backups to retain
31
31
  ##
32
32
  def clear_redo(filename)
33
- filename ||= Doing.config.settings['doing_file']
33
+ filename ||= Doing.setting('doing_file')
34
34
  backups = Dir.glob("undone*___#{File.basename(filename)}", base: backup_dir).sort.reverse
35
35
  backups.each do |file|
36
36
  FileUtils.rm(File.join(backup_dir, file))
@@ -44,7 +44,7 @@ module Doing
44
44
  ## @return [String] filename
45
45
  ##
46
46
  def last_backup(filename = nil, count: 1)
47
- filename ||= Doing.config.settings['doing_file']
47
+ filename ||= Doing.setting('doing_file')
48
48
 
49
49
  backup = get_backups(filename).slice(count - 1)
50
50
  backup.nil? ? nil : File.join(backup_dir, backup)
@@ -59,7 +59,7 @@ module Doing
59
59
  ##
60
60
  def restore_last_backup(filename = nil, count: 1)
61
61
  Doing.logger.benchmark(:restore_backup, :start)
62
- filename ||= Doing.config.settings['doing_file']
62
+ filename ||= Doing.setting('doing_file')
63
63
 
64
64
  backup_file = last_backup(filename, count: count)
65
65
  raise DoingRuntimeError, 'End of undo history' if backup_file.nil?
@@ -77,7 +77,7 @@ module Doing
77
77
  ## @param filename The filename
78
78
  ##
79
79
  def redo_backup(filename = nil, count: 1)
80
- filename ||= Doing.config.settings['doing_file']
80
+ filename ||= Doing.setting('doing_file')
81
81
  # redo_file = File.join(backup_dir, "undone___#{File.basename(filename)}")
82
82
  undones = Dir.glob("undone*#{File.basename(filename)}", base: backup_dir).sort.reverse
83
83
  total = undones.count
@@ -101,7 +101,7 @@ module Doing
101
101
  end
102
102
 
103
103
  def clear_undone(filename = nil)
104
- filename ||= Doing.config.settings['doing_file']
104
+ filename ||= Doing.setting('doing_file')
105
105
  # redo_file = File.join(backup_dir, "undone___#{File.basename(filename)}")
106
106
  Dir.glob("undone*#{File.basename(filename)}", base: backup_dir).each do |f|
107
107
  FileUtils.rm(File.join(backup_dir, f))
@@ -115,7 +115,7 @@ module Doing
115
115
  ## @param filename The filename to restore
116
116
  ##
117
117
  def select_redo(filename = nil)
118
- filename ||= Doing.config.settings['doing_file']
118
+ filename ||= Doing.setting('doing_file')
119
119
 
120
120
  undones = Dir.glob("undone*#{File.basename(filename)}", base: backup_dir).sort
121
121
 
@@ -155,7 +155,7 @@ module Doing
155
155
  ## @param filename The filename to restore
156
156
  ##
157
157
  def select_backup(filename = nil)
158
- filename ||= Doing.config.settings['doing_file']
158
+ filename ||= Doing.setting('doing_file')
159
159
 
160
160
  options = get_backups(filename).each_with_object([]) do |file, arr|
161
161
  d, _base = date_of_backup(file)
@@ -219,7 +219,7 @@ module Doing
219
219
  ##
220
220
  def write_backup(filename = nil)
221
221
  Doing.logger.benchmark(:_write_backup, :start)
222
- filename ||= Doing.config.settings['doing_file']
222
+ filename ||= Doing.setting('doing_file')
223
223
 
224
224
  unless File.exist?(filename)
225
225
  Doing.logger.debug('Backup:', "original file doesn't exist (#{filename})")
@@ -234,7 +234,7 @@ module Doing
234
234
 
235
235
  FileUtils.cp(filename, backup_file)
236
236
 
237
- prune_backups(filename, Doing.config.settings['history_size'].to_i)
237
+ prune_backups(filename, Doing.setting('history_size').to_i)
238
238
  clear_undone(filename)
239
239
  Doing.logger.benchmark(:_write_backup, :finish)
240
240
  end
@@ -246,13 +246,13 @@ module Doing
246
246
  end
247
247
 
248
248
  def get_backups(filename = nil, include_forward: false)
249
- filename ||= Doing.config.settings['doing_file']
249
+ filename ||= Doing.setting('doing_file')
250
250
  backups = Dir.glob("*___#{File.basename(filename)}", base: backup_dir).sort.reverse
251
251
  backups.delete_if { |f| f =~ /^undone/ } unless include_forward
252
252
  end
253
253
 
254
254
  def save_undone(filename = nil)
255
- filename ||= Doing.config.settings['doing_file']
255
+ filename ||= Doing.setting('doing_file')
256
256
  undone_file = File.join(backup_dir, "undone#{timestamp_filename}___#{File.basename(filename)}")
257
257
  FileUtils.cp(filename, undone_file)
258
258
  end
@@ -279,7 +279,7 @@ module Doing
279
279
  end
280
280
 
281
281
  def create_backup_dir
282
- dir = File.expand_path(Doing.config.settings['backup_dir']) || File.join(user_home, '.doing_backup')
282
+ dir = File.expand_path(Doing.setting('backup_dir')) || File.join(user_home, '.doing_backup')
283
283
  if File.exist?(dir) && !File.directory?(dir)
284
284
  raise DoingRuntimeError, "Backup error: #{dir} is not a directory"
285
285
 
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '2.1.30'
2
+ VERSION = '2.1.31pre'
3
3
  end
data/lib/doing/wwid.rb CHANGED
@@ -48,7 +48,7 @@ module Doing
48
48
  ## @param path [String] Override path to a doing file, optional
49
49
  ##
50
50
  def init_doing_file(path = nil)
51
- @doing_file = File.expand_path(@config['doing_file'])
51
+ @doing_file = File.expand_path(Doing.setting('doing_file'))
52
52
 
53
53
  if path.nil?
54
54
  create(@doing_file) unless File.exist?(@doing_file)
@@ -77,7 +77,7 @@ module Doing
77
77
  lines.each do |line|
78
78
  next if line =~ /^\s*$/
79
79
 
80
- if line =~ /^(\S[\S ]+):( .*)?$/
80
+ if line =~ /^(\S[\S ]+):\s*(@\S+\s*)*$/
81
81
  section = Regexp.last_match(1)
82
82
  @content.add_section(Section.new(section, original: line), log: false)
83
83
  elsif line =~ /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*)/
@@ -117,7 +117,7 @@ module Doing
117
117
  FileUtils.mkdir_p(File.dirname(filename)) unless File.directory?(File.dirname(filename))
118
118
 
119
119
  File.open(filename, 'w+') do |f|
120
- f.puts "#{@config['current_section']}:"
120
+ f.puts "#{Doing.setting('current_section')}:"
121
121
  end
122
122
  end
123
123
 
@@ -189,7 +189,7 @@ module Doing
189
189
 
190
190
  raise EmptyInput, 'No content' if title.sub(/^.*?\| */, '').strip.empty?
191
191
 
192
- title.expand_date_tags(@config['date_tags'])
192
+ title.expand_date_tags(Doing.setting('date_tags'))
193
193
 
194
194
  if title =~ date_rx
195
195
  m = title.match(date_rx)
@@ -236,7 +236,7 @@ module Doing
236
236
  ##
237
237
  def guess_section(frag, guessed: false, suggest: false)
238
238
  return 'All' if frag =~ /^all$/i
239
- frag ||= @config['current_section']
239
+ frag ||= Doing.setting('current_section')
240
240
 
241
241
  return frag.cap_first if @content.section?(frag)
242
242
 
@@ -342,7 +342,7 @@ module Doing
342
342
  ##
343
343
  def add_item(title, section = nil, opt)
344
344
  opt ||= {}
345
- section ||= @config['current_section']
345
+ section ||= Doing.setting('current_section')
346
346
  @content.add_section(section, log: false)
347
347
  opt[:back] ||= opt[:date] ? opt[:date] : Time.now
348
348
  opt[:date] ||= Time.now
@@ -356,7 +356,7 @@ module Doing
356
356
 
357
357
  if @auto_tag
358
358
  title = autotag(title)
359
- title.add_tags!(@config['default_tags']) unless @config['default_tags'].empty?
359
+ title.add_tags!(Doing.setting('default_tags')) if Doing.setting('default_tags').good?
360
360
  end
361
361
 
362
362
  title.compress!
@@ -553,7 +553,7 @@ module Doing
553
553
  def last_entry(opt)
554
554
  opt ||= {}
555
555
  opt[:tag_bool] ||= :and
556
- opt[:section] ||= @config['current_section']
556
+ opt[:section] ||= Doing.setting('current_section')
557
557
 
558
558
  items = filter_items(Items.new, opt: opt)
559
559
 
@@ -1076,7 +1076,7 @@ module Doing
1076
1076
  end
1077
1077
 
1078
1078
  if opt[:flag]
1079
- tag = @config['marker_tag'] || 'flagged'
1079
+ tag = Doing.setting('marker_tag', 'flagged')
1080
1080
  items.map! do |i|
1081
1081
  old_item = i.clone
1082
1082
  i.tag(tag, date: false, remove: opt[:remove], single: single)
@@ -1117,7 +1117,7 @@ module Doing
1117
1117
  items.map! do |i|
1118
1118
  old_item = i.clone
1119
1119
  i.tag(tag, date: false, remove: opt[:remove], single: single)
1120
- i.expand_date_tags(@config['date_tags'])
1120
+ i.expand_date_tags(Doing.setting('date_tags'))
1121
1121
  Hooks.trigger :post_entry_updated, self, i, old_item
1122
1122
  end
1123
1123
  end
@@ -1176,7 +1176,7 @@ module Doing
1176
1176
  end
1177
1177
 
1178
1178
  def verify_duration(date, finish_date, title: nil)
1179
- max_elapsed = @config.dig('interaction', 'confirm_longer_than') || 0
1179
+ max_elapsed = Doing.setting('interaction.confirm_longer_than', 0)
1180
1180
  max_elapsed = max_elapsed.chronify_qty if max_elapsed.is_a?(String)
1181
1181
  date = date.chronify(guess: :end, context: :today) if finish_date.is_a?(String)
1182
1182
 
@@ -1289,7 +1289,7 @@ module Doing
1289
1289
  tag = tag.strip
1290
1290
 
1291
1291
  if tag =~ /^done$/ && opt[:date] && item.should_time?
1292
- max_elapsed = @config.dig('interaction', 'confirm_longer_than') || 0
1292
+ max_elapsed = Doing.setting('interaction.confirm_longer_than', 0)
1293
1293
  max_elapsed = max_elapsed.chronify_qty if max_elapsed.is_a?(String)
1294
1294
  elapsed = done_date - item.date
1295
1295
 
@@ -1344,7 +1344,7 @@ module Doing
1344
1344
  logger.warn('Skipped:', 'Archiving is skipped when operating on all entries')
1345
1345
  end
1346
1346
 
1347
- item.expand_date_tags(@config['date_tags'])
1347
+ item.expand_date_tags(Doing.setting('date_tags'))
1348
1348
  Hooks.trigger :post_entry_updated, self, item, old_item
1349
1349
  end
1350
1350
 
@@ -1424,7 +1424,7 @@ module Doing
1424
1424
  def stop_start(target_tag, opt)
1425
1425
  opt ||= {}
1426
1426
  tag = target_tag.dup
1427
- opt[:section] ||= @config['current_section']
1427
+ opt[:section] ||= Doing.setting('current_section')
1428
1428
  opt[:archive] ||= false
1429
1429
  opt[:back] ||= Time.now
1430
1430
  opt[:new_item] ||= false
@@ -1485,7 +1485,7 @@ module Doing
1485
1485
  $stdout.puts output
1486
1486
  else
1487
1487
  Util.write_to_file(file, output, backup: backup)
1488
- run_after if @config.key?('run_after')
1488
+ run_after if Doing.setting('run_after')
1489
1489
  end
1490
1490
  end
1491
1491
 
@@ -1593,7 +1593,7 @@ module Doing
1593
1593
  ## @return [Array] View names
1594
1594
  ##
1595
1595
  def views
1596
- @config.has_key?('views') ? @config['views'].keys : []
1596
+ Doing.setting('views') ? Doing.setting('views').keys : []
1597
1597
  end
1598
1598
 
1599
1599
  ##
@@ -1612,7 +1612,7 @@ module Doing
1612
1612
  ## @param title [String] The title of the view to retrieve
1613
1613
  ##
1614
1614
  def get_view(title)
1615
- return @config['views'][title] if @config['views'].has_key?(title)
1615
+ return Doing.setting(['views', title], nil)
1616
1616
 
1617
1617
  false
1618
1618
  end
@@ -1626,21 +1626,21 @@ module Doing
1626
1626
  logger.benchmark(:list_section, :start)
1627
1627
  opt[:config_template] ||= 'default'
1628
1628
 
1629
- tpl_cfg = @config.dig('templates', opt[:config_template])
1629
+ tpl_cfg = Doing.setting(['templates', opt[:config_template]])
1630
1630
 
1631
1631
  cfg = if opt[:view_template]
1632
- @config.dig('views', opt[:view_template]).deep_merge(tpl_cfg, { extend_existing_arrays: true, sort_merged_arrays: true })
1632
+ Doing.setting(['views', opt[:view_template]]).deep_merge(tpl_cfg, { extend_existing_arrays: true, sort_merged_arrays: true })
1633
1633
  else
1634
1634
  tpl_cfg
1635
1635
  end
1636
1636
 
1637
1637
  cfg.deep_merge({
1638
- 'wrap_width' => @config['wrap_width'] || 0,
1639
- 'date_format' => @config['default_date_format'],
1640
- 'order' => @config['order'] || :asc,
1641
- 'tags_color' => @config['tags_color'],
1642
- 'duration' => @config['duration'],
1643
- 'interval_format' => @config['interval_format']
1638
+ 'wrap_width' => Doing.setting('wrap_width') || 0,
1639
+ 'date_format' => Doing.setting('default_date_format'),
1640
+ 'order' => Doing.setting('order') || :asc,
1641
+ 'tags_color' => Doing.setting('tags_color'),
1642
+ 'duration' => Doing.setting('duration'),
1643
+ 'interval_format' => Doing.setting('interval_format')
1644
1644
  }, { extend_existing_arrays: true, sort_merged_arrays: true })
1645
1645
 
1646
1646
  opt[:duration] ||= cfg['duration'] || false
@@ -1697,7 +1697,7 @@ module Doing
1697
1697
  end
1698
1698
 
1699
1699
  opt[:output] ||= 'template'
1700
- opt[:wrap_width] ||= @config['templates']['default']['wrap_width'] || 0
1700
+ opt[:wrap_width] ||= Doing.setting('templates.default.wrap_width', 0)
1701
1701
 
1702
1702
  logger.benchmark(:list_section, :finish)
1703
1703
  output(items, title, is_single, opt)
@@ -1710,7 +1710,7 @@ module Doing
1710
1710
  ## @param section [String] The source section
1711
1711
  ## @param options [Hash] Options
1712
1712
  ##
1713
- def archive(section = @config['current_section'], options)
1713
+ def archive(section = Doing.setting('current_section'), options)
1714
1714
  options ||= {}
1715
1715
  count = options[:keep] || 0
1716
1716
  destination = options[:destination] || 'Archive'
@@ -1746,13 +1746,13 @@ module Doing
1746
1746
  opt[:totals] ||= false
1747
1747
  opt[:sort_tags] ||= false
1748
1748
 
1749
- cfg = @config['templates'][opt[:config_template]].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
1750
- 'wrap_width' => @config['wrap_width'] || 0,
1751
- 'date_format' => @config['default_date_format'],
1752
- 'order' => @config['order'] || :asc,
1753
- 'tags_color' => @config['tags_color'],
1754
- 'duration' => @config['duration'],
1755
- 'interval_format' => @config['interval_format']
1749
+ cfg = Doing.setting('templates').deep_merge(Doing.setting('templates.default'), { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
1750
+ 'wrap_width' => Doing.setting('wrap_width') || 0,
1751
+ 'date_format' => Doing.setting('default_date_format'),
1752
+ 'order' => Doing.setting('order') || :asc,
1753
+ 'tags_color' => Doing.setting('tags_color'),
1754
+ 'duration' => Doing.setting('duration'),
1755
+ 'interval_format' => Doing.setting('interval_format')
1756
1756
  }, { extend_existing_arrays: true, sort_merged_arrays: true })
1757
1757
 
1758
1758
  template = opt[:template] || cfg['template']
@@ -1866,18 +1866,18 @@ module Doing
1866
1866
  opt[:totals] ||= false
1867
1867
  opt[:sort_tags] ||= false
1868
1868
 
1869
- cfg = @config['templates'][opt[:config_template]].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
1870
- 'wrap_width' => @config['wrap_width'] || 0,
1871
- 'date_format' => @config['default_date_format'],
1872
- 'order' => @config['order'] || :asc,
1873
- 'tags_color' => @config['tags_color'],
1874
- 'duration' => @config['duration'],
1875
- 'interval_format' => @config['interval_format']
1869
+ cfg = Doing.setting('templates.recent').deep_merge(Doing.setting('templates.default'), { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
1870
+ 'wrap_width' => Doing.setting('wrap_width') || 0,
1871
+ 'date_format' => Doing.setting('default_date_format'),
1872
+ 'order' => Doing.setting('order') || :asc,
1873
+ 'tags_color' => Doing.setting('tags_color'),
1874
+ 'duration' => Doing.setting('duration'),
1875
+ 'interval_format' => Doing.setting('interval_format')
1876
1876
  }, { extend_existing_arrays: true, sort_merged_arrays: true })
1877
1877
  opt[:duration] ||= cfg['duration'] || false
1878
1878
  opt[:interval_format] ||= cfg['interval_format'] || 'text'
1879
1879
 
1880
- section ||= @config['current_section']
1880
+ section ||= Doing.setting('current_section')
1881
1881
  section = guess_section(section)
1882
1882
 
1883
1883
  opt[:section] = section
@@ -1899,13 +1899,13 @@ module Doing
1899
1899
  ##
1900
1900
  def last(times: true, section: nil, options: {})
1901
1901
  section = section.nil? || section =~ /all/i ? 'All' : guess_section(section)
1902
- cfg = @config['templates'][options[:config_template]].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
1903
- 'wrap_width' => @config['wrap_width'] || 0,
1904
- 'date_format' => @config['default_date_format'],
1905
- 'order' => @config['order'] || :asc,
1906
- 'tags_color' => @config['tags_color'],
1907
- 'duration' => @config['duration'],
1908
- 'interval_format' => @config['interval_format']
1902
+ cfg = Doing.setting(['templates', options[:config_template]]).deep_merge(Doing.setting('templates.default'), { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
1903
+ 'wrap_width' => Doing.setting('wrap_width', 0),
1904
+ 'date_format' => Doing.setting('default_date_format'),
1905
+ 'order' => Doing.setting('order', :asc),
1906
+ 'tags_color' => Doing.setting('tags_color'),
1907
+ 'duration' => Doing.setting('duration'),
1908
+ 'interval_format' => Doing.setting('interval_format')
1909
1909
  }, { extend_existing_arrays: true, sort_merged_arrays: true })
1910
1910
  options[:duration] ||= cfg['duration'] || false
1911
1911
  options[:interval_format] ||= cfg['interval_format'] || 'text'
@@ -1960,7 +1960,7 @@ module Doing
1960
1960
  replaced: []
1961
1961
  }
1962
1962
 
1963
- @config['autotag']['whitelist'].each do |tag|
1963
+ Doing.setting('autotag.whitelist').each do |tag|
1964
1964
  next if text =~ /@#{tag}\b/i
1965
1965
 
1966
1966
  text.sub!(/(?<= |\A)(#{tag.strip})(?= |\Z)/i) do |m|
@@ -1970,7 +1970,7 @@ module Doing
1970
1970
  end
1971
1971
  end
1972
1972
 
1973
- @config['autotag']['synonyms'].each do |tag, v|
1973
+ Doing.setting('autotag.synonyms').each do |tag, v|
1974
1974
  v.each do |word|
1975
1975
  word = word.wildcard_to_rx
1976
1976
  next unless text =~ /\b#{word}\b/i
@@ -1982,8 +1982,8 @@ module Doing
1982
1982
  end
1983
1983
  end
1984
1984
 
1985
- if @config['autotag'].key? 'transform'
1986
- @config['autotag']['transform'].each do |tag|
1985
+ if Doing.setting('autotag.transform')
1986
+ Doing.setting('autotag.transform').each do |tag|
1987
1987
  next unless tag =~ /\S+:\S+/
1988
1988
 
1989
1989
  if tag =~ /::/
@@ -2055,11 +2055,11 @@ module Doing
2055
2055
  def tag_times(format: :text, sort_by: :time, sort_order: :asc)
2056
2056
  return '' if @timers.empty?
2057
2057
 
2058
- max = @timers.keys.sort_by { |k| k.length }.reverse[0].length + 1
2058
+ max = @timers.keys.sort_by(&:length).reverse[0].length + 1
2059
2059
 
2060
2060
  total = @timers.delete('All')
2061
2061
 
2062
- tags_data = @timers.delete_if { |_k, v| v == 0 }
2062
+ tags_data = @timers.delete_if { |_k, v| v.zero? }
2063
2063
  sorted_tags_data = if sort_by.normalize_tag_sort == :name
2064
2064
  tags_data.sort_by { |k, _v| k }
2065
2065
  else
@@ -2070,7 +2070,7 @@ module Doing
2070
2070
  case format
2071
2071
  when :html
2072
2072
 
2073
- output = <<EOS
2073
+ output = <<EOHEAD
2074
2074
  <table>
2075
2075
  <caption id="tagtotals">Tag Totals</caption>
2076
2076
  <colgroup>
@@ -2084,13 +2084,13 @@ module Doing
2084
2084
  </tr>
2085
2085
  </thead>
2086
2086
  <tbody>
2087
- EOS
2087
+ EOHEAD
2088
2088
  sorted_tags_data.reverse.each do |k, v|
2089
- if v > 0
2089
+ if v.positive?
2090
2090
  output += "<tr><td style='text-align:left;'>#{k}</td><td style='text-align:left;'>#{v.time_string(format: :clock)}</td></tr>\n"
2091
2091
  end
2092
2092
  end
2093
- tail = <<EOS
2093
+ tail = <<EOTAIL
2094
2094
  <tr>
2095
2095
  <td style="text-align:left;" colspan="2"></td>
2096
2096
  </tr>
@@ -2102,21 +2102,21 @@ EOS
2102
2102
  </tr>
2103
2103
  </tfoot>
2104
2104
  </table>
2105
- EOS
2105
+ EOTAIL
2106
2106
  output + tail
2107
2107
  when :markdown
2108
- pad = sorted_tags_data.map {|k, v| k }.group_by(&:size).max.last[0].length
2108
+ pad = sorted_tags_data.map { |k, _| k }.group_by(&:size).max.last[0].length
2109
2109
  pad = 7 if pad < 7
2110
- output = <<~EOS
2111
- | #{' ' * (pad - 7) }project | time |
2110
+ output = <<~EOHEADER
2111
+ | #{' ' * (pad - 7)}project | time |
2112
2112
  | #{'-' * (pad - 1)}: | :------- |
2113
- EOS
2113
+ EOHEADER
2114
2114
  sorted_tags_data.reverse.each do |k, v|
2115
- if v > 0
2115
+ if v.positive?
2116
2116
  output += "| #{' ' * (pad - k.length)}#{k} | #{v.time_string(format: :clock)} |\n"
2117
2117
  end
2118
2118
  end
2119
- tail = "[Tag Totals]"
2119
+ tail = '[Tag Totals]'
2120
2120
  output + tail
2121
2121
  when :json
2122
2122
  output = []
@@ -2203,38 +2203,37 @@ EOS
2203
2203
  end
2204
2204
 
2205
2205
  ##
2206
- ## Load configuration files and updated the @config
2206
+ ## Load configuration files and updated the @settings
2207
2207
  ## attribute with a Doing::Configuration object
2208
2208
  ##
2209
2209
  ## @param filename [String] (optional) path to
2210
2210
  ## alternative config file
2211
2211
  ##
2212
2212
  def configure(filename = nil)
2213
+ logger.benchmark(:configure, :start)
2214
+
2213
2215
  if filename
2214
2216
  Doing.config_with(filename, { ignore_local: true })
2215
2217
  elsif ENV['DOING_CONFIG']
2216
2218
  Doing.config_with(ENV['DOING_CONFIG'], { ignore_local: true })
2217
2219
  end
2218
2220
 
2219
- logger.benchmark(:configure, :start)
2220
- config = Doing.config
2221
2221
  logger.benchmark(:configure, :finish)
2222
2222
 
2223
- config.settings['backup_dir'] = ENV['DOING_BACKUP_DIR'] if ENV['DOING_BACKUP_DIR']
2224
- @config = config.settings
2223
+ Doing.set('backup_dir', ENV['DOING_BACKUP_DIR']) if ENV['DOING_BACKUP_DIR']
2225
2224
  end
2226
2225
 
2227
2226
  def get_diff(filename = nil)
2228
- configure if @config.nil?
2227
+ configure if Doing.settings.nil?
2229
2228
 
2230
- filename ||= @config['doing_file']
2229
+ filename ||= Doing.setting('doing_file')
2231
2230
  init_doing_file(filename)
2232
2231
  current_content = @content.clone
2233
2232
  backup_file = Util::Backup.last_backup(filename, count: 1)
2234
2233
  raise DoingRuntimeError, 'No undo history to diff' if backup_file.nil?
2235
2234
 
2236
2235
  backup = WWID.new
2237
- backup.config = @config
2236
+ backup.config = Doing.settings
2238
2237
  backup.init_doing_file(backup_file)
2239
2238
  current_content.diff(backup.content)
2240
2239
  end
@@ -2378,12 +2377,12 @@ EOS
2378
2377
  end
2379
2378
 
2380
2379
  def run_after
2381
- return unless @config.key?('run_after')
2380
+ return unless Doing.setting('run_after')
2382
2381
 
2383
- _, stderr, status = Open3.capture3(@config['run_after'])
2382
+ _, stderr, status = Open3.capture3(Doing.setting('run_after'))
2384
2383
  return unless status.exitstatus.positive?
2385
2384
 
2386
- logger.log_now(:error, 'Script error:', "Error running #{@config['run_after']}")
2385
+ logger.log_now(:error, 'Script error:', "Error running #{Doing.setting('run_after')}")
2387
2386
  logger.log_now(:error, 'STDERR output:', stderr)
2388
2387
  end
2389
2388
  end