doing 2.1.26 → 2.1.30
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 +15 -20
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +52 -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 +2 -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 +53 -12
- 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 +8 -8
- 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/open.rb +3 -3
- 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.gemspec +1 -0
- data/doing.rdoc +297 -206
- data/lib/completion/_doing.zsh +32 -32
- data/lib/completion/doing.bash +30 -30
- data/lib/completion/doing.fish +87 -77
- 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 +37 -8
- data/lib/doing/changelog/version.rb +11 -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/completion/zsh_completion.rb +5 -0
- data/lib/doing/configuration.rb +9 -5
- 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/section.rb +1 -1
- 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 +54 -36
- data/lib/doing.rb +5 -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 +39 -8
- data/lib/doing/string.rb +0 -765
- data/lib/doing/symbol.rb +0 -28
data/bin/commands/changes.rb
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
# @@changelog @@changes
|
|
2
|
+
|
|
3
|
+
MARKDOWN_THEME = {
|
|
4
|
+
em: %i[white dark],
|
|
5
|
+
header: %i[cyan bold],
|
|
6
|
+
hr: :yellow,
|
|
7
|
+
link: %i[bright_cyan underline],
|
|
8
|
+
list: :yellow,
|
|
9
|
+
strong: %i[yellow bold],
|
|
10
|
+
table: :yellow,
|
|
11
|
+
quote: :yellow,
|
|
12
|
+
image: :bright_black,
|
|
13
|
+
note: :yellow,
|
|
14
|
+
comment: :bright_black
|
|
15
|
+
}.deep_freeze
|
|
16
|
+
|
|
17
|
+
CHANGE_RX = /^(?:(?:(?:[<>=]+|p(?:rior)|b(?:efore)|o(?:lder)|s(?:ince)|a(?:fter)|n(?:ewer))? *[0-9.*?]+ *)+|(?:[\d.]+ *(?:-|to)+ *[0-9.]+))$/
|
|
18
|
+
|
|
2
19
|
desc 'List recent changes in Doing'
|
|
3
20
|
long_desc %(Display a formatted list of changes in recent versions.
|
|
4
21
|
|
|
@@ -10,14 +27,30 @@ command %i[changes changelog] do |c|
|
|
|
10
27
|
|
|
11
28
|
c.desc %(Look up a specific version. Specify versions as "MAJ.MIN.PATCH", MIN
|
|
12
29
|
and PATCH are optional. Use > or < to see all changes since or prior
|
|
13
|
-
to a version.)
|
|
30
|
+
to a version. Wildcards (*?) accepted unless using < or >.)
|
|
14
31
|
c.arg_name 'VERSION'
|
|
15
|
-
c.flag %i[l lookup], must_match:
|
|
32
|
+
c.flag %i[l lookup], must_match: CHANGE_RX
|
|
16
33
|
|
|
17
34
|
c.desc %(Show changelogs matching search terms (uses pattern-based searching).
|
|
18
35
|
Add slashes to search with regular expressions, e.g. `--search "/output.*flag/"`)
|
|
19
36
|
c.flag %i[s search]
|
|
20
37
|
|
|
38
|
+
c.desc 'Sort order (asc/desc)'
|
|
39
|
+
c.arg_name 'ORDER'
|
|
40
|
+
c.flag %i[sort], must_match: REGEX_SORT_ORDER, default_value: :desc, type: OrderSymbol
|
|
41
|
+
|
|
42
|
+
c.desc 'Only output changes, no version numbers, headers, or dates'
|
|
43
|
+
c.switch %i[C changes], default_value: false, negatable: false
|
|
44
|
+
|
|
45
|
+
c.desc 'Output raw Markdown'
|
|
46
|
+
c.switch %i[m md markdown], default_value: false, negatable: false
|
|
47
|
+
|
|
48
|
+
c.desc 'Force rendered output'
|
|
49
|
+
c.switch %i[render], default_value: false, negatable: false
|
|
50
|
+
|
|
51
|
+
c.desc 'Open changelog in interactive viewer'
|
|
52
|
+
c.switch %i[i interactive], default_value: false, negatable: false
|
|
53
|
+
|
|
21
54
|
c.example 'doing changes', desc: 'View changes in the current version'
|
|
22
55
|
c.example 'doing changes --all', desc: 'See the entire changelog'
|
|
23
56
|
c.example 'doing changes --lookup 2.0.21', desc: 'See changes from version 2.0.21'
|
|
@@ -25,18 +58,26 @@ command %i[changes changelog] do |c|
|
|
|
25
58
|
c.example 'doing changes --search "tags +bool"', desc: 'See all changes containing "tags" and "bool"'
|
|
26
59
|
c.example 'doing changes -l "> 2.1" -s "pattern"', desc: 'Lookup and search can be combined'
|
|
27
60
|
|
|
61
|
+
c.action do |_global_options, options, _args|
|
|
62
|
+
cl = Doing::Changes.new(lookup: options[:lookup], search: options[:search], changes: options[:changes], sort: options[:sort])
|
|
28
63
|
|
|
29
|
-
|
|
30
|
-
|
|
64
|
+
if options[:interactive]
|
|
65
|
+
cl.interactive
|
|
66
|
+
else
|
|
67
|
+
content = if options[:all] || options[:search] || options[:lookup]
|
|
68
|
+
cl.to_s
|
|
69
|
+
else
|
|
70
|
+
cl.latest
|
|
71
|
+
end
|
|
31
72
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
73
|
+
parsed = if (options[:markdown] || !$stdout.isatty) && !options[:render]
|
|
74
|
+
content
|
|
75
|
+
else
|
|
76
|
+
TTY::Markdown.parse(content, width: 80, theme: MARKDOWN_THEME, symbols: { override: { bullet: '•' } })
|
|
77
|
+
end
|
|
37
78
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
79
|
+
Doing::Pager.paginate = true
|
|
80
|
+
Doing::Pager.page parsed
|
|
81
|
+
end
|
|
41
82
|
end
|
|
42
83
|
end
|
data/bin/commands/colors.rb
CHANGED
|
@@ -5,10 +5,12 @@ command :colors do |c|
|
|
|
5
5
|
bgs = []
|
|
6
6
|
fgs = []
|
|
7
7
|
@colors::attributes.each do |color|
|
|
8
|
+
colname = color.to_s
|
|
9
|
+
colname << " (#{color.to_s.sub(/bold/, 'bright')})" if colname =~ /bold/
|
|
8
10
|
if color.to_s =~ /bg/
|
|
9
|
-
bgs.push("#{@colors.send(color, " ")}#{@colors.default} <-- #{
|
|
11
|
+
bgs.push("#{@colors.send(color, " ")}#{@colors.default} <-- #{colname}")
|
|
10
12
|
else
|
|
11
|
-
fgs.push("#{@colors.send(color, "XXXX")}#{@colors.default} <-- #{
|
|
13
|
+
fgs.push("#{@colors.send(color, "XXXX")}#{@colors.default} <-- #{colname}")
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
out = []
|
data/bin/commands/commands.rb
CHANGED
|
@@ -27,9 +27,11 @@ command :commands do |c|
|
|
|
27
27
|
Doing::Prompt.choose_from(available,
|
|
28
28
|
prompt: 'Select commands to enable',
|
|
29
29
|
multiple: true,
|
|
30
|
-
sorted: true)
|
|
30
|
+
sorted: true)
|
|
31
31
|
end
|
|
32
|
-
|
|
32
|
+
raise UserCancelled unless to_enable
|
|
33
|
+
|
|
34
|
+
to_enable.strip.split("\n").each do |cmd|
|
|
33
35
|
default_command = File.join(File.dirname(__FILE__), "#{cmd}.rb")
|
|
34
36
|
custom_command = File.join(File.expand_path(custom_dir), "#{cmd}.rb")
|
|
35
37
|
unless File.exist?(default_command) || File.exist?(custom_command)
|
|
@@ -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
|
@@ -45,7 +45,7 @@ command :config do |c|
|
|
|
45
45
|
edit.arg_name 'EDITOR'
|
|
46
46
|
edit.flag %i[e editor], default_value: nil
|
|
47
47
|
|
|
48
|
-
if
|
|
48
|
+
if Sys::Platform.mac?
|
|
49
49
|
edit.desc 'Application to use'
|
|
50
50
|
edit.arg_name 'APP_NAME'
|
|
51
51
|
edit.flag %i[a app]
|
|
@@ -76,7 +76,7 @@ command :config do |c|
|
|
|
76
76
|
|
|
77
77
|
config_file = @config.choose_config
|
|
78
78
|
|
|
79
|
-
if
|
|
79
|
+
if Sys::Platform.mac?
|
|
80
80
|
if options[:default]
|
|
81
81
|
editor = Doing::Util.find_default_editor('config')
|
|
82
82
|
if editor
|
|
@@ -139,7 +139,7 @@ command :config do |c|
|
|
|
139
139
|
dump.example 'doing config get', desc: 'Output the entire configuration'
|
|
140
140
|
dump.example 'doing config get timer_format --output raw', desc: 'Output the value of timer_format as a plain string'
|
|
141
141
|
dump.example 'doing config get doing_file', desc: 'Output the value of the doing_file setting, respecting local configurations'
|
|
142
|
-
dump.example 'doing config get -o json plug.plugpath', desc: 'Key path is fuzzy matched: output the value of plugins
|
|
142
|
+
dump.example 'doing config get -o json plug.plugpath', desc: 'Key path is fuzzy matched: output the value of plugins.plugin_path as JSON'
|
|
143
143
|
|
|
144
144
|
dump.desc 'Format for output (json|yaml|raw)'
|
|
145
145
|
dump.arg_name 'FORMAT'
|
|
@@ -188,7 +188,7 @@ command :config do |c|
|
|
|
188
188
|
c.arg 'KEY VALUE'
|
|
189
189
|
c.command :set do |set|
|
|
190
190
|
set.example 'doing config set timer_format human', desc: 'Set the value of timer_format to "human"'
|
|
191
|
-
set.example 'doing config set plug.plugpath ~/my_plugins', desc: 'Key path is fuzzy matched: set the value of plugins
|
|
191
|
+
set.example 'doing config set plug.plugpath ~/my_plugins', desc: 'Key path is fuzzy matched: set the value of plugins.plugin_path'
|
|
192
192
|
|
|
193
193
|
set.desc 'Delete specified key'
|
|
194
194
|
set.switch %i[r remove], default_value: false, negatable: false
|
|
@@ -206,7 +206,7 @@ command :config do |c|
|
|
|
206
206
|
old_type = old_value&.class.to_s || nil
|
|
207
207
|
|
|
208
208
|
if old_value.is_a?(Hash) && !options[:remove]
|
|
209
|
-
Doing.logger.log_now(:warn, 'Config:', "Config key must point to a single value, #{real_path.join('
|
|
209
|
+
Doing.logger.log_now(:warn, 'Config:', "Config key must point to a single value, #{real_path.join('.').boldwhite} is a mapping")
|
|
210
210
|
didyou = 'Did you mean:'
|
|
211
211
|
old_value.keys.each do |k|
|
|
212
212
|
Doing.logger.log_now(:warn, "#{didyou}", "#{keypath}.#{k}?")
|
|
@@ -218,17 +218,17 @@ command :config do |c|
|
|
|
218
218
|
|
|
219
219
|
config_file = @config.choose_config(create: true)
|
|
220
220
|
|
|
221
|
-
cfg =
|
|
221
|
+
cfg = Doing::Util.safe_load_file(config_file) || {}
|
|
222
222
|
|
|
223
223
|
$stderr.puts "Updating #{config_file}".yellow
|
|
224
224
|
|
|
225
225
|
if options[:remove]
|
|
226
226
|
cfg.deep_set(real_path, nil)
|
|
227
|
-
$stderr.puts "#{'Deleting key:'.yellow} #{real_path.join('
|
|
227
|
+
$stderr.puts "#{'Deleting key:'.yellow} #{real_path.join('.').boldwhite}"
|
|
228
228
|
else
|
|
229
229
|
current_value = cfg.dig(*real_path)
|
|
230
230
|
cfg.deep_set(real_path, value.set_type(old_type))
|
|
231
|
-
$stderr.puts "#{' Key path:'.yellow} #{real_path.join('
|
|
231
|
+
$stderr.puts "#{' Key path:'.yellow} #{real_path.join('.').boldwhite}"
|
|
232
232
|
$stderr.puts "#{'Inherited:'.yellow} #{(old_value ? old_value.to_s : 'empty').boldwhite}"
|
|
233
233
|
$stderr.puts "#{' Current:'.yellow} #{ (current_value ? current_value.to_s : 'empty').boldwhite }"
|
|
234
234
|
$stderr.puts "#{' New:'.yellow} #{value.set_type(old_type).to_s.boldwhite}"
|
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)
|