doing 2.1.21 → 2.1.25

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +19 -16
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +51 -13
  6. data/Gemfile.lock +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +6 -3
  9. data/bin/doing +254 -103
  10. data/docs/doc/Array.html +74 -34
  11. data/docs/doc/BooleanTermParser/Clause.html +5 -5
  12. data/docs/doc/BooleanTermParser/Operator.html +4 -4
  13. data/docs/doc/BooleanTermParser/Query.html +8 -8
  14. data/docs/doc/BooleanTermParser/QueryParser.html +2 -2
  15. data/docs/doc/BooleanTermParser/QueryTransformer.html +2 -2
  16. data/docs/doc/BooleanTermParser.html +1 -1
  17. data/docs/doc/Doing/Color.html +4 -4
  18. data/docs/doc/Doing/Completion.html +2 -2
  19. data/docs/doc/Doing/Configuration.html +16 -18
  20. data/docs/doc/Doing/Errors/DoingNoTraceError.html +2 -2
  21. data/docs/doc/Doing/Errors/DoingRuntimeError.html +2 -2
  22. data/docs/doc/Doing/Errors/DoingStandardError.html +2 -2
  23. data/docs/doc/Doing/Errors/EmptyInput.html +2 -2
  24. data/docs/doc/Doing/Errors/NoResults.html +2 -2
  25. data/docs/doc/Doing/Errors/PluginException.html +3 -3
  26. data/docs/doc/Doing/Errors/UserCancelled.html +2 -2
  27. data/docs/doc/Doing/Errors/WrongCommand.html +2 -2
  28. data/docs/doc/Doing/Errors.html +1 -1
  29. data/docs/doc/Doing/Hooks.html +6 -6
  30. data/docs/doc/Doing/Item.html +50 -16
  31. data/docs/doc/Doing/Items.html +10 -10
  32. data/docs/doc/Doing/LogAdapter.html +24 -24
  33. data/docs/doc/Doing/Note.html +7 -7
  34. data/docs/doc/Doing/Pager.html +4 -4
  35. data/docs/doc/Doing/Plugins.html +7 -7
  36. data/docs/doc/Doing/Prompt.html +16 -16
  37. data/docs/doc/Doing/Section.html +6 -6
  38. data/docs/doc/Doing/TemplateString.html +8 -8
  39. data/docs/doc/Doing/Types.html +206 -0
  40. data/docs/doc/Doing/Util/Backup.html +10 -10
  41. data/docs/doc/Doing/Util.html +16 -19
  42. data/docs/doc/Doing/WWID.html +65 -53
  43. data/docs/doc/Doing.html +4 -4
  44. data/docs/doc/GLI/Commands/Help.html +185 -0
  45. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +17 -17
  46. data/docs/doc/GLI/Commands.html +5 -3
  47. data/docs/doc/GLI.html +4 -2
  48. data/docs/doc/Hash.html +119 -21
  49. data/docs/doc/Numeric.html +5 -5
  50. data/docs/doc/PhraseParser/Operator.html +4 -4
  51. data/docs/doc/PhraseParser/PhraseClause.html +5 -5
  52. data/docs/doc/PhraseParser/Query.html +10 -10
  53. data/docs/doc/PhraseParser/QueryParser.html +2 -2
  54. data/docs/doc/PhraseParser/QueryTransformer.html +2 -2
  55. data/docs/doc/PhraseParser/TermClause.html +5 -5
  56. data/docs/doc/PhraseParser.html +1 -1
  57. data/docs/doc/Status.html +7 -7
  58. data/docs/doc/String.html +206 -51
  59. data/docs/doc/Symbol.html +8 -8
  60. data/docs/doc/Time.html +6 -6
  61. data/docs/doc/_index.html +51 -14
  62. data/docs/doc/class_list.html +1 -1
  63. data/docs/doc/file.README.html +2 -2
  64. data/docs/doc/index.html +2 -2
  65. data/docs/doc/method_list.html +348 -252
  66. data/docs/doc/top-level-namespace.html +2 -93
  67. data/docs/index.md +1 -1
  68. data/doing.rdoc +177 -20
  69. data/example_plugin.rb +2 -2
  70. data/lib/completion/_doing.zsh +24 -24
  71. data/lib/completion/doing.bash +31 -20
  72. data/lib/completion/doing.fish +32 -10
  73. data/lib/doing/array.rb +5 -4
  74. data/lib/doing/array_chronify.rb +4 -3
  75. data/lib/doing/changelog/change.rb +115 -0
  76. data/lib/doing/changelog/changes.rb +73 -0
  77. data/lib/doing/changelog/entry.rb +21 -0
  78. data/lib/doing/changelog/version.rb +97 -0
  79. data/lib/doing/changelog.rb +6 -0
  80. data/lib/doing/completion/fish_completion.rb +2 -1
  81. data/lib/doing/configuration.rb +20 -14
  82. data/lib/doing/good.rb +64 -0
  83. data/lib/doing/hash.rb +28 -5
  84. data/lib/doing/help_monkey_patch.rb +31 -0
  85. data/lib/doing/hooks.rb +8 -4
  86. data/lib/doing/item.rb +24 -35
  87. data/lib/doing/log_adapter.rb +1 -1
  88. data/lib/doing/pager.rb +1 -1
  89. data/lib/doing/plugins/export/template_export.rb +9 -3
  90. data/lib/doing/plugins/import/calendar_import.rb +1 -1
  91. data/lib/doing/plugins/import/doing_import.rb +1 -1
  92. data/lib/doing/plugins/import/timing_import.rb +1 -1
  93. data/lib/doing/prompt.rb +4 -2
  94. data/lib/doing/string.rb +30 -12
  95. data/lib/doing/string_chronify.rb +1 -1
  96. data/lib/doing/template_string.rb +9 -2
  97. data/lib/doing/types.rb +23 -16
  98. data/lib/doing/util.rb +12 -11
  99. data/lib/doing/version.rb +1 -1
  100. data/lib/doing/wwid.rb +65 -46
  101. data/lib/doing.rb +3 -0
  102. data/lib/helpers/threaded_tests.rb +106 -99
  103. data/lib/helpers/threaded_tests_string.rb +50 -0
  104. metadata +12 -2
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ # A single version's entries
5
+ class Change
6
+ attr_reader :version, :content
7
+
8
+ attr_accessor :entries
9
+
10
+ def initialize(version, content)
11
+ @version = Version.new(version)
12
+ @content = content
13
+ parse_entries
14
+ end
15
+
16
+ def parse_entries
17
+ @entries = []
18
+ types = @content.scan(/(?<=\n|\A)#### (NEW|IMPROVED|FIXED)(.*?)(?=\n####|\Z)/m)
19
+ types.each do |type|
20
+ type[1].scan(/\s*- +(.*?)$/).each do |entry|
21
+ @entries << Entry.new(entry[0].strip, type[0])
22
+ end
23
+ end
24
+ end
25
+
26
+ def search_entries(search_string)
27
+ case_type = :ignore
28
+
29
+ matches = []
30
+
31
+ if search_string.is_rx?
32
+ matches = @entries.select { |e| e.string =~ search_string.to_rx(distance: 2, case_type: case_type) }
33
+ else
34
+ query = search_string.gsub(/(-)?--/, '\1]]').to_phrase_query
35
+
36
+ if query[:must].nil? && query[:must_not].nil?
37
+ query[:must] = query[:should]
38
+ query[:should] = []
39
+ end
40
+
41
+ @entries.each do |entry|
42
+ m = no_searches?(entry.string, query[:must_not])
43
+ m &&= all_searches?(entry.string, query[:must])
44
+ m &&= any_searches?(entry.string, query[:should])
45
+ matches << entry if m
46
+ end
47
+ end
48
+
49
+ @entries = matches.count.positive? ? matches : nil
50
+ end
51
+
52
+ def to_h
53
+ { version: @version, content: @content }
54
+ end
55
+
56
+ def to_s
57
+ out = ["### #{@version}"]
58
+ items = {
59
+ new: [],
60
+ improved: [],
61
+ fixed: [],
62
+ other: []
63
+ }
64
+ @entries.each do |e|
65
+ type = e.type.downcase.to_sym
66
+ if items.key?(type)
67
+ items[type] << e
68
+ else
69
+ items[:other] << e
70
+ end
71
+ end
72
+
73
+ items.each do |type, members|
74
+ if members.count.positive?
75
+ out << "#### #{type.to_s.capitalize}"
76
+ out << members.map(&:to_s).join("\n")
77
+ end
78
+ end
79
+
80
+ out.join("\n\n")
81
+ end
82
+
83
+ private
84
+
85
+ def all_searches?(text, searches)
86
+ return true if searches.nil? || searches.empty?
87
+
88
+ searches.each do |s|
89
+ rx = Regexp.new(s.wildcard_to_rx, true)
90
+ return false unless text =~ rx
91
+ end
92
+ true
93
+ end
94
+
95
+ def no_searches?(text, searches)
96
+ return true if searches.nil? || searches.empty?
97
+
98
+ searches.each do |s|
99
+ rx = Regexp.new(s.wildcard_to_rx, true)
100
+ return false if text =~ rx
101
+ end
102
+ true
103
+ end
104
+
105
+ def any_searches?(text, searches)
106
+ return true if searches.nil? || searches.empty?
107
+
108
+ searches.each do |s|
109
+ rx = Regexp.new(s.wildcard_to_rx, true)
110
+ return true if text =~ rx
111
+ end
112
+ false
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ # A collection of Changes
5
+ class Changes
6
+ attr_reader :changes
7
+
8
+ def initialize(lookup: nil, search: nil)
9
+ changelog = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'CHANGELOG.md'))
10
+ raise 'Error locating changelog' unless File.exist?(changelog)
11
+
12
+ @content = IO.read(changelog)
13
+ parse_changes(lookup, search)
14
+ end
15
+
16
+ def latest
17
+ @changes[0].to_s.force_encoding('utf-8')
18
+ end
19
+
20
+ def to_s
21
+ @changes.map(&:to_s).join("\n\n").force_encoding('utf-8')
22
+ end
23
+
24
+ private
25
+
26
+ def parse_changes(lookup, search)
27
+ change_rx = /(?<=\n|\A)### (\d+\.\d+\.\d+(?:\w*))(.*)(?=\n### |\Z)/m
28
+ @changes = @content.scan(change_rx).each_with_object([]) do |m, a|
29
+ next if m[0].nil? || m[1].nil?
30
+
31
+ a << Change.new(m[0], m[1].strip)
32
+ end
33
+
34
+ lookup(lookup) unless lookup.nil?
35
+ search(search) unless search.nil?
36
+ end
37
+
38
+ def lookup(lookup_version)
39
+ range = []
40
+
41
+ if lookup_version =~ /([\d.]+) *-+ *([\d.]+)/
42
+ m = Regexp.last_match
43
+ lookup("> #{m[1]}")
44
+ lookup("< #{m[2]}")
45
+ elsif lookup_version.scan(/[<>]/).count > 1
46
+ params = lookup_version.scan(/[<>] [\d.]+/)
47
+ params.each { |query| lookup(query) }
48
+ else
49
+ comp = case lookup_version
50
+ when /(<|prior|before|older)/
51
+ :older
52
+ when />|since|after|newer/
53
+ :newer
54
+ else
55
+ :equal
56
+ end
57
+ version = Version.new(lookup_version)
58
+
59
+ @changes.select! do |change|
60
+ change.version.compare(version, comp)
61
+ end
62
+ end
63
+ end
64
+
65
+ def search(query)
66
+ @changes.map do |c|
67
+ c.entries = c.search_entries(query)
68
+ end
69
+
70
+ @changes.delete_if { |c| c.nil? || c.entries.nil? }
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ # An individual changelog item
5
+ class Entry
6
+ attr_reader :type, :string
7
+
8
+ def initialize(string, type)
9
+ @string = string
10
+ @type = type
11
+ end
12
+
13
+ def clean(string)
14
+ string.gsub(/\|/, '\|')
15
+ end
16
+
17
+ def to_s
18
+ "- #{clean(@string)}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ # Semantic versioning
5
+ class Version
6
+ attr_reader :maj, :min, :patch
7
+
8
+ def initialize(string)
9
+ @maj, @min, @patch = version_to_a(string)
10
+ end
11
+
12
+ def version_to_a(string)
13
+ raise 'Version not a string' unless string.is_a?(String)
14
+
15
+ v = string.match(/(?<maj>\d+)(?:\.(?<min>[\d*?]+))?(?:\.(?<patch>[\d*?]+))?/)
16
+
17
+ raise 'Error parsing semantic version string' if v.nil?
18
+
19
+ maj = v['maj'].to_i
20
+ min = case v['min']
21
+ when /[*?]/
22
+ v['min'].sub(/(\d+)?[^\d]/, '\1\d+')
23
+ when /^[0-9]+$/
24
+ v['min'].to_i
25
+ end
26
+ pat = case v['patch']
27
+ when /[*?]/
28
+ v['patch'].sub(/(\d+)?[^\d]/, '\1\d+')
29
+ when /^[0-9]+$/
30
+ v['patch'].to_i
31
+ end
32
+ [maj, min, pat]
33
+ end
34
+
35
+ def wild?(val)
36
+ val.is_a?(String)
37
+ end
38
+
39
+
40
+ def compare(other, comp)
41
+ case comp
42
+ when :older
43
+ if @maj <= other.maj
44
+ if @maj < other.maj
45
+ true
46
+ elsif @maj == other.maj && (other.min.nil? || @min < other.min)
47
+ true
48
+ elsif @maj == other.maj && @min == other.min
49
+ other.patch.nil? ? false : @patch < other.patch
50
+ else
51
+ false
52
+ end
53
+ else
54
+ false
55
+ end
56
+ when :newer
57
+ if @maj >= other.maj
58
+ if @maj > other.maj
59
+ true
60
+ elsif @maj == other.maj && (other.min.nil? || @min > other.min)
61
+ true
62
+ elsif @maj == other.maj && @min == other.min
63
+ other.patch.nil? || @patch >= other.patch
64
+ else
65
+ false
66
+ end
67
+ else
68
+ false
69
+ end
70
+ when :equal
71
+ if @maj == other.maj
72
+ if other.min.nil?
73
+ true
74
+ elsif wild?(other.min)
75
+ @min.to_s =~ /^#{other.min}/ ? true : false
76
+ else
77
+ if @min == other.min
78
+ if other.patch.nil?
79
+ true
80
+ elsif wild?(other.patch)
81
+ @patch.to_s =~ /^#{other.patch}/ ? true : false
82
+ else
83
+ @patch == other.patch
84
+ end
85
+ else
86
+ false
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def to_s
94
+ "#{@maj}.#{@min || 0}.#{@patch || 0}"
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'changelog/version'
4
+ require_relative 'changelog/entry'
5
+ require_relative 'changelog/change'
6
+ require_relative 'changelog/changes'
@@ -123,8 +123,9 @@ module Doing
123
123
  complete -f -c doing -n '__fish_doing_using_command view' -a '(__fish_doing_complete_views)'
