doing 2.1.25 → 2.1.26

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/.yardoc/checksums +4 -4
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +283 -108
  6. data/Gemfile.lock +1 -1
  7. data/README.md +1 -1
  8. data/bin/commands/add_section.rb +13 -0
  9. data/bin/commands/again.rb +99 -0
  10. data/bin/commands/archive.rb +96 -0
  11. data/bin/commands/cancel.rb +102 -0
  12. data/bin/commands/changes.rb +42 -0
  13. data/bin/commands/choose.rb +9 -0
  14. data/bin/commands/colors.rb +19 -0
  15. data/bin/commands/commands.rb +87 -0
  16. data/bin/commands/commands_accepting.rb +25 -0
  17. data/bin/commands/completion.rb +24 -0
  18. data/bin/commands/config.rb +245 -0
  19. data/bin/commands/done.rb +249 -0
  20. data/bin/commands/finish.rb +149 -0
  21. data/bin/commands/flag.rb +126 -0
  22. data/bin/commands/grep.rb +124 -0
  23. data/bin/commands/import.rb +101 -0
  24. data/bin/commands/install_fzf.rb +17 -0
  25. data/bin/commands/last.rb +114 -0
  26. data/bin/commands/meanwhile.rb +86 -0
  27. data/bin/commands/note.rb +130 -0
  28. data/bin/commands/now.rb +151 -0
  29. data/bin/commands/on.rb +66 -0
  30. data/bin/commands/open.rb +53 -0
  31. data/bin/commands/plugins.rb +23 -0
  32. data/bin/commands/recent.rb +78 -0
  33. data/bin/commands/redo.rb +22 -0
  34. data/bin/commands/reset.rb +106 -0
  35. data/bin/commands/rotate.rb +73 -0
  36. data/bin/commands/sections.rb +11 -0
  37. data/bin/commands/select.rb +123 -0
  38. data/bin/commands/show.rb +231 -0
  39. data/bin/commands/since.rb +64 -0
  40. data/bin/commands/tag.rb +179 -0
  41. data/bin/commands/tag_dir.rb +29 -0
  42. data/bin/commands/tags.rb +93 -0
  43. data/bin/commands/template.rb +61 -0
  44. data/bin/commands/today.rb +65 -0
  45. data/bin/commands/undo.rb +49 -0
  46. data/bin/commands/view.rb +238 -0
  47. data/bin/commands/views.rb +11 -0
  48. data/bin/commands/yesterday.rb +73 -0
  49. data/bin/doing +39 -3641
  50. data/docs/doc/Array.html +1 -1
  51. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  52. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  53. data/docs/doc/BooleanTermParser/Query.html +1 -1
  54. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  55. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  56. data/docs/doc/BooleanTermParser.html +1 -1
  57. data/docs/doc/Doing/Color.html +1 -1
  58. data/docs/doc/Doing/Completion.html +1 -1
  59. data/docs/doc/Doing/Configuration.html +2 -1
  60. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  61. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  62. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  63. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  64. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  65. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  66. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  67. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  68. data/docs/doc/Doing/Errors.html +1 -1
  69. data/docs/doc/Doing/Hooks.html +1 -1
  70. data/docs/doc/Doing/Item.html +1 -1
  71. data/docs/doc/Doing/Items.html +1 -1
  72. data/docs/doc/Doing/LogAdapter.html +1 -1
  73. data/docs/doc/Doing/Note.html +1 -1
  74. data/docs/doc/Doing/Pager.html +1 -1
  75. data/docs/doc/Doing/Plugins.html +1 -1
  76. data/docs/doc/Doing/Prompt.html +46 -1
  77. data/docs/doc/Doing/Section.html +1 -1
  78. data/docs/doc/Doing/TemplateString.html +1 -1
  79. data/docs/doc/Doing/Types.html +1 -1
  80. data/docs/doc/Doing/Util/Backup.html +1 -1
  81. data/docs/doc/Doing/Util.html +1 -1
  82. data/docs/doc/Doing/WWID.html +1 -1
  83. data/docs/doc/Doing.html +2 -2
  84. data/docs/doc/FalseClass.html +201 -0
  85. data/docs/doc/GLI/Commands/Help.html +1 -1
  86. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  87. data/docs/doc/GLI/Commands.html +1 -1
  88. data/docs/doc/GLI.html +1 -1
  89. data/docs/doc/Hash.html +1 -1
  90. data/docs/doc/Numeric.html +1 -1
  91. data/docs/doc/Object.html +203 -0
  92. data/docs/doc/PhraseParser/Operator.html +1 -1
  93. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  94. data/docs/doc/PhraseParser/Query.html +1 -1
  95. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  96. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  97. data/docs/doc/PhraseParser/TermClause.html +1 -1
  98. data/docs/doc/PhraseParser.html +1 -1
  99. data/docs/doc/Status.html +1 -1
  100. data/docs/doc/String.html +1 -1
  101. data/docs/doc/Symbol.html +1 -1
  102. data/docs/doc/Time.html +1 -1
  103. data/docs/doc/TrueClass.html +201 -0
  104. data/docs/doc/_index.html +1 -1
  105. data/docs/doc/file.README.html +2 -2
  106. data/docs/doc/index.html +2 -2
  107. data/docs/doc/method_list.html +374 -366
  108. data/docs/doc/top-level-namespace.html +1 -1
  109. data/doing.rdoc +15 -5
  110. data/lib/completion/_doing.zsh +3 -3
  111. data/lib/completion/doing.fish +1 -1
  112. data/lib/doing/changelog/changes.rb +1 -1
  113. data/lib/doing/configuration.rb +1 -0
  114. data/lib/doing/pager.rb +1 -0
  115. data/lib/doing/prompt.rb +8 -0
  116. data/lib/doing/version.rb +1 -1
  117. data/lib/examples/commands/wiki.rb +6 -7
  118. data/lib/helpers/threaded_tests.rb +25 -19
  119. metadata +45 -1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- doing (2.1.25)
