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
|
@@ -1,25 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# @@commands_accepting
|
|
2
4
|
arg_name 'OPTION'
|
|
3
5
|
command :commands_accepting do |c|
|
|
4
6
|
c.desc 'Output in single column for completion'
|
|
5
7
|
c.switch %i[c column]
|
|
6
8
|
|
|
9
|
+
c.desc 'Join multiple arguments using boolean (AND|OR|NOT)'
|
|
10
|
+
c.flag [:bool], must_match: REGEX_BOOL,
|
|
11
|
+
default_value: :and,
|
|
12
|
+
type: BooleanSymbol
|
|
13
|
+
|
|
7
14
|
c.action do |g, o, a|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
cmds = []
|
|
16
|
+
commands.each { |cmd, v| cmds.push(cmd) if has_flags?(v, a, o[:bool]) }
|
|
17
|
+
|
|
18
|
+
if o[:column]
|
|
19
|
+
puts cmds.sort
|
|
20
|
+
else
|
|
21
|
+
description = "Commands "
|
|
22
|
+
description += "not " if o[:bool] == :not
|
|
23
|
+
description += "accepting "
|
|
24
|
+
description += a.map { |arg| "--#{arg}" }.join(o[:bool] == :and ? ' and ' : ' or ')
|
|
25
|
+
puts "#{description}: #{cmds.sort.join(', ')}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def has_flags?(options, args, bool)
|
|
30
|
+
case bool
|
|
31
|
+
when :and
|
|
32
|
+
all_flags?(options, args)
|
|
33
|
+
when :not
|
|
34
|
+
no_flags?(options, args)
|
|
35
|
+
else
|
|
36
|
+
any_flags?(options, args)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def all_flags?(options, args)
|
|
41
|
+
args.each do |arg|
|
|
42
|
+
has_flag = false
|
|
43
|
+
options.flags.merge(options.switches).each do |_, flag|
|
|
44
|
+
if flag.name == arg.to_sym || flag.aliases&.include?(arg.to_sym)
|
|
45
|
+
has_flag = true
|
|
46
|
+
break
|
|
15
47
|
end
|
|
16
48
|
end
|
|
49
|
+
return false unless has_flag
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def any_flags?(options, args)
|
|
56
|
+
args.each do |option|
|
|
57
|
+
options.flags.merge(options.switches).each do |_, flag|
|
|
58
|
+
return true if flag.name == option.to_sym || flag.aliases&.include?(option.to_sym)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
17
61
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
62
|
+
false
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def no_flags?(options, args)
|
|
66
|
+
args.each do |option|
|
|
67
|
+
options.flags.merge(options.switches).each do |_, flag|
|
|
68
|
+
return false if flag.name == option.to_sym || flag.aliases&.include?(option.to_sym)
|
|
22
69
|
end
|
|
23
70
|
end
|
|
71
|
+
|
|
72
|
+
true
|
|
24
73
|
end
|
|
25
74
|
end
|
|
75
|
+
|
|
76
|
+
|
data/bin/commands/completion.rb
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# @@completion
|
|
2
4
|
desc 'Generate shell completion scripts'
|
|
3
|
-
long_desc 'Generates the necessary scripts to add command line completion to various shells,
|
|
4
|
-
tab will offer completions of subcommands and their options.'
|
|
5
|
+
long_desc 'Generates the necessary scripts to add command line completion to various shells,
|
|
6
|
+
so typing \'doing\' and hitting tab will offer completions of subcommands and their options.'
|
|
5
7
|
command :completion do |c|
|
|
6
8
|
c.example 'doing completion', desc: 'Output zsh (default) to STDOUT'
|
|
7
|
-
c.example 'doing completion --type zsh --file ~/.zsh-completions/_doing.zsh',
|
|
8
|
-
|
|
9
|
-
c.example 'doing completion --type
|
|
9
|
+
c.example 'doing completion --type zsh --file ~/.zsh-completions/_doing.zsh',
|
|
10
|
+
desc: 'Output zsh completions to file'
|
|
11
|
+
c.example 'doing completion --type fish --file ~/.config/fish/completions/doing.fish',
|
|
12
|
+
desc: 'Output fish completions to file'
|
|
13
|
+
c.example 'doing completion --type bash --file ~/.bash_it/completion/enabled/doing.bash',
|
|
14
|
+
desc: 'Output bash completions to file'
|
|
10
15
|
|
|
11
16
|
c.desc 'Shell to generate for (bash, zsh, fish)'
|
|
12
17
|
c.arg_name 'SHELL'
|
|
@@ -17,8 +22,6 @@ command :completion do |c|
|
|
|
17
22
|
c.flag %i[f file], default_value: 'STDOUT'
|
|
18
23
|
|
|
19
24
|
c.action do |_global_options, options, _args|
|
|
20
|
-
script_dir = File.join(File.dirname(__FILE__), '..', 'scripts')
|
|
21
|
-
|
|
22
25
|
Doing::Completion.generate_completion(type: options[:type], file: options[:file])
|
|
23
26
|
end
|
|
24
27
|
end
|
data/bin/commands/config.rb
CHANGED
data/bin/commands/done.rb
CHANGED
|
@@ -24,10 +24,6 @@ command %i[done did] do |c|
|
|
|
24
24
|
c.arg_name 'DATE_STRING'
|
|
25
25
|
c.flag %i[at finished], type: DateEndString
|
|
26
26
|
|
|
27
|
-
c.desc 'Backdate start date by interval or set to time [4pm|20m|2h|"yesterday noon"]'
|
|
28
|
-
c.arg_name 'DATE_STRING'
|
|
29
|
-
c.flag %i[b back started], type: DateBeginString
|
|
30
|
-
|
|
31
27
|
c.desc %(
|
|
32
28
|
Start and end times as a date/time range `doing done --from "1am to 8am"`.
|
|
33
29
|
Overrides other date flags.
|
|
@@ -45,24 +41,14 @@ command %i[done did] do |c|
|
|
|
45
41
|
c.arg_name 'NAME'
|
|
46
42
|
c.flag %i[s section]
|
|
47
43
|
|
|
48
|
-
c.desc "Edit entry with #{Doing::Util.default_editor} (with no arguments, edits the last entry)"
|
|
49
|
-
c.switch %i[e editor], negatable: false, default_value: false
|
|
50
|
-
|
|
51
|
-
c.desc 'Include a note'
|
|
52
|
-
c.arg_name 'TEXT'
|
|
53
|
-
c.flag %i[n note]
|
|
54
|
-
|
|
55
|
-
c.desc 'Prompt for note via multi-line input'
|
|
56
|
-
c.switch %i[ask], negatable: false, default_value: false
|
|
57
|
-
|
|
58
44
|
c.desc 'Finish last entry not already marked @done'
|
|
59
45
|
c.switch %i[u unfinished], negatable: false, default_value: false
|
|
60
46
|
|
|
61
|
-
|
|
62
|
-
# c.arg_name 'editor_app'
|
|
63
|
-
# # c.flag [:a, :app]
|
|
47
|
+
add_options(:add_entry, c)
|
|
64
48
|
|
|
65
49
|
c.action do |_global_options, options, args|
|
|
50
|
+
@wwid.auto_tag = !options[:noauto]
|
|
51
|
+
|
|
66
52
|
took = 0
|
|
67
53
|
donedate = nil
|
|
68
54
|
|
data/bin/commands/finish.rb
CHANGED
|
@@ -22,37 +22,10 @@ command :finish do |c|
|
|
|
22
22
|
c.arg_name 'DATE_STRING'
|
|
23
23
|
c.flag %i[at finished], type: DateEndString
|
|
24
24
|
|
|
25
|
-
c.desc '
|
|
26
|
-
|
|
27
|
-
c.arg_name 'TAG'
|
|
28
|
-
c.flag [:tag], type: TagArray
|
|
25
|
+
c.desc 'Overwrite existing @done tag with new date'
|
|
26
|
+
c.switch %i[update], negatable: false, default_value: false
|
|
29
27
|
|
|
30
|
-
c.desc '
|
|
31
|
-
c.arg_name 'QUERY'
|
|
32
|
-
c.flag [:search]
|
|
33
|
-
|
|
34
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
35
|
-
c.arg_name 'QUERY'
|
|
36
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
37
|
-
|
|
38
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
39
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
40
|
-
|
|
41
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
42
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
43
|
-
|
|
44
|
-
c.desc 'Finish items that *don\'t* match search/tag filters'
|
|
45
|
-
c.switch [:not], default_value: false, negatable: false
|
|
46
|
-
|
|
47
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
48
|
-
c.arg_name 'TYPE'
|
|
49
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
50
|
-
|
|
51
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
|
52
|
-
c.arg_name 'BOOLEAN'
|
|
53
|
-
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
54
|
-
|
|
55
|
-
c.desc 'Remove done tag'
|
|
28
|
+
c.desc 'Remove @done tag'
|
|
56
29
|
c.switch %i[r remove], negatable: false, default_value: false
|
|
57
30
|
|
|
58
31
|
c.desc 'Finish last entry (or entries) not already marked @done'
|
|
@@ -73,6 +46,9 @@ command :finish do |c|
|
|
|
73
46
|
c.desc 'Select item(s) to finish from a menu of matching entries'
|
|
74
47
|
c.switch %i[i interactive], negatable: false, default_value: false
|
|
75
48
|
|
|
49
|
+
add_options(:search, c)
|
|
50
|
+
add_options(:tag_filter, c)
|
|
51
|
+
|
|
76
52
|
c.action do |_global_options, options, args|
|
|
77
53
|
options[:fuzzy] = false
|
|
78
54
|
unless options[:auto]
|
|
@@ -141,6 +117,7 @@ command :finish do |c|
|
|
|
141
117
|
tags: ['done'],
|
|
142
118
|
took: options[:took],
|
|
143
119
|
unfinished: options[:unfinished],
|
|
120
|
+
update: options[:update],
|
|
144
121
|
val: options[:val]
|
|
145
122
|
}
|
|
146
123
|
|
data/bin/commands/flag.rb
CHANGED
|
@@ -26,39 +26,12 @@ command %i[mark flag] do |c|
|
|
|
26
26
|
c.desc 'Flag last entry (or entries) not marked @done'
|
|
27
27
|
c.switch %i[u unfinished], negatable: false, default_value: false
|
|
28
28
|
|
|
29
|
-
c.desc 'Flag the last entry containing TAG.
|
|
30
|
-
Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool. Wildcards allowed (*, ?).'
|
|
31
|
-
c.arg_name 'TAG'
|
|
32
|
-
c.flag [:tag], type: TagArray
|
|
33
|
-
|
|
34
|
-
c.desc 'Flag the last entry matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
|
35
|
-
c.arg_name 'QUERY'
|
|
36
|
-
c.flag [:search]
|
|
37
|
-
|
|
38
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
39
|
-
c.arg_name 'QUERY'
|
|
40
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
41
|
-
|
|
42
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
43
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
44
|
-
|
|
45
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
46
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
47
|
-
|
|
48
|
-
c.desc 'Flag items that *don\'t* match search/tag/date filters'
|
|
49
|
-
c.switch [:not], default_value: false, negatable: false
|
|
50
|
-
|
|
51
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
52
|
-
c.arg_name 'TYPE'
|
|
53
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
54
|
-
|
|
55
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
|
56
|
-
c.arg_name 'BOOLEAN'
|
|
57
|
-
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
58
|
-
|
|
59
29
|
c.desc 'Select item(s) to flag from a menu of matching entries'
|
|
60
30
|
c.switch %i[i interactive], negatable: false, default_value: false
|
|
61
31
|
|
|
32
|
+
add_options(:search, c)
|
|
33
|
+
add_options(:tag_filter, c)
|
|
34
|
+
|
|
62
35
|
c.action do |_global_options, options, _args|
|
|
63
36
|
options[:fuzzy] = false
|
|
64
37
|
mark = @settings['marker_tag'] || 'flagged'
|
|
@@ -67,15 +40,9 @@ command %i[mark flag] do |c|
|
|
|
67
40
|
|
|
68
41
|
section = 'All'
|
|
69
42
|
|
|
70
|
-
if options[:section]
|
|
71
|
-
section = @wwid.guess_section(options[:section]) || options[:section].cap_first
|
|
72
|
-
end
|
|
43
|
+
section = @wwid.guess_section(options[:section]) || options[:section].cap_first if options[:section]
|
|
73
44
|
|
|
74
|
-
|
|
75
|
-
search_tags = []
|
|
76
|
-
else
|
|
77
|
-
search_tags = options[:tag]
|
|
78
|
-
end
|
|
45
|
+
search_tags = options[:tag].nil? ? [] : options[:tag]
|
|
79
46
|
|
|
80
47
|
if options[:interactive]
|
|
81
48
|
count = 0
|
|
@@ -84,8 +51,6 @@ command %i[mark flag] do |c|
|
|
|
84
51
|
count = options[:count].to_i
|
|
85
52
|
end
|
|
86
53
|
|
|
87
|
-
options[:case] = options[:case].normalize_case
|
|
88
|
-
|
|
89
54
|
if options[:search]
|
|
90
55
|
search = options[:search]
|
|
91
56
|
search.sub!(/^'?/, "'") if options[:exact]
|
|
@@ -93,16 +58,15 @@ command %i[mark flag] do |c|
|
|
|
93
58
|
end
|
|
94
59
|
|
|
95
60
|
if count.zero? && !options[:force]
|
|
96
|
-
if options[:search]
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
61
|
+
section_q = if options[:search]
|
|
62
|
+
' matching your search terms'
|
|
63
|
+
elsif options[:tag]
|
|
64
|
+
' matching your tag search'
|
|
65
|
+
elsif section == 'All'
|
|
66
|
+
''
|
|
67
|
+
else
|
|
68
|
+
" in section #{section}"
|
|
69
|
+
end
|
|
106
70
|
|
|
107
71
|
question = if options[:remove]
|
|
108
72
|
"Are you sure you want to unflag all entries#{section_q}"
|
|
@@ -119,7 +83,7 @@ command %i[mark flag] do |c|
|
|
|
119
83
|
options[:section] = section
|
|
120
84
|
options[:tag] = search_tags
|
|
121
85
|
options[:tags] = [mark]
|
|
122
|
-
options[:tag_bool] = options[:bool]
|
|
86
|
+
options[:tag_bool] = options[:bool]
|
|
123
87
|
|
|
124
88
|
@wwid.tag_last(options)
|
|
125
89
|
end
|
data/bin/commands/grep.rb
CHANGED
|
@@ -16,25 +16,6 @@ command %i[grep search] do |c|
|
|
|
16
16
|
c.arg_name 'NAME'
|
|
17
17
|
c.flag %i[s section], default_value: 'All'
|
|
18
18
|
|
|
19
|
-
c.desc 'Search 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'
|
|
20
|
-
c.arg_name 'DATE_STRING'
|
|
21
|
-
c.flag [:before], type: DateBeginString
|
|
22
|
-
|
|
23
|
-
c.desc 'Search 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'
|
|
24
|
-
c.arg_name 'DATE_STRING'
|
|
25
|
-
c.flag [:after], type: DateEndString
|
|
26
|
-
|
|
27
|
-
c.desc %(
|
|
28
|
-
Date range to show, or a single day to filter date on.
|
|
29
|
-
Date range argument should be quoted. Date specifications can be natural language.
|
|
30
|
-
To specify a range, use "to" or "through": `doing search --from "monday 8am to friday 5pm"`.
|
|
31
|
-
|
|
32
|
-
If values are only time(s) (6am to noon) all dates will be included, but entries will be filtered
|
|
33
|
-
by time of day.
|
|
34
|
-
)
|
|
35
|
-
c.arg_name 'DATE_OR_RANGE'
|
|
36
|
-
c.flag [:from], type: DateRangeString
|
|
37
|
-
|
|
38
19
|
c.desc "Output to export format (#{Doing::Plugins.plugin_names(type: :export)})"
|
|
39
20
|
c.arg_name 'FORMAT'
|
|
40
21
|
c.flag %i[o output]
|
|
@@ -57,10 +38,9 @@ command %i[grep search] do |c|
|
|
|
57
38
|
c.switch [:totals], default_value: false, negatable: false
|
|
58
39
|
|
|
59
40
|
c.desc 'Sort tags by (name|time)'
|
|
60
|
-
default = '
|
|
61
|
-
default = @settings['tag_sort'] || 'name'
|
|
41
|
+
default = @settings['tag_sort'].normalize_tag_sort || :name
|
|
62
42
|
c.arg_name 'KEY'
|
|
63
|
-
c.flag [:tag_sort], must_match:
|
|
43
|
+
c.flag [:tag_sort], must_match: REGEX_TAG_SORT, default_value: default, type: TagSortSymbol
|
|
64
44
|
|
|
65
45
|
c.desc 'Only show items with recorded time intervals'
|
|
66
46
|
c.switch [:only_timed], default_value: false, negatable: false
|
|
@@ -76,7 +56,9 @@ command %i[grep search] do |c|
|
|
|
76
56
|
|
|
77
57
|
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
78
58
|
c.arg_name 'TYPE'
|
|
79
|
-
c.flag [:case], must_match:
|
|
59
|
+
c.flag [:case], must_match: REGEX_CASE,
|
|
60
|
+
default_value: @settings.dig('search', 'case').normalize_case,
|
|
61
|
+
type: CaseSymbol
|
|
80
62
|
|
|
81
63
|
c.desc "Highlight search matches in output. Only affects command line output"
|
|
82
64
|
c.switch %i[h hilite], default_value: @settings.dig('search', 'highlight')
|
|
@@ -95,7 +77,12 @@ command %i[grep search] do |c|
|
|
|
95
77
|
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
96
78
|
|
|
97
79
|
c.desc 'Combine multiple tags or value queries using AND, OR, or NOT'
|
|
98
|
-
c.
|
|
80
|
+
c.arg_name 'BOOLEAN'
|
|
81
|
+
c.flag [:bool], must_match: REGEX_BOOL,
|
|
82
|
+
default_value: :pattern,
|
|
83
|
+
type: BooleanSymbol
|
|
84
|
+
|
|
85
|
+
add_options(:date_filter, c)
|
|
99
86
|
|
|
100
87
|
c.action do |_global_options, options, args|
|
|
101
88
|
options[:fuzzy] = false
|
|
@@ -106,14 +93,11 @@ command %i[grep search] do |c|
|
|
|
106
93
|
|
|
107
94
|
section = @wwid.guess_section(options[:section]) if options[:section]
|
|
108
95
|
|
|
109
|
-
options[:case] = options[:case].normalize_case
|
|
110
|
-
options[:bool] = options[:bool].normalize_bool
|
|
111
|
-
|
|
112
96
|
search = args.join(' ')
|
|
113
97
|
search.sub!(/^'?/, "'") if options[:exact]
|
|
114
98
|
|
|
115
99
|
options[:times] = true if options[:totals]
|
|
116
|
-
options[:sort_tags] = options[:tag_sort]
|
|
100
|
+
options[:sort_tags] = options[:tag_sort]
|
|
117
101
|
options[:highlight] = true
|
|
118
102
|
options[:search] = search
|
|
119
103
|
options[:section] = section
|
data/bin/commands/import.rb
CHANGED
|
@@ -11,23 +11,9 @@ command :import do |c|
|
|
|
11
11
|
c.arg_name 'TYPE'
|
|
12
12
|
c.flag :type, default_value: 'doing'
|
|
13
13
|
|
|
14
|
-
c.desc 'Only import items matching search. Surround with slashes for regex (/query/), start with single quote for exact match ("\'query")'
|
|
15
|
-
c.arg_name 'QUERY'
|
|
16
|
-
c.flag [:search]
|
|
17
|
-
|
|
18
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
19
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
20
|
-
|
|
21
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
22
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
23
|
-
|
|
24
14
|
c.desc 'Import items that *don\'t* match search/tag/date filters'
|
|
25
15
|
c.switch [:not], default_value: false, negatable: false
|
|
26
16
|
|
|
27
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
28
|
-
c.arg_name 'TYPE'
|
|
29
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
30
|
-
|
|
31
17
|
c.desc 'Only import items with recorded time intervals'
|
|
32
18
|
c.switch [:only_timed], default_value: false, negatable: false
|
|
33
19
|
|
|
@@ -46,26 +32,12 @@ command :import do |c|
|
|
|
46
32
|
c.arg_name 'PREFIX'
|
|
47
33
|
c.flag :prefix
|
|
48
34
|
|
|
49
|
-
# TODO: Allow time range filtering
|
|
50
|
-
c.desc 'Import entries older than date'
|
|
51
|
-
c.arg_name 'DATE_STRING'
|
|
52
|
-
c.flag [:before], type: DateBeginString
|
|
53
|
-
|
|
54
|
-
c.desc 'Import entries newer than date'
|
|
55
|
-
c.arg_name 'DATE_STRING'
|
|
56
|
-
c.flag [:after], type: DateEndString
|
|
57
|
-
|
|
58
|
-
c.desc %(
|
|
59
|
-
Date range to import. Date range argument should be quoted. Date specifications can be natural language.
|
|
60
|
-
To specify a range, use "to" or "through": `--from "monday to friday"` or `--from 10/1 to 10/31`.
|
|
61
|
-
Has no effect unless the import plugin has implemented date range filtering.
|
|
62
|
-
)
|
|
63
|
-
c.arg_name 'DATE_OR_RANGE'
|
|
64
|
-
c.flag %i[f from], type: DateRangeString
|
|
65
|
-
|
|
66
35
|
c.desc 'Allow entries that overlap existing times'
|
|
67
36
|
c.switch [:overlap], negatable: true
|
|
68
37
|
|
|
38
|
+
add_options(:search, c)
|
|
39
|
+
add_options(:date_filter, c)
|
|
40
|
+
|
|
69
41
|
c.action do |_global_options, options, args|
|
|
70
42
|
options[:fuzzy] = false
|
|
71
43
|
if options[:section]
|
|
@@ -88,8 +60,6 @@ command :import do |c|
|
|
|
88
60
|
options[:date_filter][0] = options[:after] || Time.now - (1 << 64)
|
|
89
61
|
end
|
|
90
62
|
|
|
91
|
-
options[:case] = options[:case].normalize_case
|
|
92
|
-
|
|
93
63
|
if options[:type] =~ Doing::Plugins.plugin_regex(type: :import)
|
|
94
64
|
options[:no_overlap] = !options[:overlap]
|
|
95
65
|
@wwid.import(args, options)
|
data/bin/commands/last.rb
CHANGED
|
@@ -21,18 +21,6 @@ command :last do |c|
|
|
|
21
21
|
c.desc "Delete the last entry"
|
|
22
22
|
c.switch %i[d delete], negatable: false, default_value: false
|
|
23
23
|
|
|
24
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
|
25
|
-
c.arg_name 'TAG'
|
|
26
|
-
c.flag [:tag], type: TagArray
|
|
27
|
-
|
|
28
|
-
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
|
|
29
|
-
c.arg_name 'BOOLEAN'
|
|
30
|
-
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
31
|
-
|
|
32
|
-
c.desc 'Search filter, surround with slashes for regex (/query/), start with single quote for exact match ("\'query")'
|
|
33
|
-
c.arg_name 'QUERY'
|
|
34
|
-
c.flag [:search]
|
|
35
|
-
|
|
36
24
|
c.desc "Output using a template from configuration"
|
|
37
25
|
c.arg_name 'TEMPLATE_KEY'
|
|
38
26
|
c.flag [:config_template], type: TemplateName, default_value: 'last'
|
|
@@ -44,38 +32,17 @@ command :last do |c|
|
|
|
44
32
|
c.desc "Highlight search matches in output. Only affects command line output"
|
|
45
33
|
c.switch %i[h hilite], default_value: @settings.dig('search', 'highlight')
|
|
46
34
|
|
|
47
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
48
|
-
c.arg_name 'QUERY'
|
|
49
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
50
|
-
|
|
51
35
|
c.desc 'Show elapsed time if entry is not tagged @done'
|
|
52
36
|
c.switch [:duration]
|
|
53
37
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
58
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
59
|
-
|
|
60
|
-
c.desc 'Show items that *don\'t* match search string or tag filter'
|
|
61
|
-
c.switch [:not], default_value: false, negatable: false
|
|
62
|
-
|
|
63
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
64
|
-
c.arg_name 'TYPE'
|
|
65
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
38
|
+
add_options(:search, c)
|
|
39
|
+
add_options(:tag_filter, c)
|
|
66
40
|
|
|
67
41
|
c.action do |global_options, options, _args|
|
|
68
42
|
options[:fuzzy] = false
|
|
69
43
|
raise InvalidArgument, '--tag and --search can not be used together' if options[:tag] && options[:search]
|
|
70
44
|
|
|
71
|
-
|
|
72
|
-
options[:tag] = []
|
|
73
|
-
else
|
|
74
|
-
options[:tag] = options[:tag]
|
|
75
|
-
options[:bool] = options[:bool].normalize_bool
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
options[:case] = options[:case].normalize_case
|
|
45
|
+
options[:tag] ||= []
|
|
79
46
|
|
|
80
47
|
options[:search] = options[:search].sub(/^'?/, "'") if options[:search] && options[:exact]
|
|
81
48
|
|
data/bin/commands/meanwhile.rb
CHANGED
|
@@ -15,24 +15,14 @@ command :meanwhile do |c|
|
|
|
15
15
|
c.arg_name 'NAME'
|
|
16
16
|
c.flag %i[s section]
|
|
17
17
|
|
|
18
|
-
c.desc "Edit entry with #{Doing::Util.default_editor}"
|
|
19
|
-
c.switch %i[e editor], negatable: false, default_value: false
|
|
20
|
-
|
|
21
18
|
c.desc 'Archive previous @meanwhile entry'
|
|
22
19
|
c.switch %i[a archive], negatable: false, default_value: false
|
|
23
20
|
|
|
24
|
-
c
|
|
25
|
-
c.arg_name 'DATE_STRING'
|
|
26
|
-
c.flag %i[b back started], type: DateBeginString
|
|
27
|
-
|
|
28
|
-
c.desc 'Note'
|
|
29
|
-
c.arg_name 'TEXT'
|
|
30
|
-
c.flag %i[n note]
|
|
31
|
-
|
|
32
|
-
c.desc 'Prompt for note via multi-line input'
|
|
33
|
-
c.switch %i[ask], negatable: false, default_value: false
|
|
21
|
+
add_options(:add_entry, c)
|
|
34
22
|
|
|
35
23
|
c.action do |_global_options, options, args|
|
|
24
|
+
@wwid.auto_tag = !options[:noauto]
|
|
25
|
+
|
|
36
26
|
if options[:back]
|
|
37
27
|
date = options[:back]
|
|
38
28
|
|
data/bin/commands/note.rb
CHANGED
|
@@ -24,50 +24,19 @@ command :note do |c|
|
|
|
24
24
|
c.desc "Replace/Remove last entry's note (default append)"
|
|
25
25
|
c.switch %i[r remove], negatable: false, default_value: false
|
|
26
26
|
|
|
27
|
-
c.desc 'Add/remove note from last entry matching tag. Wildcards allowed (*, ?)'
|
|
28
|
-
c.arg_name 'TAG'
|
|
29
|
-
c.flag [:tag], type: TagArray
|
|
30
|
-
|
|
31
|
-
c.desc 'Add/remove note from last entry matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
|
32
|
-
c.arg_name 'QUERY'
|
|
33
|
-
c.flag [:search]
|
|
34
|
-
|
|
35
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
36
|
-
c.arg_name 'QUERY'
|
|
37
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
38
|
-
|
|
39
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
40
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
41
|
-
|
|
42
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
43
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
44
|
-
|
|
45
|
-
c.desc 'Add note to item that *doesn\'t* match search/tag filters'
|
|
46
|
-
c.switch [:not], default_value: false, negatable: false
|
|
47
|
-
|
|
48
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
49
|
-
c.arg_name 'TYPE'
|
|
50
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
51
|
-
|
|
52
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
|
53
|
-
c.arg_name 'BOOLEAN'
|
|
54
|
-
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
55
|
-
|
|
56
27
|
c.desc 'Select item for new note from a menu of matching entries'
|
|
57
28
|
c.switch %i[i interactive], negatable: false, default_value: false
|
|
58
29
|
|
|
59
30
|
c.desc 'Prompt for note via multi-line input'
|
|
60
31
|
c.switch %i[ask], negatable: false, default_value: false
|
|
61
32
|
|
|
33
|
+
add_options(:search, c)
|
|
34
|
+
add_options(:tag_filter, c)
|
|
35
|
+
|
|
62
36
|
c.action do |_global_options, options, args|
|
|
63
37
|
options[:fuzzy] = false
|
|
64
|
-
if options[:section]
|
|
65
|
-
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
options[:tag_bool] = options[:bool].normalize_bool
|
|
69
|
-
|
|
70
|
-
options[:case] = options[:case].normalize_case
|
|
38
|
+
options[:section] = @wwid.guess_section(options[:section]) || options[:section].cap_first if options[:section]
|
|
39
|
+
options[:tag_bool] = options[:bool]
|
|
71
40
|
|
|
72
41
|
if options[:search]
|
|
73
42
|
search = options[:search]
|
|
@@ -78,30 +47,22 @@ command :note do |c|
|
|
|
78
47
|
last_entry = @wwid.last_entry(options)
|
|
79
48
|
old_entry = last_entry.clone
|
|
80
49
|
|
|
81
|
-
unless last_entry
|
|
82
|
-
Doing.logger.warn('Not found:', 'No entry matching parameters was found.')
|
|
83
|
-
return
|
|
84
|
-
end
|
|
50
|
+
raise NoResults, 'No entry matching parameters was found.' unless last_entry
|
|
85
51
|
|
|
86
52
|
last_note = last_entry.note || Doing::Note.new
|
|
87
53
|
new_note = Doing::Note.new
|
|
88
54
|
|
|
89
|
-
if $stdin.stat.size.positive?
|
|
90
|
-
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
unless args.empty?
|
|
94
|
-
new_note.add(args.join(' '))
|
|
95
|
-
end
|
|
55
|
+
new_note.add($stdin.read.strip) if $stdin.stat.size.positive?
|
|
56
|
+
new_note.add(args.join(' ')) unless args.empty?
|
|
96
57
|
|
|
97
58
|
if options[:editor]
|
|
98
59
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
|
99
60
|
|
|
100
|
-
if options[:remove]
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
61
|
+
input = if options[:remove]
|
|
62
|
+
Doing::Note.new
|
|
63
|
+
else
|
|
64
|
+
last_entry.note || Doing::Note.new
|
|
65
|
+
end
|
|
105
66
|
|
|
106
67
|
input.add(new_note)
|
|
107
68
|
|