doing 2.1.18 → 2.1.23
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 +19 -16
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +121 -53
- data/Gemfile.lock +11 -11
- data/README.md +1 -1
- data/Rakefile +12 -4
- data/bin/doing +297 -234
- data/docs/doc/Array.html +7 -30
- 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/Color.html +3 -3
- data/docs/doc/Doing/Completion.html +3 -3
- data/docs/doc/Doing/Configuration.html +6 -5
- 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/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/Hooks.html +3 -3
- data/docs/doc/Doing/Item.html +3 -3
- data/docs/doc/Doing/Items.html +3 -3
- data/docs/doc/Doing/LogAdapter.html +3 -3
- data/docs/doc/Doing/Note.html +3 -3
- data/docs/doc/Doing/Pager.html +3 -3
- data/docs/doc/Doing/Plugins.html +3 -3
- data/docs/doc/Doing/Prompt.html +7 -7
- data/docs/doc/Doing/Section.html +3 -3
- data/docs/doc/Doing/TemplateString.html +4 -4
- data/docs/doc/Doing/Types.html +201 -0
- data/docs/doc/Doing/Util/Backup.html +3 -3
- data/docs/doc/Doing/Util.html +4 -7
- data/docs/doc/Doing/WWID.html +66 -8
- data/docs/doc/Doing.html +6 -6
- data/docs/doc/GLI/Commands/Help.html +185 -0
- data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +3 -3
- data/docs/doc/GLI/Commands.html +7 -5
- data/docs/doc/GLI.html +6 -4
- data/docs/doc/Hash.html +80 -16
- data/docs/doc/Numeric.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 +195 -26
- data/docs/doc/Symbol.html +3 -3
- data/docs/doc/Time.html +3 -3
- data/docs/doc/_index.html +22 -8
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +4 -4
- data/docs/doc/frames.html +1 -1
- data/docs/doc/index.html +4 -4
- data/docs/doc/method_list.html +334 -270
- data/docs/doc/top-level-namespace.html +3 -3
- data/docs/index.md +1 -1
- data/doing.gemspec +1 -1
- data/doing.rdoc +173 -15
- data/lib/completion/_doing.zsh +20 -20
- data/lib/completion/doing.bash +37 -26
- data/lib/completion/doing.fish +114 -16
- data/lib/doing/array.rb +5 -4
- data/lib/doing/array_chronify.rb +4 -3
- data/lib/doing/changelog/change.rb +115 -0
- data/lib/doing/changelog/changes.rb +73 -0
- data/lib/doing/changelog/entry.rb +21 -0
- data/lib/doing/changelog/version.rb +97 -0
- data/lib/doing/changelog.rb +6 -0
- data/lib/doing/completion/fish_completion.rb +80 -11
- data/lib/doing/configuration.rb +17 -8
- data/lib/doing/hash.rb +25 -6
- data/lib/doing/help_monkey_patch.rb +31 -0
- data/lib/doing/hooks.rb +5 -1
- data/lib/doing/item.rb +10 -25
- data/lib/doing/items.rb +3 -1
- data/lib/doing/log_adapter.rb +1 -1
- data/lib/doing/pager.rb +2 -2
- data/lib/doing/plugins/export/dayone_export.rb +1 -1
- data/lib/doing/plugins/export/markdown_export.rb +1 -1
- data/lib/doing/plugins/export/template_export.rb +9 -3
- data/lib/doing/prompt.rb +4 -2
- data/lib/doing/string.rb +44 -12
- data/lib/doing/string_chronify.rb +56 -18
- data/lib/doing/template_string.rb +7 -0
- data/lib/doing/types.rb +25 -0
- data/lib/doing/util.rb +2 -1
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +93 -69
- data/lib/doing.rb +2 -0
- data/lib/examples/commands/later.rb +32 -0
- data/lib/helpers/threaded_tests.rb +286 -0
- metadata +17 -6
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doing
|
|
4
|
+
# A collection of Changes
|
|
5
|
+
class Changes
|
|
6
|
+
attr_reader :changes
|
|
7
|
+
|
|
8
|
+
def initialize(lookup: nil, search: nil)
|
|
9
|
+
changelog = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'CHANGELOG.md'))
|
|
10
|
+
raise 'Error locating changelog' unless File.exist?(changelog)
|
|
11
|
+
|
|
12
|
+
@content = IO.read(changelog)
|
|
13
|
+
parse_changes(lookup, search)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def latest
|
|
17
|
+
@changes[0].to_s.force_encoding('utf-8')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_s
|
|
21
|
+
@changes.map(&:to_s).join("\n\n").force_encoding('utf-8')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def parse_changes(lookup, search)
|
|
27
|
+
change_rx = /(?<=\n|\A)### (\d+\.\d+\.\d+(?:\w+)?)(.*?)(?=\n### |\Z)/m
|
|
28
|
+
@changes = @content.scan(change_rx).each_with_object([]) do |m, a|
|
|
29
|
+
next if m[0].nil? || m[1].nil?
|
|
30
|
+
|
|
31
|
+
a << Change.new(m[0], m[1].strip)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
lookup(lookup) unless lookup.nil?
|
|
35
|
+
search(search) unless search.nil?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def lookup(lookup_version)
|
|
39
|
+
range = []
|
|
40
|
+
|
|
41
|
+
if lookup_version =~ /([\d.]+) *-+ *([\d.]+)/
|
|
42
|
+
m = Regexp.last_match
|
|
43
|
+
lookup("> #{m[1]}")
|
|
44
|
+
lookup("< #{m[2]}")
|
|
45
|
+
elsif lookup_version.scan(/[<>]/).count > 1
|
|
46
|
+
params = lookup_version.scan(/[<>] [\d.]+/)
|
|
47
|
+
params.each { |query| lookup(query) }
|
|
48
|
+
else
|
|
49
|
+
comp = case lookup_version
|
|
50
|
+
when /(<|prior|before|older)/
|
|
51
|
+
:older
|
|
52
|
+
when />|since|after|newer/
|
|
53
|
+
:newer
|
|
54
|
+
else
|
|
55
|
+
:equal
|
|
56
|
+
end
|
|
57
|
+
version = Version.new(lookup_version)
|
|
58
|
+
|
|
59
|
+
@changes.select! do |change|
|
|
60
|
+
change.version.compare(version, comp)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def search(query)
|
|
66
|
+
@changes.map do |c|
|
|
67
|
+
c.entries = c.search_entries(query)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
@changes.delete_if { |c| c.nil? || c.entries.nil? }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doing
|
|
4
|
+
# An individual changelog item
|
|
5
|
+
class Entry
|
|
6
|
+
attr_reader :type, :string
|
|
7
|
+
|
|
8
|
+
def initialize(string, type)
|
|
9
|
+
@string = string
|
|
10
|
+
@type = type
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def clean(string)
|
|
14
|
+
string.gsub(/\|/, '\|')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_s
|
|
18
|
+
"- #{clean(@string)}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doing
|
|
4
|
+
# Semantic versioning
|
|
5
|
+
class Version
|
|
6
|
+
attr_reader :maj, :min, :patch
|
|
7
|
+
|
|
8
|
+
def initialize(string)
|
|
9
|
+
@maj, @min, @patch = version_to_a(string)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def version_to_a(string)
|
|
13
|
+
raise 'Version not a string' unless string.is_a?(String)
|
|
14
|
+
|
|
15
|
+
v = string.match(/(?<maj>\d+)(?:\.(?<min>[\d*?]+))?(?:\.(?<patch>[\d*?]+))?/)
|
|
16
|
+
|
|
17
|
+
raise 'Error parsing semantic version string' if v.nil?
|
|
18
|
+
|
|
19
|
+
maj = v['maj'].to_i
|
|
20
|
+
min = case v['min']
|
|
21
|
+
when /[*?]/
|
|
22
|
+
v['min'].sub(/(\d+)?[^\d]/, '\1\d+')
|
|
23
|
+
when /^[0-9]+$/
|
|
24
|
+
v['min'].to_i
|
|
25
|
+
end
|
|
26
|
+
pat = case v['patch']
|
|
27
|
+
when /[*?]/
|
|
28
|
+
v['patch'].sub(/(\d+)?[^\d]/, '\1\d+')
|
|
29
|
+
when /^[0-9]+$/
|
|
30
|
+
v['patch'].to_i
|
|
31
|
+
end
|
|
32
|
+
[maj, min, pat]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def wild?(val)
|
|
36
|
+
val.is_a?(String)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def compare(other, comp)
|
|
41
|
+
case comp
|
|
42
|
+
when :older
|
|
43
|
+
if @maj <= other.maj
|
|
44
|
+
if @maj < other.maj
|
|
45
|
+
true
|
|
46
|
+
elsif @maj == other.maj && (other.min.nil? || @min < other.min)
|
|
47
|
+
true
|
|
48
|
+
elsif @maj == other.maj && @min == other.min
|
|
49
|
+
other.patch.nil? ? false : @patch < other.patch
|
|
50
|
+
else
|
|
51
|
+
false
|
|
52
|
+
end
|
|
53
|
+
else
|
|
54
|
+
false
|
|
55
|
+
end
|
|
56
|
+
when :newer
|
|
57
|
+
if @maj >= other.maj
|
|
58
|
+
if @maj > other.maj
|
|
59
|
+
true
|
|
60
|
+
elsif @maj == other.maj && (other.min.nil? || @min > other.min)
|
|
61
|
+
true
|
|
62
|
+
elsif @maj == other.maj && @min == other.min
|
|
63
|
+
other.patch.nil? || @patch >= other.patch
|
|
64
|
+
else
|
|
65
|
+
false
|
|
66
|
+
end
|
|
67
|
+
else
|
|
68
|
+
false
|
|
69
|
+
end
|
|
70
|
+
when :equal
|
|
71
|
+
if @maj == other.maj
|
|
72
|
+
if other.min.nil?
|
|
73
|
+
true
|
|
74
|
+
elsif wild?(other.min)
|
|
75
|
+
@min.to_s =~ /^#{other.min}/ ? true : false
|
|
76
|
+
else
|
|
77
|
+
if @min == other.min
|
|
78
|
+
if other.patch.nil?
|
|
79
|
+
true
|
|
80
|
+
elsif wild?(other.patch)
|
|
81
|
+
@patch.to_s =~ /^#{other.patch}/ ? true : false
|
|
82
|
+
else
|
|
83
|
+
@patch == other.patch
|
|
84
|
+
end
|
|
85
|
+
else
|
|
86
|
+
false
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def to_s
|
|
94
|
+
"#{@maj}.#{@min || 0}.#{@patch || 0}"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -31,28 +31,89 @@ module Doing
|
|
|
31
31
|
and return 0
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
function __fish_doing_cache_timer_expired
|
|
35
|
+
set -l timer __fish_doing_cache_timer_$argv[1]
|
|
36
|
+
if not set -q $timer
|
|
37
|
+
set -g $timer (date '+%s')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if test (math (date '+%s') - $$timer) -gt $argv[2]
|
|
41
|
+
set -g $timer (date '+%s')
|
|
42
|
+
return 1
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
return 0
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
function __fish_doing_subcommands
|
|
49
|
+
if not set -q __fish_doing_subcommands_cache
|
|
50
|
+
or __fish_doing_cache_timer_expired subcommands 86400
|
|
51
|
+
set -g -a __fish_doing_subcommands_cache (doing help -c)
|
|
52
|
+
end
|
|
53
|
+
printf '%s\n' $__fish_doing_subcommands_cache
|
|
54
|
+
end
|
|
55
|
+
|
|
34
56
|
function __fish_doing_complete_sections
|
|
35
|
-
|
|
57
|
+
if not set -q __fish_doing_sections_cache
|
|
58
|
+
or __fish_doing_cache_timer_expired sections 3600
|
|
59
|
+
set -g -a __fish_doing_sections_cache (doing sections -c)
|
|
60
|
+
end
|
|
61
|
+
printf '%s\n' $__fish_doing_sections_cache
|
|
62
|
+
__fish_doing_complete_show_tag
|
|
36
63
|
end
|
|
37
64
|
|
|
38
65
|
function __fish_doing_complete_views
|
|
39
|
-
|
|
66
|
+
if not set -q __fish_doing_views_cache
|
|
67
|
+
or __fish_doing_cache_timer_expired views 3600
|
|
68
|
+
set -g -a __fish_doing_views_cache (doing views -c)
|
|
69
|
+
end
|
|
70
|
+
printf '%s\n' $__fish_doing_views_cache
|
|
40
71
|
end
|
|
41
72
|
|
|
42
|
-
function
|
|
43
|
-
|
|
73
|
+
function __fish_doing_export_plugin
|
|
74
|
+
if not set -q __fish_doing_export_plugin_cache
|
|
75
|
+
or __fish_doing_cache_timer_expired export_plugins 3600
|
|
76
|
+
set -g -a __fish_doing_export_plugin_cache (doing plugins --type export -c)
|
|
77
|
+
end
|
|
78
|
+
printf '%s\n' $__fish_doing_export_plugin_cache
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
function __fish_doing_import_plugin
|
|
82
|
+
if not set -q __fish_doing_import_plugin_cache
|
|
83
|
+
or __fish_doing_cache_timer_expired import_plugins 3600
|
|
84
|
+
set -g -a __fish_doing_import_plugin_cache (doing plugins --type import -c)
|
|
85
|
+
end
|
|
86
|
+
printf '%s\n' $__fish_doing_import_plugin_cache
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
function __fish_doing_complete_template
|
|
90
|
+
if not set -q __fish_doing_template_cache
|
|
91
|
+
or __fish_doing_cache_timer_expired template 3600
|
|
92
|
+
set -g -a __fish_doing_template_cache (doing template -c)
|
|
93
|
+
end
|
|
94
|
+
printf '%s\n' $__fish_doing_template_cache
|
|
44
95
|
end
|
|
45
96
|
|
|
46
|
-
function
|
|
47
|
-
|
|
97
|
+
function __fish_doing_complete_tag
|
|
98
|
+
if not set -q __fish_doing_tag_cache
|
|
99
|
+
or __fish_doing_cache_timer_expired tags 60
|
|
100
|
+
set -g -a __fish_doing_tag_cache (doing tags)
|
|
101
|
+
end
|
|
102
|
+
printf '%s\n' $__fish_doing_tag_cache
|
|
48
103
|
end
|
|
49
104
|
|
|
50
|
-
function
|
|
51
|
-
|
|
105
|
+
function __fish_doing_complete_show_tag
|
|
106
|
+
if not set -q __fish_doing_tag_cache
|
|
107
|
+
or __fish_doing_cache_timer_expired tags 60
|
|
108
|
+
set -g -a __fish_doing_tag_cache (doing tags)
|
|
109
|
+
end
|
|
110
|
+
printf '@%s\n' $__fish_doing_tag_cache
|
|
52
111
|
end
|
|
53
112
|
|
|
54
|
-
function
|
|
55
|
-
doing
|
|
113
|
+
function __fish_doing_complete_args
|
|
114
|
+
for cmd in (doing commands_accepting -c $argv[1])
|
|
115
|
+
complete -x -c doing -l $argv[1] -n "__fish_doing_using_command $cmd" -a "(__fish_doing_complete_$argv[1])"
|
|
116
|
+
end
|
|
56
117
|
end
|
|
57
118
|
|
|
58
119
|
complete -c doing -f
|
|
@@ -64,6 +125,14 @@ module Doing
|
|
|
64
125
|
complete -f -c doing -s t -l type -x -n '__fish_doing_using_command import' -a '(__fish_doing_import_plugins)'
|
|
65
126
|
|
|
66
127
|
complete -xc doing -n '__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from (doing help -c)' -a "(doing help -c)"
|
|
128
|
+
|
|
129
|
+
function __fish_doing_complete_args
|
|
130
|
+
for cmd in (doing commands_accepting -c $argv[1])
|
|
131
|
+
complete -x -c doing -l $argv[1] -n "__fish_doing_using_command $cmd" -a "(__fish_doing_complete_$argv[1])"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
__fish_doing_complete_args tag
|
|
67
136
|
EOFUNCTIONS
|
|
68
137
|
end
|
|
69
138
|
|
|
@@ -161,7 +230,7 @@ module Doing
|
|
|
161
230
|
end
|
|
162
231
|
|
|
163
232
|
unless need_export.empty?
|
|
164
|
-
out << "complete -f -c doing -s o -l output -x -n '__fish_doing_using_command #{need_export.join(' ')}' -a '(
|
|
233
|
+
out << "complete -f -c doing -s o -l output -x -n '__fish_doing_using_command #{need_export.join(' ')}' -a '(__fish_doing_export_plugin)'"
|
|
165
234
|
end
|
|
166
235
|
|
|
167
236
|
unless need_bool.empty?
|
data/lib/doing/configuration.rb
CHANGED
|
@@ -30,6 +30,7 @@ module Doing
|
|
|
30
30
|
'command_path' => File.join(Util.user_home, '.config', 'doing', 'commands')
|
|
31
31
|
},
|
|
32
32
|
'doing_file' => '~/.local/share/doing/what_was_i_doing.md',
|
|
33
|
+
'doing_file_sort' => 'desc',
|
|
33
34
|
'backup_dir' => '~/.local/share/doing/doing_backup',
|
|
34
35
|
'history_size' => 15,
|
|
35
36
|
'current_section' => 'Currently',
|
|
@@ -159,7 +160,7 @@ module Doing
|
|
|
159
160
|
def choose_config(create: false)
|
|
160
161
|
return @config_file if @force_answer
|
|
161
162
|
|
|
162
|
-
if @additional_configs
|
|
163
|
+
if @additional_configs&.count&.positive? || create
|
|
163
164
|
choices = [@config_file].concat(@additional_configs)
|
|
164
165
|
choices.push('Create a new .doingrc in the current directory') if create && !File.exist?('.doingrc')
|
|
165
166
|
res = Doing::Prompt.choose_from(choices.uniq.sort.reverse,
|
|
@@ -189,7 +190,7 @@ module Doing
|
|
|
189
190
|
## matched, first match wins)
|
|
190
191
|
## @return [Array] ordered array of resolved keys
|
|
191
192
|
##
|
|
192
|
-
def resolve_key_path(keypath, create: false)
|
|
193
|
+
def resolve_key_path(keypath, create: false, distance: 2)
|
|
193
194
|
cfg = @settings
|
|
194
195
|
real_path = []
|
|
195
196
|
unless keypath =~ /^[.*]?$/
|
|
@@ -197,16 +198,24 @@ module Doing
|
|
|
197
198
|
while paths.length.positive? && !cfg.nil?
|
|
198
199
|
path = paths.shift
|
|
199
200
|
new_cfg = nil
|
|
200
|
-
cfg.each do |key, val|
|
|
201
|
-
next unless key =~ path.to_rx(distance: 4)
|
|
202
201
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
202
|
+
if cfg.is_a?(Hash)
|
|
203
|
+
matches = cfg.select { |key, val| key =~ path.to_rx(distance: distance) }
|
|
204
|
+
if matches.count.positive?
|
|
205
|
+
shortest = matches.keys.group_by(&:length).min.last[0]
|
|
206
|
+
real_path << shortest
|
|
207
|
+
new_cfg = matches[shortest]
|
|
208
|
+
end
|
|
209
|
+
else
|
|
210
|
+
new_cfg = cfg
|
|
206
211
|
end
|
|
207
212
|
|
|
208
213
|
if new_cfg.nil?
|
|
209
|
-
|
|
214
|
+
if distance < 5 && !create
|
|
215
|
+
return resolve_key_path(keypath, create: false, distance: distance + 1)
|
|
216
|
+
else
|
|
217
|
+
return nil unless create
|
|
218
|
+
end
|
|
210
219
|
|
|
211
220
|
resolved = real_path.count.positive? ? "Resolved #{real_path.join('->')}, but " : ''
|
|
212
221
|
Doing.logger.log_now(:warn, "#{resolved}#{path} is unknown")
|
data/lib/doing/hash.rb
CHANGED
|
@@ -6,14 +6,32 @@ module Doing
|
|
|
6
6
|
##
|
|
7
7
|
## Freeze all values in a hash
|
|
8
8
|
##
|
|
9
|
-
## @return
|
|
9
|
+
## @return Hash with all values frozen
|
|
10
10
|
##
|
|
11
11
|
def deep_freeze
|
|
12
|
-
|
|
12
|
+
chilled = {}
|
|
13
|
+
each do |k, v|
|
|
14
|
+
chilled[k] = v.is_a?(Hash) ? v.deep_freeze : v.freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
chilled.freeze
|
|
13
18
|
end
|
|
14
19
|
|
|
15
20
|
def deep_freeze!
|
|
16
|
-
replace deep_freeze
|
|
21
|
+
replace deep_thaw.deep_freeze
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def deep_thaw
|
|
25
|
+
chilled = {}
|
|
26
|
+
each do |k, v|
|
|
27
|
+
chilled[k] = v.is_a?(Hash) ? v.deep_thaw : v.dup
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
chilled.dup
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def deep_thaw!
|
|
34
|
+
replace deep_thaw
|
|
17
35
|
end
|
|
18
36
|
|
|
19
37
|
# Turn all keys into string
|
|
@@ -30,15 +48,16 @@ module Doing
|
|
|
30
48
|
|
|
31
49
|
# Set a nested hash value using an array
|
|
32
50
|
#
|
|
33
|
-
# @example
|
|
34
|
-
#
|
|
51
|
+
# @example
|
|
52
|
+
# {}.deep_set(['one', 'two'], 'value')
|
|
53
|
+
# # => { 'one' => { 'two' => 'value' } }
|
|
35
54
|
#
|
|
36
55
|
# @param path [Array] key path
|
|
37
56
|
# @param value The value
|
|
38
57
|
#
|
|
39
58
|
def deep_set(path, value)
|
|
40
59
|
if path.count == 1
|
|
41
|
-
|
|
60
|
+
unless value.nil? || value =~ /^ *$/
|
|
42
61
|
self[path[0]] = value
|
|
43
62
|
else
|
|
44
63
|
delete(path[0])
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GLI
|
|
4
|
+
module Commands
|
|
5
|
+
# Help Command Monkeypatch for paginated output
|
|
6
|
+
class Help < Command
|
|
7
|
+
def show_help(global_options,options,arguments,out,error)
|
|
8
|
+
Doing::Pager.paginate = true
|
|
9
|
+
|
|
10
|
+
command_finder = HelpModules::CommandFinder.new(@app,arguments,error)
|
|
11
|
+
if options[:c]
|
|
12
|
+
help_output = HelpModules::HelpCompletionFormat.new(@app,command_finder,arguments).format
|
|
13
|
+
out.puts help_output unless help_output.nil?
|
|
14
|
+
elsif arguments.empty? || options[:c]
|
|
15
|
+
Doing::Pager.page HelpModules::GlobalHelpFormat.new(@app,@sorter,@text_wrapping_class).format
|
|
16
|
+
else
|
|
17
|
+
name = arguments.shift
|
|
18
|
+
command = command_finder.find_command(name)
|
|
19
|
+
unless command.nil?
|
|
20
|
+
Doing::Pager.page HelpModules::CommandHelpFormat.new(
|
|
21
|
+
command,
|
|
22
|
+
@app,
|
|
23
|
+
@sorter,
|
|
24
|
+
@synopsis_formatter_class,
|
|
25
|
+
@text_wrapping_class).format
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/doing/hooks.rb
CHANGED
|
@@ -23,7 +23,11 @@ module Doing
|
|
|
23
23
|
|
|
24
24
|
# register hook(s) to be called later, public API
|
|
25
25
|
def self.register(event, priority: DEFAULT_PRIORITY, &block)
|
|
26
|
-
|
|
26
|
+
if event.is_a?(Array)
|
|
27
|
+
event.each { |ev| register_one(ev, priority_value(priority), &block) }
|
|
28
|
+
else
|
|
29
|
+
register_one(event, priority_value(priority), &block)
|
|
30
|
+
end
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
# Ensure the priority is a Fixnum
|
data/lib/doing/item.rb
CHANGED
|
@@ -125,11 +125,11 @@ module Doing
|
|
|
125
125
|
return true if same_time?(item_b)
|
|
126
126
|
|
|
127
127
|
start_a = date
|
|
128
|
-
|
|
129
|
-
end_a =
|
|
128
|
+
a_interval = interval
|
|
129
|
+
end_a = a_interval ? start_a + a_interval.to_i : start_a
|
|
130
130
|
start_b = item_b.date
|
|
131
|
-
|
|
132
|
-
end_b =
|
|
131
|
+
b_interval = item_b.interval
|
|
132
|
+
end_b = b_interval ? start_b + b_interval.to_i : start_b
|
|
133
133
|
(start_a >= start_b && start_a <= end_b) || (end_a >= start_b && end_a <= end_b) || (start_a < start_b && end_a > end_b)
|
|
134
134
|
end
|
|
135
135
|
|
|
@@ -216,8 +216,8 @@ module Doing
|
|
|
216
216
|
##
|
|
217
217
|
def tags?(tags, bool = :and, negate: false)
|
|
218
218
|
if bool == :pattern
|
|
219
|
-
tags = tags.join(' ')
|
|
220
|
-
matches = tag_pattern?(tags
|
|
219
|
+
tags = tags.to_tags.tags_to_array.join(' ')
|
|
220
|
+
matches = tag_pattern?(tags)
|
|
221
221
|
|
|
222
222
|
return negate ? !matches : matches
|
|
223
223
|
end
|
|
@@ -283,7 +283,7 @@ module Doing
|
|
|
283
283
|
new_title = @title.gsub(rx) { |m| yellow(m) }
|
|
284
284
|
new_note.add(@note.to_s.gsub(rx) { |m| yellow(m) })
|
|
285
285
|
else
|
|
286
|
-
query =
|
|
286
|
+
query = search.strip.to_phrase_query
|
|
287
287
|
|
|
288
288
|
if query[:must].nil? && query[:must_not].nil?
|
|
289
289
|
query[:must] = query[:should]
|
|
@@ -319,7 +319,7 @@ module Doing
|
|
|
319
319
|
if search.is_rx? || matching == :fuzzy
|
|
320
320
|
matches = @title + @note.to_s =~ search.to_rx(distance: distance, case_type: case_type)
|
|
321
321
|
else
|
|
322
|
-
query =
|
|
322
|
+
query = search.strip.to_phrase_query
|
|
323
323
|
|
|
324
324
|
if query[:must].nil? && query[:must_not].nil?
|
|
325
325
|
query[:must] = query[:should]
|
|
@@ -612,29 +612,14 @@ module Doing
|
|
|
612
612
|
end
|
|
613
613
|
end
|
|
614
614
|
|
|
615
|
-
def to_query(query)
|
|
616
|
-
parser = BooleanTermParser::QueryParser.new
|
|
617
|
-
transformer = BooleanTermParser::QueryTransformer.new
|
|
618
|
-
parse_tree = parser.parse(query)
|
|
619
|
-
transformer.apply(parse_tree).to_elasticsearch
|
|
620
|
-
end
|
|
621
|
-
|
|
622
|
-
def to_phrase_query(query)
|
|
623
|
-
parser = PhraseParser::QueryParser.new
|
|
624
|
-
transformer = PhraseParser::QueryTransformer.new
|
|
625
|
-
parse_tree = parser.parse(query)
|
|
626
|
-
transformer.apply(parse_tree).to_elasticsearch
|
|
627
|
-
end
|
|
628
|
-
|
|
629
615
|
def tag_pattern?(tags)
|
|
630
|
-
query = to_query
|
|
616
|
+
query = tags.to_query
|
|
631
617
|
|
|
632
618
|
no_tags?(query[:must_not]) && all_tags?(query[:must]) && any_tags?(query[:should])
|
|
633
619
|
end
|
|
634
620
|
|
|
635
621
|
def split_tags(tags)
|
|
636
|
-
tags
|
|
637
|
-
tags.map { |t| t.strip.add_at }
|
|
622
|
+
tags.to_tags.tags_to_array
|
|
638
623
|
end
|
|
639
624
|
end
|
|
640
625
|
end
|
data/lib/doing/items.rb
CHANGED
|
@@ -131,7 +131,9 @@ module Doing
|
|
|
131
131
|
out = []
|
|
132
132
|
@sections.each do |section|
|
|
133
133
|
out.push(section.original)
|
|
134
|
-
in_section(section.title).
|
|
134
|
+
items = in_section(section.title).sort_by { |i| i.date }
|
|
135
|
+
items.reverse! if Doing.config.settings['doing_file_sort'].normalize_order == 'desc'
|
|
136
|
+
items.each { |item| out.push(item.to_s)}
|
|
135
137
|
end
|
|
136
138
|
|
|
137
139
|
out.join("\n")
|
data/lib/doing/log_adapter.rb
CHANGED
|
@@ -356,7 +356,7 @@ module Doing
|
|
|
356
356
|
next if data[:count].zero?
|
|
357
357
|
|
|
358
358
|
count = data[:count]
|
|
359
|
-
tags = data[:tag] ? data[:tag].uniq.map { |t|
|
|
359
|
+
tags = data[:tag] ? data[:tag].uniq.map { |t| t.add_at.cyan }.join(', ') : 'tags'
|
|
360
360
|
topic, m = format_counter(key, data)
|
|
361
361
|
message = m.dup
|
|
362
362
|
message.sub!(/%count/, count.to_s)
|
data/lib/doing/pager.rb
CHANGED
|
@@ -54,8 +54,8 @@ module Doing
|
|
|
54
54
|
read_io.close
|
|
55
55
|
write_io.write(text)
|
|
56
56
|
write_io.close
|
|
57
|
-
rescue SystemCallError => e
|
|
58
|
-
raise Errors::DoingStandardError, "Pager error, #{e}"
|
|
57
|
+
rescue SystemCallError # => e
|
|
58
|
+
# raise Errors::DoingStandardError, "Pager error, #{e}"
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
_, status = Process.waitpid2(pid)
|
|
@@ -75,7 +75,7 @@ module Doing
|
|
|
75
75
|
note = i.note.map { |line| line.strip.link_urls(format: :markdown) } if i.note
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
title = "#{title} @
|
|
78
|
+
title = "#{title} @section(#{i.section})" unless variables[:is_single]
|
|
79
79
|
|
|
80
80
|
tags.concat(i.tag_array).sort!.uniq!
|
|
81
81
|
flagged = day_flagged = true if i.tags?(wwid.config['marker_tag'])
|
|
@@ -48,7 +48,7 @@ module Doing
|
|
|
48
48
|
note = i.note.map { |line| line.strip.link_urls(format: :markdown) } if i.note
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
title = "#{title} @
|
|
51
|
+
title = "#{title} @section(#{i.section})" unless variables[:is_single]
|
|
52
52
|
|
|
53
53
|
interval = wwid.get_interval(i, record: true) if i.title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
|
|
54
54
|
interval ||= false
|
|
@@ -49,6 +49,8 @@ module Doing
|
|
|
49
49
|
note = []
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
placeholders['tags'] = item.tags
|
|
53
|
+
|
|
52
54
|
placeholders['date'] = item.date.strftime(opt[:format])
|
|
53
55
|
|
|
54
56
|
interval = wwid.get_interval(item, record: true, formatted: false) if opt[:times]
|
|
@@ -56,8 +58,10 @@ module Doing
|
|
|
56
58
|
interval = case opt[:interval_format].to_sym
|
|
57
59
|
when :human
|
|
58
60
|
interval.time_string(format: :hm)
|
|
59
|
-
|
|
61
|
+
when :text
|
|
60
62
|
interval.time_string(format: :clock)
|
|
63
|
+
else
|
|
64
|
+
interval.time_string(format: opt[:interval_format].to_sym)
|
|
61
65
|
end
|
|
62
66
|
end
|
|
63
67
|
|
|
@@ -69,8 +73,10 @@ module Doing
|
|
|
69
73
|
duration = case opt[:interval_format].to_sym
|
|
70
74
|
when :human
|
|
71
75
|
duration.time_string(format: :hm)
|
|
72
|
-
|
|
76
|
+
when :text
|
|
73
77
|
duration.time_string(format: :clock)
|
|
78
|
+
else
|
|
79
|
+
duration.time_string(format: opt[:interval_format].to_sym)
|
|
74
80
|
end
|
|
75
81
|
end
|
|
76
82
|
duration ||= ''
|
|
@@ -119,7 +125,7 @@ module Doing
|
|
|
119
125
|
|
|
120
126
|
output.gsub!(/\\%/, '%')
|
|
121
127
|
|
|
122
|
-
output.highlight_search!(opt[:search]) if opt[:search] && !opt[:not] && opt[:hilite]
|
|
128
|
+
output.highlight_search!(opt[:search]) if opt[:template] =~ /^temp/ && opt[:search] && !opt[:not] && opt[:hilite]
|
|
123
129
|
|
|
124
130
|
out += "#{output}\n"
|
|
125
131
|
end
|
data/lib/doing/prompt.rb
CHANGED
|
@@ -42,7 +42,7 @@ module Doing
|
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
def read_lines(prompt: 'Enter text', completions: [])
|
|
45
|
+
def read_lines(prompt: 'Enter text', completions: [], default_response: '')
|
|
46
46
|
$stdin.reopen('/dev/tty')
|
|
47
47
|
return default_response if @default_answer
|
|
48
48
|
|
|
@@ -72,8 +72,10 @@ module Doing
|
|
|
72
72
|
res.join("\n").strip
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
def request_lines(prompt: 'Enter text')
|
|
75
|
+
def request_lines(prompt: 'Enter text', default_response: '')
|
|
76
76
|
$stdin.reopen('/dev/tty')
|
|
77
|
+
return default_response if @default_answer
|
|
78
|
+
|
|
77
79
|
ask_note = []
|
|
78
80
|
reader = TTY::Reader.new(interrupt: -> { raise Errors::UserCancelled }, track_history: false)
|
|
79
81
|
puts "#{boldgreen(prompt.sub(/:?$/, ':'))} #{yellow('Hit return for a new line, ')}#{boldwhite('enter a blank line (')}#{boldyellow('return twice')}#{boldwhite(') to end editing')}"
|