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.
- checksums.yaml +4 -4
- data/.yardoc/checksums +14 -19
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +23 -0
- data/Dockerfile +5 -5
- data/Dockerfile-2.6 +5 -5
- data/Dockerfile-2.7 +5 -4
- data/Dockerfile-3.0 +5 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/Rakefile +2 -3
- data/bin/commands/add_section.rb +2 -0
- data/bin/commands/again.rb +23 -65
- data/bin/commands/archive.rb +20 -61
- data/bin/commands/cancel.rb +27 -69
- data/bin/commands/changes.rb +32 -5
- data/bin/commands/colors.rb +4 -2
- data/bin/commands/commands.rb +4 -2
- data/bin/commands/commands_accepting.rb +62 -11
- data/bin/commands/completion.rb +10 -7
- data/bin/commands/config.rb +1 -1
- data/bin/commands/done.rb +3 -17
- data/bin/commands/finish.rb +7 -30
- data/bin/commands/flag.rb +15 -51
- data/bin/commands/grep.rb +12 -28
- data/bin/commands/import.rb +3 -33
- data/bin/commands/last.rb +3 -36
- data/bin/commands/meanwhile.rb +3 -13
- data/bin/commands/note.rb +13 -52
- data/bin/commands/now.rb +15 -21
- data/bin/commands/on.rb +3 -4
- data/bin/commands/recent.rb +3 -4
- data/bin/commands/redo.rb +6 -2
- data/bin/commands/reset.rb +19 -52
- data/bin/commands/rotate.rb +5 -36
- data/bin/commands/select.rb +23 -41
- data/bin/commands/show.rb +28 -74
- data/bin/commands/since.rb +3 -4
- data/bin/commands/tag.rb +4 -34
- data/bin/commands/tags.rb +5 -32
- data/bin/commands/today.rb +3 -4
- data/bin/commands/view.rb +36 -73
- data/bin/commands/yesterday.rb +4 -5
- data/bin/doing +150 -13
- data/docs/doc/Array.html +3 -502
- data/docs/doc/BooleanTermParser/Clause.html +1 -1
- data/docs/doc/BooleanTermParser/Operator.html +1 -1
- data/docs/doc/BooleanTermParser/Query.html +1 -1
- data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
- data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
- data/docs/doc/BooleanTermParser.html +1 -1
- data/docs/doc/Doing/Color.html +62 -56
- data/docs/doc/Doing/Completion.html +1 -1
- data/docs/doc/Doing/Configuration.html +35 -1
- data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
- data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
- data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
- data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
- data/docs/doc/Doing/Errors/NoResults.html +1 -1
- data/docs/doc/Doing/Errors/PluginException.html +1 -1
- data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
- data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
- data/docs/doc/Doing/Errors.html +1 -1
- data/docs/doc/Doing/Hooks.html +1 -1
- data/docs/doc/Doing/Item.html +1 -1
- data/docs/doc/Doing/Items.html +2 -2
- data/docs/doc/Doing/LogAdapter.html +1 -1
- data/docs/doc/Doing/Note.html +2 -2
- data/docs/doc/Doing/Pager.html +1 -1
- data/docs/doc/Doing/Plugins.html +1 -1
- data/docs/doc/Doing/Prompt.html +1 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/TemplateString.html +2 -2
- data/docs/doc/Doing/Types.html +41 -1
- data/docs/doc/Doing/Util/Backup.html +1 -1
- data/docs/doc/Doing/Util.html +1 -1
- data/docs/doc/Doing/WWID.html +10 -10
- data/docs/doc/Doing.html +3 -3
- data/docs/doc/FalseClass.html +35 -1
- data/docs/doc/GLI/Commands/Help.html +1 -1
- data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
- data/docs/doc/GLI/Commands.html +1 -1
- data/docs/doc/GLI.html +1 -1
- data/docs/doc/Hash.html +1 -1
- data/docs/doc/Object.html +1 -1
- data/docs/doc/PhraseParser/Operator.html +1 -1
- data/docs/doc/PhraseParser/PhraseClause.html +1 -1
- data/docs/doc/PhraseParser/Query.html +1 -1
- data/docs/doc/PhraseParser/QueryParser.html +1 -1
- data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
- data/docs/doc/PhraseParser/TermClause.html +1 -1
- data/docs/doc/PhraseParser.html +1 -1
- data/docs/doc/Status.html +1 -1
- data/docs/doc/String.html +287 -3155
- data/docs/doc/Symbol.html +40 -6
- data/docs/doc/Time.html +1 -1
- data/docs/doc/TrueClass.html +35 -1
- data/docs/doc/_index.html +5 -10
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +2 -2
- data/docs/doc/index.html +2 -2
- data/docs/doc/method_list.html +278 -678
- data/docs/doc/top-level-namespace.html +2 -2
- data/doing.rdoc +277 -175
- data/lib/completion/_doing.zsh +33 -29
- data/lib/completion/doing.bash +30 -19
- data/lib/completion/doing.fish +84 -72
- data/lib/doing/array/array.rb +4 -0
- data/lib/doing/array/nested_hash.rb +17 -0
- data/lib/doing/{array.rb → array/tags.rb} +7 -25
- data/lib/doing/changelog/change.rb +26 -11
- data/lib/doing/changelog/changes.rb +13 -3
- data/lib/doing/{array_chronify.rb → chronify/array.rb} +0 -0
- data/lib/doing/chronify/chronify.rb +5 -0
- data/lib/doing/{numeric_chronify.rb → chronify/numeric.rb} +0 -0
- data/lib/doing/{string_chronify.rb → chronify/string.rb} +0 -0
- data/lib/doing/colors.rb +115 -54
- data/lib/doing/configuration.rb +4 -0
- data/lib/doing/good.rb +8 -0
- data/lib/doing/help_monkey_patch.rb +6 -5
- data/lib/doing/item.rb +5 -5
- data/lib/doing/items.rb +2 -2
- data/lib/doing/log_adapter.rb +35 -2
- data/lib/doing/normalize.rb +188 -0
- data/lib/doing/plugins/export/dayone_export.rb +1 -1
- data/lib/doing/plugins/export/html_export.rb +1 -1
- data/lib/doing/plugins/export/json_export.rb +1 -1
- data/lib/doing/plugins/export/markdown_export.rb +1 -1
- data/lib/doing/plugins/export/template_export.rb +3 -1
- data/lib/doing/prompt.rb +1 -3
- data/lib/doing/string/highlight.rb +95 -0
- data/lib/doing/string/query.rb +129 -0
- data/lib/doing/string/string.rb +12 -0
- data/lib/doing/string/tags.rb +164 -0
- data/lib/doing/string/transform.rb +168 -0
- data/lib/doing/string/truncate.rb +75 -0
- data/lib/doing/string/url.rb +82 -0
- data/lib/doing/template_string.rb +0 -22
- data/lib/doing/types.rb +8 -0
- data/lib/doing/util.rb +13 -9
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +53 -35
- data/lib/doing.rb +4 -6
- data/lib/examples/plugins/wiki_export/wiki_export.rb +1 -1
- data/lib/helpers/threaded_tests.rb +15 -2
- data/scripts/deploy.rb +107 -0
- data/scripts/runtests.sh +4 -0
- metadata +19 -8
- data/lib/doing/string.rb +0 -765
- data/lib/doing/symbol.rb +0 -28
data/bin/commands/tags.rb
CHANGED
|
@@ -18,41 +18,14 @@ command :tags do |c|
|
|
|
18
18
|
|
|
19
19
|
c.desc 'Sort order (asc/desc)'
|
|
20
20
|
c.arg_name 'ORDER'
|
|
21
|
-
c.flag %i[o order], must_match: REGEX_SORT_ORDER, default_value:
|
|
22
|
-
|
|
23
|
-
c.desc 'Get tags for entries matching tags. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
|
24
|
-
c.arg_name 'TAG'
|
|
25
|
-
c.flag [:tag]
|
|
26
|
-
|
|
27
|
-
c.desc 'Get tags for items matching search. Surround with
|
|
28
|
-
slashes for regex (e.g. "/query/"), start with a single quote for exact match ("\'query").'
|
|
29
|
-
c.arg_name 'QUERY'
|
|
30
|
-
c.flag [:search]
|
|
31
|
-
|
|
32
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
33
|
-
c.arg_name 'QUERY'
|
|
34
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
35
|
-
|
|
36
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
37
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
38
|
-
|
|
39
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
40
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
41
|
-
|
|
42
|
-
c.desc 'Get tags from items that *don\'t* match search/tag filters'
|
|
43
|
-
c.switch [:not], default_value: false, negatable: false
|
|
44
|
-
|
|
45
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
46
|
-
c.arg_name 'TYPE'
|
|
47
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
48
|
-
|
|
49
|
-
c.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
|
|
50
|
-
c.arg_name 'BOOLEAN'
|
|
51
|
-
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
21
|
+
c.flag %i[o order], must_match: REGEX_SORT_ORDER, default_value: :asc, type: OrderSymbol
|
|
52
22
|
|
|
53
23
|
c.desc 'Select items to scan from a menu of matching entries'
|
|
54
24
|
c.switch %i[i interactive], negatable: false, default_value: false
|
|
55
25
|
|
|
26
|
+
add_options(:search, c)
|
|
27
|
+
add_options(:tag_filter, c)
|
|
28
|
+
|
|
56
29
|
c.action do |_global, options, args|
|
|
57
30
|
section = @wwid.guess_section(options[:section]) || options[:section].cap_first
|
|
58
31
|
options[:count] = args.count.positive? ? args[0].to_i : 0
|
|
@@ -78,7 +51,7 @@ command :tags do |c|
|
|
|
78
51
|
tags = tags.sort_by { |tag, count| count }
|
|
79
52
|
end
|
|
80
53
|
|
|
81
|
-
tags.reverse! if options[:order]
|
|
54
|
+
tags.reverse! if options[:order] == :desc
|
|
82
55
|
|
|
83
56
|
if options[:counts]
|
|
84
57
|
tags.each { |t, c| puts "#{t} (#{c})" }
|
data/bin/commands/today.rb
CHANGED
|
@@ -22,10 +22,9 @@ command :today do |c|
|
|
|
22
22
|
c.switch [:totals], default_value: false, negatable: false
|
|
23
23
|
|
|
24
24
|
c.desc 'Sort tags by (name|time)'
|
|
25
|
-
default = '
|
|
26
|
-
default = @settings['tag_sort'] || 'name'
|
|
25
|
+
default = @settings['tag_sort'].normalize_tag_sort || :name
|
|
27
26
|
c.arg_name 'KEY'
|
|
28
|
-
c.flag [:tag_sort], must_match:
|
|
27
|
+
c.flag [:tag_sort], must_match: REGEX_TAG_SORT, default_value: default, type: TagSortSymbol
|
|
29
28
|
|
|
30
29
|
c.desc "Output to export format (#{Doing::Plugins.plugin_names(type: :export)})"
|
|
31
30
|
c.arg_name 'FORMAT'
|
|
@@ -57,7 +56,7 @@ command :today do |c|
|
|
|
57
56
|
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}") if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
58
57
|
|
|
59
58
|
options[:times] = true if options[:totals]
|
|
60
|
-
options[:sort_tags] = options[:tag_sort]
|
|
59
|
+
options[:sort_tags] = options[:tag_sort]
|
|
61
60
|
filter_options = %i[after before duration from section sort_tags totals template config_template].each_with_object({}) { |k, hsh| hsh[k] = options[k] }
|
|
62
61
|
|
|
63
62
|
Doing::Pager.page @wwid.today(options[:times], options[:output], filter_options).chomp
|
data/bin/commands/view.rb
CHANGED
|
@@ -21,7 +21,7 @@ command :view do |c|
|
|
|
21
21
|
|
|
22
22
|
c.desc 'Age (oldest|newest)'
|
|
23
23
|
c.arg_name 'AGE'
|
|
24
|
-
c.flag %i[age], default_value:
|
|
24
|
+
c.flag %i[age], default_value: :newest, type: AgeSymbol
|
|
25
25
|
|
|
26
26
|
c.desc 'Show time intervals on @done tasks'
|
|
27
27
|
c.switch %i[t times], default_value: true, negatable: true
|
|
@@ -35,64 +35,16 @@ command :view do |c|
|
|
|
35
35
|
c.desc 'Include colors in output'
|
|
36
36
|
c.switch [:color], default_value: true, negatable: true
|
|
37
37
|
|
|
38
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
|
39
|
-
c.arg_name 'TAG'
|
|
40
|
-
c.flag [:tag]
|
|
41
|
-
|
|
42
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
43
|
-
c.arg_name 'QUERY'
|
|
44
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
45
|
-
|
|
46
|
-
c.desc 'Tag boolean (AND,OR,NOT). Use PATTERN to parse + and - as booleans'
|
|
47
|
-
c.arg_name 'BOOLEAN'
|
|
48
|
-
c.flag %i[b bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
49
|
-
|
|
50
|
-
c.desc 'Search filter, surround with slashes for regex (/query/), start with single quote for exact match ("\'query")'
|
|
51
|
-
c.arg_name 'QUERY'
|
|
52
|
-
c.flag [:search]
|
|
53
|
-
|
|
54
38
|
c.desc "Highlight search matches in output. Only affects command line output"
|
|
55
39
|
c.switch %i[h hilite], default_value: @settings.dig('search', 'highlight')
|
|
56
40
|
|
|
57
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
58
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
59
|
-
|
|
60
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
61
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
62
|
-
|
|
63
|
-
c.desc 'Show items that *don\'t* match search string'
|
|
64
|
-
c.switch [:not], default_value: false, negatable: false
|
|
65
|
-
|
|
66
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
67
|
-
c.arg_name 'TYPE'
|
|
68
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
69
|
-
|
|
70
41
|
c.desc 'Sort tags by (name|time)'
|
|
71
42
|
c.arg_name 'KEY'
|
|
72
|
-
c.flag [:tag_sort], must_match:
|
|
43
|
+
c.flag [:tag_sort], must_match: REGEX_TAG_SORT, type: TagSortSymbol
|
|
73
44
|
|
|
74
45
|
c.desc 'Tag sort direction (asc|desc)'
|
|
75
46
|
c.arg_name 'DIRECTION'
|
|
76
|
-
c.flag [:tag_order], must_match: REGEX_SORT_ORDER
|
|
77
|
-
|
|
78
|
-
c.desc 'View entries older than date. If this is only a time (8am, 1:30pm, 15:00), all dates will be included, but entries will be filtered by time of day'
|
|
79
|
-
c.arg_name 'DATE_STRING'
|
|
80
|
-
c.flag [:before], type: DateBeginString
|
|
81
|
-
|
|
82
|
-
c.desc 'View entries newer than date. If this is only a time (8am, 1:30pm, 15:00), all dates will be included, but entries will be filtered by time of day'
|
|
83
|
-
c.arg_name 'DATE_STRING'
|
|
84
|
-
c.flag [:after], type: DateEndString
|
|
85
|
-
|
|
86
|
-
c.desc %(
|
|
87
|
-
Date range to show, or a single day to filter date on.
|
|
88
|
-
Date range argument should be quoted. Date specifications can be natural language.
|
|
89
|
-
To specify a range, use "to" or "through": `doing view --from "monday 8am to friday 5pm" view_name`.
|
|
90
|
-
|
|
91
|
-
If values are only time(s) (6am to noon) all dates will be included, but entries will be filtered
|
|
92
|
-
by time of day.
|
|
93
|
-
)
|
|
94
|
-
c.arg_name 'DATE_OR_RANGE'
|
|
95
|
-
c.flag [:from], type: DateRangeString
|
|
47
|
+
c.flag [:tag_order], must_match: REGEX_SORT_ORDER, type: OrderSymbol
|
|
96
48
|
|
|
97
49
|
c.desc 'Only show items with recorded time intervals (override view settings)'
|
|
98
50
|
c.switch [:only_timed], default_value: false, negatable: false
|
|
@@ -100,9 +52,16 @@ command :view do |c|
|
|
|
100
52
|
c.desc 'Select from a menu of matching entries to perform additional operations'
|
|
101
53
|
c.switch %i[i interactive], negatable: false, default_value: false
|
|
102
54
|
|
|
55
|
+
add_options(:search, c)
|
|
56
|
+
add_options(:tag_filter, c)
|
|
57
|
+
add_options(:date_filter, c)
|
|
58
|
+
|
|
103
59
|
c.action do |global_options, options, args|
|
|
104
60
|
options[:fuzzy] = false
|
|
105
|
-
|
|
61
|
+
if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
62
|
+
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}")
|
|
63
|
+
|
|
64
|
+
end
|
|
106
65
|
|
|
107
66
|
raise InvalidArgument, '--tag and --search can not be used together' if options[:tag] && options[:search]
|
|
108
67
|
|
|
@@ -111,20 +70,20 @@ command :view do |c|
|
|
|
111
70
|
else
|
|
112
71
|
begin
|
|
113
72
|
@wwid.guess_view(args[0])
|
|
114
|
-
rescue WrongCommand
|
|
73
|
+
rescue WrongCommand
|
|
115
74
|
cmd = commands[:show]
|
|
116
|
-
options[:sort] =
|
|
117
|
-
options[:tag_order] =
|
|
75
|
+
options[:sort] = :asc
|
|
76
|
+
options[:tag_order] = :asc
|
|
118
77
|
action = cmd.send(:get_action, nil)
|
|
119
78
|
return action.call(global_options, options, args)
|
|
120
79
|
end
|
|
121
80
|
end
|
|
122
81
|
|
|
123
|
-
if options[:section]
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
82
|
+
section = if options[:section]
|
|
83
|
+
@wwid.guess_section(options[:section]) || options[:section].cap_first
|
|
84
|
+
else
|
|
85
|
+
@settings['current_section']
|
|
86
|
+
end
|
|
128
87
|
|
|
129
88
|
view = @wwid.get_view(title)
|
|
130
89
|
|
|
@@ -143,7 +102,7 @@ command :view do |c|
|
|
|
143
102
|
tag_filter = false
|
|
144
103
|
if options[:tag]
|
|
145
104
|
tag_filter = { 'tags' => [], 'bool' => 'OR' }
|
|
146
|
-
bool = options[:bool]
|
|
105
|
+
bool = options[:bool]
|
|
147
106
|
tag_filter['bool'] = bool
|
|
148
107
|
tag_filter['tags'] = if bool == :pattern
|
|
149
108
|
options[:tag]
|
|
@@ -164,41 +123,45 @@ command :view do |c|
|
|
|
164
123
|
# If the -o/--output flag was specified, override any default in the view template
|
|
165
124
|
options[:output] ||= view.key?('output_format') ? view['output_format'] : 'template'
|
|
166
125
|
|
|
167
|
-
count =
|
|
126
|
+
count = if options[:count]
|
|
127
|
+
options[:count]
|
|
128
|
+
elsif view.key?('count')
|
|
129
|
+
view['count']
|
|
130
|
+
else
|
|
131
|
+
10
|
|
132
|
+
end
|
|
168
133
|
|
|
169
134
|
section = if options[:section]
|
|
170
135
|
section
|
|
171
136
|
else
|
|
172
137
|
view['section'] || @settings['current_section']
|
|
173
138
|
end
|
|
174
|
-
order = view
|
|
139
|
+
order = if view.key?('order')
|
|
140
|
+
view['order'].normalize_order
|
|
141
|
+
else
|
|
142
|
+
:asc
|
|
143
|
+
end
|
|
175
144
|
|
|
176
145
|
totals = if options[:totals]
|
|
177
146
|
true
|
|
178
147
|
else
|
|
179
148
|
view['totals'] || false
|
|
180
149
|
end
|
|
181
|
-
tag_order =
|
|
182
|
-
options[:tag_order].normalize_order
|
|
183
|
-
else
|
|
184
|
-
view['tag_order']&.normalize_order || 'asc'
|
|
185
|
-
end
|
|
150
|
+
tag_order = options[:tag_order] || view['tag_order']&.normalize_order || :asc
|
|
186
151
|
|
|
187
152
|
options[:times] = true if totals
|
|
188
153
|
output_format = options[:output]&.downcase || 'template'
|
|
189
154
|
|
|
190
155
|
options[:sort_tags] = if options[:tag_sort]
|
|
191
|
-
options[:tag_sort]
|
|
156
|
+
options[:tag_sort]
|
|
192
157
|
elsif view.key?('tag_sort')
|
|
193
|
-
view['tag_sort']
|
|
158
|
+
view['tag_sort'].normalize_tag_sort
|
|
194
159
|
else
|
|
195
160
|
false
|
|
196
161
|
end
|
|
197
162
|
|
|
198
163
|
%w[before after from duration].each { |k| options[k.to_sym] = view[k] if view.key?(k) && !options[k.to_sym] }
|
|
199
164
|
|
|
200
|
-
options[:case] = options[:case].normalize_case
|
|
201
|
-
|
|
202
165
|
search = nil
|
|
203
166
|
|
|
204
167
|
if options[:search]
|
|
@@ -209,7 +172,7 @@ command :view do |c|
|
|
|
209
172
|
options[:age] ||= :newest
|
|
210
173
|
|
|
211
174
|
opts = options.clone
|
|
212
|
-
opts[:age] = options[:age]
|
|
175
|
+
opts[:age] = options[:age]
|
|
213
176
|
opts[:count] = count
|
|
214
177
|
opts[:format] = date_format
|
|
215
178
|
opts[:highlight] = options[:color]
|
data/bin/commands/yesterday.rb
CHANGED
|
@@ -33,9 +33,9 @@ command :yesterday do |c|
|
|
|
33
33
|
c.switch [:totals], default_value: false, negatable: false
|
|
34
34
|
|
|
35
35
|
c.desc 'Sort tags by (name|time)'
|
|
36
|
-
default = @settings['tag_sort'] ||
|
|
36
|
+
default = @settings['tag_sort'].normalize_tag_sort || :name
|
|
37
37
|
c.arg_name 'KEY'
|
|
38
|
-
c.flag [:tag_sort], must_match:
|
|
38
|
+
c.flag [:tag_sort], must_match: REGEX_TAG_SORT, default_value: default, type: TagSortSymbol
|
|
39
39
|
|
|
40
40
|
c.desc 'View entries before specified time (e.g. 8am, 12:30pm, 15:00)'
|
|
41
41
|
c.arg_name 'TIME_STRING'
|
|
@@ -51,12 +51,12 @@ command :yesterday do |c|
|
|
|
51
51
|
|
|
52
52
|
c.desc 'Tag sort direction (asc|desc)'
|
|
53
53
|
c.arg_name 'DIRECTION'
|
|
54
|
-
c.flag [:tag_order], must_match: REGEX_SORT_ORDER, default_value:
|
|
54
|
+
c.flag [:tag_order], must_match: REGEX_SORT_ORDER, default_value: :asc, type: OrderSymbol
|
|
55
55
|
|
|
56
56
|
c.action do |_global_options, options, _args|
|
|
57
57
|
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}") if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
58
58
|
|
|
59
|
-
options[:sort_tags] = options[:tag_sort]
|
|
59
|
+
options[:sort_tags] = options[:tag_sort]
|
|
60
60
|
|
|
61
61
|
if options[:from]
|
|
62
62
|
options[:from] = options[:from].split(/#{REGEX_RANGE_INDICATOR}/).map do |time|
|
|
@@ -65,7 +65,6 @@ command :yesterday do |c|
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
opt = options.clone
|
|
68
|
-
opt[:tag_order] = options[:tag_order].normalize_order
|
|
69
68
|
opt[:order] = @settings.dig('templates', options[:config_template], 'order')
|
|
70
69
|
|
|
71
70
|
Doing::Pager.page @wwid.yesterday(options[:section], options[:times], options[:output], opt).chomp
|
data/bin/doing
CHANGED
|
@@ -38,11 +38,11 @@ env_log_level = nil
|
|
|
38
38
|
if ENV['DOING_LOG_LEVEL'] || ENV['DOING_DEBUG'] || ENV['DOING_QUIET'] || ENV['DOING_VERBOSE'] || ENV['DOING_PLUGIN_DEBUG']
|
|
39
39
|
env_log_level = true
|
|
40
40
|
# Quiet always wins
|
|
41
|
-
if ENV['DOING_QUIET']
|
|
41
|
+
if ENV['DOING_QUIET']&.truthy?
|
|
42
42
|
Doing.logger.log_level = :error
|
|
43
|
-
elsif
|
|
43
|
+
elsif ENV['DOING_PLUGIN_DEBUG']&.truthy?
|
|
44
44
|
Doing.logger.log_level = :debug
|
|
45
|
-
elsif
|
|
45
|
+
elsif ENV['DOING_DEBUG']&.truthy?
|
|
46
46
|
Doing.logger.log_level = :debug
|
|
47
47
|
elsif ENV['DOING_LOG_LEVEL']
|
|
48
48
|
Doing.logger.log_level = ENV['DOING_LOG_LEVEL']
|
|
@@ -51,11 +51,8 @@ end
|
|
|
51
51
|
|
|
52
52
|
Doing.logger.benchmark(:total, :start)
|
|
53
53
|
|
|
54
|
-
if ENV['DOING_CONFIG']
|
|
55
|
-
Doing.config_with(ENV['DOING_CONFIG'], { ignore_local: true })
|
|
56
|
-
end
|
|
57
|
-
|
|
58
54
|
Doing.logger.benchmark(:configure, :start)
|
|
55
|
+
Doing.config_with(ENV['DOING_CONFIG'], { ignore_local: true }) if ENV['DOING_CONFIG']
|
|
59
56
|
@config = Doing.config
|
|
60
57
|
Doing.logger.benchmark(:configure, :finish)
|
|
61
58
|
|
|
@@ -63,8 +60,30 @@ Doing.logger.benchmark(:configure, :finish)
|
|
|
63
60
|
@settings = @config.settings
|
|
64
61
|
@wwid.config = @settings
|
|
65
62
|
|
|
66
|
-
if @settings.dig('plugins', 'command_path')
|
|
67
|
-
|
|
63
|
+
commands_from File.expand_path(@settings.dig('plugins', 'command_path')) if @settings.dig('plugins', 'command_path')
|
|
64
|
+
|
|
65
|
+
accept BooleanSymbol do |value|
|
|
66
|
+
value.normalize_bool(:pattern)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
accept CaseSymbol do |value|
|
|
70
|
+
value.normalize_case(@config.fetch('search', 'case', :smart))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
accept AgeSymbol do |value|
|
|
74
|
+
value.normalize_age(:newest)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
accept OrderSymbol do |value|
|
|
78
|
+
value.normalize_order(:asc)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
accept MatchingSymbol do |value|
|
|
82
|
+
value.normalize_matching(:pattern)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
accept TagSortSymbol do |value|
|
|
86
|
+
value.normalize_tag_sort(@config.fetch('tag_sort', :name))
|
|
68
87
|
end
|
|
69
88
|
|
|
70
89
|
accept TemplateName do |value|
|
|
@@ -119,7 +138,123 @@ accept DateIntervalString do |value|
|
|
|
119
138
|
end
|
|
120
139
|
|
|
121
140
|
accept TagArray do |value|
|
|
122
|
-
value.gsub(/[, ]+/, ' ').split(' ').map { |tag| tag.sub(/^@/, '')}.map(&:strip)
|
|
141
|
+
value.gsub(/[, ]+/, ' ').split(' ').map { |tag| tag.sub(/^@/, '') }.map(&:strip)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
##
|
|
145
|
+
## Add presets of flags and switches to a command.
|
|
146
|
+
##
|
|
147
|
+
## :add_entry => --noauto, --note, --ask, --editor, --back
|
|
148
|
+
##
|
|
149
|
+
## :search => --search, --case, --exact
|
|
150
|
+
##
|
|
151
|
+
## :tag_filter => --tag, --bool, --not, --val
|
|
152
|
+
##
|
|
153
|
+
## :date_filter => --before, --after, --from
|
|
154
|
+
##
|
|
155
|
+
## @param type [Symbol] The type
|
|
156
|
+
## @param cmd The GLI command to which the options will be added
|
|
157
|
+
##
|
|
158
|
+
def add_options(type, cmd)
|
|
159
|
+
cmd_name = cmd.name.to_s
|
|
160
|
+
action = case cmd_name
|
|
161
|
+
when /again/
|
|
162
|
+
'Repeat'
|
|
163
|
+
when /grep/
|
|
164
|
+
'Search'
|
|
165
|
+
when /mark/
|
|
166
|
+
'Flag'
|
|
167
|
+
when /(last|tags|view)/
|
|
168
|
+
'Show'
|
|
169
|
+
else
|
|
170
|
+
cmd_name.capitalize
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
case type
|
|
174
|
+
when :add_entry
|
|
175
|
+
cmd.desc 'Exclude auto tags and default tags'
|
|
176
|
+
cmd.switch %i[X noauto], default_value: false, negatable: false
|
|
177
|
+
|
|
178
|
+
cmd.desc 'Include a note'
|
|
179
|
+
cmd.arg_name 'TEXT'
|
|
180
|
+
cmd.flag %i[n note]
|
|
181
|
+
|
|
182
|
+
cmd.desc 'Prompt for note via multi-line input'
|
|
183
|
+
cmd.switch %i[ask], negatable: false, default_value: false
|
|
184
|
+
|
|
185
|
+
cmd.desc "Edit entry with #{Doing::Util.default_editor}"
|
|
186
|
+
cmd.switch %i[e editor], negatable: false, default_value: false
|
|
187
|
+
|
|
188
|
+
cmd.desc 'Backdate start date for new entry to date string [4pm|20m|2h|yesterday noon]'
|
|
189
|
+
cmd.arg_name 'DATE_STRING'
|
|
190
|
+
cmd.flag %i[b back started], type: DateBeginString
|
|
191
|
+
when :search
|
|
192
|
+
cmd.desc 'Filter entries using a search query, surround with slashes for regex (e.g. "/query.*/"),
|
|
193
|
+
start with single quote for exact match ("\'query")'
|
|
194
|
+
cmd.arg_name 'QUERY'
|
|
195
|
+
cmd.flag [:search]
|
|
196
|
+
|
|
197
|
+
cmd.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
198
|
+
cmd.arg_name 'TYPE'
|
|
199
|
+
cmd.flag [:case], must_match: REGEX_CASE,
|
|
200
|
+
default_value: @settings.dig('search', 'case').normalize_case,
|
|
201
|
+
type: CaseSymbol
|
|
202
|
+
|
|
203
|
+
cmd.desc 'Force exact search string matching (case sensitive)'
|
|
204
|
+
cmd.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
205
|
+
when :tag_filter
|
|
206
|
+
cmd.desc 'Filter entries by tag. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
|
207
|
+
cmd.arg_name 'TAG'
|
|
208
|
+
cmd.flag [:tag], type: TagArray
|
|
209
|
+
|
|
210
|
+
cmd.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50").
|
|
211
|
+
May be used multiple times, combined with --bool'
|
|
212
|
+
cmd.arg_name 'QUERY'
|
|
213
|
+
cmd.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
214
|
+
|
|
215
|
+
cmd.desc "#{action} items that *don't* match search/tag filters"
|
|
216
|
+
cmd.switch [:not], default_value: false, negatable: false
|
|
217
|
+
|
|
218
|
+
cmd.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
|
|
219
|
+
cmd.arg_name 'BOOLEAN'
|
|
220
|
+
cmd.flag [:bool], must_match: REGEX_BOOL,
|
|
221
|
+
default_value: :pattern,
|
|
222
|
+
type: BooleanSymbol
|
|
223
|
+
when :date_filter
|
|
224
|
+
if action =~ /Archive/
|
|
225
|
+
cmd.desc 'Archive entries older than date (natural language).'
|
|
226
|
+
else
|
|
227
|
+
cmd.desc "#{action} entries older than date (natural language). If this is only a time (8am, 1:30pm, 15:00), all
|
|
228
|
+
dates will be included, but entries will be filtered by time of day"
|
|
229
|
+
end
|
|
230
|
+
cmd.arg_name 'DATE_STRING'
|
|
231
|
+
cmd.flag [:before], type: DateBeginString
|
|
232
|
+
|
|
233
|
+
if action =~ /Archive/
|
|
234
|
+
cmd.desc 'Archive entries newer than date (natural language).'
|
|
235
|
+
else
|
|
236
|
+
cmd.desc "#{action} entries newer than date (natural language). If this is only a time (8am, 1:30pm, 15:00), all
|
|
237
|
+
dates will be included, but entries will be filtered by time of day"
|
|
238
|
+
end
|
|
239
|
+
cmd.arg_name 'DATE_STRING'
|
|
240
|
+
cmd.flag [:after], type: DateEndString
|
|
241
|
+
|
|
242
|
+
if action =~ /Archive/
|
|
243
|
+
cmd.desc %(
|
|
244
|
+
Date range (natural language) to archive: `doing archive --from "1/1/21 to 12/31/21"`.
|
|
245
|
+
)
|
|
246
|
+
else
|
|
247
|
+
cmd.desc %(
|
|
248
|
+
Date range (natural language) to #{action.downcase}, or a single day to filter on.
|
|
249
|
+
To specify a range, use "to": `doing #{cmd_name} --from "monday 8am to friday 5pm"`.
|
|
250
|
+
|
|
251
|
+
If values are only time(s) (6am to noon) all dates will be included, but entries will be filtered
|
|
252
|
+
by time of day.
|
|
253
|
+
)
|
|
254
|
+
end
|
|
255
|
+
cmd.arg_name 'DATE_OR_RANGE'
|
|
256
|
+
cmd.flag [:from], type: DateRangeString
|
|
257
|
+
end
|
|
123
258
|
end
|
|
124
259
|
|
|
125
260
|
program_desc 'A CLI for a What Was I Doing system'
|
|
@@ -192,7 +327,6 @@ add_commands(%w[commands_accepting install_fzf])
|
|
|
192
327
|
## Optional commands
|
|
193
328
|
add_commands(%w[again cancel flag meanwhile reset tags today yesterday since add_section tag_dir colors completion plugins sections template views changes])
|
|
194
329
|
|
|
195
|
-
|
|
196
330
|
pre do |global, _command, _options, _args|
|
|
197
331
|
# global[:pager] ||= @settings['paginate']
|
|
198
332
|
Doing::Pager.paginate = global[:pager]
|
|
@@ -232,6 +366,7 @@ post do |global, _command, _options, _args|
|
|
|
232
366
|
end
|
|
233
367
|
|
|
234
368
|
around do |global, command, options, arguments, code|
|
|
369
|
+
Doing.logger.benchmark("command_#{command.name.to_s}".to_sym, :start)
|
|
235
370
|
# Doing.logger.debug('Pager:', "Global: #{global[:pager]}, Config: #{@settings['paginate']}, Pager: #{Doing::Pager.paginate}")
|
|
236
371
|
if env_log_level.nil?
|
|
237
372
|
Doing.logger.adjust_verbosity(global)
|
|
@@ -242,10 +377,10 @@ around do |global, command, options, arguments, code|
|
|
|
242
377
|
end
|
|
243
378
|
|
|
244
379
|
if global[:yes]
|
|
245
|
-
Doing::Prompt.force_answer =
|
|
380
|
+
Doing::Prompt.force_answer = :yes
|
|
246
381
|
Doing.config.force_answer = true
|
|
247
382
|
elsif global[:no]
|
|
248
|
-
Doing::Prompt.force_answer =
|
|
383
|
+
Doing::Prompt.force_answer = :no
|
|
249
384
|
Doing.config.force_answer = false
|
|
250
385
|
else
|
|
251
386
|
Doing::Prompt.default_answer = if $stdout.isatty
|
|
@@ -281,6 +416,8 @@ around do |global, command, options, arguments, code|
|
|
|
281
416
|
global[:wwid] = @wwid
|
|
282
417
|
|
|
283
418
|
code.call
|
|
419
|
+
|
|
420
|
+
Doing.logger.benchmark("command_#{command.name.to_s}".to_sym, :finish)
|
|
284
421
|
end
|
|
285
422
|
|
|
286
423
|
exit run(ARGV)
|