doing 2.1.25 → 2.1.29

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 (163) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +15 -20
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +322 -108
  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 +2 -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 +83 -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 -3706
  55. data/docs/doc/Array.html +3 -502
  56. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  57. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  58. data/docs/doc/BooleanTermParser/Query.html +1 -1
  59. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  60. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  61. data/docs/doc/BooleanTermParser.html +1 -1
  62. data/docs/doc/Doing/Color.html +62 -56
  63. data/docs/doc/Doing/Completion.html +1 -1
  64. data/docs/doc/Doing/Configuration.html +36 -1
  65. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  66. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  67. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  68. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  69. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  70. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  71. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  72. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  73. data/docs/doc/Doing/Errors.html +1 -1
  74. data/docs/doc/Doing/Hooks.html +1 -1
  75. data/docs/doc/Doing/Item.html +1 -1
  76. data/docs/doc/Doing/Items.html +2 -2
  77. data/docs/doc/Doing/LogAdapter.html +1 -1
  78. data/docs/doc/Doing/Note.html +2 -2
  79. data/docs/doc/Doing/Pager.html +1 -1
  80. data/docs/doc/Doing/Plugins.html +1 -1
  81. data/docs/doc/Doing/Prompt.html +46 -1
  82. data/docs/doc/Doing/Section.html +1 -1
  83. data/docs/doc/Doing/TemplateString.html +2 -2
  84. data/docs/doc/Doing/Types.html +41 -1
  85. data/docs/doc/Doing/Util/Backup.html +1 -1
  86. data/docs/doc/Doing/Util.html +1 -1
  87. data/docs/doc/Doing/WWID.html +10 -10
  88. data/docs/doc/Doing.html +3 -3
  89. data/docs/doc/FalseClass.html +235 -0
  90. data/docs/doc/GLI/Commands/Help.html +1 -1
  91. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  92. data/docs/doc/GLI/Commands.html +1 -1
  93. data/docs/doc/GLI.html +1 -1
  94. data/docs/doc/Hash.html +1 -1
  95. data/docs/doc/Numeric.html +1 -1
  96. data/docs/doc/Object.html +203 -0
  97. data/docs/doc/PhraseParser/Operator.html +1 -1
  98. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  99. data/docs/doc/PhraseParser/Query.html +1 -1
  100. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  101. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  102. data/docs/doc/PhraseParser/TermClause.html +1 -1
  103. data/docs/doc/PhraseParser.html +1 -1
  104. data/docs/doc/Status.html +1 -1
  105. data/docs/doc/String.html +287 -3155
  106. data/docs/doc/Symbol.html +40 -6
  107. data/docs/doc/Time.html +1 -1
  108. data/docs/doc/TrueClass.html +235 -0
  109. data/docs/doc/_index.html +5 -10
  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 +289 -681
  114. data/docs/doc/top-level-namespace.html +2 -2
  115. data/doing.rdoc +306 -205
  116. data/lib/completion/_doing.zsh +35 -35
  117. data/lib/completion/doing.bash +30 -30
  118. data/lib/completion/doing.fish +88 -78
  119. data/lib/doing/array/array.rb +4 -0
  120. data/lib/doing/array/nested_hash.rb +17 -0
  121. data/lib/doing/{array.rb → array/tags.rb} +7 -25
  122. data/lib/doing/changelog/change.rb +26 -11
  123. data/lib/doing/changelog/changes.rb +31 -4
  124. data/lib/doing/{array_chronify.rb → chronify/array.rb} +0 -0
  125. data/lib/doing/chronify/chronify.rb +5 -0
  126. data/lib/doing/{numeric_chronify.rb → chronify/numeric.rb} +0 -0
  127. data/lib/doing/{string_chronify.rb → chronify/string.rb} +0 -0
  128. data/lib/doing/colors.rb +115 -54
  129. data/lib/doing/configuration.rb +5 -0
  130. data/lib/doing/good.rb +8 -0
  131. data/lib/doing/help_monkey_patch.rb +6 -5
  132. data/lib/doing/item.rb +5 -5
  133. data/lib/doing/items.rb +2 -2
  134. data/lib/doing/log_adapter.rb +35 -2
  135. data/lib/doing/normalize.rb +188 -0
  136. data/lib/doing/pager.rb +1 -0
  137. data/lib/doing/plugins/export/dayone_export.rb +1 -1
  138. data/lib/doing/plugins/export/html_export.rb +1 -1
  139. data/lib/doing/plugins/export/json_export.rb +1 -1
  140. data/lib/doing/plugins/export/markdown_export.rb +1 -1
  141. data/lib/doing/plugins/export/template_export.rb +3 -1
  142. data/lib/doing/prompt.rb +9 -3
  143. data/lib/doing/string/highlight.rb +95 -0
  144. data/lib/doing/string/query.rb +129 -0
  145. data/lib/doing/string/string.rb +12 -0
  146. data/lib/doing/string/tags.rb +164 -0
  147. data/lib/doing/string/transform.rb +168 -0
  148. data/lib/doing/string/truncate.rb +75 -0
  149. data/lib/doing/string/url.rb +82 -0
  150. data/lib/doing/template_string.rb +0 -22
  151. data/lib/doing/types.rb +8 -0
  152. data/lib/doing/util.rb +13 -9
  153. data/lib/doing/version.rb +1 -1
  154. data/lib/doing/wwid.rb +53 -35
  155. data/lib/doing.rb +4 -6
  156. data/lib/examples/commands/wiki.rb +6 -7
  157. data/lib/examples/plugins/wiki_export/wiki_export.rb +1 -1
  158. data/lib/helpers/threaded_tests.rb +39 -20
  159. data/scripts/deploy.rb +107 -0
  160. data/scripts/runtests.sh +4 -0
  161. metadata +63 -8
  162. data/lib/doing/string.rb +0 -765
  163. 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.25)
