doing 2.1.19 → 2.1.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardoc/checksums +19 -16
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +70 -0
- data/Gemfile.lock +11 -11
- data/README.md +1 -1
- data/Rakefile +12 -4
- data/bin/doing +297 -234
- data/docs/doc/Array.html +7 -30
- data/docs/doc/BooleanTermParser/Clause.html +3 -3
- data/docs/doc/BooleanTermParser/Operator.html +3 -3
- data/docs/doc/BooleanTermParser/Query.html +3 -3
- data/docs/doc/BooleanTermParser/QueryParser.html +3 -3
- data/docs/doc/BooleanTermParser/QueryTransformer.html +3 -3
- data/docs/doc/BooleanTermParser.html +3 -3
- data/docs/doc/Doing/Color.html +3 -3
- data/docs/doc/Doing/Completion.html +3 -3
- data/docs/doc/Doing/Configuration.html +6 -5
- data/docs/doc/Doing/Errors/DoingNoTraceError.html +3 -3
- data/docs/doc/Doing/Errors/DoingRuntimeError.html +3 -3
- data/docs/doc/Doing/Errors/DoingStandardError.html +3 -3
- data/docs/doc/Doing/Errors/EmptyInput.html +3 -3
- data/docs/doc/Doing/Errors/NoResults.html +3 -3
- data/docs/doc/Doing/Errors/PluginException.html +3 -3
- data/docs/doc/Doing/Errors/UserCancelled.html +3 -3
- data/docs/doc/Doing/Errors/WrongCommand.html +3 -3
- data/docs/doc/Doing/Errors.html +3 -3
- data/docs/doc/Doing/Hooks.html +3 -3
- data/docs/doc/Doing/Item.html +3 -3
- data/docs/doc/Doing/Items.html +3 -3
- data/docs/doc/Doing/LogAdapter.html +3 -3
- data/docs/doc/Doing/Note.html +3 -3
- data/docs/doc/Doing/Pager.html +3 -3
- data/docs/doc/Doing/Plugins.html +3 -3
- data/docs/doc/Doing/Prompt.html +7 -7
- data/docs/doc/Doing/Section.html +3 -3
- data/docs/doc/Doing/TemplateString.html +4 -4
- data/docs/doc/Doing/Types.html +201 -0
- data/docs/doc/Doing/Util/Backup.html +3 -3
- data/docs/doc/Doing/Util.html +4 -7
- data/docs/doc/Doing/WWID.html +66 -8
- data/docs/doc/Doing.html +6 -6
- data/docs/doc/GLI/Commands/Help.html +185 -0
- data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +3 -3
- data/docs/doc/GLI/Commands.html +7 -5
- data/docs/doc/GLI.html +6 -4
- data/docs/doc/Hash.html +80 -16
- data/docs/doc/Numeric.html +3 -3
- data/docs/doc/PhraseParser/Operator.html +3 -3
- data/docs/doc/PhraseParser/PhraseClause.html +3 -3
- data/docs/doc/PhraseParser/Query.html +3 -3
- data/docs/doc/PhraseParser/QueryParser.html +3 -3
- data/docs/doc/PhraseParser/QueryTransformer.html +3 -3
- data/docs/doc/PhraseParser/TermClause.html +3 -3
- data/docs/doc/PhraseParser.html +3 -3
- data/docs/doc/Status.html +3 -3
- data/docs/doc/String.html +195 -26
- data/docs/doc/Symbol.html +3 -3
- data/docs/doc/Time.html +3 -3
- data/docs/doc/_index.html +22 -8
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +4 -4
- data/docs/doc/frames.html +1 -1
- data/docs/doc/index.html +4 -4
- data/docs/doc/method_list.html +334 -270
- data/docs/doc/top-level-namespace.html +3 -3
- data/docs/index.md +1 -1
- data/doing.gemspec +1 -1
- data/doing.rdoc +173 -15
- data/lib/completion/_doing.zsh +20 -20
- data/lib/completion/doing.bash +37 -26
- data/lib/completion/doing.fish +116 -17
- data/lib/doing/array.rb +5 -4
- data/lib/doing/array_chronify.rb +4 -3
- data/lib/doing/changelog/change.rb +115 -0
- data/lib/doing/changelog/changes.rb +73 -0
- data/lib/doing/changelog/entry.rb +21 -0
- data/lib/doing/changelog/version.rb +97 -0
- data/lib/doing/changelog.rb +6 -0
- data/lib/doing/completion/fish_completion.rb +82 -12
- data/lib/doing/configuration.rb +17 -8
- data/lib/doing/hash.rb +25 -6
- data/lib/doing/help_monkey_patch.rb +31 -0
- data/lib/doing/hooks.rb +5 -1
- data/lib/doing/item.rb +10 -25
- data/lib/doing/items.rb +3 -1
- data/lib/doing/log_adapter.rb +1 -1
- data/lib/doing/pager.rb +2 -2
- data/lib/doing/plugins/export/dayone_export.rb +1 -1
- data/lib/doing/plugins/export/markdown_export.rb +1 -1
- data/lib/doing/plugins/export/template_export.rb +9 -3
- data/lib/doing/prompt.rb +4 -2
- data/lib/doing/string.rb +40 -11
- data/lib/doing/string_chronify.rb +56 -18
- data/lib/doing/template_string.rb +7 -0
- data/lib/doing/types.rb +25 -0
- data/lib/doing/util.rb +2 -1
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +91 -67
- data/lib/doing.rb +2 -0
- data/lib/examples/commands/later.rb +32 -0
- data/lib/helpers/threaded_tests.rb +286 -0
- 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
|
@@ -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
|
-
|
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
|
-
|
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
|
43
|
-
|
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
|
47
|
-
|
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
|
51
|
-
|
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
|
55
|
-
doing
|
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
|
@@ -62,8 +123,17 @@ module Doing
|
|
62
123
|
complete -f -c doing -n '__fish_doing_using_command view' -a '(__fish_doing_complete_views)'
|
63
124
|
complete -f -c doing -n '__fish_doing_using_command template' -a '(__fish_doing_complete_templates)'
|
64
125
|
complete -f -c doing -s t -l type -x -n '__fish_doing_using_command import' -a '(__fish_doing_import_plugins)'
|
126
|
+
complete -f -c doing -n '__fish_doing_using_command help' -a '(__fish_doing_subcommands)'
|
127
|
+
|
128
|
+
# complete -xc doing -n '__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from (doing help -c)' -a "(doing help -c)"
|
129
|
+
|
130
|
+
function __fish_doing_complete_args
|
131
|
+
for cmd in (doing commands_accepting -c $argv[1])
|
132
|
+
complete -x -c doing -l $argv[1] -n "__fish_doing_using_command $cmd" -a "(__fish_doing_complete_$argv[1])"
|
133
|
+
end
|
134
|
+
end
|
65
135
|
|
66
|
-
|
136
|
+
__fish_doing_complete_args tag
|
67
137
|
EOFUNCTIONS
|
68
138
|
end
|
69
139
|
|
@@ -161,7 +231,7 @@ module Doing
|
|
161
231
|
end
|
162
232
|
|
163
233
|
unless need_export.empty?
|
164
|
-
out << "complete -f -c doing -s o -l output -x -n '__fish_doing_using_command #{need_export.join(' ')}' -a '(
|
234
|
+
out << "complete -f -c doing -s o -l output -x -n '__fish_doing_using_command #{need_export.join(' ')}' -a '(__fish_doing_export_plugin)'"
|
165
235
|
end
|
166
236
|
|
167
237
|
unless need_bool.empty?
|
data/lib/doing/configuration.rb
CHANGED
@@ -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
|
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
|
-
|
204
|
-
|
205
|
-
|
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
|
-
|
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
|
9
|
+
## @return Hash with all values frozen
|
10
10
|
##
|
11
11
|
def deep_freeze
|
12
|
-
|
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
|
34
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
|
129
|
-
end_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
|
-
|
132
|
-
end_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(' ')
|
220
|
-
matches = tag_pattern?(tags
|
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 =
|
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 =
|
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
|
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
|
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).
|
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")
|
data/lib/doing/log_adapter.rb
CHANGED
@@ -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|
|
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} @
|
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} @
|
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
|
-
|
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
|
-
|
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')}"
|