doing 2.1.10 → 2.1.11

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.
@@ -152,17 +152,23 @@ module Doing
152
152
  ##
153
153
  ## @return [String] file path
154
154
  ##
155
- def choose_config
155
+ def choose_config(create: false)
156
156
  return @config_file if @force_answer
157
157
 
158
- if @additional_configs.count.positive?
158
+ if @additional_configs.count.positive? || create
159
159
  choices = [@config_file].concat(@additional_configs)
160
+ choices.push('Create a new .doingrc in the current directory') if create && !File.exist?('.doingrc')
160
161
  res = Doing::Prompt.choose_from(choices.uniq.sort.reverse,
161
162
  sorted: false,
162
163
  prompt: 'Local configs found, select which to update > ')
163
164
 
164
165
  raise UserCancelled, 'Cancelled' unless res
165
166
 
167
+ if res =~ /^Create a new/
168
+ res = File.expand_path('.doingrc')
169
+ FileUtils.touch(res)
170
+ end
171
+
166
172
  res.strip || @config_file
167
173
  else
168
174
  @config_file
@@ -249,7 +255,8 @@ module Doing
249
255
  # defaults.
250
256
  #
251
257
  def from(user_config)
252
- Util.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
258
+ # Util.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
259
+ Configuration[user_config].stringify_keys.deep_merge(DEFAULTS, { extend_existing_arrays: true, sort_merged_arrays: true })
253
260
  end
254
261
 
255
262
  ##
@@ -320,8 +327,8 @@ module Doing
320
327
 
321
328
  Hooks.trigger :post_config, self
322
329
 
323
- # config = local_config.deep_merge(config) unless @ignore_local
324
- config = Util.deep_merge_hashes(config, local_config) unless @ignore_local
330
+ config = local_config.deep_merge(config, { extend_existing_arrays: true, sort_merged_arrays: true }) unless @ignore_local
331
+ # config = Util.deep_merge_hashes(config, local_config) unless @ignore_local
325
332
 
326
333
  Hooks.trigger :post_local_config, self
327
334
 
@@ -397,7 +404,7 @@ module Doing
397
404
 
398
405
  begin
399
406
  additional_configs.each do |cfg|
400
- local_configs.deep_merge(Util.safe_load_file(cfg))
407
+ local_configs.deep_merge(Util.safe_load_file(cfg), { extend_existing_arrays: true, sort_merged_arrays: true })
401
408
  end
402
409
  rescue StandardError
403
410
  Doing.logger.error('Config:', 'Error reading local configuration(s)')
@@ -416,15 +423,18 @@ module Doing
416
423
  end
417
424
 
418
425
  begin
426
+
419
427
  user_config = Util.safe_load_file(config_file)
428
+ raise StandardError, 'Invalid config file format' unless user_config.is_a?(Hash)
429
+
420
430
  if user_config.key?('html_template')
421
431
  user_config['export_templates'] ||= {}
422
- user_config['export_templates'].deep_merge(user_config.delete('html_template'))
432
+ user_config['export_templates'].deep_merge(user_config.delete('html_template'), { extend_existing_arrays: true, sort_merged_arrays: true })
423
433
  end
424
434
 
425
435
  user_config['include_notes'] = user_config.delete(':include_notes') if user_config.key?(':include_notes')
426
436
 
427
- user_config.deep_merge(DEFAULTS)
437
+ user_config.deep_merge(DEFAULTS, { extend_existing_arrays: true, sort_merged_arrays: true })
428
438
  rescue StandardError => e
429
439
  Doing.logger.error('Config:', 'Error reading default configuration')
430
440
  Doing.logger.error('Error:', e.message)
data/lib/doing/hooks.rb CHANGED
@@ -6,11 +6,16 @@ module Doing
6
6
  DEFAULT_PRIORITY = 20
7
7
 
8
8
  @registry = {
9
- post_config: [],
10
- post_local_config: [],
11
- post_read: [],
12
- pre_write: [],
13
- post_write: []
9
+ post_config: [], # wwid
10
+ post_local_config: [], # wwid
11
+ post_read: [], # wwid
12
+ pre_entry_add: [], # wwid, new_entry
13
+ post_entry_added: [], # wwid, new_entry.dup
14
+ post_entry_updated: [], # wwid, entry
15
+ post_entry_removed: [], # wwid, entry.dup
16
+ pre_export: [], # wwid, format, entries
17
+ pre_write: [], # wwid, file
18
+ post_write: [] # wwid, file
14
19
  }
15
20
 
16
21
  # map of all hooks and their priorities
data/lib/doing/items.rb CHANGED
@@ -69,7 +69,7 @@ module Doing
69
69
  if section =~ /^all$/i
70
70
  dup
71
71
  else
72
- items = Items.new.concat(select { |item| item.section == section })
72
+ items = Items.new.concat(select { |item| !item.nil? && item.section == section })
73
73
  items.add_section(section, log: false)
74
74
  items
75
75
  end
@@ -84,6 +84,7 @@ module Doing
84
84
  deleted = delete(item)
85
85
  Doing.logger.count(:deleted)
86
86
  Doing.logger.info('Entry deleted:', deleted.title) if single
87
+ deleted
87
88
  end
88
89
 
89
90
  ##
@@ -111,6 +112,20 @@ module Doing
111
112
  end
112
113
  end
113
114
 
