doing 2.1.41 → 2.1.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +1 -1
  5. data/bin/commands/again.rb +1 -3
  6. data/bin/commands/changes.rb +60 -34
  7. data/bin/commands/commands.rb +77 -52
  8. data/bin/commands/commands_accepting.rb +57 -53
  9. data/bin/commands/config.rb +2 -2
  10. data/bin/commands/finish.rb +94 -68
  11. data/bin/commands/flag.rb +5 -1
  12. data/bin/commands/grep.rb +12 -2
  13. data/bin/commands/last.rb +2 -0
  14. data/bin/commands/now.rb +151 -107
  15. data/bin/commands/on.rb +20 -5
  16. data/bin/commands/recent.rb +4 -1
  17. data/bin/commands/show.rb +8 -0
  18. data/bin/commands/since.rb +6 -2
  19. data/bin/commands/template.rb +14 -25
  20. data/bin/commands/today.rb +4 -1
  21. data/bin/commands/undo.rb +4 -6
  22. data/bin/commands/view.rb +36 -73
  23. data/bin/commands/views.rb +102 -5
  24. data/bin/commands/yesterday.rb +3 -1
  25. data/bin/doing +31 -4
  26. data/docs/doc/Array.html +14 -3
  27. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  28. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  29. data/docs/doc/BooleanTermParser/Query.html +1 -1
  30. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  31. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  32. data/docs/doc/BooleanTermParser.html +1 -1
  33. data/docs/doc/Doing/ArrayCleanup.html +316 -0
  34. data/docs/doc/Doing/ArrayNestedHash.html +1 -1
  35. data/docs/doc/Doing/ArrayTags.html +1 -1
  36. data/docs/doc/Doing/CSVExport.html +1 -1
  37. data/docs/doc/Doing/CalendarImport.html +1 -1
  38. data/docs/doc/Doing/Change.html +74 -3
  39. data/docs/doc/Doing/Changes.html +3 -3
  40. data/docs/doc/Doing/ChronifyArray.html +1 -1
  41. data/docs/doc/Doing/ChronifyNumeric.html +1 -1
  42. data/docs/doc/Doing/ChronifyString.html +1 -1
  43. data/docs/doc/Doing/Color.html +1 -1
  44. data/docs/doc/Doing/Completion/BashCompletions.html +1 -1
  45. data/docs/doc/Doing/Completion/FishCompletions.html +1 -1
  46. data/docs/doc/Doing/Completion/StringUtils.html +1 -1
  47. data/docs/doc/Doing/Completion/ZshCompletions.html +1 -1
  48. data/docs/doc/Doing/Completion.html +1 -1
  49. data/docs/doc/Doing/Configuration.html +82 -2
  50. data/docs/doc/Doing/DayOneRenderer.html +1 -1
  51. data/docs/doc/Doing/DayoneExport.html +1 -1
  52. data/docs/doc/Doing/DoingImport.html +1 -1
  53. data/docs/doc/Doing/Entry.html +109 -4
  54. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  55. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  56. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  57. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  58. data/docs/doc/Doing/Errors/HistoryLimitError.html +1 -1
  59. data/docs/doc/Doing/Errors/InvalidPlugin.html +1 -1
  60. data/docs/doc/Doing/Errors/MissingBackupFile.html +1 -1
  61. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  62. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  63. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  64. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  65. data/docs/doc/Doing/Errors.html +1 -1
  66. data/docs/doc/Doing/HTMLExport.html +1 -1
  67. data/docs/doc/Doing/Hooks.html +1 -1
  68. data/docs/doc/Doing/Item.html +1 -1
  69. data/docs/doc/Doing/ItemDates.html +1 -1
  70. data/docs/doc/Doing/ItemQuery.html +1 -1
  71. data/docs/doc/Doing/ItemState.html +1 -1
  72. data/docs/doc/Doing/ItemTags.html +1 -1
  73. data/docs/doc/Doing/Items.html +2 -1
  74. data/docs/doc/Doing/JSONExport.html +1 -1
  75. data/docs/doc/Doing/Logger.html +1 -1
  76. data/docs/doc/Doing/MarkdownExport.html +1 -1
  77. data/docs/doc/Doing/Note.html +3 -2
  78. data/docs/doc/Doing/Pager.html +1 -1
  79. data/docs/doc/Doing/Plugins.html +181 -76
  80. data/docs/doc/Doing/Prompt.html +1 -1
  81. data/docs/doc/Doing/PromptChoose.html +1 -1
  82. data/docs/doc/Doing/PromptFZF.html +1 -1
  83. data/docs/doc/Doing/PromptInput.html +1 -1
  84. data/docs/doc/Doing/PromptSTD.html +1 -1
  85. data/docs/doc/Doing/PromptYN.html +1 -1
  86. data/docs/doc/Doing/Section.html +1 -1
  87. data/docs/doc/Doing/StringHighlight.html +1 -1
  88. data/docs/doc/Doing/StringNormalize.html +35 -1
  89. data/docs/doc/Doing/StringQuery.html +1 -1
  90. data/docs/doc/Doing/StringTags.html +1 -1
  91. data/docs/doc/Doing/StringTransform.html +35 -1
  92. data/docs/doc/Doing/StringTruncate.html +1 -1
  93. data/docs/doc/Doing/StringURL.html +1 -1
  94. data/docs/doc/Doing/SymbolNormalize.html +1 -1
  95. data/docs/doc/Doing/TaskPaperExport.html +1 -1
  96. data/docs/doc/Doing/TemplateExport.html +1 -1
  97. data/docs/doc/Doing/TemplateString.html +3 -3
  98. data/docs/doc/Doing/TimingImport.html +1 -1
  99. data/docs/doc/Doing/Types.html +23 -18
  100. data/docs/doc/Doing/Util/Backup.html +2 -156
  101. data/docs/doc/Doing/Util.html +66 -9
  102. data/docs/doc/Doing/Version.html +1 -1
  103. data/docs/doc/Doing/WWID.html +84 -3
  104. data/docs/doc/Doing.html +4 -4
  105. data/docs/doc/FalseClass.html +11 -1
  106. data/docs/doc/GLI/Commands/Help.html +1 -1
  107. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  108. data/docs/doc/GLI/Commands.html +1 -1
  109. data/docs/doc/GLI.html +1 -1
  110. data/docs/doc/Hash.html +461 -6
  111. data/docs/doc/Numeric.html +1 -1
  112. data/docs/doc/Object.html +1 -1
  113. data/docs/doc/PhraseParser/Operator.html +1 -1
  114. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  115. data/docs/doc/PhraseParser/Query.html +1 -1
  116. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  117. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  118. data/docs/doc/PhraseParser/TermClause.html +1 -1
  119. data/docs/doc/PhraseParser.html +1 -1
  120. data/docs/doc/Status.html +1 -1
  121. data/docs/doc/String.html +5 -5
  122. data/docs/doc/Symbol.html +1 -1
  123. data/docs/doc/Time.html +68 -3
  124. data/docs/doc/TrueClass.html +11 -1
  125. data/docs/doc/_index.html +16 -9
  126. data/docs/doc/class_list.html +1 -1
  127. data/docs/doc/file.README.html +2 -2
  128. data/docs/doc/index.html +2 -2
  129. data/docs/doc/method_list.html +529 -417
  130. data/docs/doc/top-level-namespace.html +11 -1
  131. data/doing.rdoc +169 -13
  132. data/lib/completion/_doing.zsh +13 -13
  133. data/lib/completion/doing.bash +22 -22
  134. data/lib/completion/doing.fish +24 -1
  135. data/lib/doing/add_options.rb +48 -1
  136. data/lib/doing/array/array.rb +2 -0
  137. data/lib/doing/array/cleanup.rb +31 -0
  138. data/lib/doing/changelog/change.rb +13 -5
  139. data/lib/doing/changelog/changes.rb +11 -2
  140. data/lib/doing/changelog/entry.rb +9 -2
  141. data/lib/doing/configuration.rb +28 -3
  142. data/lib/doing/good.rb +18 -1
  143. data/lib/doing/hash.rb +126 -22
  144. data/lib/doing/normalize.rb +13 -0
  145. data/lib/doing/note.rb +1 -1
  146. data/lib/doing/pager.rb +9 -3
  147. data/lib/doing/plugin_manager.rb +30 -5
  148. data/lib/doing/prompt/choose.rb +1 -1
  149. data/lib/doing/prompt/input.rb +1 -1
  150. data/lib/doing/string/transform.rb +6 -0
  151. data/lib/doing/types.rb +9 -8
  152. data/lib/doing/util.rb +12 -6
  153. data/lib/doing/util_backup.rb +55 -48
  154. data/lib/doing/version.rb +1 -1
  155. data/lib/doing/wwid/display.rb +4 -1
  156. data/lib/doing/wwid/editor.rb +6 -3
  157. data/lib/doing/wwid/interactive.rb +10 -20
  158. data/lib/doing/wwid/modify.rb +2 -0
  159. data/lib/doing/wwid/wwid.rb +21 -3
  160. data/lib/doing.rb +12 -3
  161. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9165fde649301eddb5bf5fc4fd9e1b52b67e1a7614102a752b0946b12e76ed07
