doing 2.1.26 → 2.1.27

Sign up to get free protection for your applications and to get access to all the features.
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