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,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ # A collection of Changes
5
+ class Changes
6
+ attr_reader :changes
7
+
8
+ def initialize(lookup: nil, search: nil)
9
+ changelog = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'CHANGELOG.md'))
10
+ raise 'Error locating changelog' unless File.exist?(changelog)
11
+
12
+ @content = IO.read(changelog)
13
+ parse_changes(lookup, search)
14
+ end
15
+
16
+ def latest
17
+ @changes[0].to_s.force_encoding('utf-8')
18
+ end
19
+
20
+ def to_s
21
+ @changes.map(&:to_s).join("\n\n").force_encoding('utf-8')
22
+ end
23
+
24
+ private
25
+
26
+ def parse_changes(lookup, search)
27
+ change_rx = /(?<=\n|\A)### (\d+\.\d+\.\d+(?:\w+)?)(.*?)(?=\n### |\Z)/m
28
+ @changes = @content.scan(change_rx).each_with_object([]) do |m, a|
29
+ next if m[0].nil? || m[1].nil?
30
+
31
+ a << Change.new(m[0], m[1].strip)
32
+ end
33
+
34
+ lookup(lookup) unless lookup.nil?
35
+ search(search) unless search.nil?
36
+ end
37
+
38
+ def lookup(lookup_version)
39
+ range = []
40
+
41
+ if lookup_version =~ /([\d.]+) *-+ *([\d.]+)/
42
+ m = Regexp.last_match
43
+ lookup("> #{m[1]}")
44
+ lookup("< #{m[2]}")
45
+ elsif lookup_version.scan(/[<>]/).count > 1
46
+ params = lookup_version.scan(/[<>] [\d.]+/)
47
+ params.each { |query| lookup(query) }
48
+ else
49
+ comp = case lookup_version
50
+ when /(<|prior|before|older)/
51
+ :older
52
+ when />|since|after|newer/
53
+ :newer
54
+ else
55
+ :equal
56
+ end
57
+ version = Version.new(lookup_version)
58
+
59
+ @changes.select! do |change|
60
+ change.version.compare(version, comp)
61
+ end
62
+ end
63
+ end
64
+
65
+ def search(query)
66
+ @changes.map do |c|
67
+ c.entries = c.search_entries(query)
68
+ end
69
+
70
+ @changes.delete_if { |c| c.nil? || c.entries.nil? }
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ # An individual changelog item
5
+ class Entry
6
+ attr_reader :type, :string
7
+
8
+ def initialize(string, type)
9
+ @string = string
10
+ @type = type
11
+ end
12
+
13
+ def clean(string)
14
+ string.gsub(/\|/, '\|')
15
+ end
16
+
17
+ def to_s
18
+ "- #{clean(@string)}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ # Semantic versioning
5
+ class Version
6
+ attr_reader :maj, :min, :patch
7
+
8
+ def initialize(string)
9
+ @maj, @min, @patch = version_to_a(string)
10
+ end
11
+
12
+ def version_to_a(string)
13
+ raise 'Version not a string' unless string.is_a?(String)
14
+
15
+ v = string.match(/(?<maj>\d+)(?:\.(?<min>[\d*?]+))?(?:\.(?<patch>[\d*?]+))?/)
16
+
17
+ raise 'Error parsing semantic version string' if v.nil?
18
+
19
+ maj = v['maj'].to_i
20
+ min = case v['min']
21
+ when /[*?]/
22
+ v['min'].sub(/(\d+)?[^\d]/, '\1\d+')
23
+ when /^[0-9]+$/
24
+ v['min'].to_i
25
+ end
26
+ pat = case v['patch']
27
+ when /[*?]/
28
+ v['patch'].sub(/(\d+)?[^\d]/, '\1\d+')
29
+ when /^[0-9]+$/
30
+ v['patch'].to_i
31
+ end
32
+ [maj, min, pat]
33
+ end
34
+
35
+ def wild?(val)
36
+ val.is_a?(String)
37
+ end
38
+
39
+
40
+ def compare(other, comp)
41
+ case comp
42
+ when :older
43
+ if @maj <= other.maj
44
+ if @maj < other.maj
45
+ true
46
+ elsif @maj == other.maj && (other.min.nil? || @min < other.min)
47
+ true
48
+ elsif @maj == other.maj && @min == other.min
49
+ other.patch.nil? ? false : @patch < other.patch
50
+ else
51
+ false
52
+ end
53
+ else
54
+ false
55
+ end
56
+ when :newer
57
+ if @maj >= other.maj
58
+ if @maj > other.maj
59
+ true
60
+ elsif @maj == other.maj && (other.min.nil? || @min > other.min)
61
+ true
62
+ elsif @maj == other.maj && @min == other.min
63
+ other.patch.nil? || @patch >= other.patch
64
+ else
65
+ false
66
+ end
67
+ else
68
+ false
69
+ end
70
+ when :equal
71
+ if @maj == other.maj
72
+ if other.min.nil?
73
+ true
74
+ elsif wild?(other.min)
75
+ @min.to_s =~ /^#{other.min}/ ? true : false
76
+ else
77
+ if @min == other.min
78
+ if other.patch.nil?
79
+ true
80
+ elsif wild?(other.patch)
81
+ @patch.to_s =~ /^#{other.patch}/ ? true : false
82
+ else
83
+ @patch == other.patch
84
+ end
85
+ else
86
+ false
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def to_s
94
+ "#{@maj}.#{@min || 0}.#{@patch || 0}"
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'changelog/version'
4
+ require_relative 'changelog/entry'
5
+ require_relative 'changelog/change'
6
+ require_relative 'changelog/changes'
@@ -31,28 +31,89 @@ module Doing
31
31
  and return 0