4
- data.tar.gz: 817142e7ea8be0f74355e5988bf6b857147e76f37b2a876feb19527c49807934
3
+ metadata.gz: d5518b6c12e5bcfd3f2faac11e927432d89791ea6608c1d342cd6fbe60ee726a
4
+ data.tar.gz: ebfadb15e7c48cd853012f69fa0e67e157f59706eeaa7c1620f49fa5aaaf0db2
5
5
  SHA512:
6
- metadata.gz: c52235f05bedf4b2aded1700df34032a57ce5b21ccbf87ad9372a3e0ab239dfb19154d95420642a81d854d54a2da013720e8c092393937698a470e9ce9920c4f
7
- data.tar.gz: 01f885b23f2d984fa40a37c6f256da01649c9974d6dd8bd1dc2603e9c749579c640dc2c0f8d86f98675f0624cfb9a13225a1594d2663e4ed35bb46f1b4aebf83
6
+ metadata.gz: 1b018215254df2fbfbbcefb2da74d06ae0910dbbb6d2fca47e7c975c8092b698de6d3985c32600eb0fa6e7e06f3821b7ba2df7e0b0df9bd9dd00e06414c1fd73
7
+ data.tar.gz: 135f0a40c8f098984eddfad269c75480fad3a7e39e806af3280a86d5609d659bf91b8467b83a45f6e6bb07cd438162e1afca5411c51bdc6533be9c3724fe80cb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,70 @@
1
+ ### 2.1.44
2
+
3
+ 2022-03-21 07:46
4
+
5
+ #### NEW
6
+
7
+ - `doing views --remove NAME` to delete a view
8
+ - Deleting all view content in editor (`doing views -e`) deletes the view
9
+
10
+ #### IMPROVED
11
+
12
+ - When saving a view, ignore keys that are the same as the default template
13
+ - Commands accepting `--save` also accept `--title TITLE`
14
+
15
+ #### FIXED
16
+
17
+ - When saving a view, store original date string instead of chronified result
18
+ - Error when testing for valid date
19
+
20
+ ### 2.1.43
21
+
22
+ 2022-03-20 12:44
23
+
24
+ #### NEW
25
+
26
+ - 'parent' key in view config allows inheritance
27
+ - Use `--save NAME` with view commands to store command line options as a view in config
28
+ - Views function as commands, so you can run `doing custom` and get `doing view custom` if 'custom' is not a recognized command
29
+ - Breaking change - boolean switches on the command line no longer override views
30
+ - Add an argument to `doing views` to dump the YAML for a single view
31
+ - Use `doing views NAME --editor` to open the YAML for a single view in the default editor, saving the result to main config
32
+ - Use `doing views [-e] -o json NAME` to dump or edit a view as json instead of YAML
33
+
34
+ #### IMPROVED
35
+
36
+ - `doing changes --only [changed,new,improved,fixed]` to only show changes of a type
37
+ - Allow all show options in view config
38
+ - Disable autocorrect for command names so custom views can better override similarly-spelled commands
39
+ - `doing changes --prefix` will output each change with a type prefix
40
+ - Include -F switch in `less` when paging to avoid pager if less than one screen
41
+
42
+ #### FIXED
43
+
44
+ - `doing templates --list` returning error
45
+
46
+ ### 2.1.42
47
+
48
+ 2022-03-17 09:38
49
+
50
+ #### NEW
51
+
52
+ - Config option `editors.pager` allows you to force a pager (ignore env settings)
53
+
54
+ #### IMPROVED
55
+
56
+ - Change pager preference order to $PAGER, less -Xr, $GIT_PAGER
57
+ - Remove `bat` from pager options as it just falls back to `less -Xr` anyway
58
+ - Using CTRL-C when entring a note interactively won't cancel the whole operation, just the note
59
+
60
+ #### FIXED
61
+
62
+ - Add delay between `doing select --editor` and opening the editor, fixes some TTY echo issues
63
+ - If `doing last --editor` has no changes, exit gracefully
64
+ - Trigger pre/post_write hooks when using undo/redo
65
+ - `doing config set` issues with keys that default to nil
66
+ - Notification for `doing config set --remove` missing last element of key path
67
+
1
68
  ### 2.1.41