4
+ doing (2.1.29)
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.28<!--END VER-->.
12
12
 
13
13
  Find all of the documentation in the [doing wiki][wiki].
14
14
 
data/Rakefile CHANGED
@@ -77,15 +77,14 @@ task :dockertest, :version, :login do |_, args|
77
77
  file = 'Dockerfile'
78
78
  end
79
79
 
80
-
81
80
  puts `docker build . --file #{file} -t #{img}`
82
81
 
83
- exec "docker run -it #{img} /bin/bash -l" if args[:login]
82
+ exec "docker run -v #{File.dirname(__FILE__)}:/doing -it #{img} /bin/bash -l" if args[:login]
84
83
 
85
84
  spinner = TTY::Spinner.new('[:spinner] Running tests ...', hide_cursor: true)
86
85
 
87
86
  spinner.auto_spin
88
- res = `docker run --rm -it #{img}`
87
+ res = `docker run --rm -v #{File.dirname(__FILE__)}:/doing -it #{img}`
89
88
  # commit = puts `bash -c "docker commit $(docker ps -a|grep #{img}|awk '{print $1}'|head -n 1) #{img}"`.strip
90
89
  spinner.success
91
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,83 @@
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.desc 'Force rendered output'
49
+ c.switch %i[render], default_value: false, negatable: false
50
+
51
+ c.desc 'Open changelog in interactive viewer'
52
+ c.switch %i[i interactive], default_value: false, negatable: false
53
+
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'
60
+
61
+ c.action do |_global_options, options, _args|
62
+ cl = Doing::Changes.new(lookup: options[:lookup], search: options[:search], changes: options[:changes], sort: options[:sort])
63
+
64
+ if options[:interactive]
65
+ cl.interactive
66
+ else
67
+ content = if options[:all] || options[:search] || options[:lookup]
68
+ cl.to_s
69
+ else
70
+ cl.latest
71
+ end
72
+
73
+ parsed = if (options[:markdown] || !$stdout.isatty) && !options[:render]
74
+ content
75
+ else
76
+ TTY::Markdown.parse(content, width: 80, theme: MARKDOWN_THEME, symbols: { override: { bullet: '•' } })
77
+ end
78
+
79
+ Doing::Pager.paginate = true
80
+ Doing::Pager.page parsed
81
+ end
82
+ end
83
+ 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