124
124
  complete -f -c doing -n '__fish_doing_using_command template' -a '(__fish_doing_complete_templates)'
125
125
  complete -f -c doing -s t -l type -x -n '__fish_doing_using_command import' -a '(__fish_doing_import_plugins)'
126
+ complete -f -c doing -n '__fish_doing_using_command help' -a '(__fish_doing_subcommands)'
126
127
 
127
- complete -xc doing -n '__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from (doing help -c)' -a "(doing help -c)"
128
+ # complete -xc doing -n '__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from (doing help -c)' -a "(doing help -c)"
128
129
 
129
130
  function __fish_doing_complete_args
130
131
  for cmd in (doing commands_accepting -c $argv[1])
@@ -45,8 +45,7 @@ module Doing
45
45
  'templates' => {
46
46
  'default' => {
47
47
  'date_format' => '%Y-%m-%d %H:%M',
48
- 'template' => '%reset%cyan%shortdate %boldwhite%80║ title %dark%boldmagenta[%boldwhite%-10section%boldmagenta]%reset
49
- %yellow%interval%boldred%duration%dark%white%80_14┃ note',
48
+ 'template' => '%reset%cyan%shortdate %boldwhite%80║ title %boldmagenta[%boldwhite%-10section%boldmagenta]%reset %yellow%interval%boldred%duration%white%80_14┃ note',
50
49
  'wrap_width' => 0,
51
50
  'order' => 'asc'
52
51
  },
@@ -63,8 +62,7 @@ module Doing
63
62
  },