32
32
  end
33
33
 
34
+ function __fish_doing_cache_timer_expired
35
+ set -l timer __fish_doing_cache_timer_$argv[1]
36
+ if not set -q $timer
37
+ set -g $timer (date '+%s')
38
+ end
39
+
40
+ if test (math (date '+%s') - $$timer) -gt $argv[2]
41
+ set -g $timer (date '+%s')
42
+ return 1
43
+ end
44
+
45
+ return 0
46
+ end
47
+
48
+ function __fish_doing_subcommands
49
+ if not set -q __fish_doing_subcommands_cache
50
+ or __fish_doing_cache_timer_expired subcommands 86400
51
+ set -g -a __fish_doing_subcommands_cache (doing help -c)
52
+ end
53
+ printf '%s\n' $__fish_doing_subcommands_cache
54
+ end
55
+
34
56
  function __fish_doing_complete_sections
35
- doing sections -c
57
+ if not set -q __fish_doing_sections_cache
58
+ or __fish_doing_cache_timer_expired sections 3600
59
+ set -g -a __fish_doing_sections_cache (doing sections -c)
60
+ end
61
+ printf '%s\n' $__fish_doing_sections_cache
62
+ __fish_doing_complete_show_tag
36
63
  end
37
64
 
38
65
  function __fish_doing_complete_views
39
- doing views -c
66
+ if not set -q __fish_doing_views_cache
67
+ or __fish_doing_cache_timer_expired views 3600
68
+ set -g -a __fish_doing_views_cache (doing views -c)
69
+ end
70
+ printf '%s\n' $__fish_doing_views_cache
40
71
  end
41
72
 
42
- function __fish_doing_subcommands
43
- doing help -c
73
+ function __fish_doing_export_plugin
74
+ if not set -q __fish_doing_export_plugin_cache
75
+ or __fish_doing_cache_timer_expired export_plugins 3600
76
+ set -g -a __fish_doing_export_plugin_cache (doing plugins --type export -c)
77
+ end
78
+ printf '%s\n' $__fish_doing_export_plugin_cache
79
+ end
80
+
81
+ function __fish_doing_import_plugin
82
+ if not set -q __fish_doing_import_plugin_cache
83
+ or __fish_doing_cache_timer_expired import_plugins 3600
84
+ set -g -a __fish_doing_import_plugin_cache (doing plugins --type import -c)
85
+ end
86
+ printf '%s\n' $__fish_doing_import_plugin_cache
87
+ end
88
+
89
+ function __fish_doing_complete_template
90
+ if not set -q __fish_doing_template_cache
91
+ or __fish_doing_cache_timer_expired template 3600
92
+ set -g -a __fish_doing_template_cache (doing template -c)
93
+ end
94
+ printf '%s\n' $__fish_doing_template_cache
44
95
  end
45
96
 
