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