64
63
  'recent' => {
65
64
  'date_format' => '%_I:%M%P',
66
- 'template' => '%reset%cyan%shortdate %boldwhite%80║ title %dark%boldmagenta[%boldwhite%-10section%boldmagenta]%reset
67
- %yellow%interval%boldred%duration%dark%white%80_14┃ note',
65
+ 'template' => '%reset%cyan%shortdate %boldwhite%80║ title %boldmagenta[%boldwhite%-10section%boldmagenta]%reset %yellow%interval%boldred%duration%white%80_14┃ note',
68
66
  'wrap_width' => 88,
69
67
  'count' => 10,
70
68
  'order' => 'asc'
@@ -160,7 +158,7 @@ module Doing
160
158
  def choose_config(create: false)
161
159
  return @config_file if @force_answer
162
160
 
163
- if @additional_configs.count.positive? || create
161
+ if @additional_configs&.count&.positive? || create
164
162
  choices = [@config_file].concat(@additional_configs)
165
163
  choices.push('Create a new .doingrc in the current directory') if create && !File.exist?('.doingrc')
166
164
  res = Doing::Prompt.choose_from(choices.uniq.sort.reverse,
@@ -190,7 +188,7 @@ module Doing
190
188
  ## matched, first match wins)
191
189
  ## @return [Array] ordered array of resolved keys
192
190
  ##
193
- def resolve_key_path(keypath, create: false)
191
+ def resolve_key_path(keypath, create: false, distance: 2)
194
192
  cfg = @settings
195
193
  real_path = []
196
194
  unless keypath =~ /^[.*]?$/
@@ -198,16 +196,24 @@ module Doing
198
196
  while paths.length.positive? && !cfg.nil?
199
197
  path = paths.shift
200
198
  new_cfg = nil
201
- cfg.each do |key, val|
202
- next unless key =~ path.to_rx(distance: 4)
203
199
 
204
- real_path << key
205
- new_cfg = val
206
- break
200
+ if cfg.is_a?(Hash)
201
+ matches = cfg.select { |key, val| key =~ path.to_rx(distance: distance) }
202
+ if matches.count.positive?
203
+ shortest = matches.keys.group_by(&:length).min.last[0]
204
+ real_path << shortest
205
+ new_cfg = matches[shortest]
206
+ end
207
+ else
208
+ new_cfg = cfg
207
209
  end
208
210
 
209
211
  if new_cfg.nil?
210
- return nil unless create
212
+ if distance < 5 && !create
213
+ return resolve_key_path(keypath, create: false, distance: distance + 1)
214
+ else
215
+ return nil unless create
216
+ end
211
217
 
212
218
  resolved = real_path.count.positive? ? "Resolved #{real_path.join('->')}, but " : ''
213
219
  Doing.logger.log_now(:warn, "#{resolved}#{path} is unknown")
@@ -306,7 +312,7 @@ module Doing
306
312
 
307
313
  @ignore_local = opt[:ignore_local] if opt[:ignore_local]
308
314
 
309
- config = read_config.dup
315
+ config = read_config.clone
310
316
 
311
317
  plugin_config = Util.deep_merge_hashes(DEFAULTS['plugins'], config['plugins'] || {})
312
318
 
@@ -314,7 +320,7 @@ module Doing
314
320
 
315
321
  Plugins.plugins.each do |_type, plugins|
316
322
  plugins.each do |title, plugin|
317
- plugin_config[title] = plugin[:config] if plugin[:config] && !plugin[:config].empty?
323
+ plugin_config[title] = plugin[:config] if plugin[:config].good?
318
324
  config['export_templates'][title] ||= nil if plugin[:templates] && !plugin[:templates].empty?
319
325
  end
320
326
  end
data/lib/doing/good.rb ADDED
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ # Object helpers
5
+ class ::Object
6
+ ##
7
+ ## Tests if object is nil or empty
8
+ ##
9
+ ## @return [Boolean] true if object is defined and
10
+ ## has content
11
+ ##
12
+ def good?
13
+ !nil? && !empty?
14
+ end
15
+ end
16
+
17
+ class ::String
18
+ ##
19
+ ## Tests if object is nil or empty
20
+ ##
21
+ ## @return [Boolean] true if object is defined and
22
+ ## has content
23
+ ##
24
+ def good?
25
+ !strip.empty?
26
+ end
27
+ end
28
+
29
+ class ::Array
30
+ ##
31
+ ## Tests if object is nil or empty
32
+ ##
33
+ ## @return [Boolean] true if object is defined and
34
+ ## has content
35
+ ##
36
+ def good?
37
+ !nil? && !empty?
38
+ end
39
+ end
40
+
41
+ class ::FalseClass
42
+ ##
43
+ ## Tests if object is nil or empty
44
+ ##
45
+ ## @return [Boolean] true if object is defined and
46
+ ## has content
47
+ ##
48
+ def good?
49
+ false
50
+ end
51
+ end
52
+
53
+ class ::TrueClass
54
+ ##
55
+ ## Tests if object is nil or empty
56
+ ##
57
+ ## @return [Boolean] true if object is defined and
58
+ ## has content
59
+ ##
60
+ def good?
61
+ true
62
+ end
63
+ end
64
+ end
data/lib/doing/hash.rb CHANGED
@@ -6,14 +6,36 @@ module Doing
6
6
  ##
7
7
  ## Freeze all values in a hash
8
8
  ##
9
- ## @return { description_of_the_return_value }
9
+ ## @return Hash with all values frozen
10
10
  ##
11
11
  def deep_freeze
12
- map { |k, v| v.is_a?(Hash) ? v.deep_freeze : v.freeze }.freeze
12
+ chilled = {}
13
+ each do |k, v|
14
+ chilled[k] = v.is_a?(Hash) ? v.deep_freeze : v.freeze
15
+ end
16
+
17
+ chilled.freeze
13
18
  end
14
19
 
15
20
  def deep_freeze!
16
- replace deep_freeze
21
+ replace deep_thaw.deep_freeze
22
+ end
23
+
24
+ def deep_thaw
25
+ chilled = {}
26
+ each do |k, v|
27
+ chilled[k] = v.is_a?(Hash) ? v.deep_thaw : v.dup
28
+ end
29
+
30
+ chilled.dup
31
+ end
32
+
33
+ def deep_thaw!
34
+ replace deep_thaw
35
+ end
36
+
37
+ def clone
38
+ Marshal.load(Marshal.dump(self))
17
39
  end
18
40
 
19
41
  # Turn all keys into string
@@ -30,8 +52,9 @@ module Doing
30
52
 
31
53
  # Set a nested hash value using an array
32
54
  #
33
- # @example `{}.deep_set(['one', 'two'], 'value')`
34
- # @example `=> { 'one' => { 'two' => 'value' } }
55
+ # @example
56
+ # {}.deep_set(['one', 'two'], 'value')
57
+ # # => { 'one' => { 'two' => 'value' } }
35
58
  #
36
59
  # @param path [Array] key path
37
60
  # @param value The value
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GLI
4
+ module Commands
5
+ # Help Command Monkeypatch for paginated output
6
+ class Help < Command
7
+ def show_help(global_options,options,arguments,out,error)
8
+ Doing::Pager.paginate = true
9
+
10
+ command_finder = HelpModules::CommandFinder.new(@app,arguments,error)
11
+ if options[:c]
12
+ help_output = HelpModules::HelpCompletionFormat.new(@app,command_finder,arguments).format
13
+ out.puts help_output unless help_output.nil?
14
+ elsif arguments.empty? || options[:c]
15
+ Doing::Pager.page HelpModules::GlobalHelpFormat.new(@app,@sorter,@text_wrapping_class).format
16
+ else
17
+ name = arguments.shift
18
+ command = command_finder.find_command(name)
19
+ unless command.nil?
20
+ Doing::Pager.page HelpModules::CommandHelpFormat.new(
21
+ command,
22
+ @app,
23
+ @sorter,
24
+ @synopsis_formatter_class,
25
+ @text_wrapping_class).format
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/doing/hooks.rb CHANGED
@@ -10,8 +10,8 @@ module Doing
10
10
  post_local_config: [], # wwid
11
11
  post_read: [], # wwid
12
12
  pre_entry_add: [], # wwid, new_entry
13
- post_entry_added: [], # wwid, new_entry.dup
14
- post_entry_updated: [], # wwid, entry
13
+ post_entry_added: [], # wwid, new_entry
14
+ post_entry_updated: [], # wwid, entry, old_entry
15
15
  post_entry_removed: [], # wwid, entry.dup
16
16
  pre_export: [], # wwid, format, entries
17
17
  pre_write: [], # wwid, file
@@ -23,7 +23,11 @@ module Doing
23
23
 
24
24
  # register hook(s) to be called later, public API
25
25
  def self.register(event, priority: DEFAULT_PRIORITY, &block)
26
- register_one(event, priority_value(priority), &block)
26
+ if event.is_a?(Array)
27
+ event.each { |ev| register_one(ev, priority_value(priority), &block) }
28
+ else
29
+ register_one(event, priority_value(priority), &block)
30
+ end
27
31
  end
28
32
 
29
33
  # Ensure the priority is a Fixnum
@@ -53,7 +57,7 @@ module Doing
53
57
 
54
58
  def self.trigger(event, *args)
55
59
  hooks = @registry[event]
56
- return if hooks.nil? || hooks.empty?
60
+ return unless hooks.good?
57
61
 
58
62
  # sort and call hooks according to priority and load order
59
63
  hooks.sort_by { |h| @hook_priority[h] }.each do |hook|