46
- function __fish_doing_export_plugins
47
- doing plugins --type export -c
97
+ function __fish_doing_complete_tag
98
+ if not set -q __fish_doing_tag_cache
99
+ or __fish_doing_cache_timer_expired tags 60
100
+ set -g -a __fish_doing_tag_cache (doing tags)
101
+ end
102
+ printf '%s\n' $__fish_doing_tag_cache
48
103
  end
49
104
 
50
- function __fish_doing_import_plugins
51
- doing plugins --type import -c
105
+ function __fish_doing_complete_show_tag
106
+ if not set -q __fish_doing_tag_cache
107
+ or __fish_doing_cache_timer_expired tags 60
108
+ set -g -a __fish_doing_tag_cache (doing tags)
109
+ end
110
+ printf '@%s\n' $__fish_doing_tag_cache
52
111
  end
53
112
 
54
- function __fish_doing_complete_templates
55
- doing template -c
113
+ function __fish_doing_complete_args
114
+ for cmd in (doing commands_accepting -c $argv[1])
115
+ complete -x -c doing -l $argv[1] -n "__fish_doing_using_command $cmd" -a "(__fish_doing_complete_$argv[1])"
116
+ end
56
117
  end
57
118
 
58
119
  complete -c doing -f
@@ -64,6 +125,14 @@ module Doing
64
125
  complete -f -c doing -s t -l type -x -n '__fish_doing_using_command import' -a '(__fish_doing_import_plugins)'
65
126
 
66
127
  complete -xc doing -n '__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from (doing help -c)' -a "(doing help -c)"
128
+
129
+ function __fish_doing_complete_args
130
+ for cmd in (doing commands_accepting -c $argv[1])
131
+ complete -x -c doing -l $argv[1] -n "__fish_doing_using_command $cmd" -a "(__fish_doing_complete_$argv[1])"
132
+ end
133
+ end
134
+
135
+ __fish_doing_complete_args tag
67
136
  EOFUNCTIONS
68
137
  end
69
138
 
@@ -161,7 +230,7 @@ module Doing
161
230
  end
162
231
 
163
232
  unless need_export.empty?
164
- out << "complete -f -c doing -s o -l output -x -n '__fish_doing_using_command #{need_export.join(' ')}' -a '(__fish_doing_export_plugins)'"
233
+ out << "complete -f -c doing -s o -l output -x -n '__fish_doing_using_command #{need_export.join(' ')}' -a '(__fish_doing_export_plugin)'"
165
234
  end
166
235
 
167
236
  unless need_bool.empty?
@@ -30,6 +30,7 @@ module Doing
30
30
  'command_path' => File.join(Util.user_home, '.config', 'doing', 'commands')
31
31
  },
32
32
  'doing_file' => '~/.local/share/doing/what_was_i_doing.md',
33
+ 'doing_file_sort' => 'desc',
33
34
  'backup_dir' => '~/.local/share/doing/doing_backup',
34
35
  'history_size' => 15,
35
36
  'current_section' => 'Currently',
@@ -159,7 +160,7 @@ module Doing
159
160
  def choose_config(create: false)
160
161
  return @config_file if @force_answer
161
162
 
162
- if @additional_configs.count.positive? || create
163
+ if @additional_configs&.count&.positive? || create
163
164
  choices = [@config_file].concat(@additional_configs)
164
165
  choices.push('Create a new .doingrc in the current directory') if create && !File.exist?('.doingrc')
