doing 2.1.18 → 2.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +19 -16
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +121 -53
  6. data/Gemfile.lock +11 -11
  7. data/README.md +1 -1
  8. data/Rakefile +12 -4
  9. data/bin/doing +297 -234
  10. data/docs/doc/Array.html +7 -30
  11. data/docs/doc/BooleanTermParser/Clause.html +3 -3
  12. data/docs/doc/BooleanTermParser/Operator.html +3 -3
  13. data/docs/doc/BooleanTermParser/Query.html +3 -3
  14. data/docs/doc/BooleanTermParser/QueryParser.html +3 -3
  15. data/docs/doc/BooleanTermParser/QueryTransformer.html +3 -3
  16. data/docs/doc/BooleanTermParser.html +3 -3
  17. data/docs/doc/Doing/Color.html +3 -3
  18. data/docs/doc/Doing/Completion.html +3 -3
  19. data/docs/doc/Doing/Configuration.html +6 -5
  20. data/docs/doc/Doing/Errors/DoingNoTraceError.html +3 -3
  21. data/docs/doc/Doing/Errors/DoingRuntimeError.html +3 -3
  22. data/docs/doc/Doing/Errors/DoingStandardError.html +3 -3
  23. data/docs/doc/Doing/Errors/EmptyInput.html +3 -3
  24. data/docs/doc/Doing/Errors/NoResults.html +3 -3
  25. data/docs/doc/Doing/Errors/PluginException.html +3 -3
  26. data/docs/doc/Doing/Errors/UserCancelled.html +3 -3
  27. data/docs/doc/Doing/Errors/WrongCommand.html +3 -3
  28. data/docs/doc/Doing/Errors.html +3 -3
  29. data/docs/doc/Doing/Hooks.html +3 -3
  30. data/docs/doc/Doing/Item.html +3 -3
  31. data/docs/doc/Doing/Items.html +3 -3
  32. data/docs/doc/Doing/LogAdapter.html +3 -3
  33. data/docs/doc/Doing/Note.html +3 -3
  34. data/docs/doc/Doing/Pager.html +3 -3
  35. data/docs/doc/Doing/Plugins.html +3 -3
  36. data/docs/doc/Doing/Prompt.html +7 -7
  37. data/docs/doc/Doing/Section.html +3 -3
  38. data/docs/doc/Doing/TemplateString.html +4 -4
  39. data/docs/doc/Doing/Types.html +201 -0
  40. data/docs/doc/Doing/Util/Backup.html +3 -3
  41. data/docs/doc/Doing/Util.html +4 -7
  42. data/docs/doc/Doing/WWID.html +66 -8
  43. data/docs/doc/Doing.html +6 -6
  44. data/docs/doc/GLI/Commands/Help.html +185 -0
  45. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +3 -3
  46. data/docs/doc/GLI/Commands.html +7 -5
  47. data/docs/doc/GLI.html +6 -4
  48. data/docs/doc/Hash.html +80 -16
  49. data/docs/doc/Numeric.html +3 -3
  50. data/docs/doc/PhraseParser/Operator.html +3 -3
  51. data/docs/doc/PhraseParser/PhraseClause.html +3 -3
  52. data/docs/doc/PhraseParser/Query.html +3 -3
  53. data/docs/doc/PhraseParser/QueryParser.html +3 -3
  54. data/docs/doc/PhraseParser/QueryTransformer.html +3 -3
  55. data/docs/doc/PhraseParser/TermClause.html +3 -3
  56. data/docs/doc/PhraseParser.html +3 -3
  57. data/docs/doc/Status.html +3 -3
  58. data/docs/doc/String.html +195 -26
  59. data/docs/doc/Symbol.html +3 -3
  60. data/docs/doc/Time.html +3 -3
  61. data/docs/doc/_index.html +22 -8
  62. data/docs/doc/class_list.html +1 -1
  63. data/docs/doc/file.README.html +4 -4
  64. data/docs/doc/frames.html +1 -1
  65. data/docs/doc/index.html +4 -4
  66. data/docs/doc/method_list.html +334 -270
  67. data/docs/doc/top-level-namespace.html +3 -3
  68. data/docs/index.md +1 -1
  69. data/doing.gemspec +1 -1
  70. data/doing.rdoc +173 -15
  71. data/lib/completion/_doing.zsh +20 -20
  72. data/lib/completion/doing.bash +37 -26
  73. data/lib/completion/doing.fish +114 -16
  74. data/lib/doing/array.rb +5 -4
  75. data/lib/doing/array_chronify.rb +4 -3
  76. data/lib/doing/changelog/change.rb +115 -0
  77. data/lib/doing/changelog/changes.rb +73 -0
  78. data/lib/doing/changelog/entry.rb +21 -0
  79. data/lib/doing/changelog/version.rb +97 -0
  80. data/lib/doing/changelog.rb +6 -0
  81. data/lib/doing/completion/fish_completion.rb +80 -11
  82. data/lib/doing/configuration.rb +17 -8
  83. data/lib/doing/hash.rb +25 -6
  84. data/lib/doing/help_monkey_patch.rb +31 -0
  85. data/lib/doing/hooks.rb +5 -1
  86. data/lib/doing/item.rb +10 -25
  87. data/lib/doing/items.rb +3 -1
  88. data/lib/doing/log_adapter.rb +1 -1
  89. data/lib/doing/pager.rb +2 -2
  90. data/lib/doing/plugins/export/dayone_export.rb +1 -1
  91. data/lib/doing/plugins/export/markdown_export.rb +1 -1
  92. data/lib/doing/plugins/export/template_export.rb +9 -3
  93. data/lib/doing/prompt.rb +4 -2
  94. data/lib/doing/string.rb +44 -12
  95. data/lib/doing/string_chronify.rb +56 -18
  96. data/lib/doing/template_string.rb +7 -0
  97. data/lib/doing/types.rb +25 -0
  98. data/lib/doing/util.rb +2 -1
  99. data/lib/doing/version.rb +1 -1
  100. data/lib/doing/wwid.rb +93 -69
  101. data/lib/doing.rb +2 -0
  102. data/lib/examples/commands/later.rb +32 -0
  103. data/lib/helpers/threaded_tests.rb +286 -0
  104. metadata +17 -6
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Example command that calls an existing command (tag) with
4
+ # preset options
5
+ desc 'Add an item to the Later section'
6
+ arg_name 'ENTRY'
7
+ command :later do |c|
8
+ c.example 'doing later "Something I\'ll think about tomorrow"', desc: 'Add an entry to the Later section'
9
+ c.example 'doing later -e', desc: 'Open $EDITOR to create an entry and optional note'
10
+
11
+ c.desc "Edit entry with #{Doing::Util.default_editor}"
12
+ c.switch %i[e editor], negatable: false, default_value: false
13
+
14
+ c.desc 'Backdate start time to date string [4pm|20m|2h|yesterday noon]'
15
+ c.arg_name 'DATE_STRING'
16
+ c.flag %i[b back started], type: DateBeginString
17
+
18
+ c.desc 'Note'
19
+ c.arg_name 'TEXT'
20
+ c.flag %i[n note]
21
+
22
+ c.desc 'Prompt for note via multi-line input'
23
+ c.switch %i[ask], negatable: false, default_value: false
24
+
25
+ c.action do |global_options, options, args|
26
+ cmd = commands[:now]
27
+ options[:section] = 'Later'
28
+ options[:finish_last] = false
29
+ action = cmd.send(:get_action, nil)
30
+ action.call(global_options, options, args)
31
+ end
32
+ end
@@ -0,0 +1,286 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tty-spinner'
4
+ require 'tty-progressbar'
5
+ require './lib/doing'
6
+ require 'open3'
7
+ require 'shellwords'
8
+
9
+ class ::String
10
+ include Doing::Color
11
+
12
+ def highlight_errors
13
+ cols = `tput cols`.strip.to_i
14
+
15
+ string = dup
16
+
17
+ errs = string.scan(/(?<==\n)(?:Failure|Error):.*?(?=\n=+)/m)
18
+
19
+ errs.map! do |error|
20
+ err = error.dup
21
+
22
+ err.gsub!(%r{^(/.*?/)([^/:]+):(\d+):in (.*?)$}) do
23
+ m = Regexp.last_match
24
+ "#{m[1].white}#{m[2].bold.white}:#{m[3].yellow}:in #{m[4].cyan}"
25
+ end
26
+ err.gsub!(/(Failure|Error): (.*?)\((.*?)\):\n (.*?)(?=\n)/m) do
27
+ m = Regexp.last_match
28
+ [
29
+ m[1].bold.boldbgred.white,
30
+ m[3].bold.boldbgcyan.white,
31
+ m[2].bold.boldbgyellow.black,
32
+ " #{m[4]} ".bold.boldbgwhite.black.reset
33
+ ].join(':'.boldblack.boldbgblack.reset)
34
+ end
35
+ err.gsub!(/(<.*?>) (was expected to) (.*?)\n( *<.*?>)./m) do
36
+ m = Regexp.last_match
37
+ "#{m[1].bold.green} #{m[2].white} #{m[3].boldwhite.boldbgred.reset}\n#{m[4].bold.white}"
38
+ end
39
+ err.gsub!(/(Finished in) ([\d.]+) (seconds)/) do
40
+ m = Regexp.last_match
41
+ "#{m[1].green} #{m[2].bold.white} #{m[3].green}"
42
+ end
43
+ err.gsub!(/(\d+) (failures)/) do
44
+ m = Regexp.last_match
45
+ "#{m[1].bold.red} #{m[2].red}"
46
+ end
47
+ err.gsub!(/100% passed/) do |m|
48
+ m.bold.green
49
+ end
50
+
51
+ err
52
+ end
53
+
54
+ errs.join("\n#{('=' * cols).blue}\n")
55
+ end
56
+ end
57
+
58
+ class ThreadedTests
59
+ include Doing::Color
60
+
61
+ def run(pattern: '*', max_threads: 8, max_tests: 0)
62
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
63
+
64
+ max_threads = 1000 if max_threads == 0
65
+
66
+ c = Doing::Color
67
+ c.coloring = true
68
+
69
+ pattern = "test/doing_*#{pattern}*_test.rb"
70
+
71
+ tests = Dir.glob(pattern)
72
+
73
+ if max_tests > 0
74
+ tests = tests.slice(0, max_tests - 1)
75
+ end
76
+
77
+ puts "#{tests.count} test files".boldcyan
78
+
79
+ banner = [
80
+ 'Running tests '.bold.white,
81
+ '['.black,
82
+ ':bar'.boldcyan,
83
+ '] '.black,
84
+ 'T'.green,
85
+ '/'.white,
86
+ 'A'.cyan,
87
+ ' ('.white,
88
+ max_threads.to_s.bold.magenta,
89
+ ' threads)'.white
90
+ ].join('')
91
+ progress = TTY::ProgressBar::Multi.new(banner,
92
+ width: 12,
93
+ hide_cursor: true)
94
+ @children = []
95
+ tests.each do |t|
96
+ test_name = File.basename(t, '.rb').sub(/doing_(.*?)_test/, '\1')
97
+ new_sp = progress.register("[#{':bar'.cyan}] #{test_name.bold.white}:status",
98
+ total: 4, width: 1, head: ' ', unknown: ' ', hide_cursor: true, clear: true)
99
+ @children.push([test_name, new_sp, nil])
100
+ end
101
+
102
+ @elapsed = 0.0
103
+ @test_total = 0
104
+ @assrt_total = 0
105
+ @error_out = []
106
+ # progress.start
107
+ @threads = []
108
+ @running_tests = []
109
+
110
+ begin
111
+ while @children.count.positive?
112
+
113
+ slices = @children.slice!(0, max_threads)
114
+ slices.each { |c| c[1].start }
115
+ slices.each do |s|
116
+ @threads << Thread.new do
117
+ run_test(s)
118
+ end
119
+ end
120
+
121
+ @threads.each { |t| t.join }
122
+ end
123
+
124
+ finish_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
125
+
126
+ progress.finish
127
+
128
+ output = []
129
+ if @error_out.count.positive?
130
+ output << c.boldred("#{@error_out.count} Issues")
131
+ else
132
+ output << c.green('Success')
133
+ end
134
+ output << c.green("#{@test_total} tests")
135
+ output << c.cyan("#{@assrt_total} assertions")
136
+ output << c.yellow("#{(finish_time - start_time).round(3)}s")
137
+ puts output.join(', ')
138
+
139
+ puts @error_out.join("\n----\n".boldwhite) if @error_out.count.positive?
140
+ rescue
141
+ progress.stop
142
+ end
143
+ end
144
+
145
+ def run_test(s)
146
+
147
+ bar = s[1]
148
+ bar.advance(status: ": #{'running'.green}")
149
+
150
+ if @running_tests.count.positive?
151
+ prev_bar = @running_tests[-1][1]
152
+ unless prev_bar.complete?
153
+ prev_bar.update(head: ' ', unfinished: ' ')
154
+ prev_bar.advance(status: ": #{'running'.green}")
155
+ end
156
+ end
157
+
158
+ @running_tests.push(s)
159
+
160
+
161
+ out, _err, status = Open3.capture3(ENV, 'rake', "test:#{s[0]}", stdin_data: nil)
162
+ unless status.success?
163
+ m = out.match(/(?<fail>\d+) failures, (?<err>\d+) errors/)
164
+ status = ": #{m['fail'].bold.red} #{'failures'.red}, #{m['err'].bold.red} #{'errors'.red}"
165
+ bar.update(head: '✖'.boldred)
166
+ bar.advance(head: '✖'.boldred, status: status)
167
+
168
+ # errs = out.scan(/(?:Failure|Error): [\w_]+\((?:.*?)\):(?:.*?)(?=\n=======)/m)
169
+ @error_out.push(out.highlight_errors)
170
+ bar.finish
171
+
172
+ next_test
173
+ Thread.exit
174
+ end
175
+
176
+ time = out.match(/^Finished in (?<time>\d+\.\d+) seconds\./)
177
+ count = out.match(/^(?<tests>\d+) tests, (?<assrt>\d+) assertions, (?<fails>\d+) failures, (?<errs>\d+) errors/)
178
+ status = [
179
+ ': ',
180
+ count['tests'].green,
181
+ '/',
182
+ count['assrt'].cyan,
183
+ # ' (',
184
+ # count['fails'].to_i == 0 ? '-'.dark.white.reset : count['fails'].bold.red,
185
+ # '/',
186
+ # count['errs'].to_i == 0 ? '-'.dark.white.reset : count['errs'].bold.red,
187
+ # ') ',
188
+ ' ',
189
+ time['time'].to_f.round(3).to_s.yellow,
190
+ 's'
191
+ ].join('')
192
+ bar.update(head: '✔'.boldgreen)
193
+ bar.advance(head: '✔'.boldgreen, status: status)
194
+ @test_total += count['tests'].to_i
195
+ @assrt_total += count['assrt'].to_i
196
+ @elapsed += time['time'].to_f
197
+
198
+ bar.finish
199
+
200
+ next_test
201
+ end
202
+
203
+ def next_test
204
+ if @children.count.positive?
205
+ t = Thread.new do
206
+ s = @children.shift
207
+ # s[1].start
208
+ # s[1].advance(status: ": #{'running'.green}")
209
+ run_test(s)
210
+ end
211
+
212
+ t.join
213
+ end
214
+ end
215
+ end
216
+
217
+
218
+ # require 'pastel'
219
+ ### Individual tests, multiple spinners
220
+ # pastel = Pastel.new
221
+ # format = "[#{pastel.yellow(':spinner')}] #{pastel.white("Running tests")} (#{pastel.green('tests')}/#{pastel.cyan('assertions')} #{pastel.yellow('time')})"
222
+ # spinners = TTY::Spinner::Multi.new(format, format: :dots, success_mark: pastel.green('✔'), error_mark: pastel.red('✖'))
223
+ # children = []
224
+ # tests = Dir.glob('test/doing_*_test.rb').each do |t|
225
+ # test_name = File.basename(t, '.rb').sub(/doing_(.*?)_test/, '\1')
226
+ # new_sp = spinners.register "[#{pastel.cyan(':spinner')}] #{test_name}:msg"
227
+ # new_sp.update(msg: '')
228
+ # children.push([test_name, new_sp])
229
+ # end
230
+
231
+ # @elapsed = 0.0
232
+ # @test_total = 0
233
+ # @assrt_total = 0
234
+ # spinners.auto_spin
235
+
236
+ # children.each do |spinner|
237
+ # spinner[1].run do |s|
238
+ # out, _err, status = Open3.capture3(ENV, 'rake', "test:#{spinner[0]}", stdin_data: nil)
239
+ # unless status.success?
240
+ # s.update(msg: "#{pastel.red('- FAILURE:')} #{pastel.bold.white(func)} in #{pastel.bold.yellow(tst)}")
241
+ # s.error
242
+ # s.stop
243
+ # puts `echo #{Shellwords.escape(out)} | colout '^(/.*?/)([^/:]+):(\d+):in (.*?)$' white,yellow,green,magenta | colout 'Failure: (.*?)\\((.*?)\\)' red,green | colout '(.*?) (was expected to be)' green,red | colout '(Finished in) ([\d.]+) (seconds)' green,white,green | colout '(\d+ failures)' red | colout '(100% passed)' green`
244
+ # Process.exit
245
+ # end
246
+
247
+ # time = out.match(/^Finished in (?<time>\d+\.\d+) seconds\./)
248
+ # count = out.match(/^(?<tests>\d+) tests, (?<assrt>\d+) assertions/)
249
+ # s.update(msg: ": #{pastel.green(count['tests'])}/#{pastel.cyan(count['assrt'])} #{pastel.yellow(time['time'].to_f.round(3))}s")
250
+ # @test_total += count['tests'].to_i
251
+ # @assrt_total += count['assrt'].to_i
252
+ # @elapsed += time['time'].to_f
253
+ # s.success
254
+ # end
255
+ # end
256
+
257
+ # output = []
258
+ # output << pastel.green('Success')
259
+ # output << pastel.green("#{@test_total} tests")
260
+ # output << pastel.cyan("#{@assrt_total} assertions")
261
+ # output << pastel.yellow("#{@elapsed.round(4)}s")
262
+ # puts output.join(', ')
263
+
264
+ ### Parallel test single spinner
265
+ # pastel = Pastel.new
266
+ # format = "[#{pastel.yellow(':spinner')}] #{pastel.white('Running parallel tests')} :msg"
267
+ # spinner = TTY::Spinner.new(format, format: :dots, success_mark: pastel.green('✔'), error_mark: pastel.red('✖'))
268
+
269
+ # spinner.run do |sp|
270
+ # sp.update(msg: '')
271
+ # out, err, status = Open3.capture3(ENV, 'rake', 'parallel:test', stdin_data: nil)
272
+
273
+ # unless status.success?
274
+ # failure = out.match(/^Failure: (.*?)\(([A-Z].*?)\)/)
275
+ # func = failure[1]
276
+ # tst = failure[2]
277
+ # sp.update(msg: "#{pastel.red('- FAILURE:')} #{pastel.bold.white(func)} in #{pastel.bold.yellow(tst)}")
278
+ # sp.error
279
+ # sp.stop
280
+ # puts `echo #{Shellwords.escape(out)} | colout '^(/.*?/)([^/:]+):(\d+):in (.*?)$' white,yellow,green,magenta | colout 'Failure: (.*?)\\((.*?)\\)' red,green | colout '(.*?) (was expected to be)' green,red | colout '(Finished in) ([\d.]+) (seconds)' green,white,green | colout '(\d+ failures)' red | colout '(100% passed)' green`
281
+ # Process.exit
282
+ # end
283
+
284
+ # sp.update(msg: pastel.green('- All tests passed'))
285
+ # sp.success
286
+ # end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doing
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.18
4
+ version: 2.1.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-18 00:00:00.000000000 Z
11
+ date: 2022-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: safe_yaml
@@ -212,20 +212,20 @@ dependencies:
212
212
  requirements:
