doing 2.1.26 → 2.1.27

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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +14 -19
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +23 -0
  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 +2 -0
  14. data/bin/commands/again.rb +23 -65
  15. data/bin/commands/archive.rb +20 -61
  16. data/bin/commands/cancel.rb +27 -69
  17. data/bin/commands/changes.rb +32 -5
  18. data/bin/commands/colors.rb +4 -2
  19. data/bin/commands/commands.rb +4 -2
  20. data/bin/commands/commands_accepting.rb +62 -11
  21. data/bin/commands/completion.rb +10 -7
  22. data/bin/commands/config.rb +1 -1
  23. data/bin/commands/done.rb +3 -17
  24. data/bin/commands/finish.rb +7 -30
  25. data/bin/commands/flag.rb +15 -51
  26. data/bin/commands/grep.rb +12 -28
  27. data/bin/commands/import.rb +3 -33
  28. data/bin/commands/last.rb +3 -36
  29. data/bin/commands/meanwhile.rb +3 -13
  30. data/bin/commands/note.rb +13 -52
  31. data/bin/commands/now.rb +15 -21
  32. data/bin/commands/on.rb +3 -4
  33. data/bin/commands/recent.rb +3 -4
  34. data/bin/commands/redo.rb +6 -2
  35. data/bin/commands/reset.rb +19 -52
  36. data/bin/commands/rotate.rb +5 -36
  37. data/bin/commands/select.rb +23 -41
  38. data/bin/commands/show.rb +28 -74
  39. data/bin/commands/since.rb +3 -4
  40. data/bin/commands/tag.rb +4 -34
  41. data/bin/commands/tags.rb +5 -32
  42. data/bin/commands/today.rb +3 -4
  43. data/bin/commands/view.rb +36 -73
  44. data/bin/commands/yesterday.rb +4 -5
  45. data/bin/doing +150 -13
  46. data/docs/doc/Array.html +3 -502
  47. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  48. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  49. data/docs/doc/BooleanTermParser/Query.html +1 -1
  50. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  51. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  52. data/docs/doc/BooleanTermParser.html +1 -1
  53. data/docs/doc/Doing/Color.html +62 -56
  54. data/docs/doc/Doing/Completion.html +1 -1
  55. data/docs/doc/Doing/Configuration.html +35 -1
  56. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  57. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  58. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  59. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  60. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  61. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  62. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  63. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  64. data/docs/doc/Doing/Errors.html +1 -1
  65. data/docs/doc/Doing/Hooks.html +1 -1
  66. data/docs/doc/Doing/Item.html +1 -1
  67. data/docs/doc/Doing/Items.html +2 -2
  68. data/docs/doc/Doing/LogAdapter.html +1 -1
  69. data/docs/doc/Doing/Note.html +2 -2
  70. data/docs/doc/Doing/Pager.html +1 -1
  71. data/docs/doc/Doing/Plugins.html +1 -1
  72. data/docs/doc/Doing/Prompt.html +1 -1
  73. data/docs/doc/Doing/Section.html +1 -1
  74. data/docs/doc/Doing/TemplateString.html +2 -2
  75. data/docs/doc/Doing/Types.html +41 -1
  76. data/docs/doc/Doing/Util/Backup.html +1 -1
  77. data/docs/doc/Doing/Util.html +1 -1
  78. data/docs/doc/Doing/WWID.html +10 -10
  79. data/docs/doc/Doing.html +3 -3
  80. data/docs/doc/FalseClass.html +35 -1
  81. data/docs/doc/GLI/Commands/Help.html +1 -1
  82. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  83. data/docs/doc/GLI/Commands.html +1 -1
  84. data/docs/doc/GLI.html +1 -1
  85. data/docs/doc/Hash.html +1 -1
  86. data/docs/doc/Object.html +1 -1
  87. data/docs/doc/PhraseParser/Operator.html +1 -1
  88. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  89. data/docs/doc/PhraseParser/Query.html +1 -1
  90. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  91. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  92. data/docs/doc/PhraseParser/TermClause.html +1 -1
  93. data/docs/doc/PhraseParser.html +1 -1
  94. data/docs/doc/Status.html +1 -1
  95. data/docs/doc/String.html +287 -3155
  96. data/docs/doc/Symbol.html +40 -6
  97. data/docs/doc/Time.html +1 -1
  98. data/docs/doc/TrueClass.html +35 -1
  99. data/docs/doc/_index.html +5 -10
  100. data/docs/doc/class_list.html +1 -1
  101. data/docs/doc/file.README.html +2 -2
  102. data/docs/doc/index.html +2 -2
  103. data/docs/doc/method_list.html +278 -678
  104. data/docs/doc/top-level-namespace.html +2 -2
  105. data/doing.rdoc +277 -175
  106. data/lib/completion/_doing.zsh +33 -29
  107. data/lib/completion/doing.bash +30 -19
  108. data/lib/completion/doing.fish +84 -72
  109. data/lib/doing/array/array.rb +4 -0
  110. data/lib/doing/array/nested_hash.rb +17 -0
  111. data/lib/doing/{array.rb → array/tags.rb} +7 -25
  112. data/lib/doing/changelog/change.rb +26 -11
  113. data/lib/doing/changelog/changes.rb +13 -3
  114. data/lib/doing/{array_chronify.rb → chronify/array.rb} +0 -0
  115. data/lib/doing/chronify/chronify.rb +5 -0
  116. data/lib/doing/{numeric_chronify.rb → chronify/numeric.rb} +0 -0
  117. data/lib/doing/{string_chronify.rb → chronify/string.rb} +0 -0
  118. data/lib/doing/colors.rb +115 -54
  119. data/lib/doing/configuration.rb +4 -0
  120. data/lib/doing/good.rb +8 -0
  121. data/lib/doing/help_monkey_patch.rb +6 -5
  122. data/lib/doing/item.rb +5 -5
  123. data/lib/doing/items.rb +2 -2
  124. data/lib/doing/log_adapter.rb +35 -2
  125. data/lib/doing/normalize.rb +188 -0
  126. data/lib/doing/plugins/export/dayone_export.rb +1 -1
  127. data/lib/doing/plugins/export/html_export.rb +1 -1
  128. data/lib/doing/plugins/export/json_export.rb +1 -1
  129. data/lib/doing/plugins/export/markdown_export.rb +1 -1
  130. data/lib/doing/plugins/export/template_export.rb +3 -1
  131. data/lib/doing/prompt.rb +1 -3
  132. data/lib/doing/string/highlight.rb +95 -0
  133. data/lib/doing/string/query.rb +129 -0
  134. data/lib/doing/string/string.rb +12 -0
  135. data/lib/doing/string/tags.rb +164 -0
  136. data/lib/doing/string/transform.rb +168 -0
  137. data/lib/doing/string/truncate.rb +75 -0
  138. data/lib/doing/string/url.rb +82 -0
  139. data/lib/doing/template_string.rb +0 -22
  140. data/lib/doing/types.rb +8 -0
  141. data/lib/doing/util.rb +13 -9
  142. data/lib/doing/version.rb +1 -1
  143. data/lib/doing/wwid.rb +53 -35
  144. data/lib/doing.rb +4 -6
  145. data/lib/examples/plugins/wiki_export/wiki_export.rb +1 -1
  146. data/lib/helpers/threaded_tests.rb +15 -2
  147. data/scripts/deploy.rb +107 -0
  148. data/scripts/runtests.sh +4 -0
  149. metadata +19 -8
  150. data/lib/doing/string.rb +0 -765
  151. data/lib/doing/symbol.rb +0 -28
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ ##
5
+ ## URL linking and formatting
6
+ ##
7
+ class ::String
8
+ ##
9
+ ## Turn raw urls into HTML links
10
+ ##
11
+ ## @param opt [Hash] Additional Options
12
+ ##
13
+ ## @option opt [Symbol] :format can be :markdown or
14
+ ## :html (default)
15
+ ##
16
+ def link_urls(**opt)
17
+ fmt = opt.fetch(:format, :html)
18
+ return self unless fmt
19
+
20
+ str = dup
21
+
22
+ str = str.remove_self_links if fmt == :markdown
23
+
24
+ str.replace_qualified_urls(format: fmt).clean_unlinked_urls
25
+ end
26
+
27
+ ## @see #link_urls
28
+ def link_urls!(**opt)
29
+ fmt = opt.fetch(:format, :html)
30
+ replace link_urls(format: fmt)
31
+ end
32
+
33
+ # Remove <self-linked> formatting
34
+ def remove_self_links
35
+ gsub(/<(.*?)>/) do |match|
36
+ m = Regexp.last_match
37
+ if m[1] =~ /^https?:/
38
+ m[1]
39
+ else
40
+ match
41
+ end
42
+ end
43
+ end
44
+
45
+ # Replace qualified urls
46
+ def replace_qualified_urls(**options)
47
+ fmt = options.fetch(:format, :html)
48
+ gsub(%r{(?mi)(?x:
49
+ (?<!["'\[(\\])
50
+ (?<protocol>(?:http|https)://)
51
+ (?<domain>[\w\-]+(?:\.[\w\-]+)+)
52
+ (?<path>[\w\-.,@?^=%&;:/~+#]*[\w\-@^=%&;/~+#])?
53
+ )}) do |_match|
54
+ m = Regexp.last_match
55
+ url = "#{m['domain']}#{m['path']}"
56
+ proto = m['protocol'].nil? ? 'http://' : m['protocol']
57
+ case fmt
58
+ when :terminal
59
+ TTY::Link.link_to("#{proto}#{url}", "#{proto}#{url}")
60
+ when :html
61
+ %(<a href="#{proto}#{url}" title="Link to #{m['domain']}">[#{url}]</a>)
62
+ when :markdown
63
+ "[#{url}](#{proto}#{url})"
64
+ else
65
+ m[0]
66
+ end
67
+ end
68
+ end
69
+
70
+ # Clean up unlinked <urls>
71
+ def clean_unlinked_urls
72
+ gsub(/<(\w+:.*?)>/) do |match|
73
+ m = Regexp.last_match
74
+ if m[1] =~ /<a href/
75
+ match
76
+ else
77
+ %(<a href="#{m[1]}" title="Link to #{m[1]}">[link]</a>)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -5,28 +5,6 @@ module Doing
5
5
  ## Template string formatting
6
6
  ##
7
7
  class TemplateString < String
8
- class ::String
9
- ##
10
- ## Extract the longest valid color from a string.
11
- ##
12
- ## Allows %colors to bleed into other text and still
13
- ## be recognized, e.g. %greensomething still finds
14
- ## %green.
15
- ##
16
- ## @return [String] a valid color name
17
- ## @api private
18
- def validate_color
19
- valid_color = nil
20
- compiled = ''
21
- split('').each do |char|
22
- compiled += char
23
- valid_color = compiled if Color.attributes.include?(compiled.to_sym)
24
- end
25
-
26
- valid_color
27
- end
28
- end
29
-
30
8
  attr_reader :original
31
9
 
32
10
  include Color
data/lib/doing/types.rb CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Doing
4
4
  module Types
5
+ REGEX_CASE = /^[cis].*?$/i.freeze
6
+ REGEX_TAG_SORT = /^(?:n(?:ame)?|t(?:ime)?)$/i.freeze
5
7
  REGEX_BOOL = /^(?:and|all|any|or|not|none|p(?:at(?:tern)?)?)$/i.freeze
6
8
  REGEX_SORT_ORDER = /^(?:a(?:sc)?|d(?:esc)?)$/i.freeze
7
9
  REGEX_VALUE_QUERY = /^(?:!)?@?(?:\S+) +(?:!?[<>=][=*]?|[$*^]=) +(?:.*?)$/.freeze
@@ -22,5 +24,11 @@ module Doing
22
24
  DateRangeString = Class.new(Array)
23
25
  DateRangeOptionalString = Class.new(Array)
24
26
  DateIntervalString = Class.new(DateTime)
27
+ BooleanSymbol = Class.new(Symbol)
28
+ CaseSymbol = Class.new(Symbol)
29
+ AgeSymbol = Class.new(String)
30
+ OrderSymbol = Class.new(Symbol)
31
+ TagSortSymbol = Class.new(Symbol)
32
+ MatchingSymbol = Class.new(Symbol)
25
33
  end
26
34
  end
data/lib/doing/util.rb CHANGED
@@ -170,29 +170,33 @@ module Doing
170
170
 
171
171
  if editor_config[editor_for]
172
172
  editor = editor_config[editor_for]
173
- # Doing.logger.debug('Editor:', "Using #{editor} from config 'editors->#{editor_for}'")
174
- return editor unless editor.good?
173
+ Doing.logger.debug('Editor:', "Using #{editor} from config 'editors.#{editor_for}' for #{editor_for}")
174
+ return editor if editor.good?
175
175
  end
176
176
 
177
177
  if editor_for != 'editor' && editor_config['default']
178
178
  editor = editor_config['default']
179
- # Doing.logger.debug('Editor:', "Using #{editor} from config: 'editors->default'")
180
- return editor unless editor.good?
179
+ Doing.logger.debug('Editor:', "Using #{editor} from config: 'editors.default' for #{editor_for}")
180
+ return editor if editor.good?
181
181
  end
182
182
 
183
183
  editor ||= ENV['DOING_EDITOR'] || ENV['GIT_EDITOR'] || ENV['EDITOR']
184
184
 
185
- unless editor.good?
186
- # Doing.logger.debug('Editor:', "Found editor in environment variables: #{editor}")
185
+ if editor.good?
186
+ Doing.logger.debug('Editor:', "Found editor in environment variables: #{editor} for #{editor_for}")
187
187
  return editor
188
188
  end
189
189
 
190
- Doing.logger.debug('ENV:', 'No EDITOR environment variable, testing available editors')
190
+ Doing.logger.debug('Editor:', 'No EDITOR environment variable, testing available editors')
191
191
  editors = %w[vim vi code subl mate mvim nano emacs]
192
192
  editors.each do |ed|
193
- return TTY::Which.which(ed) if TTY::Which.which(ed)
193
+ try = TTY::Which.which(ed)
194
+ if try
195
+ Doing.logger.debug('Editor:', "Using editor #{try} for #{editor_for}")
196
+ return try
197
+ end
194
198
 
195
- Doing.logger.debug('ENV:', "#{ed} not available")
199
+ Doing.logger.debug('Editor:', "#{ed} not available")
196
200
  end
197
201
 
198
202
  nil
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '2.1.26'
2
+ VERSION = '2.1.27'
3
3
  end
data/lib/doing/wwid.rb CHANGED
@@ -659,6 +659,7 @@ module Doing
659
659
  ## @option opt [Array] :val (nil) Array of tag value queries
660
660
  ##
661
661
  def filter_items(items = Items.new, opt: {})
662
+ logger.benchmark(:filter_items, :start)
662
663
  time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/
663
664
 
664
665
  if items.nil? || items.empty?
@@ -810,6 +811,8 @@ module Doing
810
811
  output.concat(filtered_items.reverse.slice(0, count))
811
812
  end
812
813
 
814
+ logger.benchmark(:filter_items, :finish)
815
+
813
816
  output
814
817
  end
815
818
 
@@ -1211,6 +1214,7 @@ module Doing
1211
1214
  opt[:sequential] ||= false
1212
1215
  opt[:date] ||= false
1213
1216
  opt[:remove] ||= false
1217
+ opt[:update] ||= false
1214
1218
  opt[:autotag] ||= false
1215
1219
  opt[:back] ||= false
1216
1220
  opt[:unfinished] ||= false
@@ -1323,7 +1327,7 @@ module Doing
1323
1327
  else
1324
1328
  old_title = item.title.dup
1325
1329
  should_date = opt[:date] && item.should_time?
1326
- item.title.tag!('done', remove: true) if tag =~ /done/ && !should_date
1330
+ item.title.tag!('done', remove: true) if tag =~ /done/ && (!should_date || opt[:update])
1327
1331
  item.title.tag!(tag, value: should_date ? done_date.strftime('%F %R') : nil)
1328
1332
  added << tag if old_title != item.title
1329
1333
  end
@@ -1619,6 +1623,7 @@ module Doing
1619
1623
  ## @param opt [Hash] Additional Options
1620
1624
  ##
1621
1625
  def list_section(opt, items: Items.new)
1626
+ logger.benchmark(:list_section, :start)
1622
1627
  opt[:config_template] ||= 'default'
1623
1628
 
1624
1629
  tpl_cfg = @config.dig('templates', opt[:config_template])
@@ -1632,7 +1637,7 @@ module Doing
1632
1637
  cfg.deep_merge({
1633
1638
  'wrap_width' => @config['wrap_width'] || 0,
1634
1639
  'date_format' => @config['default_date_format'],
1635
- 'order' => @config['order'] || 'asc',
1640
+ 'order' => @config['order'] || :asc,
1636
1641
  'tags_color' => @config['tags_color'],
1637
1642
  'duration' => @config['duration'],
1638
1643
  'interval_format' => @config['interval_format']
@@ -1644,8 +1649,8 @@ module Doing
1644
1649
  opt[:age] ||= :newest
1645
1650
  opt[:age] = opt[:age].normalize_age
1646
1651
  opt[:format] ||= cfg['date_format']
1647
- opt[:order] ||= cfg['order'] || 'asc'
1648
- opt[:tag_order] ||= 'asc'
1652
+ opt[:order] ||= cfg['order'] || :asc
1653
+ opt[:tag_order] ||= :asc
1649
1654
  opt[:tags_color] = cfg['tags_color'] || false if opt[:tags_color].nil?
1650
1655
  opt[:template] ||= cfg['template']
1651
1656
 
@@ -1671,7 +1676,7 @@ module Doing
1671
1676
 
1672
1677
  items = filter_items(items, opt: opt)
1673
1678
 
1674
- items.reverse! unless opt[:order] =~ /^d/i
1679
+ items.reverse! unless opt[:order].normalize_order == :desc
1675
1680
 
1676
1681
  if opt[:delete]
1677
1682
  delete_items(items, force: opt[:force])
@@ -1694,6 +1699,7 @@ module Doing
1694
1699
  opt[:output] ||= 'template'
1695
1700
  opt[:wrap_width] ||= @config['templates']['default']['wrap_width'] || 0
1696
1701
 
1702
+ logger.benchmark(:list_section, :finish)
1697
1703
  output(items, title, is_single, opt)
1698
1704
  end
1699
1705
 
@@ -1721,7 +1727,7 @@ module Doing
1721
1727
  destination = guess_section(destination)
1722
1728
 
1723
1729
  if @content.section?(destination) && (@content.section?(section) || archive_all)
1724
- do_archive(section, destination, { count: count, tags: tags, bool: bool, search: options[:search], label: options[:label], before: options[:before] })
1730
+ do_archive(section, destination, { count: count, tags: tags, bool: bool, search: options[:search], label: options[:label], before: options[:before], after: options[:after], from: options[:from] })
1725
1731
  write(doing_file)
1726
1732
  else
1727
1733
  raise InvalidArgument, 'Either source or destination does not exist'
@@ -1743,7 +1749,7 @@ module Doing
1743
1749
  cfg = @config['templates'][opt[:config_template]].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
1744
1750
  'wrap_width' => @config['wrap_width'] || 0,
1745
1751
  'date_format' => @config['default_date_format'],
1746
- 'order' => @config['order'] || 'asc',
1752
+ 'order' => @config['order'] || :asc,
1747
1753
  'tags_color' => @config['tags_color'],
1748
1754
  'duration' => @config['duration'],
1749
1755
  'interval_format' => @config['interval_format']
@@ -1762,7 +1768,7 @@ module Doing
1762
1768
  from: opt[:from],
1763
1769
  format: cfg['date_format'],
1764
1770
  interval_format: opt[:interval_format],
1765
- order: cfg['order'] || 'asc',
1771
+ order: cfg['order'] || :asc,
1766
1772
  output: output,
1767
1773
  section: opt[:section],
1768
1774
  sort_tags: opt[:sort_tags],
@@ -1797,7 +1803,7 @@ module Doing
1797
1803
  list_section({
1798
1804
  section: section,
1799
1805
  count: 0,
1800
- order: 'asc',
1806
+ order: :asc,
1801
1807
  date_filter: dates,
1802
1808
  times: times,
1803
1809
  output: output,
@@ -1863,7 +1869,7 @@ module Doing
1863
1869
  cfg = @config['templates'][opt[:config_template]].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
1864
1870
  'wrap_width' => @config['wrap_width'] || 0,
1865
1871
  'date_format' => @config['default_date_format'],
1866
- 'order' => @config['order'] || 'asc',
1872
+ 'order' => @config['order'] || :asc,
1867
1873
  'tags_color' => @config['tags_color'],
1868
1874
  'duration' => @config['duration'],
1869
1875
  'interval_format' => @config['interval_format']
@@ -1879,7 +1885,7 @@ module Doing
1879
1885
  opt[:count] = count
1880
1886
  opt[:format] = cfg['date_format']
1881
1887
  opt[:template] = opt[:template] || cfg['template']
1882
- opt[:order] = 'asc'
1888
+ opt[:order] = :asc
1883
1889
  opt[:times] = times
1884
1890
 
1885
1891
  list_section(opt)
@@ -1896,7 +1902,7 @@ module Doing
1896
1902
  cfg = @config['templates'][options[:config_template]].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
1897
1903
  'wrap_width' => @config['wrap_width'] || 0,
1898
1904
  'date_format' => @config['default_date_format'],
1899
- 'order' => @config['order'] || 'asc',
1905
+ 'order' => @config['order'] || :asc,
1900
1906
  'tags_color' => @config['tags_color'],
1901
1907
  'duration' => @config['duration'],
1902
1908
  'interval_format' => @config['interval_format']
@@ -2043,10 +2049,10 @@ module Doing
2043
2049
  ##
2044
2050
  ## @param format [String] return format (html,
2045
2051
  ## json, or text)
2046
- ## @param sort_by_name [Boolean] Sort by name if true, otherwise by time
2047
- ## @param sort_order [String] The sort order (asc or desc)
2052
+ ## @param sort_by [Symbol] Sort by :name or :time
2053
+ ## @param sort_order [Symbol] The sort order (:asc or :desc)
2048
2054
  ##
2049
- def tag_times(format: :text, sort_by_name: false, sort_order: 'asc')
2055
+ def tag_times(format: :text, sort_by: :time, sort_order: :asc)
2050
2056
  return '' if @timers.empty?
2051
2057
 
2052
2058
  max = @timers.keys.sort_by { |k| k.length }.reverse[0].length + 1
@@ -2054,13 +2060,13 @@ module Doing
2054
2060
  total = @timers.delete('All')
2055
2061
 
2056
2062
  tags_data = @timers.delete_if { |_k, v| v == 0 }
2057
- sorted_tags_data = if sort_by_name
2063
+ sorted_tags_data = if sort_by.normalize_tag_sort == :name
2058
2064
  tags_data.sort_by { |k, _v| k }
2059
2065
  else
2060
2066
  tags_data.sort_by { |_k, v| v }
2061
2067
  end
2062
2068
 
2063
- sorted_tags_data.reverse! if sort_order =~ /^asc/i
2069
+ sorted_tags_data.reverse! if sort_order.normalize_order == :asc
2064
2070
  case format
2065
2071
  when :html
2066
2072
 
@@ -2210,9 +2216,9 @@ EOS
2210
2216
  Doing.config_with(ENV['DOING_CONFIG'], { ignore_local: true })
2211
2217
  end
2212
2218
 
2213
- Doing.logger.benchmark(:configure, :start)
2219
+ logger.benchmark(:configure, :start)
2214
2220
  config = Doing.config
2215
- Doing.logger.benchmark(:configure, :finish)
2221
+ logger.benchmark(:configure, :finish)
2216
2222
 
2217
2223
  config.settings['backup_dir'] = ENV['DOING_BACKUP_DIR'] if ENV['DOING_BACKUP_DIR']
2218
2224
  @config = config.settings
@@ -2266,6 +2272,7 @@ EOS
2266
2272
  ## template trigger
2267
2273
  ##
2268
2274
  def output(items, title, is_single, opt)
2275
+ logger.benchmark(:output, :start)
2269
2276
  opt ||= {}
2270
2277
  out = nil
2271
2278
 
@@ -2283,7 +2290,7 @@ EOS
2283
2290
  end
2284
2291
 
2285
2292
  logger.debug('Output:', "#{items.count} #{items.count == 1 ? 'item' : 'items'} shown")
2286
-
2293
+ logger.benchmark(:output, :finish)
2287
2294
  out
2288
2295
  end
2289
2296
 
@@ -2327,26 +2334,37 @@ EOS
2327
2334
  section_items = @content.in_section(section)
2328
2335
  max = section_items.count - count.to_i
2329
2336
 
2337
+ opt[:after] = opt[:from][0] if opt[:from]
2338
+ opt[:before] = opt[:from][1] if opt[:from]
2339
+
2340
+ time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/
2341
+
2342
+ if opt[:before].is_a?(String) && opt[:before] =~ time_rx
2343
+ opt[:before] = opt[:before].chronify(guess: :end, future: false)
2344
+ end
2345
+
2346
+ if opt[:after].is_a?(String) && opt[:after] =~ time_rx
2347
+ opt[:after] = opt[:after].chronify(guess: :begin, future: false)
2348
+ end
2349
+
2330
2350
  counter = 0
2331
2351
 
2332
2352
  @content.map do |item|
2333
2353
  break if counter >= max
2334
- if opt[:before]
2335
- time_string = opt[:before]
2336
- cutoff = time_string.chronify(guess: :begin)
2337
- end
2338
2354
 
2339
- if (item.section.downcase != section.downcase && section != /^all$/i) || item.section.downcase == destination.downcase
2340
- item
2341
- elsif ((!tags.empty? && !item.tags?(tags, bool)) || (opt[:search] && !item.search(opt[:search].to_s)) || (opt[:before] && item.date >= cutoff))
2342
- item
2343
- else
2344
- counter += 1
2345
- old_item = item.clone
2346
- item.move_to(destination, label: label, log: false)
2347
- Hooks.trigger :post_entry_updated, self, item, old_item
2348
- item
2349
- end
2355
+ next if item.section.downcase == destination.downcase
2356
+
2357
+ next if item.section.downcase != section.downcase && section != /^all$/i
2358
+
2359
+ next if (opt[:before] && item.date > opt[:before]) || (opt[:after] && item.date < opt[:after])
2360
+
2361
+ next if (!tags.empty? && !item.tags?(tags, bool)) || (opt[:search] && !item.search(opt[:search].to_s))
2362
+
2363
+ counter += 1
2364
+ old_item = item.clone
2365
+ item.move_to(destination, label: label, log: false)
2366
+ Hooks.trigger :post_entry_updated, self, item, old_item
2367
+ item
2350
2368
  end
2351
2369
 
2352
2370
  if counter.positive?
data/lib/doing.rb CHANGED
@@ -28,11 +28,11 @@ require_relative 'doing/hash'
28
28
  require_relative 'doing/types'
29
29
  require_relative 'doing/colors'
30
30
  require_relative 'doing/template_string'
31
- require_relative 'doing/string'
31
+ require_relative 'doing/string/string'
32
32
  require_relative 'doing/time'
33
- require_relative 'doing/array'
33
+ require_relative 'doing/array/array'
34
34
  require_relative 'doing/good'
35
- require_relative 'doing/symbol'
35
+ require_relative 'doing/normalize'
36
36
  require_relative 'doing/util'
37
37
  require_relative 'doing/util_backup'
38
38
  require_relative 'doing/configuration'
@@ -50,9 +50,7 @@ require_relative 'doing/pager'
50
50
  require_relative 'doing/completion'
51
51
  require_relative 'doing/boolean_term_parser'
52
52
  require_relative 'doing/phrase_parser'
53
- require_relative 'doing/array_chronify'
54
- require_relative 'doing/numeric_chronify'
55
- require_relative 'doing/string_chronify'
53
+ require_relative 'doing/chronify/chronify'
56
54
  # require 'doing/markdown_document_listener'
57
55
 
58
56
  # Main doing module
@@ -74,7 +74,7 @@ module Doing
74
74
  self.template('wiki_css')
75
75
  end
76
76
 
77
- totals = opt[:totals] ? wwid.tag_times(format: :html, sort_by_name: opt[:sort_tags], sort_order: opt[:tag_order]) : ''
77
+ totals = opt[:totals] ? wwid.tag_times(format: :html, sort_by: opt[:sort_tags], sort_order: opt[:tag_order]) : ''
78
78
  engine = Haml::Engine.new(template)
79
79
  Doing.logger.debug('Wiki Export:', "#{items_out.count} items output to #{variables[:page_title]} wiki page")
80
80
  @out = engine.render(Object.new,
@@ -23,10 +23,19 @@ class ThreadedTests
23
23
  c = Doing::Color
24
24
  c.coloring = true
25
25
 
26
- pattern = "test/doing_*#{pattern}*_test.rb"
26
+ shuffle = false
27
+
28
+ unless pattern =~ /shuffle/i
29
+ pattern = "test/doing_*#{pattern}*_test.rb"
30
+ else
31
+ pattern = "test/doing_*_test.rb"
32
+ shuffle = true
33
+ end
27
34
 
28
35
  tests = Dir.glob(pattern)
29
36
 
37
+ tests.shuffle! if shuffle
38
+
30
39
  if max_tests.to_i > 0
31
40
  tests = tests.slice(0, max_tests.to_i - 1)
32
41
  end
@@ -140,7 +149,11 @@ class ThreadedTests
140
149
  count = out.match(/^(?<tests>\d+) tests, (?<assrt>\d+) assertions, (?<fails>\d+) failures, (?<errs>\d+) errors/)
141
150
 
142
151
  unless status.success? && !count['fails'].to_i.positive? && !count['errs'].to_i.positive?
143
- s[2] = ": #{count['fails'].bold.red} #{'failures'.red}, #{count['errs'].bold.red} #{'errors'.red}"
152
+ s[2] = if count
153
+ ": #{count['fails'].bold.red} #{'failures'.red}, #{count['errs'].bold.red} #{'errors'.red}"
154
+ else
155
+ ": #{'Unknown Error'.bold.red}"
156
+ end
144
157
  bar.update(head: '✖'.boldred)
145
158
  bar.advance(head: '✖'.boldred, status: s[2])
146
159
 
data/scripts/deploy.rb ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tty-spinner'
4
+ require 'tty-cursor'
5
+ require 'pastel'
6
+ require 'fileutils'
7
+
8
+ pastel = Pastel.new
9
+ format = "[#{pastel.yellow(':spinner')}] " + pastel.white("Release Gem")
10
+ spinners = TTY::Spinner::Multi.new(format, format: :dots, success_mark: pastel.green('✔'), error_mark: pastel.red('✖'))
11
+ sp_v = spinners.register "[#{pastel.cyan(':spinner')}] :msg"
12
+ sp_t = spinners.register "[#{pastel.cyan(':spinner')}] Run tests :msg"
13
+ sp_c = spinners.register "[#{pastel.cyan(':spinner')}] Generate completions"
14
+ sp_d = spinners.register "[#{pastel.cyan(':spinner')}] Generate docs"
15
+ sp_w = spinners.register "[#{pastel.cyan(':spinner')}] Update wiki :msg"
16
+ spinners.auto_spin
17
+
18
+ $version = nil
19
+ sp_v.update(msg: 'Get version')
20
+ sp_t.update(msg: '')
21
+ sp_w.update(msg: '')
22
+ sp_v.run do |spinner|
23
+ spinner.update(msg: 'Getting version')
24
+ versions = `rake ver`.strip
25
+ version = versions.match(/version\.rb: ([\d.]+(\w+\d*)?)/)[1]
26
+ changelog_version = versions.match(/changelog: ([\d.]+(\w+\d*)?)/)[1]
27
+ git_version = versions.match(/git tag: ([\d.]+(\w+\d*)?)/)[1]
28
+
29
+ if git_version == version
30
+ spinner.update(msg: "Error: Git version (#{git_version}) is the same as version.rb (#{version})")
31
+ spinner.error
32
+ spinners.stop
33
+ Process.exit
34
+ end
35
+
36
+ unless version == changelog_version
37
+ spinner.update(msg: "Error: version.rb (#{version}) and Changelog (#{changelog_version}) do not match")
38
+ spinner.error
39
+ spinners.stop
40
+ Process.exit
41
+ end
42
+
43
+ $version = version
44
+
45
+ spinner.update(msg: "Version #{version}")
46
+ spinner.success
47
+ end
48
+
49
+
50
+ sp_t.run do |spinner|
51
+ spinner.update(msg: '')
52
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
53
+ unless system('rake parallel:test &> results.log')
54
+ spinner.update(msg: '- Unit tests failed')
55
+ spinner.error
56
+ spinners.stop
57
+ Process.exit
58
+ end
59
+
60
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
61
+ spinner.update(msg: "- passed in #{(finish - start).round(4)} seconds")
62
+ spinner.success
63
+ end
64
+
65
+ sp_c.auto_spin
66
+ `./generate_completions.sh &> results.log`
67
+ sp_c.success
68
+
69
+ sp_d.auto_spin
70
+ `bundle exec bin/doing _doc &> results.log`
71
+ `./rdoc_to_mmd.rb > /Users/ttscoff/Sites/dev/bt/source/doing_all_commands.md`
72
+ `rake yard &> results.log`
73
+ sp_d.success
74
+
75
+
76
+ sp_w.run do |spinner|
77
+ spinner.update(msg: '- Updating All Commands')
78
+ `./rdoc_to_mmd.rb > /Users/ttscoff/Desktop/Code/doing.wiki/commands.source`
79
+ prev_dir = Dir.pwd
80
+ Dir.chdir('/Users/ttscoff/Desktop/Code/doing.wiki/')
81
+ `./reformat_commands.rb &> results.log`
82
+ spinner.update(msg: '- Committing and Pushing')
83
+ `git commit -a -m "#{$version} update" &> results.log`
84
+ `git pull &> results.log`
85
+ `FORCE_PUSH=true git push &> results.log`
86
+ spinner.update(msg: '- Tagging Release')
87
+ `git release create -m "v#{$version}" $version &> results.log`
88
+ spinner.update(msg: '- Done')
89
+ Dir.chdir(prev_dir)
90
+ sp_w.success
91
+ end
92
+
93
+ sp_r = spinners.register "[:spinner] Releasing gem :msg"
94
+
95
+ sp_r.run do |spinner|
96
+ spinner.update(msg: '- Preparing git release')
97
+ `git commit -a -m "#{$version} release prep" &> results.log`
98
+ `git pull &> results.log`
99
+ `FORCE_PUSH=true git push &> results.log`
100
+ spinner.update(msg: '- Running releasegem script')
101
+ `/Users/ttscoff/scripts/releasegem &> results.log`
102
+ spinner.update(msg: '- Bumping gem version')
103
+ `rake bump[patch] &> results.log`
104
+ sp_r.success
105
+ end
106
+
107
+ FileUtils.rm('results.log')
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+
3
+ bundle install
4
+ rake test