doing 2.1.89 → 2.1.90
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/.irbrc +2 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +251 -0
- data/CHANGELOG.md +22 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +5 -3
- data/bin/commands/changes.rb +3 -1
- data/bin/commands/choose.rb +2 -0
- data/bin/commands/colors.rb +5 -3
- data/bin/commands/commands_accepting.rb +3 -3
- data/bin/commands/completion.rb +2 -1
- data/bin/commands/config.rb +8 -6
- data/bin/commands/done.rb +19 -12
- data/bin/commands/finish.rb +4 -2
- data/bin/commands/grep.rb +9 -5
- data/bin/commands/import.rb +14 -11
- data/bin/commands/install_fzf.rb +4 -2
- data/bin/commands/last.rb +31 -27
- data/bin/commands/meanwhile.rb +6 -2
- data/bin/commands/note.rb +6 -3
- data/bin/commands/now.rb +2 -0
- data/bin/commands/open.rb +6 -1
- data/bin/commands/plugins.rb +2 -0
- data/bin/commands/recent.rb +47 -33
- data/bin/commands/reset.rb +7 -3
- data/bin/commands/rotate.rb +6 -3
- data/bin/commands/sections.rb +3 -3
- data/bin/commands/select.rb +2 -0
- data/bin/commands/show.rb +24 -20
- data/bin/commands/since.rb +10 -3
- data/bin/commands/tag.rb +18 -16
- data/bin/commands/tag_dir.rb +5 -2
- data/bin/commands/tags.rb +17 -17
- data/bin/commands/template.rb +8 -2
- data/bin/commands/today.rb +10 -2
- data/bin/commands/undo.rb +2 -0
- data/bin/commands/update.rb +9 -7
- data/bin/commands/view.rb +11 -8
- data/bin/commands/views.rb +2 -0
- data/bin/commands/yesterday.rb +6 -1
- data/bin/doing +54 -57
- data/docs/doc/Array.html +3 -3
- data/docs/doc/BooleanTermParser/Clause.html +3 -3
- data/docs/doc/BooleanTermParser/Operator.html +3 -3
- data/docs/doc/BooleanTermParser/Query.html +3 -3
- data/docs/doc/BooleanTermParser/QueryParser.html +3 -3
- data/docs/doc/BooleanTermParser/QueryTransformer.html +3 -3
- data/docs/doc/BooleanTermParser.html +3 -3
- data/docs/doc/Doing/ArrayCleanup.html +3 -3
- data/docs/doc/Doing/ArrayNestedHash.html +3 -3
- data/docs/doc/Doing/ArrayTags.html +9 -9
- data/docs/doc/Doing/ByDayExport.html +3 -3
- data/docs/doc/Doing/CSVExport.html +4 -4
- data/docs/doc/Doing/CalendarImport.html +4 -4
- data/docs/doc/Doing/Change.html +3 -3
- data/docs/doc/Doing/Changes.html +3 -3
- data/docs/doc/Doing/ChronifyArray.html +3 -3
- data/docs/doc/Doing/ChronifyNumeric.html +3 -3
- data/docs/doc/Doing/ChronifyString.html +6 -6
- data/docs/doc/Doing/Color.html +88 -47
- data/docs/doc/Doing/Completion/BashCompletions.html +3 -3
- data/docs/doc/Doing/Completion/FigCompletions.html +3 -3
- data/docs/doc/Doing/Completion/FishCompletions.html +3 -3
- data/docs/doc/Doing/Completion/StringUtils.html +3 -3
- data/docs/doc/Doing/Completion/ZshCompletions.html +3 -3
- data/docs/doc/Doing/Completion.html +5 -5
- data/docs/doc/Doing/Configuration.html +6 -6
- data/docs/doc/Doing/DayOneRenderer.html +3 -3
- data/docs/doc/Doing/DayoneExport.html +4 -4
- data/docs/doc/Doing/DoingExport.html +5 -5
- data/docs/doc/Doing/DoingImport.html +4 -4
- data/docs/doc/Doing/Entry.html +3 -3
- data/docs/doc/Doing/Errors/DoingNoTraceError.html +3 -3
- data/docs/doc/Doing/Errors/DoingRuntimeError.html +3 -3
- data/docs/doc/Doing/Errors/DoingStandardError.html +3 -3
- data/docs/doc/Doing/Errors/EmptyInput.html +3 -3
- data/docs/doc/Doing/Errors/HistoryLimitError.html +3 -3
- data/docs/doc/Doing/Errors/InvalidPlugin.html +3 -3
- data/docs/doc/Doing/Errors/MissingBackupFile.html +3 -3
- data/docs/doc/Doing/Errors/NoResults.html +3 -3
- data/docs/doc/Doing/Errors/PluginException.html +3 -3
- data/docs/doc/Doing/Errors/UserCancelled.html +3 -3
- data/docs/doc/Doing/Errors/WrongCommand.html +3 -3
- data/docs/doc/Doing/Errors.html +3 -3
- data/docs/doc/Doing/HTMLExport.html +4 -4
- data/docs/doc/Doing/Hooks.html +3 -16
- data/docs/doc/Doing/Item.html +4 -4
- data/docs/doc/Doing/ItemDates.html +3 -3
- data/docs/doc/Doing/ItemQuery.html +3 -3
- data/docs/doc/Doing/ItemState.html +3 -3
- data/docs/doc/Doing/ItemTags.html +3 -3
- data/docs/doc/Doing/Items.html +3 -3
- data/docs/doc/Doing/JSONExport.html +4 -4
- data/docs/doc/Doing/JSONImport.html +4 -4
- data/docs/doc/Doing/Logger.html +183 -3
- data/docs/doc/Doing/MarkdownExport.html +4 -4
- data/docs/doc/Doing/Note.html +3 -3
- data/docs/doc/Doing/Pager.html +54 -58
- data/docs/doc/Doing/Plugins.html +3 -3
- data/docs/doc/Doing/Prompt.html +4 -4
- data/docs/doc/Doing/PromptChoose.html +3 -3
- data/docs/doc/Doing/PromptFZF.html +3 -3
- data/docs/doc/Doing/PromptInput.html +3 -3
- data/docs/doc/Doing/PromptSTD.html +3 -3
- data/docs/doc/Doing/PromptYN.html +3 -3
- data/docs/doc/Doing/Section.html +3 -3
- data/docs/doc/Doing/StringHighlight.html +3 -3
- data/docs/doc/Doing/StringNormalize.html +3 -3
- data/docs/doc/Doing/StringQuery.html +4 -4
- data/docs/doc/Doing/StringTags.html +3 -3
- data/docs/doc/Doing/StringTransform.html +3 -3
- data/docs/doc/Doing/StringTruncate.html +3 -3
- data/docs/doc/Doing/StringURL.html +3 -3
- data/docs/doc/Doing/SymbolNormalize.html +5 -5
- data/docs/doc/Doing/TaskPaperExport.html +4 -4
- data/docs/doc/Doing/TemplateExport.html +5 -5
- data/docs/doc/Doing/TemplateString.html +7 -7
- data/docs/doc/Doing/TimingImport.html +4 -4
- data/docs/doc/Doing/Types.html +3 -3
- data/docs/doc/Doing/Util/Backup.html +4 -17
- data/docs/doc/Doing/Util.html +56 -61
- data/docs/doc/Doing/Version.html +3 -3
- data/docs/doc/Doing/WWID.html +6 -4
- data/docs/doc/Doing.html +4 -4
- data/docs/doc/FalseClass.html +3 -3
- data/docs/doc/GLI/Commands/Help.html +5 -5
- data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +3 -3
- data/docs/doc/GLI/Commands.html +3 -3
- data/docs/doc/GLI.html +3 -3
- data/docs/doc/Hash.html +4 -4
- data/docs/doc/Numeric.html +3 -3
- data/docs/doc/Object.html +3 -3
- data/docs/doc/PhraseParser/Operator.html +3 -3
- data/docs/doc/PhraseParser/PhraseClause.html +3 -3
- data/docs/doc/PhraseParser/Query.html +3 -3
- data/docs/doc/PhraseParser/QueryParser.html +3 -3
- data/docs/doc/PhraseParser/QueryTransformer.html +3 -3
- data/docs/doc/PhraseParser/TermClause.html +3 -3
- data/docs/doc/PhraseParser.html +3 -3
- data/docs/doc/Status.html +3 -3
- data/docs/doc/String.html +51 -5
- data/docs/doc/Symbol.html +3 -3
- data/docs/doc/Time.html +3 -3
- data/docs/doc/TrueClass.html +3 -3
- data/docs/doc/_index.html +4 -4
- data/docs/doc/class_list.html +6 -3
- data/docs/doc/css/full_list.css +3 -3
- data/docs/doc/css/style.css +6 -0
- data/docs/doc/file.README.html +3 -3
- data/docs/doc/file_list.html +5 -2
- data/docs/doc/frames.html +1 -1
- data/docs/doc/index.html +3 -3
- data/docs/doc/js/app.js +294 -264
- data/docs/doc/js/full_list.js +30 -4
- data/docs/doc/method_list.html +443 -392
- data/docs/doc/top-level-namespace.html +3 -3
- data/doing.gemspec +2 -0
- data/doing.rdoc +1 -1
- data/example_plugin.rb +1 -4
- data/lib/doing/add_options.rb +2 -2
- data/lib/doing/array/cleanup.rb +2 -0
- data/lib/doing/array/nested_hash.rb +2 -0
- data/lib/doing/boolean_term_parser.rb +3 -3
- data/lib/doing/changelog/changes.rb +4 -5
- data/lib/doing/changelog/version.rb +8 -11
- data/lib/doing/chronify/array.rb +4 -4
- data/lib/doing/chronify/string.rb +5 -4
- data/lib/doing/cli_status.rb +7 -2
- data/lib/doing/colors.rb +93 -51
- data/lib/doing/completion/bash_completion.rb +36 -39
- data/lib/doing/completion/completion_string.rb +2 -1
- data/lib/doing/completion/fig_completion.rb +33 -33
- data/lib/doing/completion/fish_completion.rb +22 -23
- data/lib/doing/completion/zsh_completion.rb +5 -5
- data/lib/doing/completion.rb +7 -4
- data/lib/doing/configuration.rb +21 -13
- data/lib/doing/errors.rb +1 -4
- data/lib/doing/good.rb +1 -1
- data/lib/doing/hash.rb +4 -4
- data/lib/doing/help_monkey_patch.rb +1 -1
- data/lib/doing/hooks.rb +6 -2
- data/lib/doing/item/dates.rb +3 -1
- data/lib/doing/item/query.rb +10 -10
- data/lib/doing/item/state.rb +2 -0
- data/lib/doing/logger.rb +113 -45
- data/lib/doing/markdown_document_listener.rb +25 -25
- data/lib/doing/normalize.rb +1 -1
- data/lib/doing/pager.rb +73 -29
- data/lib/doing/plugin_manager.rb +4 -5
- data/lib/doing/plugins/export/byday.rb +1 -1
- data/lib/doing/plugins/export/dayone_export.rb +28 -27
- data/lib/doing/plugins/export/doing_export.rb +1 -1
- data/lib/doing/plugins/export/html_export.rb +3 -3
- data/lib/doing/plugins/export/json_export.rb +4 -5
- data/lib/doing/plugins/export/markdown_export.rb +10 -2
- data/lib/doing/plugins/export/taskpaper_export.rb +1 -0
- data/lib/doing/plugins/export/template_export.rb +110 -107
- data/lib/doing/plugins/import/calendar_import.rb +1 -1
- data/lib/doing/plugins/import/doing_import.rb +2 -2
- data/lib/doing/plugins/import/timing_import.rb +3 -3
- data/lib/doing/prompt/choose.rb +5 -6
- data/lib/doing/prompt/fzf.rb +3 -2
- data/lib/doing/prompt/input.rb +7 -6
- data/lib/doing/prompt/yn.rb +9 -11
- data/lib/doing/string/tags.rb +7 -4
- data/lib/doing/string/transform.rb +15 -10
- data/lib/doing/string/truncate.rb +1 -0
- data/lib/doing/string/url.rb +1 -1
- data/lib/doing/template_string.rb +13 -9
- data/lib/doing/time.rb +4 -2
- data/lib/doing/util.rb +12 -11
- data/lib/doing/util_backup.rb +29 -26
- data/lib/doing/version.rb +3 -1
- data/lib/doing/wwid/display.rb +182 -151
- data/lib/doing/wwid/editor.rb +13 -12
- data/lib/doing/wwid/filetools.rb +13 -11
- data/lib/doing/wwid/filter.rb +41 -40
- data/lib/doing/wwid/guess.rb +6 -8
- data/lib/doing/wwid/interactive.rb +9 -9
- data/lib/doing/wwid/modify.rb +53 -53
- data/lib/doing/wwid/timers.rb +4 -5
- data/lib/doing/wwid/wwid.rb +0 -0
- data/lib/doing/wwid/wwidutil.rb +8 -10
- data/lib/examples/commands/wiki.rb +2 -0
- data/lib/examples/plugins/capture_thing_import.rb +1 -1
- data/lib/examples/plugins/say_export.rb +1 -2
- data/lib/examples/plugins/wiki_export/wiki_export.rb +3 -4
- data/lib/helpers/fzf/test/test_go.rb +5 -5
- data/lib/helpers/threaded_tests.rb +20 -20
- data/lib/helpers/threaded_tests_string.rb +2 -0
- data/rdoc_to_mmd.rb +5 -4
- data/rdocfixer.rb +1 -2
- data/scripts/deploy.rb +3 -4
- data/scripts/generate_bash_completions.rb +40 -43
- data/scripts/generate_fish_completions.rb +17 -15
- data/scripts/generate_zsh_completions.rb +9 -7
- data/scripts/setting_replace.rb +1 -0
- data/scripts/sort_commands.rb +4 -2
- data/yard_templates/default/method_details/setup.rb +3 -1
- metadata +3 -1
|
@@ -13,15 +13,15 @@ module Doing
|
|
|
13
13
|
attr_accessor :commands, :global_options
|
|
14
14
|
|
|
15
15
|
def generate_helpers
|
|
16
|
-
out
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
out = <<~EOFUNCTIONS
|
|
17
|
+
const completionSpec: Fig.Spec = {
|
|
18
|
+
name: "doing",
|
|
19
|
+
description: "A CLI for a What Was I Doing system",
|
|
20
|
+
subcommands: [
|
|
21
|
+
#{generate_subcommand_completions.join("\n ")}
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
export default completionSpec;
|
|
25
25
|
EOFUNCTIONS
|
|
26
26
|
@bar.advance(status: '✅')
|
|
27
27
|
@bar.finish
|
|
@@ -62,34 +62,33 @@ module Doing
|
|
|
62
62
|
arg = ''
|
|
63
63
|
|
|
64
64
|
if option[:arg]
|
|
65
|
-
arg
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
arg = <<~EOARG
|
|
66
|
+
args: {
|
|
67
|
+
#{indent} name: "#{option[:arg]}",
|
|
68
|
+
#{indent} description: "#{option[:arg]}",
|
|
69
|
+
#{indent} },
|
|
70
70
|
EOARG
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
if option[:short]
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
73
|
+
opt_data = if option[:short]
|
|
74
|
+
<<~EOOPT
|
|
75
|
+
{
|
|
76
|
+
#{indent} name: ["-#{option[:short]}", "--#{option[:long]}"],
|
|
77
|
+
#{indent} description: "#{option[:description].sanitize}",
|
|
78
|
+
#{indent} #{arg}
|
|
79
|
+
#{indent}},
|
|
80
|
+
EOOPT
|
|
81
|
+
else
|
|
82
|
+
<<~EOOPT
|
|
83
|
+
{
|
|
84
|
+
#{indent} name: ["--#{option[:long]}"],
|
|
85
|
+
#{indent} description: "#{option[:description].sanitize}",
|
|
86
|
+
#{indent} #{arg}
|
|
87
|
+
#{indent}},
|
|
88
|
+
EOOPT
|
|
89
|
+
end
|
|
90
90
|
|
|
91
91
|
option_arr << opt_data
|
|
92
|
-
|
|
93
92
|
end
|
|
94
93
|
|
|
95
94
|
cmd_opts = <<~EOCMD
|
|
@@ -107,7 +106,8 @@ module Doing
|
|
|
107
106
|
data = Completion.get_help_sections
|
|
108
107
|
@global_options = Completion.parse_options(data[:global_options])
|
|
109
108
|
@commands = Completion.parse_commands(data[:commands])
|
|
110
|
-
@bar = TTY::ProgressBar.new(" \033[0;0;33mGenerating Fig completions: \033[0;35;40m[:bar] :status\033[0m",
|
|
109
|
+
@bar = TTY::ProgressBar.new(" \033[0;0;33mGenerating Fig completions: \033[0;35;40m[:bar] :status\033[0m",
|
|
110
|
+
total: @commands.count + 1, bar_format: :square, hide_cursor: true, status: 'processing subcommands')
|
|
111
111
|
width = TTY::Screen.columns - 45
|
|
112
112
|
@bar.resize(width)
|
|
113
113
|
end
|
|
@@ -4,7 +4,6 @@ module Doing
|
|
|
4
4
|
module Completion
|
|
5
5
|
# Generate completions for Fish
|
|
6
6
|
class FishCompletions
|
|
7
|
-
|
|
8
7
|
attr_accessor :commands, :global_options
|
|
9
8
|
|
|
10
9
|
def generate_helpers
|
|
@@ -152,7 +151,6 @@ module Doing
|
|
|
152
151
|
end
|
|
153
152
|
|
|
154
153
|
def generate_subcommand_option_completions
|
|
155
|
-
|
|
156
154
|
out = []
|
|
157
155
|
need_export = []
|
|
158
156
|
need_bool = []
|
|
@@ -163,32 +161,32 @@ module Doing
|
|
|
163
161
|
need_age = []
|
|
164
162
|
need_section = []
|
|
165
163
|
|
|
166
|
-
@commands.each_with_index do |cmd,
|
|
164
|
+
@commands.each_with_index do |cmd, _i|
|
|
167
165
|
@bar.advance(status: cmd[:commands].first)
|
|
168
166
|
data = Completion.get_help_sections(cmd[:commands].first)
|
|
169
167
|
|
|
170
168
|
if data[:synopsis].join(' ').strip.split(/ /).last =~ /(path|file)/i
|
|
171
|
-
out << "complete -c doing -F -n '__fish_doing_using_command #{cmd[:commands].join(
|
|
169
|
+
out << "complete -c doing -F -n '__fish_doing_using_command #{cmd[:commands].join(' ')}'"
|
|
172
170
|
end
|
|
173
171
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
172
|
+
next unless data[:command_options]
|
|
173
|
+
|
|
174
|
+
Completion.parse_options(data[:command_options]).each do |option|
|
|
175
|
+
next if option.nil?
|
|
176
|
+
|
|
177
|
+
arg = option[:arg] ? '-r' : ''
|
|
178
|
+
short = option[:short] ? "-s #{option[:short]}" : ''
|
|
179
|
+
long = option[:long] ? "-l #{option[:long]}" : ''
|
|
180
|
+
out << "complete -c doing #{long} #{short} -f #{arg} -n '__fish_doing_using_command #{cmd[:commands].join(' ')}' -d #{Shellwords.escape(option[:description])}"
|
|
181
|
+
|
|
182
|
+
need_export.concat(cmd[:commands]) if option[:long] == 'output'
|
|
183
|
+
need_bool.concat(cmd[:commands]) if option[:long] == 'bool'
|
|
184
|
+
need_case.concat(cmd[:commands]) if option[:long] == 'case'
|
|
185
|
+
need_sort.concat(cmd[:commands]) if option[:long] == 'sort'
|
|
186
|
+
need_tag_sort.concat(cmd[:commands]) if option[:long] == 'tag_sort'
|
|
187
|
+
need_tag_order.concat(cmd[:commands]) if option[:long] == 'tag_order'
|
|
188
|
+
need_age.concat(cmd[:commands]) if option[:long] == 'age'
|
|
189
|
+
need_section.concat(cmd[:commands]) if option[:long] == 'section'
|
|
192
190
|
end
|
|
193
191
|
end
|
|
194
192
|
|
|
@@ -232,7 +230,8 @@ module Doing
|
|
|
232
230
|
data = Completion.get_help_sections
|
|
233
231
|
@global_options = Completion.parse_options(data[:global_options])
|
|
234
232
|
@commands = Completion.parse_commands(data[:commands])
|
|
235
|
-
@bar = TTY::ProgressBar.new("\033[0;0;33mGenerating Fish completions: \033[0;35;40m[:bar] :status\033[0m",
|
|
233
|
+
@bar = TTY::ProgressBar.new("\033[0;0;33mGenerating Fish completions: \033[0;35;40m[:bar] :status\033[0m",
|
|
234
|
+
total: @commands.count + 1, bar_format: :square, hide_cursor: true, status: 'processing subcommands')
|
|
236
235
|
width = TTY::Screen.columns - 45
|
|
237
236
|
@bar.resize(width)
|
|
238
237
|
end
|
|
@@ -13,7 +13,7 @@ module Doing
|
|
|
13
13
|
attr_accessor :commands, :global_options
|
|
14
14
|
|
|
15
15
|
def generate_helpers
|
|
16
|
-
out
|
|
16
|
+
out = <<~EOFUNCTIONS
|
|
17
17
|
compdef _doing doing
|
|
18
18
|
|
|
19
19
|
function _doing() {
|
|
@@ -49,7 +49,7 @@ module Doing
|
|
|
49
49
|
|
|
50
50
|
def generate_subcommand_completions
|
|
51
51
|
out = []
|
|
52
|
-
@commands.each_with_index do |cmd,
|
|
52
|
+
@commands.each_with_index do |cmd, _i|
|
|
53
53
|
cmd[:commands].each do |c|
|
|
54
54
|
out << "'#{c}:#{cmd[:description].gsub(/'/, '\\\'')}'"
|
|
55
55
|
end
|
|
@@ -58,10 +58,9 @@ module Doing
|
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def generate_subcommand_option_completions(indent: ' ')
|
|
61
|
-
|
|
62
61
|
out = []
|
|
63
62
|
|
|
64
|
-
@commands.each_with_index do |cmd,
|
|
63
|
+
@commands.each_with_index do |cmd, _i|
|
|
65
64
|
@bar.advance(status: cmd[:commands].first)
|
|
66
65
|
|
|
67
66
|
data = Completion.get_help_sections(cmd[:commands].first)
|
|
@@ -93,7 +92,8 @@ module Doing
|
|
|
93
92
|
data = Completion.get_help_sections
|
|
94
93
|
@global_options = Completion.parse_options(data[:global_options])
|
|
95
94
|
@commands = Completion.parse_commands(data[:commands])
|
|
96
|
-
@bar = TTY::ProgressBar.new(" \033[0;0;33mGenerating Zsh completions: \033[0;35;40m[:bar] :status\033[0m",
|
|
95
|
+
@bar = TTY::ProgressBar.new(" \033[0;0;33mGenerating Zsh completions: \033[0;35;40m[:bar] :status\033[0m",
|
|
96
|
+
total: @commands.count + 1, bar_format: :square, hide_cursor: true, status: 'processing subcommands')
|
|
97
97
|
width = TTY::Screen.columns - 45
|
|
98
98
|
@bar.resize(width)
|
|
99
99
|
end
|
data/lib/doing/completion.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Doing
|
|
|
16
16
|
COMMAND_RX = /^(?<cmd>[^, \t]+)(?<alias>(?:, [^, \t]+)*)?\s+- (?<desc>.*?)$/.freeze
|
|
17
17
|
|
|
18
18
|
class << self
|
|
19
|
-
def get_help_sections(command =
|
|
19
|
+
def get_help_sections(command = '')
|
|
20
20
|
res = `doing help #{command}|command cat`.strip
|
|
21
21
|
scanned = res.scan(SECTIONS_RX)
|
|
22
22
|
sections = {}
|
|
@@ -97,8 +97,10 @@ module Doing
|
|
|
97
97
|
FileUtils.mkdir_p(default_dir)
|
|
98
98
|
src = File.expand_path(File.join(File.dirname(__FILE__), '..', 'completion', default_filenames[type]))
|
|
99
99
|
|
|
100
|
-
if File.exist?(File.join(default_dir,
|
|
101
|
-
|
|
100
|
+
if File.exist?(File.join(default_dir,
|
|
101
|
+
default_filenames[type])) && !Doing::Prompt.yn("Update #{type} completion script",
|
|
102
|
+
default_response: 'n')
|
|
103
|
+
return
|
|
102
104
|
|
|
103
105
|
end
|
|
104
106
|
|
|
@@ -203,7 +205,8 @@ module Doing
|
|
|
203
205
|
case type.to_s
|
|
204
206
|
when /^b/i
|
|
205
207
|
unless dir =~ %r{(\.bash_it/completion|bash_completion/completions)}
|
|
206
|
-
link_completion(file,
|
|
208
|
+
link_completion(file,
|
|
209
|
+
['~/.bash_it/completion/enabled', '/usr/share/bash-completion/completions', '/usr/share/bash_completion/completions'], 'doing.bash')
|
|
207
210
|
end
|
|
208
211
|
when /^fig/i
|
|
209
212
|
when /^f/i
|
data/lib/doing/configuration.rb
CHANGED
|
@@ -116,7 +116,7 @@ module Doing
|
|
|
116
116
|
'interaction' => {
|
|
117
117
|
'confirm_longer_than' => '5h'
|
|
118
118
|
}
|
|
119
|
-
}
|
|
119
|
+
}.freeze
|
|
120
120
|
|
|
121
121
|
def initialize(file = nil, options: {})
|
|
122
122
|
@config_file = file.nil? ? default_config_file : File.expand_path(file)
|
|
@@ -237,11 +237,9 @@ module Doing
|
|
|
237
237
|
if new_cfg.nil?
|
|
238
238
|
return real_path if real_path[-1] == path && real_path.count == element_count
|
|
239
239
|
|
|
240
|
-
if distance < 5 && !create
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
return nil unless create
|
|
244
|
-
end
|
|
240
|
+
return resolve_key_path(keypath, create: false, distance: distance + 1) if distance < 5 && !create
|
|
241
|
+
|
|
242
|
+
return nil unless create
|
|
245
243
|
|
|
246
244
|
resolved = real_path.count.positive? ? "Resolved #{real_path.join('.')}, but " : ''
|
|
247
245
|
Doing.logger.log_now(:warn, "#{resolved}#{path} is unknown")
|
|
@@ -251,13 +249,19 @@ module Doing
|
|
|
251
249
|
raise InvalidArgument, 'Invalid key path' unless res
|
|
252
250
|
|
|
253
251
|
real_path.push(path).concat(paths).compact!
|
|
254
|
-
|
|
252
|
+
unless keypath == real_path.join('.')
|
|
253
|
+
Doing.logger.debug('Config:',
|
|
254
|
+
"translated key path #{keypath} to #{real_path.join('.')}")
|
|
255
|
+
end
|
|
255
256
|
return real_path
|
|
256
257
|
end
|
|
257
258
|
cfg = new_cfg
|
|
258
259
|
end
|
|
259
260
|
end
|
|
260
|
-
|
|
261
|
+
unless keypath == real_path.join('.')
|
|
262
|
+
Doing.logger.debug('Config:',
|
|
263
|
+
"translated key path #{keypath} to #{real_path.join('.')}")
|
|
264
|
+
end
|
|
261
265
|
real_path
|
|
262
266
|
end
|
|
263
267
|
|
|
@@ -295,7 +299,8 @@ module Doing
|
|
|
295
299
|
#
|
|
296
300
|
def from(user_config)
|
|
297
301
|
# Util.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
|
|
298
|
-
Configuration[user_config].stringify_keys.deep_merge(DEFAULTS,
|
|
302
|
+
Configuration[user_config].stringify_keys.deep_merge(DEFAULTS,
|
|
303
|
+
{ extend_existing_arrays: true, sort_merged_arrays: true })
|
|
299
304
|
end
|
|
300
305
|
|
|
301
306
|
##
|
|
@@ -346,7 +351,7 @@ module Doing
|
|
|
346
351
|
|
|
347
352
|
load_plugins(plugin_config['plugin_path'])
|
|
348
353
|
|
|
349
|
-
Plugins.plugins.
|
|
354
|
+
Plugins.plugins.each_value do |plugins|
|
|
350
355
|
plugins.each do |title, plugin|
|
|
351
356
|
plugin_config[title] = plugin[:config] if plugin[:config].good?
|
|
352
357
|
config['export_templates'][title] ||= nil if plugin[:templates] && !plugin[:templates].empty?
|
|
@@ -366,7 +371,10 @@ module Doing
|
|
|
366
371
|
|
|
367
372
|
Hooks.trigger :post_config, self
|
|
368
373
|
|
|
369
|
-
|
|
374
|
+
unless @ignore_local
|
|
375
|
+
config = local_config.deep_merge(config,
|
|
376
|
+
{ extend_existing_arrays: true, sort_merged_arrays: true })
|
|
377
|
+
end
|
|
370
378
|
# config = Util.deep_merge_hashes(config, local_config) unless @ignore_local
|
|
371
379
|
|
|
372
380
|
Hooks.trigger :post_local_config, self
|
|
@@ -483,13 +491,13 @@ module Doing
|
|
|
483
491
|
end
|
|
484
492
|
|
|
485
493
|
begin
|
|
486
|
-
|
|
487
494
|
user_config = Util.safe_load_file(config_file)
|
|
488
495
|
raise StandardError, 'Invalid config file format' unless user_config.is_a?(Hash)
|
|
489
496
|
|
|
490
497
|
if user_config.key?('html_template')
|
|
491
498
|
user_config['export_templates'] ||= {}
|
|
492
|
-
user_config['export_templates'].deep_merge(user_config.delete('html_template'),
|
|
499
|
+
user_config['export_templates'].deep_merge(user_config.delete('html_template'),
|
|
500
|
+
{ extend_existing_arrays: true, sort_merged_arrays: true })
|
|
493
501
|
end
|
|
494
502
|
|
|
495
503
|
user_config['include_notes'] = user_config.delete(':include_notes') if user_config.key?(':include_notes')
|
data/lib/doing/errors.rb
CHANGED
|
@@ -6,9 +6,7 @@ module Doing
|
|
|
6
6
|
def initialize(msg = nil, level: nil, topic: 'Error:', exit_code: 1)
|
|
7
7
|
level ||= :error
|
|
8
8
|
Doing.logger.output_results
|
|
9
|
-
if msg
|
|
10
|
-
Doing.logger.log_now(level, topic, msg)
|
|
11
|
-
end
|
|
9
|
+
Doing.logger.log_now(level, topic, msg) if msg
|
|
12
10
|
|
|
13
11
|
Process.exit exit_code
|
|
14
12
|
end
|
|
@@ -52,7 +50,6 @@ module Doing
|
|
|
52
50
|
class NoResults < DoingNoTraceError
|
|
53
51
|
def initialize(msg = 'No results', topic = 'Exited:')
|
|
54
52
|
super(msg, level: :warn, topic: topic, exit_code: 0)
|
|
55
|
-
|
|
56
53
|
end
|
|
57
54
|
end
|
|
58
55
|
|
data/lib/doing/good.rb
CHANGED
data/lib/doing/hash.rb
CHANGED
|
@@ -153,7 +153,7 @@ module Doing
|
|
|
153
153
|
## Remove keys with empty values
|
|
154
154
|
##
|
|
155
155
|
def remove_empty
|
|
156
|
-
delete_if { |
|
|
156
|
+
delete_if { |_k, v| !v.is_a?(FalseClass) && !v.good? }
|
|
157
157
|
end
|
|
158
158
|
|
|
159
159
|
def tag_filter_to_options
|
|
@@ -193,9 +193,9 @@ module Doing
|
|
|
193
193
|
## @param to_delete [Array] the keys to delete if key doesn't exist
|
|
194
194
|
##
|
|
195
195
|
def delete_unless_key(key, to_delete)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
196
|
+
return if key?(key)
|
|
197
|
+
|
|
198
|
+
to_delete.each { |k| delete(k) }
|
|
199
199
|
end
|
|
200
200
|
end
|
|
201
201
|
end
|
|
@@ -4,7 +4,7 @@ module GLI
|
|
|
4
4
|
module Commands
|
|
5
5
|
# Help Command Monkeypatch for paginated output
|
|
6
6
|
class Help < Command
|
|
7
|
-
def show_help(
|
|
7
|
+
def show_help(_global_options, options, arguments, out, error)
|
|
8
8
|
Doing::Pager.paginate = true
|
|
9
9
|
|
|
10
10
|
command_finder = HelpModules::CommandFinder.new(@app, arguments, error)
|
data/lib/doing/hooks.rb
CHANGED
|
@@ -40,10 +40,14 @@ module Doing
|
|
|
40
40
|
# register a single hook to be called later, internal API
|
|
41
41
|
def self.register_one(event, priority, &block)
|
|
42
42
|
unless @registry[event]
|
|
43
|
-
raise Doing::Errors::HookUnavailable.new("Invalid hook. Doing only supports #{@registry.keys.inspect}", 'hook',
|
|
43
|
+
raise Doing::Errors::HookUnavailable.new("Invalid hook. Doing only supports #{@registry.keys.inspect}", 'hook',
|
|
44
|
+
event)
|
|
44
45
|
end
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
unless block.respond_to? :call
|
|
48
|
+
raise Doing::Errors::PluginUncallable.new('Hooks must respond to :call', 'hook',
|
|
49
|
+
event)
|
|
50
|
+
end
|
|
47
51
|
|
|
48
52
|
Doing.logger.debug('Hook Manager:', "Registered #{event} hook") if ENV['DOING_PLUGIN_DEBUG']
|
|
49
53
|
|
data/lib/doing/item/dates.rb
CHANGED
data/lib/doing/item/query.rb
CHANGED
|
@@ -448,16 +448,16 @@ module Doing
|
|
|
448
448
|
end
|
|
449
449
|
|
|
450
450
|
def value_string_matches?(tag_val, comp, value)
|
|
451
|
-
case comp
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
451
|
+
tag_val =~ case comp
|
|
452
|
+
when /\^=/
|
|
453
|
+
/^#{value.wildcard_to_rx}/i
|
|
454
|
+
when /\$=/
|
|
455
|
+
/#{value.wildcard_to_rx}$/i
|
|
456
|
+
when /==/
|
|
457
|
+
/^#{value.wildcard_to_rx}$/i
|
|
458
|
+
else
|
|
459
|
+
/#{value.wildcard_to_rx}/i
|
|
460
|
+
end
|
|
461
461
|
end
|
|
462
462
|
|
|
463
463
|
def value_number_matches?(tag_val, comp, value)
|
data/lib/doing/item/state.rb
CHANGED
data/lib/doing/logger.rb
CHANGED
|
@@ -270,58 +270,126 @@ module Doing
|
|
|
270
270
|
def benchmark(key, state)
|
|
271
271
|
return unless ENV['DOING_BENCHMARK']
|
|
272
272
|
|
|
273
|
+
# Pre-allocate benchmarks hash to avoid repeated allocation
|
|
273
274
|
@benchmarks ||= {}
|
|
274
|
-
|
|
275
|
+
|
|
276
|
+
# Use direct assignment instead of ||= for better performance
|
|
277
|
+
@benchmarks[key] = { start: nil, finish: nil } if @benchmarks[key].nil?
|
|
275
278
|
@benchmarks[key][state] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
276
279
|
end
|
|
277
280
|
|
|
281
|
+
# Measure execution time of a block with automatic start/finish
|
|
282
|
+
def measure(key, &_block)
|
|
283
|
+
return yield unless ENV['DOING_BENCHMARK']
|
|
284
|
+
|
|
285
|
+
benchmark(key, :start)
|
|
286
|
+
result = yield
|
|
287
|
+
benchmark(key, :finish)
|
|
288
|
+
result
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# Get benchmark statistics for a specific key
|
|
292
|
+
def benchmark_stats(key)
|
|
293
|
+
return nil unless @benchmarks.dig(key, :start) && @benchmarks.dig(key, :finish)
|
|
294
|
+
|
|
295
|
+
{
|
|
296
|
+
key: key,
|
|
297
|
+
duration: (@benchmarks[key][:finish] - @benchmarks[key][:start]).round(4),
|
|
298
|
+
start_time: @benchmarks[key][:start].round(4),
|
|
299
|
+
end_time: @benchmarks[key][:finish].round(4)
|
|
300
|
+
}
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Get all benchmark statistics sorted by duration
|
|
304
|
+
def all_benchmark_stats
|
|
305
|
+
return [] unless @benchmarks
|
|
306
|
+
|
|
307
|
+
@benchmarks.map do |key, timers|
|
|
308
|
+
next unless timers[:start] && timers[:finish]
|
|
309
|
+
|
|
310
|
+
{
|
|
311
|
+
key: key,
|
|
312
|
+
duration: (timers[:finish] - timers[:start]).round(4),
|
|
313
|
+
start_time: timers[:start].round(4),
|
|
314
|
+
end_time: timers[:finish].round(4)
|
|
315
|
+
}
|
|
316
|
+
end.compact.sort_by { |stats| -stats[:duration] }
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Generate a compact benchmark summary
|
|
320
|
+
def benchmark_summary
|
|
321
|
+
return unless ENV['DOING_BENCHMARK'] && @benchmarks
|
|
322
|
+
|
|
323
|
+
stats = all_benchmark_stats
|
|
324
|
+
return if stats.empty?
|
|
325
|
+
|
|
326
|
+
total_duration = stats.find { |s| s[:key] == :total }&.dig(:duration) || 0
|
|
327
|
+
return if total_duration <= 0
|
|
328
|
+
|
|
329
|
+
output = []
|
|
330
|
+
output << "Benchmark Summary (Total: #{total_duration.round(4)}s):"
|
|
331
|
+
stats.reject { |s| s[:key] == :total }.each do |stat|
|
|
332
|
+
percentage = (stat[:duration] / total_duration * 100).round(1)
|
|
333
|
+
output << " #{stat[:key]}: #{stat[:duration]}s (#{percentage}%)"
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
output.join("\n")
|
|
337
|
+
end
|
|
338
|
+
|
|
278
339
|
def log_benchmarks
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
output = []
|
|
282
|
-
beginning = @benchmarks[:total][:start]
|
|
283
|
-
ending = @benchmarks[:total][:finish]
|
|
284
|
-
total = ending - beginning
|
|
285
|
-
factor = TTY::Screen.columns / total
|
|
286
|
-
|
|
287
|
-
cols = Array.new(TTY::Screen.columns)
|
|
288
|
-
|
|
289
|
-
colors = %w[bgred bggreen bgyellow bgblue bgmagenta bgcyan bgwhite boldbgred boldbggreen boldbgyellow boldbgblue boldbgwhite]
|
|
290
|
-
idx = 0
|
|
291
|
-
# @benchmarks.delete(:total)
|
|
292
|
-
|
|
293
|
-
@benchmarks.sort_by { |_, timers| [timers[:start], timers[:finish]] }.each do |k, timers|
|
|
294
|
-
if timers[:finish] && timers[:start]
|
|
295
|
-
color = colors[idx % colors.count]
|
|
296
|
-
fg = if idx < 7
|
|
297
|
-
Color.boldblack
|
|
298
|
-
else
|
|
299
|
-
Color.boldwhite
|
|
300
|
-
end
|
|
301
|
-
color = Color.send(color) + fg
|
|
302
|
-
|
|
303
|
-
start = ((timers[:start] - beginning) * factor).floor
|
|
304
|
-
finish = ((timers[:finish] - beginning) * factor).ceil
|
|
305
|
-
|
|
306
|
-
cols.fill("#{color}-", start..finish)
|
|
307
|
-
cols[start] = "#{color}|"
|
|
308
|
-
cols[finish] = "#{color}|"
|
|
309
|
-
output << "#{color}#{k}#{Color.default}: #{timers[:finish] - timers[:start]}"
|
|
310
|
-
else
|
|
311
|
-
output << "#{k}: error"
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
idx += 1
|
|
315
|
-
end
|
|
340
|
+
return unless ENV['DOING_BENCHMARK'] && @benchmarks
|
|
316
341
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
342
|
+
# Cache screen width to avoid repeated calls
|
|
343
|
+
screen_width = TTY::Screen.columns
|
|
344
|
+
return if screen_width <= 0
|
|
345
|
+
|
|
346
|
+
beginning = @benchmarks[:total]&.dig(:start)
|
|
347
|
+
ending = @benchmarks[:total]&.dig(:finish)
|
|
348
|
+
return unless beginning && ending
|
|
349
|
+
|
|
350
|
+
total = ending - beginning
|
|
351
|
+
return if total <= 0
|
|
352
|
+
|
|
353
|
+
factor = screen_width.to_f / total
|
|
354
|
+
cols = Array.new(screen_width, ' ')
|
|
355
|
+
output = []
|
|
320
356
|
|
|
321
|
-
|
|
357
|
+
# Pre-allocate colors array to avoid repeated allocation
|
|
358
|
+
colors = %w[bgred bggreen bgyellow bgblue bgmagenta bgcyan bgwhite
|
|
359
|
+
boldbgred boldbggreen boldbgyellow boldbgblue boldbgwhite]
|
|
360
|
+
color_count = colors.size
|
|
322
361
|
|
|
323
|
-
|
|
362
|
+
# Sort benchmarks once and cache the result
|
|
363
|
+
sorted_benchmarks = @benchmarks.reject { |k, _| k == :total }
|
|
364
|
+
.select { |_, timers| timers[:finish] && timers[:start] }
|
|
365
|
+
.sort_by { |_, timers| timers[:start] }
|
|
366
|
+
|
|
367
|
+
sorted_benchmarks.each_with_index do |(key, timers), idx|
|
|
368
|
+
color_name = colors[idx % color_count]
|
|
369
|
+
fg_color = idx < 7 ? Color.boldblack : Color.boldwhite
|
|
370
|
+
color = Color.send(color_name) + fg_color
|
|
371
|
+
|
|
372
|
+
start_pos = ((timers[:start] - beginning) * factor).floor
|
|
373
|
+
finish_pos = ((timers[:finish] - beginning) * factor).ceil
|
|
374
|
+
|
|
375
|
+
# Ensure positions are within bounds
|
|
376
|
+
start_pos = [start_pos, 0].max
|
|
377
|
+
finish_pos = [finish_pos, screen_width - 1].min
|
|
378
|
+
|
|
379
|
+
if start_pos < finish_pos
|
|
380
|
+
cols.fill("#{color}-", start_pos..finish_pos)
|
|
381
|
+
cols[start_pos] = "#{color}|"
|
|
382
|
+
cols[finish_pos] = "#{color}|"
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
duration = (timers[:finish] - timers[:start]).round(4)
|
|
386
|
+
output << "#{color}#{key}#{Color.default}: #{duration}"
|
|
324
387
|
end
|
|
388
|
+
|
|
389
|
+
# Output all messages at once to reduce I/O overhead
|
|
390
|
+
output.each { |msg| $stdout.puts color_message(:debug, 'Benchmark:', msg) }
|
|
391
|
+
$stdout.puts color_message(:debug, 'Benchmark:', "Total: #{total.round(4)}")
|
|
392
|
+
$stdout.puts cols.join + Color.reset
|
|
325
393
|
end
|
|
326
394
|
|
|
327
395
|
def log_change(tags_added: [], tags_removed: [], count: 1, item: nil, single: false)
|
|
@@ -467,9 +535,9 @@ module Doing
|
|
|
467
535
|
|
|
468
536
|
message.sub!(/^(\s*\S.*?): (.*?)$/) do
|
|
469
537
|
m = Regexp.last_match
|
|
470
|
-
|
|
538
|
+
msg_content = m[2] =~ /(\e\[[\d;]+m)/ ? m[2] : "#{message_fg}#{m[2]}"
|
|
471
539
|
|
|
472
|
-
"#{topic_fg}#{m[1]}#{colors.reset}: #{
|
|
540
|
+
"#{topic_fg}#{m[1]}#{colors.reset}: #{msg_content}"
|
|
473
541
|
end
|
|
474
542
|
|
|
475
543
|
"#{prefix} #{message.highlight_tags}#{colors.reset}"
|