doing 2.1.24 → 2.1.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +17 -21
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +325 -102
  6. data/Dockerfile +5 -5
  7. data/Dockerfile-2.6 +5 -5
  8. data/Dockerfile-2.7 +5 -4
  9. data/Dockerfile-3.0 +5 -4
  10. data/Gemfile.lock +1 -1
  11. data/README.md +1 -1
  12. data/Rakefile +3 -3
  13. data/bin/commands/add_section.rb +15 -0
  14. data/bin/commands/again.rb +57 -0
  15. data/bin/commands/archive.rb +55 -0
  16. data/bin/commands/cancel.rb +60 -0
  17. data/bin/commands/changes.rb +73 -0
  18. data/bin/commands/choose.rb +9 -0
  19. data/bin/commands/colors.rb +21 -0
  20. data/bin/commands/commands.rb +89 -0
  21. data/bin/commands/commands_accepting.rb +76 -0
  22. data/bin/commands/completion.rb +27 -0
  23. data/bin/commands/config.rb +245 -0
  24. data/bin/commands/done.rb +235 -0
  25. data/bin/commands/finish.rb +126 -0
  26. data/bin/commands/flag.rb +90 -0
  27. data/bin/commands/grep.rb +108 -0
  28. data/bin/commands/import.rb +71 -0
  29. data/bin/commands/install_fzf.rb +17 -0
  30. data/bin/commands/last.rb +81 -0
  31. data/bin/commands/meanwhile.rb +76 -0
  32. data/bin/commands/note.rb +91 -0
  33. data/bin/commands/now.rb +145 -0
  34. data/bin/commands/on.rb +65 -0
  35. data/bin/commands/open.rb +53 -0
  36. data/bin/commands/plugins.rb +23 -0
  37. data/bin/commands/recent.rb +77 -0
  38. data/bin/commands/redo.rb +26 -0
  39. data/bin/commands/reset.rb +73 -0
  40. data/bin/commands/rotate.rb +42 -0
  41. data/bin/commands/sections.rb +11 -0
  42. data/bin/commands/select.rb +105 -0
  43. data/bin/commands/show.rb +185 -0
  44. data/bin/commands/since.rb +63 -0
  45. data/bin/commands/tag.rb +149 -0
  46. data/bin/commands/tag_dir.rb +29 -0
  47. data/bin/commands/tags.rb +66 -0
  48. data/bin/commands/template.rb +61 -0
  49. data/bin/commands/today.rb +64 -0
  50. data/bin/commands/undo.rb +49 -0
  51. data/bin/commands/view.rb +201 -0
  52. data/bin/commands/views.rb +11 -0
  53. data/bin/commands/yesterday.rb +72 -0
  54. data/bin/doing +241 -3662
  55. data/docs/doc/Array.html +13 -449
  56. data/docs/doc/BooleanTermParser/Clause.html +5 -5
  57. data/docs/doc/BooleanTermParser/Operator.html +4 -4
  58. data/docs/doc/BooleanTermParser/Query.html +8 -8
  59. data/docs/doc/BooleanTermParser/QueryParser.html +2 -2
  60. data/docs/doc/BooleanTermParser/QueryTransformer.html +2 -2
  61. data/docs/doc/BooleanTermParser.html +1 -1
  62. data/docs/doc/Doing/Color.html +65 -59
  63. data/docs/doc/Doing/Completion.html +2 -2
  64. data/docs/doc/Doing/Configuration.html +49 -16
  65. data/docs/doc/Doing/Errors/DoingNoTraceError.html +2 -2
  66. data/docs/doc/Doing/Errors/DoingRuntimeError.html +2 -2
  67. data/docs/doc/Doing/Errors/DoingStandardError.html +2 -2
  68. data/docs/doc/Doing/Errors/EmptyInput.html +2 -2
  69. data/docs/doc/Doing/Errors/NoResults.html +2 -2
  70. data/docs/doc/Doing/Errors/PluginException.html +3 -3
  71. data/docs/doc/Doing/Errors/UserCancelled.html +2 -2
  72. data/docs/doc/Doing/Errors/WrongCommand.html +2 -2
  73. data/docs/doc/Doing/Errors.html +1 -1
  74. data/docs/doc/Doing/Hooks.html +6 -6
  75. data/docs/doc/Doing/Item.html +50 -16
  76. data/docs/doc/Doing/Items.html +10 -10
  77. data/docs/doc/Doing/LogAdapter.html +24 -24
  78. data/docs/doc/Doing/Note.html +7 -7
  79. data/docs/doc/Doing/Pager.html +4 -4
  80. data/docs/doc/Doing/Plugins.html +7 -7
  81. data/docs/doc/Doing/Prompt.html +59 -14
  82. data/docs/doc/Doing/Section.html +6 -6
  83. data/docs/doc/Doing/TemplateString.html +8 -8
  84. data/docs/doc/Doing/Types.html +46 -1
  85. data/docs/doc/Doing/Util/Backup.html +10 -10
  86. data/docs/doc/Doing/Util.html +15 -15
  87. data/docs/doc/Doing/WWID.html +73 -61
  88. data/docs/doc/Doing.html +3 -3
  89. data/docs/doc/FalseClass.html +235 -0
  90. data/docs/doc/GLI/Commands/Help.html +3 -3
  91. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +17 -17
  92. data/docs/doc/GLI/Commands.html +1 -1
  93. data/docs/doc/GLI.html +1 -1
  94. data/docs/doc/Hash.html +45 -11
  95. data/docs/doc/Numeric.html +5 -5
  96. data/docs/doc/Object.html +203 -0
  97. data/docs/doc/PhraseParser/Operator.html +4 -4
  98. data/docs/doc/PhraseParser/PhraseClause.html +5 -5
  99. data/docs/doc/PhraseParser/Query.html +10 -10
  100. data/docs/doc/PhraseParser/QueryParser.html +2 -2
  101. data/docs/doc/PhraseParser/QueryTransformer.html +2 -2
  102. data/docs/doc/PhraseParser/TermClause.html +5 -5
  103. data/docs/doc/PhraseParser.html +1 -1
  104. data/docs/doc/Status.html +7 -7
  105. data/docs/doc/String.html +306 -3111
  106. data/docs/doc/Symbol.html +45 -11
  107. data/docs/doc/Time.html +6 -6
  108. data/docs/doc/TrueClass.html +235 -0
  109. data/docs/doc/_index.html +37 -19
  110. data/docs/doc/class_list.html +1 -1
  111. data/docs/doc/file.README.html +2 -2
  112. data/docs/doc/index.html +2 -2
  113. data/docs/doc/method_list.html +240 -576
  114. data/docs/doc/top-level-namespace.html +2 -2
  115. data/doing.rdoc +297 -169
  116. data/example_plugin.rb +2 -2
  117. data/lib/completion/_doing.zsh +35 -31
  118. data/lib/completion/doing.bash +30 -19
  119. data/lib/completion/doing.fish +81 -67
  120. data/lib/doing/array/array.rb +4 -0
  121. data/lib/doing/array/nested_hash.rb +17 -0
  122. data/lib/doing/{array.rb → array/tags.rb} +7 -25
  123. data/lib/doing/changelog/change.rb +26 -11
  124. data/lib/doing/changelog/changes.rb +16 -4
  125. data/lib/doing/{array_chronify.rb → chronify/array.rb} +0 -0
  126. data/lib/doing/chronify/chronify.rb +5 -0
  127. data/lib/doing/{numeric_chronify.rb → chronify/numeric.rb} +0 -0
  128. data/lib/doing/{string_chronify.rb → chronify/string.rb} +0 -0
  129. data/lib/doing/colors.rb +115 -54
  130. data/lib/doing/configuration.rb +9 -6
  131. data/lib/doing/good.rb +72 -0
  132. data/lib/doing/hash.rb +4 -0
  133. data/lib/doing/help_monkey_patch.rb +6 -5
  134. data/lib/doing/hooks.rb +3 -3
  135. data/lib/doing/item.rb +19 -15
  136. data/lib/doing/items.rb +2 -2
  137. data/lib/doing/log_adapter.rb +35 -2
  138. data/lib/doing/normalize.rb +188 -0
  139. data/lib/doing/pager.rb +1 -0
  140. data/lib/doing/plugins/export/dayone_export.rb +1 -1
  141. data/lib/doing/plugins/export/html_export.rb +1 -1
  142. data/lib/doing/plugins/export/json_export.rb +1 -1
  143. data/lib/doing/plugins/export/markdown_export.rb +1 -1
  144. data/lib/doing/plugins/export/template_export.rb +3 -1
  145. data/lib/doing/plugins/import/calendar_import.rb +1 -1
  146. data/lib/doing/plugins/import/doing_import.rb +1 -1
  147. data/lib/doing/plugins/import/timing_import.rb +1 -1
  148. data/lib/doing/prompt.rb +9 -3
  149. data/lib/doing/string/highlight.rb +95 -0
  150. data/lib/doing/string/query.rb +129 -0
  151. data/lib/doing/string/string.rb +12 -0
  152. data/lib/doing/string/tags.rb +164 -0
  153. data/lib/doing/string/transform.rb +168 -0
  154. data/lib/doing/string/truncate.rb +75 -0
  155. data/lib/doing/string/url.rb +82 -0
  156. data/lib/doing/template_string.rb +2 -24
  157. data/lib/doing/types.rb +9 -0
  158. data/lib/doing/util.rb +20 -16
  159. data/lib/doing/version.rb +1 -1
  160. data/lib/doing/wwid.rb +91 -51
  161. data/lib/doing.rb +5 -6
  162. data/lib/examples/commands/wiki.rb +6 -7
  163. data/lib/examples/plugins/wiki_export/wiki_export.rb +1 -1
  164. data/lib/helpers/threaded_tests.rb +69 -79
  165. data/lib/helpers/threaded_tests_string.rb +50 -0
  166. data/scripts/deploy.rb +107 -0
  167. data/scripts/runtests.sh +4 -0
  168. metadata +65 -8
  169. data/lib/doing/string.rb +0 -765
  170. data/lib/doing/symbol.rb +0 -28