4
+ doing (2.1.26)
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.24<!--END VER-->.
11
+ The current version of `doing` is <!--VER-->2.1.25<!--END VER-->.
12
12
 
13
13
  Find all of the documentation in the [doing wiki][wiki].
14
14
 
@@ -0,0 +1,13 @@
1
+ # @@add_section
2
+ desc 'Add a new section to the "doing" file'
3
+ arg_name 'SECTION_NAME'
4
+ command :add_section do |c|
5
+ c.example 'doing add_section Ideas', desc: 'Add a section called Ideas to the doing file'
6
+
7
+ c.action do |_global_options, _options, args|
8
+ raise InvalidArgument, "Section #{args[0]} already exists" if @wwid.sections.include?(args[0])
9
+
10
+ @wwid.content.add_section(args.join(' ').cap_first, log: true)
11
+ @wwid.write(@wwid.doing_file)
12
+ end
13
+ end
@@ -0,0 +1,99 @@
1
+ # @@again @@resume
2
+ desc 'Repeat last entry as new entry'
3
+ long_desc 'This command is designed to allow multiple time intervals to be created for an entry by duplicating it with a new start (and end, eventually) time'
4
+ command %i[again resume] do |c|
5
+ c.example 'doing resume', desc: 'Duplicate the most recent entry with a new start time, removing any @done tag'
6
+ c.example 'doing again', desc: 'again is an alias for resume'
7
+ c.example 'doing resume --editor', desc: 'Repeat the last entry, opening the new entry in the default editor'
8
+ c.example 'doing resume --tag project1 --in Projects', desc: 'Repeat the last entry tagged @project1, creating the new entry in the Projects section'
9
+ c.example 'doing resume --interactive', desc: 'Select the entry to repeat from a menu'
10
+
11
+ c.desc 'Get last entry from a specific section'
12
+ c.arg_name 'NAME'
13
+ c.flag %i[s section], default_value: 'All'
14
+
15
+ c.desc 'Add new entry to section (default: same section as repeated entry)'
16
+ c.arg_name 'SECTION_NAME'
17
+ c.flag [:in]
18
+
19
+ c.desc 'Backdate start date by interval or set to time [4pm|20m|2h|"yesterday noon"]'
20
+ c.arg_name 'DATE_STRING'
21
+ c.flag %i[b back started], type: DateBeginString
22
+
23
+ c.desc 'Repeat last entry matching tags. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
24
+ c.arg_name 'TAG'
25
+ c.flag [:tag], type: TagArray
26
+
27
+ c.desc 'Repeat last entry matching search. Surround with
28
+ slashes for regex (e.g. "/query/"), start with a single quote for exact match ("\'query").'
29
+ c.arg_name 'QUERY'
30
+ c.flag [:search]
31
+
32
+ c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
33
+ c.arg_name 'QUERY'
34
+ c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
35
+
36
+ # c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
37
+ # c.switch [:fuzzy], default_value: false, negatable: false
38
+
39
+ c.desc 'Force exact search string matching (case sensitive)'
40
+ c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
41
+
42
+ c.desc 'Resume items that *don\'t* match search/tag filters'
43
+ c.switch [:not], default_value: false, negatable: false
44
+
45
+ c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
46
+ c.arg_name 'TYPE'
47
+ c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
48
+
49
+ c.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
50
+ c.arg_name 'BOOLEAN'
51
+ c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
52
+
53
+ c.desc "Edit duplicated entry with #{Doing::Util.default_editor} before adding"
54
+ c.switch %i[e editor], negatable: false, default_value: false
55
+
56
+ c.desc 'Add a note'
57
+ c.arg_name 'TEXT'
58
+ c.flag %i[n note]
59
+
60
+ c.desc 'Prompt for note via multi-line input'
61
+ c.switch %i[ask], negatable: false, default_value: false
62
+
63
+ c.desc 'Select item to resume from a menu of matching entries'
64
+ c.switch %i[i interactive], negatable: false, default_value: false
65
+
66
+ c.action do |_global_options, options, _args|
67
+ options[:fuzzy] = false
68
+ tags = options[:tag].nil? ? [] : options[:tag]
69
+
70
+ options[:case] = options[:case].normalize_case
71
+
72
+ if options[:search]
73
+ search = options[:search]
74
+ search.sub!(/^'?/, "'") if options[:exact]
75
+ options[:search] = search
76
+ end
77
+
78
+ if options[:back]
79
+ date = options[:back]
80
+ raise InvalidTimeExpression, 'Unable to parse date string for --back' if date.nil?
81
+ else
82
+ date = Time.now
83
+ end
84
+
85
+ note = Doing::Note.new(options[:note])
86
+ note.add(Doing::Prompt.read_lines(prompt: 'Add a note')) if options[:ask]
87
+
88
+ options[:note] = note
89
+
90
+ opts = options.clone
91
+
92
+ opts[:tag] = tags
93
+ opts[:tag_bool] = options[:bool].normalize_bool
94
+ opts[:interactive] = options[:interactive]
95
+ opts[:date] = date
96
+
97
+ @wwid.repeat_last(opts)
98
+ end
99
+ end
@@ -0,0 +1,96 @@
1
+ # @@archive @@move
2
+ desc 'Move entries between sections'
3
+ long_desc %(Argument can be a section name to move all entries from a section,
4
+ or start with an "@" to move entries matching a tag.
5
+
6
+ Default with no argument moves items from the "#{@settings['current_section']}" section to Archive.)
7
+ arg_name 'SECTION_OR_TAG'
8
+ default_value @settings['current_section']
9
+ command %i[archive move] do |c|
10
+ c.example 'doing archive Currently', desc: 'Move all entries in the Currently section to Archive section'
11
+ c.example 'doing archive @done', desc: 'Move all entries tagged @done to Archive'
12
+ c.example 'doing archive --to Later @project1', desc: 'Move all entries tagged @project1 to Later section'
13
+ c.example 'doing move Later --tag project1 --to Currently', desc: 'Move entries in Later tagged @project1 to Currently (move is an alias for archive)'
14
+
15
+ c.desc 'How many items to keep (ignored if archiving by tag or search)'
16
+ c.arg_name 'X'
17
+ c.flag %i[k keep], must_match: /^\d+$/, type: Integer
18
+
19
+ c.desc 'Move entries to'
20
+ c.arg_name 'SECTION_NAME'
21
+ c.flag %i[t to], default_value: 'Archive'
22
+
23
+ c.desc 'Label moved items with @from(SECTION_NAME)'
24
+ c.switch [:label], default_value: true, negatable: true
25
+
26
+ c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?). Added for compatibility with other commands'
27
+ c.arg_name 'TAG'
28
+ c.flag [:tag], type: TagArray
29
+
30
+ c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
31
+ c.arg_name 'BOOLEAN'
32
+ c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
33
+
34
+ c.desc 'Search filter'
35
+ c.arg_name 'QUERY'
36
+ c.flag [:search]
37
+
38
+ c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
39
+ c.arg_name 'QUERY'
40
+ c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
41
+
42
+ # c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
43
+ # c.switch [:fuzzy], default_value: false, negatable: false
44
+
45
+ c.desc 'Force exact search string matching (case sensitive)'
46
+ c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
47
+
48
+ c.desc 'Show items that *don\'t* match search string'
49
+ c.switch [:not], default_value: false, negatable: false
50
+
51
+ c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
52
+ c.arg_name 'TYPE'
53
+ c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
54
+
55
+ c.desc 'Archive entries older than date
56
+ (Flexible date format, e.g. 1/27/2021, 2020-07-19, or Monday 3pm)'
57
+ c.arg_name 'DATE_STRING'
58
+ c.flag [:before], type: DateEndString
59
+
60
+ c.action do |_global_options, options, args|
61
+ options[:fuzzy] = false
62
+ if args.empty?
63
+ section = @settings['current_section']
64
+ tags = []
65
+ elsif args[0] =~ /^all/i
66
+ section = 'all'
67
+ elsif args[0] =~ /^@\S+/
68
+ section = 'all'
69
+ tags = args.map { |t| t.sub(/^@/, '').strip }
70
+ else
71
+ section = args[0].cap_first
72
+ tags = args.length > 1 ? args[1..].map { |t| t.sub(/^@/, '').strip } : []
73
+ end
74
+
75
+ raise InvalidArgument, '--keep and --count can not be used together' if options[:keep] && options[:count]
76
+
77
+ tags.concat(options[:tag]) if options[:tag]
78
+
79
+ search = nil
80
+
81
+ options[:case] = options[:case].normalize_case
82
+
83
+ if options[:search]
84
+ search = options[:search]
85
+ search.sub!(/^'?/, "'") if options[:exact]
86
+ end
87
+
88
+ opts = options.clone
89
+ opts[:search] = search
90
+ opts[:bool] = options[:bool].normalize_bool
91
+ opts[:destination] = options[:to]
92
+ opts[:tags] = tags
93
+
94
+ @wwid.archive(section, opts)
95
+ end
96
+ end
@@ -0,0 +1,102 @@
1
+ # @@cancel
2
+ desc 'End last X entries with no time tracked'
3
+ long_desc 'Adds @done tag without datestamp so no elapsed time is recorded. Alias for `doing finish --no-date`'
4
+ arg_name 'COUNT'
5
+ command :cancel do |c|
6
+ c.example 'doing cancel', desc: 'Cancel the last entry'
7
+ c.example 'doing cancel --tag project1 -u 5', desc: 'Cancel the last 5 unfinished entries containing @project1'
8
+
9
+ c.desc 'Archive entries'
10
+ c.switch %i[a archive], negatable: false, default_value: false
11
+
12
+ c.desc 'Section'
13
+ c.arg_name 'NAME'
14
+ c.flag %i[s section]
15
+
16
+ c.desc 'Cancel the last X entries containing TAG. Separate multiple tags with comma (--tag=tag1,tag2). Wildcards allowed (*, ?)'
17
+ c.arg_name 'TAG'
18
+ c.flag [:tag], type: TagArray
19
+
20
+ c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
21
+ c.arg_name 'BOOLEAN'
22
+ c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
23
+
24
+ c.desc 'Cancel the last X entries matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
25
+ c.arg_name 'QUERY'
26
+ c.flag [:search]
27
+
28
+ c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
29
+ c.arg_name 'QUERY'
30
+ c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
31
+
32
+ # c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
33
+ # c.switch [:fuzzy], default_value: false, negatable: false
34
+
35
+ c.desc 'Force exact search string matching (case sensitive)'
36
+ c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
37
+
38
+ c.desc 'Finish items that *don\'t* match search/tag filters'
39
+ c.switch [:not], default_value: false, negatable: false
40
+
41
+ c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
42
+ c.arg_name 'TYPE'
43
+ c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
44
+
45
+ c.desc 'Cancel last entry (or entries) not already marked @done'
46
+ c.switch %i[u unfinished], negatable: false, default_value: false
47
+
48
+ c.desc 'Select item(s) to cancel from a menu of matching entries'
49
+ c.switch %i[i interactive], negatable: false, default_value: false
50
+
51
+ c.action do |_global_options, options, args|
52
+ options[:fuzzy] = false
53
+ if options[:section]
54
+ section = @wwid.guess_section(options[:section]) || options[:section].cap_first
55
+ else
56
+ section = @settings['current_section']
57
+ end
58
+
59
+ if options[:tag].nil?
60
+ tags = []
61
+ else
62
+ tags = options[:tag]
63
+ end
64
+
65
+ raise InvalidArgument, 'Only one argument allowed' if args.length > 1
66
+
67
+ raise InvalidArgument, 'Invalid argument (specify number of recent items to mark @done)' unless args.empty? || args[0] =~ /\d+/
68
+
69
+ if options[:interactive]
70
+ count = 0
71
+ else
72
+ count = args[0] ? args[0].to_i : 1
73
+ end
74
+
75
+ search = nil
76
+
77
+ if options[:search]
78
+ search = options[:search]
79
+ search.sub!(/^'?/, "'") if options[:exact]
80
+ end
81
+
82
+ opts = {
83
+ archive: options[:archive],
84
+ case: options[:case].normalize_case,
85
+ count: count,
86
+ date: false,
87
+ fuzzy: options[:fuzzy],
88
+ interactive: options[:interactive],
89
+ not: options[:not],
90
+ search: search,
91
+ section: section,
92
+ sequential: false,
93
+ tag: tags,
94
+ tag_bool: options[:bool].normalize_bool,
95
+ tags: ['done'],
96
+ unfinished: options[:unfinished],
97
+ val: options[:val]
98
+ }
99
+
100
+ @wwid.tag_last(opts)
101
+ end
102
+ end
@@ -0,0 +1,42 @@
1
+ # @@changelog @@changes
2
+ desc 'List recent changes in Doing'
3
+ long_desc %(Display a formatted list of changes in recent versions.
4
+
5
+ Without flags, displays only the most recent version.
6
+ Use --lookup or --all for history.)
7
+ command %i[changes changelog] do |c|
8
+ c.desc 'Display all versions'
9
+ c.switch %i[a all], default_value: false, negatable: false
10
+
11
+ c.desc %(Look up a specific version. Specify versions as "MAJ.MIN.PATCH", MIN
12
+ and PATCH are optional. Use > or < to see all changes since or prior
13
+ to a version.)
14
+ c.arg_name 'VERSION'
15
+ c.flag %i[l lookup], must_match: /^(?:(?:(?:[<>=]|p(?:rior)|b(?:efore)|o(?:lder)|s(?:ince)|a(?:fter)|n(?:ewer))? *[\d.*?]+ *)+|(?:[\d.]+ *-+ *[\d.]+))$/
16
+
17
+ c.desc %(Show changelogs matching search terms (uses pattern-based searching).
18
+ Add slashes to search with regular expressions, e.g. `--search "/output.*flag/"`)
19
+ c.flag %i[s search]
20
+
21
+ c.example 'doing changes', desc: 'View changes in the current version'
22
+ c.example 'doing changes --all', desc: 'See the entire changelog'
23
+ c.example 'doing changes --lookup 2.0.21', desc: 'See changes from version 2.0.21'
24
+ c.example 'doing changes --lookup "> 2.1"', desc: 'See all changes since 2.1.0'
25
+ c.example 'doing changes --search "tags +bool"', desc: 'See all changes containing "tags" and "bool"'
26
+ c.example 'doing changes -l "> 2.1" -s "pattern"', desc: 'Lookup and search can be combined'
27
+
28
+
29
+ c.action do |_global_options, options, args|
30
+ cl = Doing::Changes.new(lookup: options[:lookup], search: options[:search])
31
+
32
+ content = if options[:all] || options[:search] || options[:lookup]
33
+ cl.to_s
34
+ else
35
+ cl.latest
36
+ end
37
+
38
+ parsed = TTY::Markdown.parse(content, width: 80, symbols: {override: {bullet: "•"}})
39
+ Doing::Pager.paginate = true
40
+ Doing::Pager.page parsed
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ # @@choose
2
+ desc 'Select a section to display from a menu'
3
+ command :choose do |c|
4
+ c.action do |_global_options, _options, _args|
5
+ section = @wwid.choose_section
6
+
7
+ Doing::Pager.page @wwid.list_section({ section: section.cap_first, count: 0 }) if section
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ # @@colors
2
+ desc 'List available color variables for configuration templates and views'
3
+ command :colors do |c|
4
+ c.action do |_global_options, _options, _args|
5
+ bgs = []
6
+ fgs = []
7
+ @colors::attributes.each do |color|
8
+ if color.to_s =~ /bg/
9
+ bgs.push("#{@colors.send(color, " ")}#{@colors.default} <-- #{color.to_s}")
10
+ else
11
+ fgs.push("#{@colors.send(color, "XXXX")}#{@colors.default} <-- #{color.to_s}")
12
+ end
13
+ end
14
+ out = []
15
+ out << fgs.join("\n")
16
+ out << bgs.join("\n")
17
+ Doing::Pager.page out.join("\n")
18
+ end
19
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
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'
9
+
10
+ c.default_command :add
11
+
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|
18
+ cfg = @settings
19
+ custom_dir = @settings.dig('plugins', 'command_path')
20
+
21
+ available = cfg['disabled_commands']
22
+ raise UserCancelled, 'No commands available to enable' unless args.good? || available.good?
23
+
24
+ to_enable = if args.good?
25
+ args
26
+ else
27
+ Doing::Prompt.choose_from(available,
28
+ prompt: 'Select commands to enable',
29
+ multiple: true,
30
+ sorted: true).strip.split("\n")
31
+ end
32
+ to_enable.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
+ end
38
+
39
+ raise InvalidArgument, "Command #{cmd} is not disabled" unless available.include?(cmd)
40
+
41
+ available.delete(cmd)
42
+ end
43
+
44
+ cfg.deep_set(['disabled_commands'], available)
45
+
46
+ Doing::Util.write_to_file(@config.config_file, YAML.dump(cfg), backup: true)
47
+ Doing.logger.warn('Config:', "#{@config.config_file} updated")
48
+ end
49
+ end
50
+
51
+ # @@commands.disable
52
+ c.desc 'Disable Doing commands'
53
+ c.command %i[remove disable] do |remove|
54
+ remove.action do |_global, _options, args|
55
+ available = Dir.glob(File.join(File.dirname(__FILE__), '*.rb')).map { |cmd| File.basename(cmd, '.rb') }
56
+ cfg = @settings
57
+ custom_dir = @settings.dig('plugins', 'command_path')
58
+ custom_commands = Dir.glob(File.join(File.expand_path(custom_dir), '*.rb'))
59
+ available.concat(custom_commands.map { |cmd| File.basename(cmd, '.rb') })
60
+ disabled = cfg['disabled_commands']
61
+ disabled.each { |cmd| available.delete(cmd) }
62
+ to_disable = if args.good?
63
+ args
64
+ else
65
+ Doing::Prompt.choose_from(available,
66
+ prompt: 'Select commands to enable',
67
+ multiple: true,
68
+ sorted: true).strip.split("\n")
69
+ end
70
+ to_disable.each do |cmd|
71
+ default_command = File.join(File.dirname(__FILE__), "#{cmd}.rb")
72
+ custom_command = File.join(File.expand_path(custom_dir), "#{cmd}.rb")
73
+ unless File.exist?(default_command) || File.exist?(custom_command)
74
+ raise InvalidArgument, "Command #{cmd} not found"
75
+
76
+ end
77
+
78
+ raise InvalidArgument, "Command #{cmd} is not enabled" unless available.include?(cmd)
79
+ end
80
+
81
+ cfg.deep_set(['disabled_commands'], disabled.concat(to_disable))
82
+
83
+ Doing::Util.write_to_file(@config.config_file, YAML.dump(cfg), backup: true)
84
+ Doing.logger.warn('Config:', "#{@config.config_file} updated")
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,25 @@
1
+ # @@commands_accepting
2
+ arg_name 'OPTION'
3
+ command :commands_accepting do |c|
4
+ c.desc 'Output in single column for completion'
5
+ c.switch %i[c column]
6
+
7
+ c.action do |g, o, a|
8
+ a.each do |option|
9
+ cmds = []
10
+ commands.each do |cmd, v|
11
+ v.flags.merge(v.switches).each do |n, flag|
12
+ if flag.name == option.to_sym || flag.aliases&.include?(option.to_sym)
13
+ cmds.push(cmd)
14
+ end
15
+ end
16
+ end
17
+
18
+ if o[:column]
19
+ puts cmds.sort
20
+ else
21
+ puts "Commands accepting --#{option}: #{cmds.sort.join(', ')}"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ # @@completion
2
+ desc 'Generate shell completion scripts'
3
+ long_desc 'Generates the necessary scripts to add command line completion to various shells, so typing \'doing\' and hitting
4
+ tab will offer completions of subcommands and their options.'
5
+ command :completion do |c|
6
+ c.example 'doing completion', desc: 'Output zsh (default) to STDOUT'
7
+ c.example 'doing completion --type zsh --file ~/.zsh-completions/_doing.zsh', desc: 'Output zsh completions to file'
8
+ c.example 'doing completion --type fish --file ~/.config/fish/completions/doing.fish', desc: 'Output fish completions to file'
9
+ c.example 'doing completion --type bash --file ~/.bash_it/completion/enabled/doing.bash', desc: 'Output bash completions to file'
10
+
11
+ c.desc 'Shell to generate for (bash, zsh, fish)'
12
+ c.arg_name 'SHELL'
13
+ c.flag %i[t type], must_match: /^(?:[bzf](?:[ai]?sh)?|all)$/i, default_value: 'zsh'
14
+
15
+ c.desc 'File to write output to'
16
+ c.arg_name 'PATH'
17
+ c.flag %i[f file], default_value: 'STDOUT'
18
+
19
+ c.action do |_global_options, options, _args|
20
+ script_dir = File.join(File.dirname(__FILE__), '..', 'scripts')
21
+
22
+ Doing::Completion.generate_completion(type: options[:type], file: options[:file])
23
+ end
24
+ end