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