data/Dockerfile CHANGED
@@ -1,9 +1,9 @@
1
1
  FROM ruby:3.0.1
2
- RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
2
+ # RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
3
3
  RUN mkdir /doing
4
4
  WORKDIR /doing
5
- COPY ./ /doing/
5
+ # COPY ./ /doing/
6
6
  RUN gem install bundler:2.2.17
7
- # RUN bundle update --bundler
8
- RUN bundle install
9
- CMD ["rake", "parallel:test"]
7
+ RUN apt-get update -y
8
+ RUN apt-get install -y less
9
+ CMD ["scripts/runtests.sh"]
data/Dockerfile-2.6 CHANGED
@@ -1,9 +1,9 @@
1
1
  FROM ruby:2.6
2
+ # RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
2
3
  RUN mkdir /doing
3
4
  WORKDIR /doing
4
- COPY ./ /doing/
5
+ # COPY ./ /doing/
5
6
  RUN gem install bundler:2.2.17
6
- # RUN bundle update --bundler
7
- RUN bundle install
8
- # ENTRYPOINT rake parallel:test
9
- CMD ["rake", "parallel:test"]
7
+ RUN apt-get update -y
8
+ RUN apt-get install -y less
9
+ CMD ["scripts/runtests.sh"]
data/Dockerfile-2.7 CHANGED
@@ -1,8 +1,9 @@
1
1
  FROM ruby:2.7