2
69
 
3
70
  2022-03-16 09:29
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- doing (2.1.41)
4
+ doing (2.1.44)
5
5
  chronic (~> 0.10, >= 0.10.2)
6
6
  deep_merge (~> 1.2, >= 1.2.1)
7
7
  gli (~> 2.20, >= 2.20.1)
data/README.md CHANGED
@@ -8,7 +8,7 @@ _If you're one of the rare people like me who find this useful, feel free to
8
8
 
9
9
  <!--README-->
10
10
 
11
- The current version of `doing` is <!--VER-->2.1.39<!--END VER-->.
11
+ The current version of `doing` is <!--VER-->2.1.43<!--END VER-->.
12
12
 
13
13
  Find all of the documentation in the [doing wiki][wiki].
14
14
 
@@ -33,9 +33,7 @@ command %i[again resume] do |c|
33
33
  c.action do |_global_options, options, _args|
34
34
  options[:fuzzy] = false
35
35
 
36
- if options[:search]
37
- options[:search] = options[:exact] ? options[:search].sub(/^'?/, "'") : options[:search]
38
- end
36
+ options[:search] = options[:search].sub(/^'?/, "'") if options[:search] && options[:exact]
39
37
 
40
38
  if options[:back]
41
39
  options[:date] = options[:back]
@@ -14,52 +14,78 @@ MARKDOWN_THEME = {
14
14
  comment: :bright_black
15
15
  }.deep_freeze
16
16
 
17
- CHANGE_RX = /^(?:(?:(?:[<>=]+|p(?:rior)|b(?:efore)|o(?:lder)|s(?:ince)|a(?:fter)|n(?:ewer))? *[0-9.*?]{1,10} *)+|(?:[\d.]+ *(?:-|to)+ *[0-9.]{1,10}))$/
17
+ module Doing
18
+ # changes command methods
19
+ class ChangesCommand
20
+ CHANGE_RX = /^(?:(?:(?:[<>=]+|p(?:rior)|b(?:efore)|o(?:lder)|s(?:ince)|a(?:fter)|n(?:ewer))? *[0-9.*?]{1,10} *)+|(?:[\d.]+ *(?:-|to)+ *[0-9.]{1,10}))$/
18
21
 
19
- desc 'List recent changes in Doing'
20
- long_desc %(Display a formatted list of changes in recent versions.
22
+ def add_options(cmd)
23
+ cmd.desc 'Display all versions'
24
+ cmd.switch %i[a all], default_value: false, negatable: false
21
25
 
22
- Without flags, displays only the most recent version.
23
- Use --lookup or --all for history.)
24
- command %i[changes changelog] do |c|
25
- c.desc 'Display all versions'
26
- c.switch %i[a all], default_value: false, negatable: false
26
+ cmd.desc %(Look up a specific version. Specify versions as "MAJ.MIN.PATCH", MIN
27
+ and PATCH are optional. Use > or < to see all changes since or prior
28
+ to a version. Wildcards (*?) accepted unless using < or >.)
29
+ cmd.arg_name 'VERSION'
30
+ cmd.flag %i[l lookup], must_match: CHANGE_RX
27
31
 
28
- c.desc %(Look up a specific version. Specify versions as "MAJ.MIN.PATCH", MIN
29
- and PATCH are optional. Use > or < to see all changes since or prior
30
- to a version. Wildcards (*?) accepted unless using < or >.)
31
- c.arg_name 'VERSION'
32
- c.flag %i[l lookup], must_match: CHANGE_RX
32
+ cmd.desc %(Show changelogs matching search terms (uses pattern-based searching).
33
+ Add slashes to search with regular expressions, e.g. `--search "/output.*flag/"`)
34
+ cmd.flag %i[s search]
33
35
 
34
- c.desc %(Show changelogs matching search terms (uses pattern-based searching).
35
- Add slashes to search with regular expressions, e.g. `--search "/output.*flag/"`)
36
- c.flag %i[s search]
36
+ cmd.desc 'Sort order (asc/desc)'
37
+ cmd.arg_name 'ORDER'
38
+ cmd.flag %i[sort], must_match: REGEX_SORT_ORDER, default_value: :desc, type: OrderSymbol
37
39
 
38
- c.desc 'Sort order (asc/desc)'
39
- c.arg_name 'ORDER'
40
- c.flag %i[sort], must_match: REGEX_SORT_ORDER, default_value: :desc, type: OrderSymbol
40
+ cmd.desc 'Only output changes, no version numbers, headers, or dates'
41
+ cmd.switch %i[C changes], default_value: false, negatable: false
41
42
 
42
- c.desc 'Only output changes, no version numbers, headers, or dates'
43
- c.switch %i[C changes], default_value: false, negatable: false
43
+ cmd.desc 'Include (CHANGE|NEW|IMPROVED|FIXED) prefix on each line'
44
+ cmd.switch %i[p prefix]
44
45
 
45
- c.desc 'Output raw Markdown'
46
- c.switch %i[m md markdown], default_value: false, negatable: false
46
+ cmd.desc 'Only show changes of type(s), comma-separated'
47
+ cmd.arg_name 'TYPES'
48
+ cmd.flag %i[only], default_value: 'changed,new,improved,fixed'
47
49
 
48
- c.desc 'Force rendered output'
49
- c.switch %i[render], default_value: false, negatable: false
50
+ cmd.desc 'Output raw Markdown'
51
+ cmd.switch %i[m md markdown], default_value: false, negatable: false
50
52
 
51
- c.desc 'Open changelog in interactive viewer'
52
- c.switch %i[i interactive], default_value: false, negatable: false
53
+ cmd.desc 'Force rendered output'
54
+ cmd.switch %i[render], default_value: false, negatable: false
53
55
 
54
- c.example 'doing changes', desc: 'View changes in the current version'
55
- c.example 'doing changes --all', desc: 'See the entire changelog'
56
- c.example 'doing changes --lookup 2.0.21', desc: 'See changes from version 2.0.21'
57
- c.example 'doing changes --lookup "> 2.1"', desc: 'See all changes since 2.1.0'
58
- c.example 'doing changes --search "tags +bool"', desc: 'See all changes containing "tags" and "bool"'
59
- c.example 'doing changes -l "> 2.1" -s "pattern"', desc: 'Lookup and search can be combined'
56
+ cmd.desc 'Open changelog in interactive viewer'
57
+ cmd.switch %i[i interactive], default_value: false, negatable: false
58
+ end
59
+
60
+ def add_examples(cmd)
61
+ cmd.example 'doing changes', desc: 'View changes in the current version'
62
+ cmd.example 'doing changes --all', desc: 'See the entire changelog'
63
+ cmd.example 'doing changes --lookup 2.0.21', desc: 'See changes from version 2.0.21'
64
+ cmd.example 'doing changes --lookup "> 2.1"', desc: 'See all changes since 2.1.0'
65
+ cmd.example 'doing changes --search "tags +bool"', desc: 'See all changes containing "tags" and "bool"'
66
+ cmd.example 'doing changes -l "> 2.1" -s "pattern"', desc: 'Lookup and search can be combined'
67
+ end
68
+ end
69
+ end
70
+
71
+ desc 'List recent changes in Doing'
72
+ long_desc %(Display a formatted list of changes in recent versions.
73
+
74
+ Without flags, displays only the most recent version.
75
+ Use --lookup or --all for history.)
76
+ command %i[changes changelog] do |c|
77
+ cmd = Doing::ChangesCommand.new
78
+ cmd.add_options(c)
79
+ cmd.add_examples(c)
60
80
 
61
81
  c.action do |_global_options, options, _args|
62
- cl = Doing::Changes.new(lookup: options[:lookup], search: options[:search], changes: options[:changes], sort: options[:sort])
82
+ only = options[:only].split(/ *, */).map(&:normalize_change_type)
83
+ cl = Doing::Changes.new(lookup: options[:lookup],
84
+ search: options[:search],
85
+ changes: options[:changes],
86
+ prefix: options[:prefix],
87
+ sort: options[:sort],
88
+ only: only)
63
89
 
64
90
  if options[:interactive]
65
91
  cl.interactive
@@ -1,37 +1,71 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # @@commands
4
- desc 'Enable and disable Doing commands'
5
- command :commands do |c|
6
- c.example 'doing commands add', desc: 'Get a menu of available commands'
7
- c.example 'doing commands add COMMAND', desc: 'Specify a command to enable'
8
- c.example 'doing commands remove COMMAND', desc: 'Specify a command to disable'
3
+ module Doing
4
+ # commands command methods
5
+ class CommandsCommand
6
+ def add_examples(cmd)
7
+ cmd.example 'doing commands add', desc: 'Get a menu of available commands'
8
+ cmd.example 'doing commands add COMMAND', desc: 'Specify a command to enable'
9
+ cmd.example 'doing commands remove COMMAND', desc: 'Specify a command to disable'
10
+ end
9
11
 
10
- c.default_command :add
12
+ def remove_command(args)
13
+ available = Dir.glob(File.join(File.dirname(__FILE__), '*.rb')).map { |cmd| File.basename(cmd, '.rb') }
14
+ cfg = Doing.settings
15
+ custom_dir = Doing.setting('plugins.command_path')
16
+ custom_commands = Dir.glob(File.join(File.expand_path(custom_dir), '*.rb'))
17
+ available.concat(custom_commands.map { |cmd| File.basename(cmd, '.rb') })
18
+ disabled = Doing.setting('disabled_commands')
19
+ disabled.each { |cmd| available.delete(cmd) }
20
+ to_disable = if args.good?
21
+ args
22
+ else
23
+ Prompt.choose_from(available,
24
+ prompt: 'Select commands to enable',
25
+ multiple: true,
26
+ sorted: true)
27
+ end
28
+ raise UserCancelled unless to_disable.good?
11
29
 
12
- # @@commands.enable
13
- c.desc 'Enable Doing commands'
14
- c.long_desc 'Run without arguments to select commands from a list.'
15
- c.arg_name 'COMMAND [COMMAND...]'
16
- c.command %i[add enable] do |add|
17
- add.action do |_global, _options, args|
30
+ to_disable = to_disable.strip.split("\n") if to_disable.is_a?(String)
31
+
32
+ to_disable.each do |cmd|
33
+ default_command = File.join(File.dirname(__FILE__), "#{cmd}.rb")
34
+ custom_command = File.join(File.expand_path(custom_dir), "#{cmd}.rb")
35
+ unless File.exist?(default_command) || File.exist?(custom_command)
36
+ raise InvalidArgument, "Command #{cmd} not found"
37
+
38
+ end
39
+
40
+ raise InvalidArgument, "Command #{cmd} is not enabled" unless available.include?(cmd)
41
+ end
42
+
43
+ cfg.deep_set(['disabled_commands'], disabled.concat(to_disable))
44
+
45
+ Util.write_to_file(Doing.config.config_file, YAML.dump(cfg), backup: true)
46
+ Doing.logger.warn('Config:', "#{Doing.config.config_file} updated")
47
+ end
48
+
49
+ def add_command(args)
18
50
  cfg = Doing.settings
19
- custom_dir = cfg.dig('plugins', 'command_path')
51
+ custom_dir = Doing.setting('plugins.command_path')
52
+ available = Doing.setting('disabled_commands')
20
53
 
21
- available = cfg['disabled_commands']
22
54
  raise UserCancelled, 'No commands available to enable' unless args.good? || available.good?
23
55
 
24
56
  to_enable = if args.good?
25
57
  args
26
58
  else
27
- Doing::Prompt.choose_from(available,
28
- prompt: 'Select commands to enable',
29
- multiple: true,
30
- sorted: true)
59
+ Prompt.choose_from(available,
60
+ prompt: 'Select commands to enable',
61
+ multiple: true,
62
+ sorted: true)
31
63
  end
32
- raise UserCancelled unless to_enable
64
+ raise UserCancelled unless to_enable.good?
33
65
 
34
- to_enable.strip.split("\n").each do |cmd|
66
+ to_enable = to_enable.strip.split("\n") if to_enable.is_a?(String)
67
+
68
+ to_enable.each do |cmd|
35
69
  default_command = File.join(File.dirname(__FILE__), "#{cmd}.rb")
36
70
  custom_command = File.join(File.expand_path(custom_dir), "#{cmd}.rb")
37
71
  unless File.exist?(default_command) || File.exist?(custom_command)
@@ -45,45 +79,36 @@ command :commands do |c|
45
79
 
46
80
  cfg.deep_set(['disabled_commands'], available)
47
81
 
48
- Doing::Util.write_to_file(Doing.config.config_file, YAML.dump(cfg), backup: true)
82
+ Util.write_to_file(Doing.config.config_file, YAML.dump(cfg), backup: true)
49
83
  Doing.logger.warn('Config:', "#{Doing.config.config_file} updated")
50
84
  end
51
85
  end
86
+ end
87
+
88
+ # @@commands
89
+ desc 'Enable and disable Doing commands'
90
+ command :commands do |c|
91
+ c.default_command :add
92
+
93
+ cmd = Doing::CommandsCommand.new
94
+
95
+ cmd.add_examples(c)
96
+
97
+ # @@commands.enable
98
+ c.desc 'Enable Doing commands'
99
+ c.long_desc 'Run without arguments to select commands from a list.'
100
+ c.arg_name 'COMMAND [COMMAND...]'
101
+ c.command %i[add enable] do |add|
102
+ add.action do |_global, _options, args|
103
+ cmd.add_command(args)
104
+ end
105
+ end
52
106
 
53
107
  # @@commands.disable
54
108
  c.desc 'Disable Doing commands'
55
109
  c.command %i[remove disable] do |remove|
56
110
  remove.action do |_global, _options, args|
57
- available = Dir.glob(File.join(File.dirname(__FILE__), '*.rb')).map { |cmd| File.basename(cmd, '.rb') }
58
- cfg = Doing.settings
59
- custom_dir = cfg.dig('plugins', 'command_path')
60
- custom_commands = Dir.glob(File.join(File.expand_path(custom_dir), '*.rb'))
61
- available.concat(custom_commands.map { |cmd| File.basename(cmd, '.rb') })
62
- disabled = cfg['disabled_commands']
63
- disabled.each { |cmd| available.delete(cmd) }
64
- to_disable = if args.good?
65
- args
66
- else
67
- Doing::Prompt.choose_from(available,
68
- prompt: 'Select commands to enable',
69
- multiple: true,
70
- sorted: true).strip.split("\n")
71
- end
72
- to_disable.each do |cmd|
73
- default_command = File.join(File.dirname(__FILE__), "#{cmd}.rb")
74
- custom_command = File.join(File.expand_path(custom_dir), "#{cmd}.rb")
75
- unless File.exist?(default_command) || File.exist?(custom_command)
76
- raise InvalidArgument, "Command #{cmd} not found"
77
-
78
- end
79
-
80
- raise InvalidArgument, "Command #{cmd} is not enabled" unless available.include?(cmd)
81
- end
82
-
83
- cfg.deep_set(['disabled_commands'], disabled.concat(to_disable))
84
-
85
- Doing::Util.write_to_file(Doing.config.config_file, YAML.dump(cfg), backup: true)
86
- Doing.logger.warn('Config:', "#{Doing.config.config_file} updated")
111
+ cmd.remove_command(args)
87
112
  end
88
113
  end
89
114
  end
@@ -1,5 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ module Doing
4
+ # commands_accepting command methods
5
+ class CommandsAcceptingCommand
6
+ def flags?(options, args, bool)
7
+ case bool
8
+ when :and
9
+ all_flags?(options, args)
10
+ when :not
11
+ no_flags?(options, args)
12
+ else
13
+ any_flags?(options, args)
14
+ end
15
+ end
16
+
17
+ def all_flags?(options, args)
18
+ args.each do |arg|
19
+ has_flag = false
20
+ options.flags.merge(options.switches).each do |_, flag|
21
+ if flag.name == arg.to_sym || flag.aliases&.include?(arg.to_sym)
22
+ has_flag = true
23
+ break
24
+ end
25
+ end
26
+ return false unless has_flag
27
+ end
28
+
29
+ true
30
+ end
31
+
32
+ def any_flags?(options, args)
33
+ args.each do |option|
34
+ options.flags.merge(options.switches).each do |_, flag|
35
+ return true if flag.name == option.to_sym || flag.aliases&.include?(option.to_sym)
36
+ end
37
+ end
38
+
39
+ false
40
+ end
41
+
42
+ def no_flags?(options, args)
43
+ args.each do |option|
44
+ options.flags.merge(options.switches).each do |_, flag|
45
+ return false if flag.name == option.to_sym || flag.aliases&.include?(option.to_sym)
46
+ end
47
+ end
48
+
49
+ true
50
+ end
51
+ end
52
+ end
53
+
3
54
  # @@commands_accepting
4
55
  arg_name 'OPTION'
5
56
  command :commands_accepting do |c|
@@ -11,66 +62,19 @@ command :commands_accepting do |c|
11
62
  default_value: :and,
12
63
  type: BooleanSymbol
13
64
 
14
- c.action do |g, o, a|
65
+ c.action do |_g, o, a|
66
+ cac = Doing::CommandsAcceptingCommand.new
15
67
  cmds = []
16
- commands.each { |cmd, v| cmds.push(cmd) if has_flags?(v, a, o[:bool]) }
68
+ commands.each { |cmd, v| cmds.push(cmd) if cac.flags?(v, a, o[:bool]) }
17
69
 
18
70
  if o[:column]
19
71
  puts cmds.sort
20
72
  else
21
- description = "Commands "
22
- description += "not " if o[:bool] == :not
23
- description += "accepting "
73
+ description = 'Commands '
74
+ description += 'not ' if o[:bool] == :not
75
+ description += 'accepting '
24
76
  description += a.map { |arg| "--#{arg}" }.join(o[:bool] == :and ? ' and ' : ' or ')
25
77
  puts "#{description}: #{cmds.sort.join(', ')}"
26
78
  end
27
79
  end
28
-
29
- def has_flags?(options, args, bool)
30
- case bool
31
- when :and
32
- all_flags?(options, args)
33
- when :not
34
- no_flags?(options, args)
35
- else
36
- any_flags?(options, args)
37
- end
38
- end
39
-
40
- def all_flags?(options, args)
41
- args.each do |arg|
42
- has_flag = false
43
- options.flags.merge(options.switches).each do |_, flag|
44
- if flag.name == arg.to_sym || flag.aliases&.include?(arg.to_sym)
45
- has_flag = true
46
- break
47
- end
48
- end
49
- return false unless has_flag
50
- end
51
-
52
- true
53
- end
54
-
55
- def any_flags?(options, args)
56
- args.each do |option|
57
- options.flags.merge(options.switches).each do |_, flag|
58
- return true if flag.name == option.to_sym || flag.aliases&.include?(option.to_sym)
59
- end
60
- end
61
-
62
- false
63
- end
64
-
65
- def no_flags?(options, args)
66
- args.each do |option|
67
- options.flags.merge(options.switches).each do |_, flag|
68
- return false if flag.name == option.to_sym || flag.aliases&.include?(option.to_sym)
69
- end
70
- end
71
-
72
- true
73
- end
74
80
  end
75
-
76
-
@@ -214,7 +214,7 @@ command :config do |c|
214
214
  keypath = args.join('.')
215
215
  real_path = Doing.config.resolve_key_path(keypath, create: true)
216
216
  old_value = Doing.config.settings.dig(*real_path)
217
- old_type = old_value&.class.to_s || nil
217
+ old_type = old_value.good? ? old_value&.class.to_s : nil
218
218
 
219
219
  if old_value.is_a?(Hash) && !options[:remove]
220
220
  Doing.logger.log_now(:warn, 'Config:', ['Config key must point to a single value, ',
@@ -235,8 +235,8 @@ command :config do |c|
235
235
  $stderr.puts "> Config: Updating #{config_file}".yellow
236
236
 
237
237
  if options[:remove]
238
- cfg.deep_set(real_path, nil)
239
238
  $stderr.puts "#{'Deleting key:'.yellow} #{real_path.join('.').boldwhite}"
239
+ cfg.deep_set(real_path, nil)
240
240
  else
241
241
  current_value = cfg.dig(*real_path)
242
242
  cfg.deep_set(real_path, value.set_type(old_type))