115
+ ##
116
+ ## Return Items containing items that don't exist in receiver
117
+ ##
118
+ ## @param items [Items] Receiver
119
+ ##
120
+ def diff(items)
121
+ diff = Items.new
122
+ each do |item|
123
+ res = items.select { |i| i.equal?(item) }
124
+ diff.push(item) unless res.count.positive?
125
+ end
126
+ diff
127
+ end
128
+
114
129
  # Output sections and items in Doing file format
115
130
  def to_s
116
131
  out = []
data/lib/doing/pager.rb CHANGED
@@ -64,22 +64,8 @@ module Doing
64
64
 
65
65
  private
66
66
 
67
- def command_exist?(command)
68
- exts = ENV.fetch("PATHEXT", "").split(::File::PATH_SEPARATOR)
69
- if Pathname.new(command).absolute?
70
- ::File.exist?(command) ||
71
- exts.any? { |ext| ::File.exist?("#{command}#{ext}")}
72
- else
73
- ENV.fetch("PATH", "").split(::File::PATH_SEPARATOR).any? do |dir|
74
- file = ::File.join(dir, command)
75
- ::File.exist?(file) ||
76
- exts.any? { |ext| ::File.exist?("#{file}#{ext}") }
77
- end
78
- end
79
- end
80
-
81
67
  def git_pager
82
- command_exist?("git") ? `git config --get-all core.pager` : nil
68
+ TTY::Which.exist?('git') ? `#{TTY::Which.which('git')} config --get-all core.pager` : nil
83
69
  end
84
70
 
85
71
  def pagers
@@ -91,11 +77,7 @@ module Doing
91
77
  execs = commands.empty? ? pagers : commands
92
78
  execs
93
79
  .compact.map(&:strip).reject(&:empty?).uniq
94
- .find { |cmd| command_exist?(cmd.split.first) }
95
- end
96
-
97
- def exec_available?(*commands)
98
- !find_executable(*commands).nil?
80
+ .find { |cmd| TTY::Which.exist?(cmd.split.first) }
99
81
  end
100
82
 
101
83
  def which_pager
@@ -73,7 +73,12 @@ module Doing
73
73
  dups = filtered - new_items.count
74
74
  Doing.logger.info(%(Skipped #{dups} items with overlapping times)) if dups.positive?
75
75
 
76
+ new_items.map { |item| Hooks.trigger :pre_entry_add, self, item }
77
+
76
78
  wwid.content.concat(new_items)
79
+
80
+ new_items.map { |item| Hooks.trigger :post_entry_added, self, item.dup }
81
+
77
82
  Doing.logger.info(%(Imported #{new_items.count} items to #{section}))
78
83
  end
79
84
 
@@ -80,7 +80,9 @@ module Doing
80
80
 
81
81
  imported.each do |item|
82
82
  wwid.content.add_section(item.section) unless wwid.content.section?(item.section)
83
+ Hooks.trigger :pre_entry_add, self, item
83
84
  wwid.content.push(item)
85
+ Hooks.trigger :post_entry_added, self, item.dup
84
86
  end
85
87
 
86
88
  Doing.logger.info('Imported:', "#{imported.count} items")
@@ -77,7 +77,12 @@ module Doing
77
77
  dups = filtered - new_items.count
78
78
  Doing.logger.debug('Skipped:' , %(#{dups} items with overlapping times)) if dups.positive?
79
79
 
80
+ new_items.map { |item| Hooks.trigger :pre_entry_add, self, item }
81
+
80
82
  wwid.content.concat(new_items)
83
+
84
+ new_items.map { |item| Hooks.trigger :post_entry_added, self, item.dup }
85
+
81
86
  Doing.logger.info('Imported:', %(#{new_items.count} items to #{section}))
82
87
  end
83
88
 
@@ -37,6 +37,19 @@ module Doing
37
37
  end
38
38
  end
39
39
 
40
+ ##
41
+ ## Retrieve the most recent backup
42
+ ##
43
+ ## @param filename The filename
44
+ ## @return [String] filename
45
+ ##
46
+ def last_backup(filename = nil, count: 1)
47
+ filename ||= Doing.config.settings['doing_file']
48
+
49
+ backup = get_backups(filename).slice(count - 1)
50
+ backup.nil? ? nil : File.join(backup_dir, backup)
51
+ end
52
+
40
53
  ##
41
54
  ## Restore the most recent backup. If a filename is
42
55
  ## provided, only backups of that filename will be used.
@@ -48,15 +61,13 @@ module Doing
48
61
  Doing.logger.benchmark(:restore_backup, :start)
49
62
  filename ||= Doing.config.settings['doing_file']
50
63
 
51
- result = get_backups(filename).slice(count - 1)
52
- raise DoingRuntimeError, 'End of undo history' if result.nil?
53
-
54
- backup_file = File.join(backup_dir, result)
64
+ backup_file = last_backup(filename, count: count)
65
+ raise DoingRuntimeError, 'End of undo history' if backup_file.nil?
55
66
 
56
67
  save_undone(filename)
57
68
  FileUtils.mv(backup_file, filename)
58
69
  prune_backups_after(File.basename(backup_file))
59
- Doing.logger.warn('File update:', "restored from #{result}")
70
+ Doing.logger.warn('File update:', "restored from #{backup_file}")
60
71
  Doing.logger.benchmark(:restore_backup, :finish)
61
72
  end
62
73
 
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '2.1.10'
2
+ VERSION = '2.1.11'
3
3
  end