2
+ RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
2
3
  RUN mkdir /doing
3
4
  WORKDIR /doing
4
- COPY ./ /doing/
5
+ # COPY ./ /doing/
5
6
  RUN gem install bundler:2.2.17
6
- # RUN bundle update --bundler
7
- RUN bundle install
8
- CMD ["rake", "parallel:test"]
7
+ RUN apt-get update -y
8
+ RUN apt-get install -y less
9
+ CMD ["scripts/runtests.sh"]
data/Dockerfile-3.0 CHANGED
@@ -1,8 +1,9 @@
1
1
  FROM ruby:3.0.0
2
+ # RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
2
3
  RUN mkdir /doing
3
4
  WORKDIR /doing
4
- COPY ./ /doing/
5
+ # COPY ./ /doing/
5
6
  RUN gem install bundler:2.2.17
6
- # RUN bundle update --bundler
7
- RUN bundle install
8
- CMD ["rake", "parallel:test"]
7
+ RUN apt-get update -y
8
+ RUN apt-get install -y less
9
+ CMD ["scripts/runtests.sh"]
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- doing (2.1.24)
4
+ doing (2.1.28)
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.22<!--END VER-->.
11
+ The current version of `doing` is <!--VER-->2.1.27<!--END VER-->.
12
12
 
