doing 2.1.25 → 2.1.29
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 +322 -108
- data/Dockerfile +5 -5
- data/Dockerfile-2.6 +5 -5
- data/Dockerfile-2.7 +5 -4
- data/Dockerfile-3.0 +5 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/Rakefile +2 -3
- data/bin/commands/add_section.rb +15 -0
- data/bin/commands/again.rb +57 -0
- data/bin/commands/archive.rb +55 -0
- data/bin/commands/cancel.rb +60 -0
- data/bin/commands/changes.rb +83 -0
- data/bin/commands/choose.rb +9 -0
- data/bin/commands/colors.rb +21 -0
- data/bin/commands/commands.rb +89 -0
- data/bin/commands/commands_accepting.rb +76 -0
- data/bin/commands/completion.rb +27 -0
- data/bin/commands/config.rb +245 -0
- data/bin/commands/done.rb +235 -0
- data/bin/commands/finish.rb +126 -0
- data/bin/commands/flag.rb +90 -0
- data/bin/commands/grep.rb +108 -0
- data/bin/commands/import.rb +71 -0
- data/bin/commands/install_fzf.rb +17 -0
- data/bin/commands/last.rb +81 -0
- data/bin/commands/meanwhile.rb +76 -0
- data/bin/commands/note.rb +91 -0
- data/bin/commands/now.rb +145 -0
- data/bin/commands/on.rb +65 -0
- data/bin/commands/open.rb +53 -0
- data/bin/commands/plugins.rb +23 -0
- data/bin/commands/recent.rb +77 -0
- data/bin/commands/redo.rb +26 -0
- data/bin/commands/reset.rb +73 -0
- data/bin/commands/rotate.rb +42 -0
- data/bin/commands/sections.rb +11 -0
- data/bin/commands/select.rb +105 -0
- data/bin/commands/show.rb +185 -0
- data/bin/commands/since.rb +63 -0
- data/bin/commands/tag.rb +149 -0
- data/bin/commands/tag_dir.rb +29 -0
- data/bin/commands/tags.rb +66 -0
- data/bin/commands/template.rb +61 -0
- data/bin/commands/today.rb +64 -0
- data/bin/commands/undo.rb +49 -0
- data/bin/commands/view.rb +201 -0
- data/bin/commands/views.rb +11 -0
- data/bin/commands/yesterday.rb +72 -0
- data/bin/doing +241 -3706
- 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 +36 -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 +46 -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 +235 -0
- 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/Numeric.html +1 -1
- data/docs/doc/Object.html +203 -0
- 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 +235 -0
- 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 +289 -681
- data/docs/doc/top-level-namespace.html +2 -2
- data/doing.rdoc +306 -205
- data/lib/completion/_doing.zsh +35 -35
- data/lib/completion/doing.bash +30 -30
- data/lib/completion/doing.fish +88 -78
- 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 +31 -4
- data/lib/doing/{array_chronify.rb → chronify/array.rb} +0 -0
- data/lib/doing/chronify/chronify.rb +5 -0
- data/lib/doing/{numeric_chronify.rb → chronify/numeric.rb} +0 -0
- data/lib/doing/{string_chronify.rb → chronify/string.rb} +0 -0
- data/lib/doing/colors.rb +115 -54
- data/lib/doing/configuration.rb +5 -0
- data/lib/doing/good.rb +8 -0
- data/lib/doing/help_monkey_patch.rb +6 -5
- data/lib/doing/item.rb +5 -5
- data/lib/doing/items.rb +2 -2
- data/lib/doing/log_adapter.rb +35 -2
- data/lib/doing/normalize.rb +188 -0
- data/lib/doing/pager.rb +1 -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 +9 -3
- data/lib/doing/string/highlight.rb +95 -0
- data/lib/doing/string/query.rb +129 -0
- data/lib/doing/string/string.rb +12 -0
- data/lib/doing/string/tags.rb +164 -0
- data/lib/doing/string/transform.rb +168 -0
- data/lib/doing/string/truncate.rb +75 -0
- data/lib/doing/string/url.rb +82 -0
- data/lib/doing/template_string.rb +0 -22
- data/lib/doing/types.rb +8 -0
- data/lib/doing/util.rb +13 -9
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +53 -35
- data/lib/doing.rb +4 -6
- data/lib/examples/commands/wiki.rb +6 -7
- data/lib/examples/plugins/wiki_export/wiki_export.rb +1 -1
- data/lib/helpers/threaded_tests.rb +39 -20
- data/scripts/deploy.rb +107 -0
- data/scripts/runtests.sh +4 -0
- metadata +63 -8
- data/lib/doing/string.rb +0 -765
- data/lib/doing/symbol.rb +0 -28
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doing
|
|
4
|
+
##
|
|
5
|
+
## URL linking and formatting
|
|
6
|
+
##
|
|
7
|
+
class ::String
|
|
8
|
+
##
|
|
9
|
+
## Turn raw urls into HTML links
|
|
10
|
+
##
|
|
11
|
+
## @param opt [Hash] Additional Options
|
|
12
|
+
##
|
|
13
|
+
## @option opt [Symbol] :format can be :markdown or
|
|
14
|
+
## :html (default)
|
|
15
|
+
##
|
|
16
|
+
def link_urls(**opt)
|
|
17
|
+
fmt = opt.fetch(:format, :html)
|
|
18
|
+
return self unless fmt
|
|
19
|
+
|
|
20
|
+
str = dup
|
|
21
|
+
|
|
22
|
+
str = str.remove_self_links if fmt == :markdown
|
|
23
|
+
|
|
24
|
+
str.replace_qualified_urls(format: fmt).clean_unlinked_urls
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
## @see #link_urls
|
|
28
|
+
def link_urls!(**opt)
|
|
29
|
+
fmt = opt.fetch(:format, :html)
|
|
30
|
+
replace link_urls(format: fmt)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Remove <self-linked> formatting
|
|
34
|
+
def remove_self_links
|
|
35
|
+
gsub(/<(.*?)>/) do |match|
|
|
36
|
+
m = Regexp.last_match
|
|
37
|
+
if m[1] =~ /^https?:/
|
|
38
|
+
m[1]
|
|
39
|
+
else
|
|
40
|
+
match
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Replace qualified urls
|
|
46
|
+
def replace_qualified_urls(**options)
|
|
47
|
+
fmt = options.fetch(:format, :html)
|
|
48
|
+
gsub(%r{(?mi)(?x:
|
|
49
|
+
(?<!["'\[(\\])
|
|
50
|
+
(?<protocol>(?:http|https)://)
|
|
51
|
+
(?<domain>[\w\-]+(?:\.[\w\-]+)+)
|
|
52
|
+
(?<path>[\w\-.,@?^=%&;:/~+#]*[\w\-@^=%&;/~+#])?
|
|
53
|
+
)}) do |_match|
|
|
54
|
+
m = Regexp.last_match
|
|
55
|
+
url = "#{m['domain']}#{m['path']}"
|
|
56
|
+
proto = m['protocol'].nil? ? 'http://' : m['protocol']
|
|
57
|
+
case fmt
|
|
58
|
+
when :terminal
|
|
59
|
+
TTY::Link.link_to("#{proto}#{url}", "#{proto}#{url}")
|
|
60
|
+
when :html
|
|
61
|
+
%(<a href="#{proto}#{url}" title="Link to #{m['domain']}">[#{url}]</a>)
|
|
62
|
+
when :markdown
|
|
63
|
+
"[#{url}](#{proto}#{url})"
|
|
64
|
+
else
|
|
65
|
+
m[0]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Clean up unlinked <urls>
|
|
71
|
+
def clean_unlinked_urls
|
|
72
|
+
gsub(/<(\w+:.*?)>/) do |match|
|
|
73
|
+
m = Regexp.last_match
|
|
74
|
+
if m[1] =~ /<a href/
|
|
75
|
+
match
|
|
76
|
+
else
|
|
77
|
+
%(<a href="#{m[1]}" title="Link to #{m[1]}">[link]</a>)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -5,28 +5,6 @@ module Doing
|
|
|
5
5
|
## Template string formatting
|
|
6
6
|
##
|
|
7
7
|
class TemplateString < String
|
|
8
|
-
class ::String
|
|
9
|
-
##
|
|
10
|
-
## Extract the longest valid color from a string.
|
|
11
|
-
##
|
|
12
|
-
## Allows %colors to bleed into other text and still
|
|
13
|
-
## be recognized, e.g. %greensomething still finds
|
|
14
|
-
## %green.
|
|
15
|
-
##
|
|
16
|
-
## @return [String] a valid color name
|
|
17
|
-
## @api private
|
|
18
|
-
def validate_color
|
|
19
|
-
valid_color = nil
|
|
20
|
-
compiled = ''
|
|
21
|
-
split('').each do |char|
|
|
22
|
-
compiled += char
|
|
23
|
-
valid_color = compiled if Color.attributes.include?(compiled.to_sym)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
valid_color
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
8
|
attr_reader :original
|
|
31
9
|
|
|
32
10
|
include Color
|
data/lib/doing/types.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Doing
|
|
4
4
|
module Types
|
|
5
|
+
REGEX_CASE = /^[cis].*?$/i.freeze
|
|
6
|
+
REGEX_TAG_SORT = /^(?:n(?:ame)?|t(?:ime)?)$/i.freeze
|
|
5
7
|
REGEX_BOOL = /^(?:and|all|any|or|not|none|p(?:at(?:tern)?)?)$/i.freeze
|
|
6
8
|
REGEX_SORT_ORDER = /^(?:a(?:sc)?|d(?:esc)?)$/i.freeze
|
|
7
9
|
REGEX_VALUE_QUERY = /^(?:!)?@?(?:\S+) +(?:!?[<>=][=*]?|[$*^]=) +(?:.*?)$/.freeze
|
|
@@ -22,5 +24,11 @@ module Doing
|
|
|
22
24
|
DateRangeString = Class.new(Array)
|
|
23
25
|
DateRangeOptionalString = Class.new(Array)
|
|
24
26
|
DateIntervalString = Class.new(DateTime)
|
|
27
|
+
BooleanSymbol = Class.new(Symbol)
|
|
28
|
+
CaseSymbol = Class.new(Symbol)
|
|
29
|
+
AgeSymbol = Class.new(String)
|
|
30
|
+
OrderSymbol = Class.new(Symbol)
|
|
31
|
+
TagSortSymbol = Class.new(Symbol)
|
|
32
|
+
MatchingSymbol = Class.new(Symbol)
|
|
25
33
|
end
|
|
26
34
|
end
|
data/lib/doing/util.rb
CHANGED
|
@@ -170,29 +170,33 @@ module Doing
|
|
|
170
170
|
|
|
171
171
|
if editor_config[editor_for]
|
|
172
172
|
editor = editor_config[editor_for]
|
|
173
|
-
|
|
174
|
-
return editor
|
|
173
|
+
Doing.logger.debug('Editor:', "Using #{editor} from config 'editors.#{editor_for}' for #{editor_for}")
|
|
174
|
+
return editor if editor.good?
|
|
175
175
|
end
|
|
176
176
|
|
|
177
177
|
if editor_for != 'editor' && editor_config['default']
|
|
178
178
|
editor = editor_config['default']
|
|
179
|
-
|
|
180
|
-
return editor
|
|
179
|
+
Doing.logger.debug('Editor:', "Using #{editor} from config: 'editors.default' for #{editor_for}")
|
|
180
|
+
return editor if editor.good?
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
editor ||= ENV['DOING_EDITOR'] || ENV['GIT_EDITOR'] || ENV['EDITOR']
|
|
184
184
|
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
if editor.good?
|
|
186
|
+
Doing.logger.debug('Editor:', "Found editor in environment variables: #{editor} for #{editor_for}")
|
|
187
187
|
return editor
|
|
188
188
|
end
|
|
189
189
|
|
|
190
|
-
Doing.logger.debug('
|
|
190
|
+
Doing.logger.debug('Editor:', 'No EDITOR environment variable, testing available editors')
|
|
191
191
|
editors = %w[vim vi code subl mate mvim nano emacs]
|
|
192
192
|
editors.each do |ed|
|
|
193
|
-
|
|
193
|
+
try = TTY::Which.which(ed)
|
|
194
|
+
if try
|
|
195
|
+
Doing.logger.debug('Editor:', "Using editor #{try} for #{editor_for}")
|
|
196
|
+
return try
|
|
197
|
+
end
|
|
194
198
|
|
|
195
|
-
Doing.logger.debug('
|
|
199
|
+
Doing.logger.debug('Editor:', "#{ed} not available")
|
|
196
200
|
end
|
|
197
201
|
|
|
198
202
|
nil
|
data/lib/doing/version.rb
CHANGED
data/lib/doing/wwid.rb
CHANGED
|
@@ -659,6 +659,7 @@ module Doing
|
|
|
659
659
|
## @option opt [Array] :val (nil) Array of tag value queries
|
|
660
660
|
##
|
|
661
661
|
def filter_items(items = Items.new, opt: {})
|
|
662
|
+
logger.benchmark(:filter_items, :start)
|
|
662
663
|
time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/
|
|
663
664
|
|
|
664
665
|
if items.nil? || items.empty?
|
|
@@ -810,6 +811,8 @@ module Doing
|
|
|
810
811
|
output.concat(filtered_items.reverse.slice(0, count))
|
|
811
812
|
end
|
|
812
813
|
|
|
814
|
+
logger.benchmark(:filter_items, :finish)
|
|
815
|
+
|
|
813
816
|
output
|
|
814
817
|
end
|
|
815
818
|
|
|
@@ -1211,6 +1214,7 @@ module Doing
|
|
|
1211
1214
|
opt[:sequential] ||= false
|
|
1212
1215
|
opt[:date] ||= false
|
|
1213
1216
|
opt[:remove] ||= false
|
|
1217
|
+
opt[:update] ||= false
|
|
1214
1218
|
opt[:autotag] ||= false
|
|
1215
1219
|
opt[:back] ||= false
|
|
1216
1220
|
opt[:unfinished] ||= false
|
|
@@ -1323,7 +1327,7 @@ module Doing
|
|
|
1323
1327
|
else
|
|
1324
1328
|
old_title = item.title.dup
|
|
1325
1329
|
should_date = opt[:date] && item.should_time?
|
|
1326
|
-
item.title.tag!('done', remove: true) if tag =~ /done/ && !should_date
|
|
1330
|
+
item.title.tag!('done', remove: true) if tag =~ /done/ && (!should_date || opt[:update])
|
|
1327
1331
|
item.title.tag!(tag, value: should_date ? done_date.strftime('%F %R') : nil)
|
|
1328
1332
|
added << tag if old_title != item.title
|
|
1329
1333
|
end
|
|
@@ -1619,6 +1623,7 @@ module Doing
|
|
|
1619
1623
|
## @param opt [Hash] Additional Options
|
|
1620
1624
|
##
|
|
1621
1625
|
def list_section(opt, items: Items.new)
|
|
1626
|
+
logger.benchmark(:list_section, :start)
|
|
1622
1627
|
opt[:config_template] ||= 'default'
|
|
1623
1628
|
|
|
1624
1629
|
tpl_cfg = @config.dig('templates', opt[:config_template])
|
|
@@ -1632,7 +1637,7 @@ module Doing
|
|
|
1632
1637
|
cfg.deep_merge({
|
|
1633
1638
|
'wrap_width' => @config['wrap_width'] || 0,
|
|
1634
1639
|
'date_format' => @config['default_date_format'],
|
|
1635
|
-
'order' => @config['order'] ||
|
|
1640
|
+
'order' => @config['order'] || :asc,
|
|
1636
1641
|
'tags_color' => @config['tags_color'],
|
|
1637
1642
|
'duration' => @config['duration'],
|
|
1638
1643
|
'interval_format' => @config['interval_format']
|
|
@@ -1644,8 +1649,8 @@ module Doing
|
|
|
1644
1649
|
opt[:age] ||= :newest
|
|
1645
1650
|
opt[:age] = opt[:age].normalize_age
|
|
1646
1651
|
opt[:format] ||= cfg['date_format']
|
|
1647
|
-
opt[:order] ||= cfg['order'] ||
|
|
1648
|
-
opt[:tag_order] ||=
|
|
1652
|
+
opt[:order] ||= cfg['order'] || :asc
|
|
1653
|
+
opt[:tag_order] ||= :asc
|
|
1649
1654
|
opt[:tags_color] = cfg['tags_color'] || false if opt[:tags_color].nil?
|
|
1650
1655
|
opt[:template] ||= cfg['template']
|
|
1651
1656
|
|
|
@@ -1671,7 +1676,7 @@ module Doing
|
|
|
1671
1676
|
|
|
1672
1677
|
items = filter_items(items, opt: opt)
|
|
1673
1678
|
|
|
1674
|
-
items.reverse! unless opt[:order]
|
|
1679
|
+
items.reverse! unless opt[:order].normalize_order == :desc
|
|
1675
1680
|
|
|
1676
1681
|
if opt[:delete]
|
|
1677
1682
|
delete_items(items, force: opt[:force])
|
|
@@ -1694,6 +1699,7 @@ module Doing
|
|
|
1694
1699
|
opt[:output] ||= 'template'
|
|
1695
1700
|
opt[:wrap_width] ||= @config['templates']['default']['wrap_width'] || 0
|
|
1696
1701
|
|
|
1702
|
+
logger.benchmark(:list_section, :finish)
|
|
1697
1703
|
output(items, title, is_single, opt)
|
|
1698
1704
|
end
|
|
1699
1705
|
|
|
@@ -1721,7 +1727,7 @@ module Doing
|
|
|
1721
1727
|
destination = guess_section(destination)
|
|
1722
1728
|
|
|
1723
1729
|
if @content.section?(destination) && (@content.section?(section) || archive_all)
|
|
1724
|
-
do_archive(section, destination, { count: count, tags: tags, bool: bool, search: options[:search], label: options[:label], before: options[:before] })
|
|
1730
|
+
do_archive(section, destination, { count: count, tags: tags, bool: bool, search: options[:search], label: options[:label], before: options[:before], after: options[:after], from: options[:from] })
|
|
1725
1731
|
write(doing_file)
|
|
1726
1732
|
else
|
|
1727
1733
|
raise InvalidArgument, 'Either source or destination does not exist'
|
|
@@ -1743,7 +1749,7 @@ module Doing
|
|
|
1743
1749
|
cfg = @config['templates'][opt[:config_template]].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
|
|
1744
1750
|
'wrap_width' => @config['wrap_width'] || 0,
|
|
1745
1751
|
'date_format' => @config['default_date_format'],
|
|
1746
|
-
'order' => @config['order'] ||
|
|
1752
|
+
'order' => @config['order'] || :asc,
|
|
1747
1753
|
'tags_color' => @config['tags_color'],
|
|
1748
1754
|
'duration' => @config['duration'],
|
|
1749
1755
|
'interval_format' => @config['interval_format']
|
|
@@ -1762,7 +1768,7 @@ module Doing
|
|
|
1762
1768
|
from: opt[:from],
|
|
1763
1769
|
format: cfg['date_format'],
|
|
1764
1770
|
interval_format: opt[:interval_format],
|
|
1765
|
-
order: cfg['order'] ||
|
|
1771
|
+
order: cfg['order'] || :asc,
|
|
1766
1772
|
output: output,
|
|
1767
1773
|
section: opt[:section],
|
|
1768
1774
|
sort_tags: opt[:sort_tags],
|
|
@@ -1797,7 +1803,7 @@ module Doing
|
|
|
1797
1803
|
list_section({
|
|
1798
1804
|
section: section,
|
|
1799
1805
|
count: 0,
|
|
1800
|
-
order:
|
|
1806
|
+
order: :asc,
|
|
1801
1807
|
date_filter: dates,
|
|
1802
1808
|
times: times,
|
|
1803
1809
|
output: output,
|
|
@@ -1863,7 +1869,7 @@ module Doing
|
|
|
1863
1869
|
cfg = @config['templates'][opt[:config_template]].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
|
|
1864
1870
|
'wrap_width' => @config['wrap_width'] || 0,
|
|
1865
1871
|
'date_format' => @config['default_date_format'],
|
|
1866
|
-
'order' => @config['order'] ||
|
|
1872
|
+
'order' => @config['order'] || :asc,
|
|
1867
1873
|
'tags_color' => @config['tags_color'],
|
|
1868
1874
|
'duration' => @config['duration'],
|
|
1869
1875
|
'interval_format' => @config['interval_format']
|
|
@@ -1879,7 +1885,7 @@ module Doing
|
|
|
1879
1885
|
opt[:count] = count
|
|
1880
1886
|
opt[:format] = cfg['date_format']
|
|
1881
1887
|
opt[:template] = opt[:template] || cfg['template']
|
|
1882
|
-
opt[:order] =
|
|
1888
|
+
opt[:order] = :asc
|
|
1883
1889
|
opt[:times] = times
|
|
1884
1890
|
|
|
1885
1891
|
list_section(opt)
|
|
@@ -1896,7 +1902,7 @@ module Doing
|
|
|
1896
1902
|
cfg = @config['templates'][options[:config_template]].deep_merge(@config['templates']['default'], { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
|
|
1897
1903
|
'wrap_width' => @config['wrap_width'] || 0,
|
|
1898
1904
|
'date_format' => @config['default_date_format'],
|
|
1899
|
-
'order' => @config['order'] ||
|
|
1905
|
+
'order' => @config['order'] || :asc,
|
|
1900
1906
|
'tags_color' => @config['tags_color'],
|
|
1901
1907
|
'duration' => @config['duration'],
|
|
1902
1908
|
'interval_format' => @config['interval_format']
|
|
@@ -2043,10 +2049,10 @@ module Doing
|
|
|
2043
2049
|
##
|
|
2044
2050
|
## @param format [String] return format (html,
|
|
2045
2051
|
## json, or text)
|
|
2046
|
-
## @param
|
|
2047
|
-
## @param sort_order [
|
|
2052
|
+
## @param sort_by [Symbol] Sort by :name or :time
|
|
2053
|
+
## @param sort_order [Symbol] The sort order (:asc or :desc)
|
|
2048
2054
|
##
|
|
2049
|
-
def tag_times(format: :text,
|
|
2055
|
+
def tag_times(format: :text, sort_by: :time, sort_order: :asc)
|
|
2050
2056
|
return '' if @timers.empty?
|
|
2051
2057
|
|
|
2052
2058
|
max = @timers.keys.sort_by { |k| k.length }.reverse[0].length + 1
|
|
@@ -2054,13 +2060,13 @@ module Doing
|
|
|
2054
2060
|
total = @timers.delete('All')
|
|
2055
2061
|
|
|
2056
2062
|
tags_data = @timers.delete_if { |_k, v| v == 0 }
|
|
2057
|
-
sorted_tags_data = if
|
|
2063
|
+
sorted_tags_data = if sort_by.normalize_tag_sort == :name
|
|
2058
2064
|
tags_data.sort_by { |k, _v| k }
|
|
2059
2065
|
else
|
|
2060
2066
|
tags_data.sort_by { |_k, v| v }
|
|
2061
2067
|
end
|
|
2062
2068
|
|
|
2063
|
-
sorted_tags_data.reverse! if sort_order
|
|
2069
|
+
sorted_tags_data.reverse! if sort_order.normalize_order == :asc
|
|
2064
2070
|
case format
|
|
2065
2071
|
when :html
|
|
2066
2072
|
|
|
@@ -2210,9 +2216,9 @@ EOS
|
|
|
2210
2216
|
Doing.config_with(ENV['DOING_CONFIG'], { ignore_local: true })
|
|
2211
2217
|
end
|
|
2212
2218
|
|
|
2213
|
-
|
|
2219
|
+
logger.benchmark(:configure, :start)
|
|
2214
2220
|
config = Doing.config
|
|
2215
|
-
|
|
2221
|
+
logger.benchmark(:configure, :finish)
|
|
2216
2222
|
|
|
2217
2223
|
config.settings['backup_dir'] = ENV['DOING_BACKUP_DIR'] if ENV['DOING_BACKUP_DIR']
|
|
2218
2224
|
@config = config.settings
|
|
@@ -2266,6 +2272,7 @@ EOS
|
|
|
2266
2272
|
## template trigger
|
|
2267
2273
|
##
|
|
2268
2274
|
def output(items, title, is_single, opt)
|
|
2275
|
+
logger.benchmark(:output, :start)
|
|
2269
2276
|
opt ||= {}
|
|
2270
2277
|
out = nil
|
|
2271
2278
|
|
|
@@ -2283,7 +2290,7 @@ EOS
|
|
|
2283
2290
|
end
|
|
2284
2291
|
|
|
2285
2292
|
logger.debug('Output:', "#{items.count} #{items.count == 1 ? 'item' : 'items'} shown")
|
|
2286
|
-
|
|
2293
|
+
logger.benchmark(:output, :finish)
|
|
2287
2294
|
out
|
|
2288
2295
|
end
|
|
2289
2296
|
|
|
@@ -2327,26 +2334,37 @@ EOS
|
|
|
2327
2334
|
section_items = @content.in_section(section)
|
|
2328
2335
|
max = section_items.count - count.to_i
|
|
2329
2336
|
|
|
2337
|
+
opt[:after] = opt[:from][0] if opt[:from]
|
|
2338
|
+
opt[:before] = opt[:from][1] if opt[:from]
|
|
2339
|
+
|
|
2340
|
+
time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/
|
|
2341
|
+
|
|
2342
|
+
if opt[:before].is_a?(String) && opt[:before] =~ time_rx
|
|
2343
|
+
opt[:before] = opt[:before].chronify(guess: :end, future: false)
|
|
2344
|
+
end
|
|
2345
|
+
|
|
2346
|
+
if opt[:after].is_a?(String) && opt[:after] =~ time_rx
|
|
2347
|
+
opt[:after] = opt[:after].chronify(guess: :begin, future: false)
|
|
2348
|
+
end
|
|
2349
|
+
|
|
2330
2350
|
counter = 0
|
|
2331
2351
|
|
|
2332
2352
|
@content.map do |item|
|
|
2333
2353
|
break if counter >= max
|
|
2334
|
-
if opt[:before]
|
|
2335
|
-
time_string = opt[:before]
|
|
2336
|
-
cutoff = time_string.chronify(guess: :begin)
|
|
2337
|
-
end
|
|
2338
2354
|
|
|
2339
|
-
if
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2355
|
+
next if item.section.downcase == destination.downcase
|
|
2356
|
+
|
|
2357
|
+
next if item.section.downcase != section.downcase && section != /^all$/i
|
|
2358
|
+
|
|
2359
|
+
next if (opt[:before] && item.date > opt[:before]) || (opt[:after] && item.date < opt[:after])
|
|
2360
|
+
|
|
2361
|
+
next if (!tags.empty? && !item.tags?(tags, bool)) || (opt[:search] && !item.search(opt[:search].to_s))
|
|
2362
|
+
|
|
2363
|
+
counter += 1
|
|
2364
|
+
old_item = item.clone
|
|
2365
|
+
item.move_to(destination, label: label, log: false)
|
|
2366
|
+
Hooks.trigger :post_entry_updated, self, item, old_item
|
|
2367
|
+
item
|
|
2350
2368
|
end
|
|
2351
2369
|
|
|
2352
2370
|
if counter.positive?
|
data/lib/doing.rb
CHANGED
|
@@ -28,11 +28,11 @@ require_relative 'doing/hash'
|
|
|
28
28
|
require_relative 'doing/types'
|
|
29
29
|
require_relative 'doing/colors'
|
|
30
30
|
require_relative 'doing/template_string'
|
|
31
|
-
require_relative 'doing/string'
|
|
31
|
+
require_relative 'doing/string/string'
|
|
32
32
|
require_relative 'doing/time'
|
|
33
|
-
require_relative 'doing/array'
|
|
33
|
+
require_relative 'doing/array/array'
|
|
34
34
|
require_relative 'doing/good'
|
|
35
|
-
require_relative 'doing/
|
|
35
|
+
require_relative 'doing/normalize'
|
|
36
36
|
require_relative 'doing/util'
|
|
37
37
|
require_relative 'doing/util_backup'
|
|
38
38
|
require_relative 'doing/configuration'
|
|
@@ -50,9 +50,7 @@ require_relative 'doing/pager'
|
|
|
50
50
|
require_relative 'doing/completion'
|
|
51
51
|
require_relative 'doing/boolean_term_parser'
|
|
52
52
|
require_relative 'doing/phrase_parser'
|
|
53
|
-
require_relative 'doing/
|
|
54
|
-
require_relative 'doing/numeric_chronify'
|
|
55
|
-
require_relative 'doing/string_chronify'
|
|
53
|
+
require_relative 'doing/chronify/chronify'
|
|
56
54
|
# require 'doing/markdown_document_listener'
|
|
57
55
|
|
|
58
56
|
# Main doing module
|
|
@@ -36,8 +36,7 @@ command :wiki do |c|
|
|
|
36
36
|
c.switch [:only_timed], default_value: false, negatable: false
|
|
37
37
|
|
|
38
38
|
c.action do |global, options, args|
|
|
39
|
-
|
|
40
|
-
tags = wwid.tag_groups([], opt: options)
|
|
39
|
+
tags = @wwid.tag_groups([], opt: options)
|
|
41
40
|
|
|
42
41
|
wiki = Doing::Plugins.plugins.dig(:export, 'wiki', :class)
|
|
43
42
|
|
|
@@ -46,7 +45,7 @@ command :wiki do |c|
|
|
|
46
45
|
|
|
47
46
|
raise RuntimeError, 'Missing plugin "wiki"' unless wiki
|
|
48
47
|
|
|
49
|
-
out = wiki.render(wwid, items, variables: export_options)
|
|
48
|
+
out = wiki.render(@wwid, items, variables: export_options)
|
|
50
49
|
|
|
51
50
|
if out
|
|
52
51
|
FileUtils.mkdir_p('doing_wiki')
|
|
@@ -56,13 +55,13 @@ command :wiki do |c|
|
|
|
56
55
|
end
|
|
57
56
|
end
|
|
58
57
|
|
|
59
|
-
template = if
|
|
60
|
-
IO.read(File.expand_path(
|
|
58
|
+
template = if @settings['export_templates']['wiki_index'] && File.exist?(File.expand_path(@settings['export_templates']['wiki_index']))
|
|
59
|
+
IO.read(File.expand_path(@settings['export_templates']['wiki_index']))
|
|
61
60
|
else
|
|
62
61
|
wiki.template('wiki_index')
|
|
63
62
|
end
|
|
64
|
-
style = if
|
|
65
|
-
IO.read(File.expand_path(
|
|
63
|
+
style = if @settings['export_templates']['wiki_css'] && File.exist?(File.expand_path(@settings['export_templates']['wiki_css']))
|
|
64
|
+
IO.read(File.expand_path(@settings['export_templates']['wiki_css']))
|
|
66
65
|
else
|
|
67
66
|
wiki.template('wiki_css')
|
|
68
67
|
end
|
|
@@ -74,7 +74,7 @@ module Doing
|
|
|
74
74
|
self.template('wiki_css')
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
totals = opt[:totals] ? wwid.tag_times(format: :html,
|
|
77
|
+
totals = opt[:totals] ? wwid.tag_times(format: :html, sort_by: opt[:sort_tags], sort_order: opt[:tag_order]) : ''
|
|
78
78
|
engine = Haml::Engine.new(template)
|
|
79
79
|
Doing.logger.debug('Wiki Export:', "#{items_out.count} items output to #{variables[:page_title]} wiki page")
|
|
80
80
|
@out = engine.render(Object.new,
|
|
@@ -18,17 +18,26 @@ class ThreadedTests
|
|
|
18
18
|
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
19
19
|
@results = File.expand_path('results.log')
|
|
20
20
|
|
|
21
|
-
max_threads = 1000 if max_threads == 0
|
|
21
|
+
max_threads = 1000 if max_threads.to_i == 0
|
|
22
22
|
|
|
23
23
|
c = Doing::Color
|
|
24
24
|
c.coloring = true
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
shuffle = false
|
|
27
|
+
|
|
28
|
+
unless pattern =~ /shuffle/i
|
|
29
|
+
pattern = "test/doing_*#{pattern}*_test.rb"
|
|
30
|
+
else
|
|
31
|
+
pattern = "test/doing_*_test.rb"
|
|
32
|
+
shuffle = true
|
|
33
|
+
end
|
|
27
34
|
|
|
28
35
|
tests = Dir.glob(pattern)
|
|
29
36
|
|
|
30
|
-
if
|
|
31
|
-
|
|
37
|
+
tests.shuffle! if shuffle
|
|
38
|
+
|
|
39
|
+
if max_tests.to_i > 0
|
|
40
|
+
tests = tests.slice(0, max_tests.to_i - 1)
|
|
32
41
|
end
|
|
33
42
|
|
|
34
43
|
puts "#{tests.count} test files".boldcyan
|
|
@@ -89,24 +98,30 @@ class ThreadedTests
|
|
|
89
98
|
finish_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
90
99
|
|
|
91
100
|
progress.finish
|
|
101
|
+
rescue
|
|
102
|
+
progress.stop
|
|
103
|
+
ensure
|
|
104
|
+
msg = @running_tests.map { |t| t[1].format.uncolor.sub(/^\[:bar\] (.*?):status/, "#{c.bold}#{c.white}\\1#{c.reset}#{t[2]}") }.join("\n")
|
|
105
|
+
|
|
106
|
+
Doing::Prompt.clear_screen(msg)
|
|
92
107
|
|
|
93
108
|
output = []
|
|
94
|
-
if @error_out.count.positive?
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
109
|
+
output << if @error_out.count.positive?
|
|
110
|
+
c.boldred("#{@error_out.count} Issues")
|
|
111
|
+
else
|
|
112
|
+
c.green('Success')
|
|
113
|
+
end
|
|
99
114
|
output << c.green("#{@test_total} tests")
|
|
100
115
|
output << c.cyan("#{@assrt_total} assertions")
|
|
101
116
|
output << c.yellow("#{(finish_time - start_time).round(3)}s")
|
|
102
117
|
puts output.join(', ')
|
|
103
118
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
if @error_out.count.positive?
|
|
120
|
+
res = Doing::Prompt.yn('Display error report?', default_response: false)
|
|
121
|
+
Doing::Pager.paginate = true
|
|
122
|
+
Doing::Pager.page(@error_out.join("\n----\n".boldwhite)) if res
|
|
123
|
+
end
|
|
107
124
|
end
|
|
108
|
-
ensure
|
|
109
|
-
FileUtils.rm(@results)
|
|
110
125
|
end
|
|
111
126
|
|
|
112
127
|
def run_test(s)
|
|
@@ -129,10 +144,16 @@ class ThreadedTests
|
|
|
129
144
|
end
|
|
130
145
|
|
|
131
146
|
@running_tests.push(s)
|
|
132
|
-
out, _err, status = Open3.capture3(ENV,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
147
|
+
out, _err, status = Open3.capture3(ENV, 'rake', "test:#{s[0]}", stdin_data: nil)
|
|
148
|
+
time = out.match(/^Finished in (?<time>\d+\.\d+) seconds\./)
|
|
149
|
+
count = out.match(/^(?<tests>\d+) tests, (?<assrt>\d+) assertions, (?<fails>\d+) failures, (?<errs>\d+) errors/)
|
|
150
|
+
|
|
151
|
+
unless status.success? && !count['fails'].to_i.positive? && !count['errs'].to_i.positive?
|
|
152
|
+
s[2] = if count
|
|
153
|
+
": #{count['fails'].bold.red} #{'failures'.red}, #{count['errs'].bold.red} #{'errors'.red}"
|
|
154
|
+
else
|
|
155
|
+
": #{'Unknown Error'.bold.red}"
|
|
156
|
+
end
|
|
136
157
|
bar.update(head: '✖'.boldred)
|
|
137
158
|
bar.advance(head: '✖'.boldred, status: s[2])
|
|
138
159
|
|
|
@@ -144,8 +165,6 @@ class ThreadedTests
|
|
|
144
165
|
Thread.exit
|
|
145
166
|
end
|
|
146
167
|
|
|
147
|
-
time = out.match(/^Finished in (?<time>\d+\.\d+) seconds\./)
|
|
148
|
-
count = out.match(/^(?<tests>\d+) tests, (?<assrt>\d+) assertions, (?<fails>\d+) failures, (?<errs>\d+) errors/)
|
|
149
168
|
s[2] = [
|
|
150
169
|
': ',
|
|
151
170
|
count['tests'].green,
|