213
213
  - - "~>"
214
214
  - !ruby/object:Gem::Version
215
- version: '2.19'
215
+ version: '2.20'
216
216
  - - ">="
217
217
  - !ruby/object:Gem::Version
218
- version: 2.19.2
218
+ version: 2.20.1
219
219
  type: :runtime
220
220
  prerelease: false
221
221
  version_requirements: !ruby/object:Gem::Requirement
222
222
  requirements:
223
223
  - - "~>"
224
224
  - !ruby/object:Gem::Version
225
- version: '2.19'
225
+ version: '2.20'
226
226
  - - ">="
227
227
  - !ruby/object:Gem::Version
228
- version: 2.19.2
228
+ version: 2.20.1
229
229
  - !ruby/object:Gem::Dependency
230
230
  name: haml
231
231
  requirement: !ruby/object:Gem::Requirement
@@ -490,12 +490,14 @@ files:
490
490
  - docs/doc/Doing/Prompt.html
491
491
  - docs/doc/Doing/Section.html
492
492
  - docs/doc/Doing/TemplateString.html
493
+ - docs/doc/Doing/Types.html
493
494
  - docs/doc/Doing/Util.html
494
495
  - docs/doc/Doing/Util/Backup.html
495
496
  - docs/doc/Doing/WWID.html