13
13
  Find all of the documentation in the [doing wiki][wiki].
14
14
 
data/Rakefile CHANGED
@@ -77,14 +77,14 @@ task :dockertest, :version, :login do |_, args|
77
77
  file = 'Dockerfile'
78
78
  end
79
79
 
80
- exec "docker run -it #{img} /bin/bash -l" if args[:login]
81
-
82
80
  puts `docker build . --file #{file} -t #{img}`
83
81
 
82
+ exec "docker run -v #{File.dirname(__FILE__)}:/doing -it #{img} /bin/bash -l" if args[:login]
83
+
84
84
  spinner = TTY::Spinner.new('[:spinner] Running tests ...', hide_cursor: true)
85
85
 
86
86
  spinner.auto_spin
87
- res = `docker run --rm -it #{img}`
87
+ res = `docker run --rm -v #{File.dirname(__FILE__)}:/doing -it #{img}`
88
88
  # commit = puts `bash -c "docker commit $(docker ps -a|grep #{img}|awk '{print $1}'|head -n 1) #{img}"`.strip
89
89
  spinner.success
90
90
  spinner.stop
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @@add_section
4
+ desc 'Add a new section to the "doing" file'
5
+ arg_name 'SECTION_NAME'
6
+ command :add_section do |c|
7
+ c.example 'doing add_section Ideas', desc: 'Add a section called Ideas to the doing file'
8
+
9
+ c.action do |_global_options, _options, args|
10
+ raise InvalidArgument, "Section #{args[0]} already exists" if @wwid.sections.include?(args[0])
11
+
12
+ @wwid.content.add_section(args.join(' ').cap_first, log: true)
13
+ @wwid.write(@wwid.doing_file)
14
+ end
15
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @@again @@resume
4
+ desc 'Repeat last entry as new entry'
5
+ long_desc 'This command is designed to allow multiple time intervals to be created
6
+ for an entry by duplicating it with a new start (and end, eventually) time'
7
+ command %i[again resume] do |c|
8
+ c.example 'doing resume',
9
+ desc: 'Duplicate the most recent entry with a new start time, removing any @done tag'
10
+ c.example 'doing again',
11
+ desc: 'again is an alias for resume'
12
+ c.example 'doing resume --editor',
13
+ desc: 'Repeat the last entry, opening the new entry in the default editor'
14
+ c.example 'doing resume --tag project1 --in Projects',
15
+ desc: 'Repeat the last entry tagged @project1, creating the new entry in the Projects section'
16
+ c.example 'doing resume --interactive', desc: 'Select the entry to repeat from a menu'
17
+
18
+ c.desc 'Get last entry from a specific section'
19
+ c.arg_name 'NAME'
20
+ c.flag %i[s section], default_value: 'All'
21
+
22
+ c.desc 'Add new entry to section (default: same section as repeated entry)'
23
+ c.arg_name 'SECTION_NAME'
24
+ c.flag [:in]
25
+
26
+ c.desc 'Select item to resume from a menu of matching entries'
27
+ c.switch %i[i interactive], negatable: false, default_value: false
28
+
29
+ add_options(:add_entry, c)
30
+ add_options(:search, c)
31
+ add_options(:tag_filter, c)
32
+
33
+ c.action do |_global_options, options, _args|
34
+ options[:fuzzy] = false
35
+
36
+ if options[:search]
37
+ options[:search] = options[:exact] ? options[:search].sub(/^'?/, "'") : options[:search]
38
+ end
39
+
40
+ if options[:back]
41
+ options[:date] = options[:back]
42
+ raise InvalidTimeExpression, 'Unable to parse date string for --back' if date.nil?
43
+
44
+ else
45
+ options[:date] = Time.now
46
+ end
47
+
48
+ note = Doing::Note.new(options[:note])
49
+ note.add(Doing::Prompt.read_lines(prompt: 'Add a note')) if options[:ask]
50
+
51
+ options[:note] = note
52
+ options[:tag] ||= []
53
+ options[:tag_bool] = options[:bool]
54
+
55
+ @wwid.repeat_last(options)
56
+ end
57
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @@archive @@move
4
+ desc 'Move entries between sections'
5
+ long_desc %(Argument can be a section name to move all entries from a section,
6
+ or start with an "@" to move entries matching a tag.
7
+
8
+ Default with no argument moves items from the "#{@settings['current_section']}" section to Archive.)
9
+ arg_name 'SECTION_OR_TAG'
10
+ default_value @settings['current_section']
11
+ command %i[archive move] do |c|
12
+ c.example 'doing archive Currently', desc: 'Move all entries in the Currently section to Archive section'
13
+ c.example 'doing archive @done', desc: 'Move all entries tagged @done to Archive'
14
+ c.example 'doing archive --to Later @project1', desc: 'Move all entries tagged @project1 to Later section'
15
+ c.example 'doing move Later --tag project1 --to Currently',
16
+ desc: 'Move entries in Later tagged @project1 to Currently (move is an alias for archive)'
17
+
18
+ c.desc 'How many items to keep (ignored if archiving by tag or search)'
19
+ c.arg_name 'X'
20
+ c.flag %i[k keep], must_match: /^\d+$/, type: Integer
21
+
22
+ c.desc 'Move entries to'
23
+ c.arg_name 'SECTION_NAME'
24
+ c.flag %i[t to], default_value: 'Archive'
25
+
26
+ c.desc 'Label moved items with @from(SECTION_NAME)'
27
+ c.switch [:label], default_value: true, negatable: true
28
+
29
+ add_options(:search, c)
30
+ add_options(:tag_filter, c)
31
+ add_options(:date_filter, c)
32
+
33
+ c.action do |_global_options, options, args|
34
+ options[:fuzzy] = false
35
+ section, tags = if args.empty?
36
+ [@settings['current_section'], []]
37
+ elsif args[0] =~ /^all/i
38
+ ['all', []]
39
+ elsif args[0] =~ /^@\S+/
40
+ ['all', args.tags_to_array]
41
+ else
42
+ [args.shift.cap_first, args.tags_to_array]
43
+ end
44
+
45
+ raise InvalidArgument, '--keep and --count can not be used together' if options[:keep] && options[:count]
46
+
47
+ tags.concat(options[:tag]) if options[:tag]
48
+
49
+ options[:search] = options[:search].sub(/^'?/, "'") if options[:search] && options[:exact]
50
+ options[:destination] = options[:to]
51
+ options[:tags] = tags
52
+
53
+ @wwid.archive(section, options)
54
+ end
55
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @@cancel
4
+ desc 'End last X entries with no time tracked'
5
+ long_desc 'Adds @done tag without datestamp so no elapsed time is recorded.
6
+ Alias for `doing finish --no-date`'
7
+ arg_name 'COUNT'
8
+ command :cancel do |c|
9
+ c.example 'doing cancel', desc: 'Cancel the last entry'
10
+ c.example 'doing cancel --tag project1 -u 5', desc: 'Cancel the last 5 unfinished entries containing @project1'
11
+
12
+ c.desc 'Archive entries'
13
+ c.switch %i[a archive], negatable: false, default_value: false
14
+
15
+ c.desc 'Section'
16
+ c.arg_name 'NAME'
17
+ c.flag %i[s section]
18
+
19
+ c.desc 'Cancel last entry (or entries) not already marked @done'
20
+ c.switch %i[u unfinished], negatable: false, default_value: false
21
+
22
+ c.desc 'Select item(s) to cancel from a menu of matching entries'
23
+ c.switch %i[i interactive], negatable: false, default_value: false
24
+
25
+ add_options(:search, c)
26
+ add_options(:tag_filter, c)
27
+
28
+ c.action do |_global_options, options, args|
29
+ options[:fuzzy] = false
30
+ options[:section] = if options[:section]
31
+ @wwid.guess_section(options[:section]) || options[:section].cap_first
32
+ else
33
+ @settings['current_section']
34
+ end
35
+
36
+ raise InvalidArgument, 'Only one argument allowed' if args.length > 1
37
+
38
+ unless args.empty? || args[0] =~ /\d+/
39
+ raise InvalidArgument, 'Invalid argument (specify number of recent items to mark @done)'
40
+
41
+ end
42
+
43
+ options[:count] = if options[:interactive]
44
+ 0
45
+ else
46
+ args[0] ? args[0].to_i : 1
47
+ end
48
+
49
+ options[:search] = options[:search].sub(/^'?/, "'") if options[:search] && options[:exact]
50
+
51
+ options[:case] = options[:case].normalize_case
52
+ options[:date] = false
53
+ options[:sequential] = false
54
+ options[:tag] ||= []
55
+ options[:tag_bool] = options[:bool].normalize_bool
56
+ options[:tags] = ['done']
57
+
58
+ @wwid.tag_last(options)
59
+ end
60
+ end
@@ -0,0 +1,73 @@
1
+ # @@changelog @@changes
2
+
3
+ MARKDOWN_THEME = {
4
+ em: %i[white dark],
5
+ header: %i[cyan bold],
6
+ hr: :yellow,
7
+ link: %i[bright_cyan underline],
8
+ list: :yellow,
9
+ strong: %i[yellow bold],
10
+ table: :yellow,
11
+ quote: :yellow,
12
+ image: :bright_black,
13
+ note: :yellow,
14
+ comment: :bright_black
15
+ }.deep_freeze
16
+
17
+ CHANGE_RX = /^(?:(?:(?:[<>=]|p(?:rior)|b(?:efore)|o(?:lder)|s(?:ince)|a(?:fter)|n(?:ewer))? *[\d.*?]+ *)+|(?:[\d.]+ *-+ *[\d.]+))$/
18
+
19
+ desc 'List recent changes in Doing'
20
+ long_desc %(Display a formatted list of changes in recent versions.
21
+
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
27
+
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.)
31
+ c.arg_name 'VERSION'
32
+ c.flag %i[l lookup], must_match: CHANGE_RX
33
+
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]
37
+
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
41
+
42
+ c.desc 'Only output changes, no version numbers, headers, or dates'
43
+ c.switch %i[C changes], default_value: false, negatable: false
44
+
45
+ c.desc 'Output raw Markdown'
46
+ c.switch %i[m md markdown], default_value: false, negatable: false
47
+
48
+ c.example 'doing changes', desc: 'View changes in the current version'
49
+ c.example 'doing changes --all', desc: 'See the entire changelog'
50
+ c.example 'doing changes --lookup 2.0.21', desc: 'See changes from version 2.0.21'
51
+ c.example 'doing changes --lookup "> 2.1"', desc: 'See all changes since 2.1.0'
52
+ c.example 'doing changes --search "tags +bool"', desc: 'See all changes containing "tags" and "bool"'
53
+ c.example 'doing changes -l "> 2.1" -s "pattern"', desc: 'Lookup and search can be combined'
54
+
55
+ c.action do |_global_options, options, _args|
56
+ cl = Doing::Changes.new(lookup: options[:lookup], search: options[:search], changes: options[:changes], sort: options[:sort])
57
+
58
+ content = if options[:all] || options[:search] || options[:lookup]
59
+ cl.to_s
60
+ else
61
+ cl.latest
62
+ end
63
+
64
+ parsed = if options[:markdown] || !$stdout.isatty
65
+ content
66
+ else
67
+ TTY::Markdown.parse(content, width: 80, theme: MARKDOWN_THEME, symbols: { override: { bullet: '•' } })
68
+ end
69
+
70
+ Doing::Pager.paginate = true
71
+ Doing::Pager.page parsed
72
+ end
73
+ 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,21 @@
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
+ colname = color.to_s
9
+ colname << " (#{color.to_s.sub(/bold/, 'bright')})" if colname =~ /bold/
10
+ if color.to_s =~ /bg/
11
+ bgs.push("#{@colors.send(color, " ")}#{@colors.default} <-- #{colname}")
12
+ else
13
+ fgs.push("#{@colors.send(color, "XXXX")}#{@colors.default} <-- #{colname}")
14
+ end
15
+ end
16
+ out = []
17
+ out << fgs.join("\n")
18
+ out << bgs.join("\n")
19
+ Doing::Pager.page out.join("\n")
20
+ end
21
+ end
@@ -0,0 +1,89 @@
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)
31
+ end
32
+ raise UserCancelled unless to_enable
33
+
34
+ to_enable.strip.split("\n").each do |cmd|
35
+ default_command = File.join(File.dirname(__FILE__), "#{cmd}.rb")
36
+ custom_command = File.join(File.expand_path(custom_dir), "#{cmd}.rb")
37
+ unless File.exist?(default_command) || File.exist?(custom_command)
38
+ raise InvalidArgument, "Command #{cmd} not found"
39
+ end
40
+
41
+ raise InvalidArgument, "Command #{cmd} is not disabled" unless available.include?(cmd)
42
+
43
+ available.delete(cmd)
44
+ end
45
+
46
+ cfg.deep_set(['disabled_commands'], available)
47
+
48
+ Doing::Util.write_to_file(@config.config_file, YAML.dump(cfg), backup: true)
49
+ Doing.logger.warn('Config:', "#{@config.config_file} updated")
50
+ end
51
+ end
52
+
53
+ # @@commands.disable
54
+ c.desc 'Disable Doing commands'
55
+ c.command %i[remove disable] do |remove|
56
+ remove.action do |_global, _options, args|
57
+ available = Dir.glob(File.join(File.dirname(__FILE__), '*.rb')).map { |cmd| File.basename(cmd, '.rb') }
58
+ cfg = @settings
59
+ custom_dir = @settings.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(@config.config_file, YAML.dump(cfg), backup: true)
86
+ Doing.logger.warn('Config:', "#{@config.config_file} updated")
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @@commands_accepting
4
+ arg_name 'OPTION'
5
+ command :commands_accepting do |c|
6
+ c.desc 'Output in single column for completion'
7
+ c.switch %i[c column]
8
+
9
+ c.desc 'Join multiple arguments using boolean (AND|OR|NOT)'
10
+ c.flag [:bool], must_match: REGEX_BOOL,
11
+ default_value: :and,
12
+ type: BooleanSymbol
13
+
14
+ c.action do |g, o, a|
15
+ cmds = []
16
+ commands.each { |cmd, v| cmds.push(cmd) if has_flags?(v, a, o[:bool]) }
17
+
18
+ if o[:column]
19
+ puts cmds.sort
20
+ else
21
+ description = "Commands "
22
+ description += "not " if o[:bool] == :not
23
+ description += "accepting "
24
+ description += a.map { |arg| "--#{arg}" }.join(o[:bool] == :and ? ' and ' : ' or ')
25
+ puts "#{description}: #{cmds.sort.join(', ')}"
26
+ end
27
+ 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
+ end
75
+
76
+
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @@completion
4
+ desc 'Generate shell completion scripts'
5
+ long_desc 'Generates the necessary scripts to add command line completion to various shells,
6
+ so typing \'doing\' and hitting tab will offer completions of subcommands and their options.'
7
+ command :completion do |c|
8
+ c.example 'doing completion', desc: 'Output zsh (default) to STDOUT'
9
+ c.example 'doing completion --type zsh --file ~/.zsh-completions/_doing.zsh',
10
+ desc: 'Output zsh completions to file'
11
+ c.example 'doing completion --type fish --file ~/.config/fish/completions/doing.fish',
12
+ desc: 'Output fish completions to file'
13
+ c.example 'doing completion --type bash --file ~/.bash_it/completion/enabled/doing.bash',
14
+ desc: 'Output bash completions to file'
15
+
16
+ c.desc 'Shell to generate for (bash, zsh, fish)'
17
+ c.arg_name 'SHELL'
18
+ c.flag %i[t type], must_match: /^(?:[bzf](?:[ai]?sh)?|all)$/i, default_value: 'zsh'
19
+
20
+ c.desc 'File to write output to'
21
+ c.arg_name 'PATH'
22
+ c.flag %i[f file], default_value: 'STDOUT'
23
+
24
+ c.action do |_global_options, options, _args|
25
+ Doing::Completion.generate_completion(type: options[:type], file: options[:file])
26
+ end
27
+ end