165
166
  res = Doing::Prompt.choose_from(choices.uniq.sort.reverse,
@@ -189,7 +190,7 @@ module Doing
189
190
  ## matched, first match wins)
190
191
  ## @return [Array] ordered array of resolved keys
191
192
  ##
192
- def resolve_key_path(keypath, create: false)
193
+ def resolve_key_path(keypath, create: false, distance: 2)
193
194
  cfg = @settings
194
195
  real_path = []
195
196
  unless keypath =~ /^[.*]?$/
@@ -197,16 +198,24 @@ module Doing
197
198
  while paths.length.positive? && !cfg.nil?
198
199
  path = paths.shift
199
200
  new_cfg = nil
200
- cfg.each do |key, val|
201
- next unless key =~ path.to_rx(distance: 4)
202
201
 
203
- real_path << key
204
- new_cfg = val
205
- break
202
+ if cfg.is_a?(Hash)
203
+ matches = cfg.select { |key, val| key =~ path.to_rx(distance: distance) }
204
+ if matches.count.positive?
205
+ shortest = matches.keys.group_by(&:length).min.last[0]
206
+ real_path << shortest
207
+ new_cfg = matches[shortest]
208
+ end
209
+ else
210
+ new_cfg = cfg
206
211
  end
207
212
 
208
213
  if new_cfg.nil?
209
- return nil unless create
214
+ if distance < 5 && !create
215
+ return resolve_key_path(keypath, create: false, distance: distance + 1)
216
+ else
217
+ return nil unless create
218
+ end
210
219
 
211
220
  resolved = real_path.count.positive? ? "Resolved #{real_path.join('->')}, but " : ''
212
221
  Doing.logger.log_now(:warn, "#{resolved}#{path} is unknown")
data/lib/doing/hash.rb CHANGED
@@ -6,14 +6,32 @@ module Doing
6
6
  ##
7
7
  ## Freeze all values in a hash
8
8
  ##
9
- ## @return { description_of_the_return_value }
9
+ ## @return Hash with all values frozen
10
10
  ##
11
11
  def deep_freeze
12
- map { |k, v| v.is_a?(Hash) ? v.deep_freeze : v.freeze }.freeze
12
+ chilled = {}
13
+ each do |k, v|
14
+ chilled[k] = v.is_a?(Hash) ? v.deep_freeze : v.freeze
15
+ end
16
+
17
+ chilled.freeze
13
18
  end
14
19
 
15
20
  def deep_freeze!
16
- replace deep_freeze
21
+ replace deep_thaw.deep_freeze
22
+ end
23
+
24
+ def deep_thaw
25
+ chilled = {}
26
+ each do |k, v|
27
+ chilled[k] = v.is_a?(Hash) ? v.deep_thaw : v.dup
28
+ end
29
+
30
+ chilled.dup
31
+ end
32
+
33
+ def deep_thaw!
34
+ replace deep_thaw
17
35
  end
18
36
 
19
37
  # Turn all keys into string
@@ -30,15 +48,16 @@ module Doing
30
48
 
31
49
  # Set a nested hash value using an array
32
50
  #
33
- # @example `{}.deep_set(['one', 'two'], 'value')`
34
- # @example `=> { 'one' => { 'two' => 'value' } }
51
+ # @example
52
+ # {}.deep_set(['one', 'two'], 'value')
53
+ # # => { 'one' => { 'two' => 'value' } }
35
54
  #
36
55
  # @param path [Array] key path
37
56
  # @param value The value
38
57
  #
39
58
  def deep_set(path, value)
40
59
  if path.count == 1
41
- if value
60
+ unless value.nil? || value =~ /^ *$/
42
61
  self[path[0]] = value
43
62
  else
44
63
  delete(path[0])
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GLI
4
+ module Commands
5
+ # Help Command Monkeypatch for paginated output
6
+ class Help < Command
7
+ def show_help(global_options,options,arguments,out,error)
8
+ Doing::Pager.paginate = true
9
+
10
+ command_finder = HelpModules::CommandFinder.new(@app,arguments,error)
11
+ if options[:c]
12
+ help_output = HelpModules::HelpCompletionFormat.new(@app,command_finder,arguments).format
13
+ out.puts help_output unless help_output.nil?
14
+ elsif arguments.empty? || options[:c]
15
+ Doing::Pager.page HelpModules::GlobalHelpFormat.new(@app,@sorter,@text_wrapping_class).format
16
+ else
17
+ name = arguments.shift
18
+ command = command_finder.find_command(name)
19
+ unless command.nil?
20
+ Doing::Pager.page HelpModules::CommandHelpFormat.new(
21
+ command,
22
+ @app,
23
+ @sorter,
24
+ @synopsis_formatter_class,
25
+ @text_wrapping_class).format
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/doing/hooks.rb CHANGED
@@ -23,7 +23,11 @@ module Doing
23
23
 
24
24
  # register hook(s) to be called later, public API
25
25
  def self.register(event, priority: DEFAULT_PRIORITY, &block)
26
- register_one(event, priority_value(priority), &block)
26
+ if event.is_a?(Array)
27
+ event.each { |ev| register_one(ev, priority_value(priority), &block) }
28
+ else
29
+ register_one(event, priority_value(priority), &block)
30
+ end
27
31
  end
28
32
 
29
33
  # Ensure the priority is a Fixnum
data/lib/doing/item.rb CHANGED
@@ -125,11 +125,11 @@ module Doing
125
125
  return true if same_time?(item_b)
126
126
 
127
127
  start_a = date
128
- interval = interval
129
- end_a = interval ? start_a + interval.to_i : start_a
128
+ a_interval = interval
129
+ end_a = a_interval ? start_a + a_interval.to_i : start_a
130
130
  start_b = item_b.date
131
- interval = item_b.interval
132
- end_b = interval ? start_b + interval.to_i : start_b
131
+ b_interval = item_b.interval
132
+ end_b = b_interval ? start_b + b_interval.to_i : start_b
133
133
  (start_a >= start_b && start_a <= end_b) || (end_a >= start_b && end_a <= end_b) || (start_a < start_b && end_a > end_b)
134
134
  end
135
135
 
@@ -216,8 +216,8 @@ module Doing
216
216
  ##
217
217
  def tags?(tags, bool = :and, negate: false)
218
218
  if bool == :pattern
219
- tags = tags.join(' ') if tags.is_a?(Array)
220
- matches = tag_pattern?(tags.gsub(/ *, */, ' '))
219
+ tags = tags.to_tags.tags_to_array.join(' ')
220
+ matches = tag_pattern?(tags)
221
221
 
222
222
  return negate ? !matches : matches
223
223
  end
@@ -283,7 +283,7 @@ module Doing
283
283
  new_title = @title.gsub(rx) { |m| yellow(m) }
284
284
  new_note.add(@note.to_s.gsub(rx) { |m| yellow(m) })
285
285
  else
286
- query = to_phrase_query(search.strip)
286
+ query = search.strip.to_phrase_query
287
287
 
288
288
  if query[:must].nil? && query[:must_not].nil?
289
289
  query[:must] = query[:should]
@@ -319,7 +319,7 @@ module Doing
319
319
  if search.is_rx? || matching == :fuzzy
320
320
  matches = @title + @note.to_s =~ search.to_rx(distance: distance, case_type: case_type)
321
321
  else
322
- query = to_phrase_query(search.strip)
322
+ query = search.strip.to_phrase_query
323
323
 
324
324
  if query[:must].nil? && query[:must_not].nil?
325
325
  query[:must] = query[:should]
@@ -612,29 +612,14 @@ module Doing
612
612
  end
613
613
  end
614
614
 
615
- def to_query(query)
616
- parser = BooleanTermParser::QueryParser.new
617
- transformer = BooleanTermParser::QueryTransformer.new
618
- parse_tree = parser.parse(query)
619
- transformer.apply(parse_tree).to_elasticsearch
620
- end
621
-
622
- def to_phrase_query(query)
623
- parser = PhraseParser::QueryParser.new
624
- transformer = PhraseParser::QueryTransformer.new
625
- parse_tree = parser.parse(query)
626
- transformer.apply(parse_tree).to_elasticsearch
627
- end
628
-
629
615
  def tag_pattern?(tags)
630
- query = to_query(tags)
616
+ query = tags.to_query
631
617
 
632
618
  no_tags?(query[:must_not]) && all_tags?(query[:must]) && any_tags?(query[:should])
633
619
  end
634
620
 
635
621
  def split_tags(tags)
636
- tags = tags.split(/ *, */) if tags.is_a? String
637
- tags.map { |t| t.strip.add_at }
622
+ tags.to_tags.tags_to_array
638
623
  end
639
624
  end
640
625
  end
data/lib/doing/items.rb CHANGED
@@ -131,7 +131,9 @@ module Doing
131
131
  out = []
132
132
  @sections.each do |section|
133
133
  out.push(section.original)
134
- in_section(section.title).each { |item| out.push(item.to_s)}
134
+ items = in_section(section.title).sort_by { |i| i.date }
135
+ items.reverse! if Doing.config.settings['doing_file_sort'].normalize_order == 'desc'
136
+ items.each { |item| out.push(item.to_s)}
135
137
  end
136
138
 
137
139
  out.join("\n")
@@ -356,7 +356,7 @@ module Doing
356
356
  next if data[:count].zero?
357
357
 
358
358
  count = data[:count]
359
- tags = data[:tag] ? data[:tag].uniq.map { |t| "@#{t}".cyan }.join(', ') : 'tags'
359
+ tags = data[:tag] ? data[:tag].uniq.map { |t| t.add_at.cyan }.join(', ') : 'tags'
360
360
  topic, m = format_counter(key, data)
361
361
  message = m.dup
362
362
  message.sub!(/%count/, count.to_s)
data/lib/doing/pager.rb CHANGED
@@ -54,8 +54,8 @@ module Doing
54
54
  read_io.close
55
55
  write_io.write(text)
56
56
  write_io.close
57
- rescue SystemCallError => e
58
- raise Errors::DoingStandardError, "Pager error, #{e}"
57
+ rescue SystemCallError # => e
58
+ # raise Errors::DoingStandardError, "Pager error, #{e}"
59
59
  end
60
60
 
61
61
  _, status = Process.waitpid2(pid)
@@ -75,7 +75,7 @@ module Doing
75
75
  note = i.note.map { |line| line.strip.link_urls(format: :markdown) } if i.note
76
76
  end
77
77
 
78
- title = "#{title} @project(#{i.section})" unless variables[:is_single]
78
+ title = "#{title} @section(#{i.section})" unless variables[:is_single]
79
79
 
80
80
  tags.concat(i.tag_array).sort!.uniq!
81
81
  flagged = day_flagged = true if i.tags?(wwid.config['marker_tag'])
@@ -48,7 +48,7 @@ module Doing
48
48
  note = i.note.map { |line| line.strip.link_urls(format: :markdown) } if i.note
49
49
  end
50
50
 
51
- title = "#{title} @project(#{i.section})" unless variables[:is_single]
51
+ title = "#{title} @section(#{i.section})" unless variables[:is_single]
52
52
 
53
53
  interval = wwid.get_interval(i, record: true) if i.title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
54
54
  interval ||= false
@@ -49,6 +49,8 @@ module Doing
49
49
  note = []
50
50
  end
51
51
 
52
+ placeholders['tags'] = item.tags
53
+
52
54
  placeholders['date'] = item.date.strftime(opt[:format])
53
55
 
54
56
  interval = wwid.get_interval(item, record: true, formatted: false) if opt[:times]
@@ -56,8 +58,10 @@ module Doing
56
58
  interval = case opt[:interval_format].to_sym
57
59
  when :human
58
60
  interval.time_string(format: :hm)
59
- else
61
+ when :text
60
62
  interval.time_string(format: :clock)
63
+ else
64
+ interval.time_string(format: opt[:interval_format].to_sym)
61
65
  end
62
66
  end
63
67
 
@@ -69,8 +73,10 @@ module Doing
69
73
  duration = case opt[:interval_format].to_sym
70
74
  when :human
71
75
  duration.time_string(format: :hm)
72
- else
76
+ when :text
73
77
  duration.time_string(format: :clock)
78
+ else
79
+ duration.time_string(format: opt[:interval_format].to_sym)
74
80
  end
75
81
  end
76
82
  duration ||= ''
@@ -119,7 +125,7 @@ module Doing
119
125
 
120
126
  output.gsub!(/\\%/, '%')
121
127
 
122
- output.highlight_search!(opt[:search]) if opt[:search] && !opt[:not] && opt[:hilite]
128
+ output.highlight_search!(opt[:search]) if opt[:template] =~ /^temp/ && opt[:search] && !opt[:not] && opt[:hilite]
123
129
 
124
130
  out += "#{output}\n"
125
131
  end
data/lib/doing/prompt.rb CHANGED
@@ -42,7 +42,7 @@ module Doing
42
42
  end
43
43
  end
44
44
 
45
- def read_lines(prompt: 'Enter text', completions: [])
45
+ def read_lines(prompt: 'Enter text', completions: [], default_response: '')
46
46
  $stdin.reopen('/dev/tty')
47
47
  return default_response if @default_answer
48
48
 
@@ -72,8 +72,10 @@ module Doing
72
72
  res.join("\n").strip
73
73
  end
74
74
 
75
- def request_lines(prompt: 'Enter text')
75
+ def request_lines(prompt: 'Enter text', default_response: '')
76
76
  $stdin.reopen('/dev/tty')
77
+ return default_response if @default_answer
78
+
77
79
  ask_note = []
78
80
  reader = TTY::Reader.new(interrupt: -> { raise Errors::UserCancelled }, track_history: false)
79
81
  puts "#{boldgreen(prompt.sub(/:?$/, ':'))} #{yellow('Hit return for a new line, ')}#{boldwhite('enter a blank line (')}#{boldyellow('return twice')}#{boldwhite(') to end editing')}"