496
497
  - docs/doc/Doing/WWIDFile.html
497
498
  - docs/doc/GLI.html
498
499
  - docs/doc/GLI/Commands.html
500
+ - docs/doc/GLI/Commands/Help.html
499
501
  - docs/doc/GLI/Commands/MarkdownDocumentListener.html
500
502
  - docs/doc/Hash.html
501
503
  - docs/doc/Numeric.html
@@ -539,6 +541,11 @@ files:
539
541
  - lib/doing/array.rb
540
542
  - lib/doing/array_chronify.rb
541
543
  - lib/doing/boolean_term_parser.rb
544
+ - lib/doing/changelog.rb
545
+ - lib/doing/changelog/change.rb
546
+ - lib/doing/changelog/changes.rb
547
+ - lib/doing/changelog/entry.rb
548
+ - lib/doing/changelog/version.rb
542
549
  - lib/doing/cli_status.rb
543
550
  - lib/doing/colors.rb
544
551
  - lib/doing/completion.rb
@@ -549,6 +556,7 @@ files:
549
556
  - lib/doing/configuration.rb
550
557
  - lib/doing/errors.rb
551
558
  - lib/doing/hash.rb
559
+ - lib/doing/help_monkey_patch.rb
552
560
  - lib/doing/hooks.rb
553
561
  - lib/doing/item.rb
554
562
  - lib/doing/items.rb
@@ -577,11 +585,13 @@ files:
577
585
  - lib/doing/symbol.rb
578
586
  - lib/doing/template_string.rb
579
587
  - lib/doing/time.rb
588
+ - lib/doing/types.rb
580
589
  - lib/doing/util.rb
581
590
  - lib/doing/util_backup.rb
582
591
  - lib/doing/version.rb
583
592
  - lib/doing/wwid.rb
584
593
  - lib/examples/commands/autotag.rb
594
+ - lib/examples/commands/later.rb
585
595
  - lib/examples/commands/wiki.rb
586
596
  - lib/examples/plugins/capture_thing_import.rb
587
597
  - lib/examples/plugins/hooks.rb
@@ -676,6 +686,7 @@ files:
676
686
  - lib/helpers/fzf/test/fzf.vader
677
687
  - lib/helpers/fzf/test/test_go.rb
678
688
  - lib/helpers/fzf/uninstall
689
+ - lib/helpers/threaded_tests.rb
679
690
  - lib/templates/doing-dayone-entry.erb
680
691
  - lib/templates/doing-dayone.erb
681
692
  - lib/templates/doing-markdown.erb