doing 2.1.40 → 2.1.41
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/.yardopts +1 -1
- data/CHANGELOG.md +22 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +4 -4
- data/bin/commands/changes.rb +1 -1
- data/bin/commands/tag_dir.rb +49 -15
- data/{Dockerfile → docker/Dockerfile} +3 -1
- data/{Dockerfile-2.6 → docker/Dockerfile-2.6} +2 -2
- data/{Dockerfile-2.7 → docker/Dockerfile-2.7} +2 -2
- data/{Dockerfile-3.0 → docker/Dockerfile-3.0} +2 -2
- data/{bash_profile → docker/bash_profile} +0 -0
- data/{inputrc → docker/inputrc} +0 -0
- data/docs/doc/Array.html +84 -2
- 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/ArrayNestedHash.html +198 -0
- data/docs/doc/Doing/ArrayTags.html +424 -0
- data/docs/doc/Doing/CSVExport.html +266 -0
- data/docs/doc/Doing/CalendarImport.html +232 -0
- data/docs/doc/Doing/Change.html +617 -0
- data/docs/doc/Doing/Changes.html +468 -0
- data/docs/doc/Doing/ChronifyArray.html +347 -0
- data/docs/doc/Doing/ChronifyNumeric.html +271 -0
- data/docs/doc/Doing/ChronifyString.html +682 -0
- data/docs/doc/Doing/Color.html +2 -2
- data/docs/doc/Doing/Completion/BashCompletions.html +445 -0
- data/docs/doc/Doing/Completion/FishCompletions.html +445 -0
- data/docs/doc/Doing/Completion/StringUtils.html +229 -0
- data/docs/doc/Doing/Completion/ZshCompletions.html +445 -0
- data/docs/doc/Doing/Completion.html +17 -3
- data/docs/doc/Doing/Configuration.html +1 -1
- data/docs/doc/Doing/DayOneRenderer.html +383 -0
- data/docs/doc/Doing/DayoneExport.html +290 -0
- data/docs/doc/Doing/DoingImport.html +391 -0
- data/docs/doc/Doing/Entry.html +381 -0
- 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/HistoryLimitError.html +1 -1
- data/docs/doc/Doing/Errors/InvalidPlugin.html +1 -1
- data/docs/doc/Doing/Errors/MissingBackupFile.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/HTMLExport.html +256 -0
- data/docs/doc/Doing/Hooks.html +1 -1
- data/docs/doc/Doing/Item.html +47 -3
- data/docs/doc/Doing/ItemDates.html +564 -0
- data/docs/doc/Doing/ItemQuery.html +614 -0
- data/docs/doc/Doing/ItemState.html +387 -0
- data/docs/doc/Doing/ItemTags.html +498 -0
- data/docs/doc/Doing/Items.html +460 -11
- data/docs/doc/Doing/JSONExport.html +222 -0
- data/docs/doc/Doing/Logger.html +1 -1
- data/docs/doc/Doing/MarkdownExport.html +266 -0
- data/docs/doc/Doing/MarkdownRenderer.html +383 -0
- data/docs/doc/Doing/Note.html +16 -3
- data/docs/doc/Doing/Pager.html +1 -1
- data/docs/doc/Doing/Plugins.html +1 -1
- data/docs/doc/Doing/Prompt.html +31 -682
- data/docs/doc/Doing/PromptChoose.html +484 -0
- data/docs/doc/Doing/PromptFZF.html +391 -0
- data/docs/doc/Doing/PromptInput.html +572 -0
- data/docs/doc/Doing/PromptSTD.html +293 -0
- data/docs/doc/Doing/PromptYN.html +237 -0
- data/docs/doc/Doing/Section.html +58 -2
- data/docs/doc/Doing/StringHighlight.html +533 -0
- data/docs/doc/Doing/StringNormalize.html +929 -0
- data/docs/doc/Doing/StringQuery.html +725 -0
- data/docs/doc/Doing/StringTags.html +884 -0
- data/docs/doc/Doing/StringTransform.html +565 -0
- data/docs/doc/Doing/StringTruncate.html +448 -0
- data/docs/doc/Doing/StringURL.html +409 -0
- data/docs/doc/Doing/SymbolNormalize.html +341 -0
- data/docs/doc/Doing/TaskPaperExport.html +222 -0
- data/docs/doc/Doing/TemplateExport.html +249 -0
- data/docs/doc/Doing/TemplateString.html +101 -2
- data/docs/doc/Doing/TimingImport.html +285 -0
- data/docs/doc/Doing/Types.html +1 -1
- data/docs/doc/Doing/Util/Backup.html +9 -7
- data/docs/doc/Doing/Util.html +2 -2
- data/docs/doc/Doing/Version.html +523 -0
- data/docs/doc/Doing/WWID/WWIDUtil.html +510 -0
- data/docs/doc/Doing/WWID.html +4377 -217
- data/docs/doc/Doing/WWIDDisplay.html +865 -0
- data/docs/doc/Doing/WWIDEditor.html +466 -0
- data/docs/doc/Doing/WWIDFileTools.html +359 -0
- data/docs/doc/Doing/WWIDFilter.html +466 -0
- data/docs/doc/Doing/WWIDGuess.html +299 -0
- data/docs/doc/Doing/WWIDInteractive.html +752 -0
- data/docs/doc/Doing/WWIDModify.html +1078 -0
- data/docs/doc/Doing/WWIDTags.html +302 -0
- data/docs/doc/Doing/WWIDTimers.html +359 -0
- data/docs/doc/Doing/WWIDUtil.html +510 -0
- data/docs/doc/Doing.html +9 -6
- data/docs/doc/FalseClass.html +1 -1
- data/docs/doc/GLI/Commands/Help.html +1 -1
- data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
- data/docs/doc/GLI/Commands.html +1 -1
- data/docs/doc/GLI.html +1 -1
- data/docs/doc/Hash.html +1 -1
- data/docs/doc/Numeric.html +23 -78
- data/docs/doc/Object.html +1 -1
- data/docs/doc/PhraseParser/Operator.html +1 -1
- data/docs/doc/PhraseParser/PhraseClause.html +1 -1
- data/docs/doc/PhraseParser/Query.html +1 -1
- data/docs/doc/PhraseParser/QueryParser.html +1 -1
- data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
- data/docs/doc/PhraseParser/TermClause.html +1 -1
- data/docs/doc/PhraseParser.html +1 -1
- data/docs/doc/Status.html +1 -1
- data/docs/doc/String.html +58 -633
- data/docs/doc/Symbol.html +9 -224
- data/docs/doc/Time.html +119 -13
- data/docs/doc/TrueClass.html +1 -1
- data/docs/doc/_index.html +324 -8
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +1 -1
- data/docs/doc/index.html +1 -1
- data/docs/doc/method_list.html +2326 -542
- data/docs/doc/top-level-namespace.html +2 -2
- data/doing.rdoc +13 -3
- data/lib/completion/_doing.zsh +1 -1
- data/lib/completion/doing.bash +2 -2
- data/lib/completion/doing.fish +3 -1
- data/lib/doing/array/array.rb +16 -12
- data/lib/doing/array/nested_hash.rb +1 -1
- data/lib/doing/array/tags.rb +6 -5
- data/lib/doing/changelog/changelog.rb +6 -0
- data/lib/doing/chronify/array.rb +1 -3
- data/lib/doing/chronify/chronify.rb +12 -0
- data/lib/doing/chronify/numeric.rb +3 -2
- data/lib/doing/chronify/string.rb +1 -1
- data/lib/doing/completion/completion_string.rb +25 -0
- data/lib/doing/completion.rb +1 -1
- data/lib/doing/good.rb +8 -0
- data/lib/doing/item/dates.rb +1 -1
- data/lib/doing/{item.rb → item/item.rb} +10 -5
- data/lib/doing/item/query.rb +1 -1
- data/lib/doing/item/state.rb +1 -1
- data/lib/doing/item/tags.rb +1 -1
- data/lib/doing/items/filter.rb +67 -0
- data/lib/doing/items/items.rb +57 -0
- data/lib/doing/items/modify.rb +36 -0
- data/lib/doing/items/sections.rb +83 -0
- data/lib/doing/items/util.rb +74 -0
- data/lib/doing/normalize.rb +10 -2
- data/lib/doing/plugins/export/markdown_export.rb +4 -2
- data/lib/doing/plugins/import/doing_import.rb +1 -1
- data/lib/doing/prompt/choose.rb +118 -0
- data/lib/doing/prompt/fzf.rb +84 -0
- data/lib/doing/prompt/input.rb +129 -0
- data/lib/doing/prompt/prompt.rb +41 -0
- data/lib/doing/prompt/std.rb +32 -0
- data/lib/doing/prompt/yn.rb +64 -0
- data/lib/doing/section.rb +4 -0
- data/lib/doing/string/highlight.rb +1 -1
- data/lib/doing/string/query.rb +1 -1
- data/lib/doing/string/string.rb +18 -7
- data/lib/doing/string/tags.rb +14 -3
- data/lib/doing/string/transform.rb +1 -1
- data/lib/doing/string/truncate.rb +1 -1
- data/lib/doing/string/url.rb +1 -1
- data/lib/doing/time.rb +19 -1
- data/lib/doing/util_backup.rb +2 -2
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid/display.rb +357 -360
- data/lib/doing/wwid/editor.rb +173 -176
- data/lib/doing/wwid/filetools.rb +156 -159
- data/lib/doing/wwid/filter.rb +191 -183
- data/lib/doing/wwid/guess.rb +58 -60
- data/lib/doing/wwid/interactive.rb +332 -330
- data/lib/doing/wwid/modify.rb +509 -512
- data/lib/doing/wwid/tags.rb +38 -41
- data/lib/doing/wwid/timers.rb +293 -296
- data/lib/doing/{wwid.rb → wwid/wwid.rb} +32 -23
- data/lib/doing/wwid/wwidutil.rb +79 -82
- data/lib/doing.rb +5 -5
- data/lib/helpers/threaded_tests.rb +1 -0
- metadata +76 -14
- data/lib/doing/changelog.rb +0 -6
- data/lib/doing/completion/string.rb +0 -17
- data/lib/doing/items.rb +0 -221
- data/lib/doing/prompt.rb +0 -330
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
<strong class="classes">Classes:</strong> <span class='object_link'><a href="Array.html" title="Array (class)">Array</a></span>, <span class='object_link'><a href="FalseClass.html" title="FalseClass (class)">FalseClass</a></span>, <span class='object_link'><a href="Hash.html" title="Hash (class)">Hash</a></span>, <span class='object_link'><a href="Object.html" title="Object (class)">Object</a></span>, <span class='object_link'><a href="String.html" title="String (class)">String</a></span>, <span class='object_link'><a href="Symbol.html" title="Symbol (class)">Symbol</a></span>, <span class='object_link'><a href="Time.html" title="Time (class)">Time</a></span>, <span class='object_link'><a href="TrueClass.html" title="TrueClass (class)">TrueClass</a></span>
|
|
89
|
+
<strong class="classes">Classes:</strong> <span class='object_link'><a href="Array.html" title="Array (class)">Array</a></span>, <span class='object_link'><a href="FalseClass.html" title="FalseClass (class)">FalseClass</a></span>, <span class='object_link'><a href="Hash.html" title="Hash (class)">Hash</a></span>, <span class='object_link'><a href="Numeric.html" title="Numeric (class)">Numeric</a></span>, <span class='object_link'><a href="Object.html" title="Object (class)">Object</a></span>, <span class='object_link'><a href="String.html" title="String (class)">String</a></span>, <span class='object_link'><a href="Symbol.html" title="Symbol (class)">Symbol</a></span>, <span class='object_link'><a href="Time.html" title="Time (class)">Time</a></span>, <span class='object_link'><a href="TrueClass.html" title="TrueClass (class)">TrueClass</a></span>
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
</p>
|
|
@@ -206,7 +206,7 @@
|
|
|
206
206
|
</div>
|
|
207
207
|
|
|
208
208
|
<div id="footer">
|
|
209
|
-
Generated on
|
|
209
|
+
Generated on Wed Mar 16 09:42:15 2022 by
|
|
210
210
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
211
211
|
0.9.27 (ruby-3.0.1).
|
|
212
212
|
</div>
|
data/doing.rdoc
CHANGED
|
@@ -5,7 +5,7 @@ record of what you've been doing, complete with tag-based time tracking. The
|
|
|
5
5
|
command line tool allows you to add entries, annotate with tags and notes, and
|
|
6
6
|
view your entries with myriad options, with a focus on a "natural" language syntax.
|
|
7
7
|
|
|
8
|
-
v2.1.
|
|
8
|
+
v2.1.41
|
|
9
9
|
|
|
10
10
|
=== Global Options
|
|
11
11
|
=== --config_file arg
|
|
@@ -439,7 +439,7 @@ Look up a specific version. Specify versions as "MAJ.MIN.PATCH", MIN
|
|
|
439
439
|
to a version. Wildcards (*?) accepted unless using < or >.
|
|
440
440
|
|
|
441
441
|
[Default Value] None
|
|
442
|
-
[Must Match] (?-mix:^(?:(?:(?:[<>=]+|p(?:rior)|b(?:efore)|o(?:lder)|s(?:ince)|a(?:fter)|n(?:ewer))? *[0-9.*?]
|
|
442
|
+
[Must Match] (?-mix:^(?:(?:(?:[<>=]+|p(?:rior)|b(?:efore)|o(?:lder)|s(?:ince)|a(?:fter)|n(?:ewer))? *[0-9.*?]{1,10} *)+|(?:[\d.]+ *(?:-|to)+ *[0-9.]{1,10}))$)
|
|
443
443
|
|
|
444
444
|
|
|
445
445
|
===== -s|--search arg
|
|
@@ -2628,11 +2628,21 @@ Adds default_tags to a .doingrc file in the current directory. Any entry created
|
|
|
2628
2628
|
subdirectories will be tagged with the default tags. You can modify these any time using the `config set` commnand or
|
|
2629
2629
|
manually editing the .doingrc file.
|
|
2630
2630
|
===== Options
|
|
2631
|
-
=====
|
|
2631
|
+
===== --clear
|
|
2632
2632
|
Remove all default_tags from the local .doingrc
|
|
2633
2633
|
|
|
2634
2634
|
|
|
2635
2635
|
|
|
2636
|
+
===== -e|--editor
|
|
2637
|
+
Use default editor to edit tag list
|
|
2638
|
+
|
|
2639
|
+
|
|
2640
|
+
|
|
2641
|
+
===== -r|--remove
|
|
2642
|
+
Delete tag(s) from the current list
|
|
2643
|
+
|
|
2644
|
+
|
|
2645
|
+
|
|
2636
2646
|
==== Command: <tt>tags [MAX_COUNT]</tt>
|
|
2637
2647
|
List all tags in the current Doing file
|
|
2638
2648
|
|
data/lib/completion/_doing.zsh
CHANGED
|
@@ -183,7 +183,7 @@ function _doing() {
|
|
|
183
183
|
args=( {'(--autotag)-a','(-a)--autotag'}"[Autotag entries based on autotag configuration in ~/]" "--bool[Boolean used to combine multiple tags]:BOOLEAN:" {'(--count)-c','(-c)--count'}"[How many recent entries to tag]:COUNT:" "--case[Case sensitivity for search string matching ((c)ase-sensitive]:TYPE:" {'(--date)-d','(-d)--date'}"[Include current date/time with tag]" "--force[Dont ask permission to tag all entries when count is 0t ask permission to tag all entries when count is 0]" {'(--interactive)-i','(-i)--interactive'}"[Select item(s) to tag from a menu of matching entries]" "--not[Tag items that *dont* match search/tag filterst* match search/tag filters]" {'(--remove)-r','(-r)--remove'}"[Remove given tag(s)]" "--regex[Interpret tag string as regular expression]" "--rename[Replace existing tag with tag argument]:ORIG_TAG:" {'(--section)-s','(-s)--section'}"[Section]:SECTION_NAME:" "--search[Filter entries using a search query]:QUERY:" "--tag[Filter entries by tag]:TAG:" {'(--unfinished)-u','(-u)--unfinished'}"[Tag last entry]" {'(--value)-v','(-v)--value'}"[Include a value]:VALUE:" "--val[Perform a tag value query]:QUERY:" {'(--exact)-x','(-x)--exact'}"[Force exact search string matching]" )
|
|
184
184
|
;;
|
|
185
185
|
tag_dir)
|
|
186
|
-
args=( {'(--remove)-r','(-r)--remove'}"[
|
|
186
|
+
args=( "--clear[Remove all default_tags from the local]" {'(--editor)-e','(-e)--editor'}"[Use default editor to edit tag list]" {'(--remove)-r','(-r)--remove'}"[Delete tag(s) from the current list]" )
|
|
187
187
|
;;
|
|
188
188
|
tags)
|
|
189
189
|
args=( "--bool[Boolean used to combine multiple tags]:BOOLEAN:" {'(--counts)-c','(-c)--counts'}"[Show count of occurrences]" "--case[Case sensitivity for search string matching ((c)ase-sensitive]:TYPE:" {'(--interactive)-i','(-i)--interactive'}"[Select items to scan from a menu of matching entries]" {'(--line)-l','(-l)--line'}"[Output in a single line with @ symbols]" "--not[Show items that *dont* match search/tag filterst* match search/tag filters]" {'(--order)-o','(-o)--order'}"[Sort order]:ORDER:" {'(--section)-s','(-s)--section'}"[Section]:SECTION_NAME:" "--search[Filter entries using a search query]:QUERY:" "--sort[Sort by name or count]:SORT_ORDER:" "--tag[Filter entries by tag]:TAG:" "--val[Perform a tag value query]:QUERY:" {'(--exact)-x','(-x)--exact'}"[Force exact search string matching]" )
|
data/lib/completion/doing.bash
CHANGED
|
@@ -321,9 +321,9 @@ _doing_tag() {
|
|
|
321
321
|
_doing_tag_dir() {
|
|
322
322
|
|
|
323
323
|
if [[ "$token" == --* ]]; then
|
|
324
|
-
COMPREPLY=( $( compgen -W '--remove' -- $token ) )
|
|
324
|
+
COMPREPLY=( $( compgen -W '--clear --editor --remove' -- $token ) )
|
|
325
325
|
elif [[ "$token" == -* ]]; then
|
|
326
|
-
COMPREPLY=( $( compgen -W '-r --remove' -- $token ) )
|
|
326
|
+
COMPREPLY=( $( compgen -W '-e -r --clear --editor --remove' -- $token ) )
|
|
327
327
|
|
|
328
328
|
fi
|
|
329
329
|
}
|
data/lib/completion/doing.fish
CHANGED
|
@@ -505,7 +505,9 @@ complete -c doing -l unfinished -s u -f -n '__fish_doing_using_command tag' -d
|
|
|
505
505
|
complete -c doing -l value -s v -f -r -n '__fish_doing_using_command tag' -d Include\ a\ value
|
|
506
506
|
complete -c doing -l val -f -r -n '__fish_doing_using_command tag' -d Perform\ a\ tag\ value\ query
|
|
507
507
|
complete -c doing -l exact -s x -f -n '__fish_doing_using_command tag' -d Force\ exact\ search\ string\ matching
|
|
508
|
-
complete -c doing -l
|
|
508
|
+
complete -c doing -l clear -f -n '__fish_doing_using_command tag_dir' -d Remove\ all\ default_tags\ from\ the\ local
|
|
509
|
+
complete -c doing -l editor -s e -f -n '__fish_doing_using_command tag_dir' -d Use\ default\ editor\ to\ edit\ tag\ list
|
|
510
|
+
complete -c doing -l remove -s r -f -n '__fish_doing_using_command tag_dir' -d Delete\ tag\(s\)\ from\ the\ current\ list
|
|
509
511
|
complete -c doing -l bool -f -r -n '__fish_doing_using_command tags' -d Boolean\ used\ to\ combine\ multiple\ tags
|
|
510
512
|
complete -c doing -l counts -s c -f -n '__fish_doing_using_command tags' -d Show\ count\ of\ occurrences
|
|
511
513
|
complete -c doing -l case -f -r -n '__fish_doing_using_command tags' -d Case\ sensitivity\ for\ search\ string\ matching\ \[\(c\)ase-sensitive
|
data/lib/doing/array/array.rb
CHANGED
|
@@ -3,18 +3,22 @@
|
|
|
3
3
|
require_relative 'tags'
|
|
4
4
|
require_relative 'nested_hash'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
module Doing
|
|
7
|
+
class ::Array
|
|
8
|
+
include ArrayTags
|
|
9
|
+
include ArrayNestedHash
|
|
10
|
+
##
|
|
11
|
+
## Force UTF-8 encoding of strings in array
|
|
12
|
+
##
|
|
13
|
+
## @return [Array] Encoded lines
|
|
14
|
+
##
|
|
15
|
+
def utf8
|
|
16
|
+
c = self.class
|
|
17
|
+
if String.method_defined? :force_encoding
|
|
18
|
+
replace c.new(map(&:utf8))
|
|
19
|
+
else
|
|
20
|
+
self
|
|
21
|
+
end
|
|
18
22
|
end
|
|
19
23
|
end
|
|
20
24
|
end
|
data/lib/doing/array/tags.rb
CHANGED
|
@@ -4,12 +4,14 @@ module Doing
|
|
|
4
4
|
##
|
|
5
5
|
## Array helpers
|
|
6
6
|
##
|
|
7
|
-
|
|
7
|
+
module ArrayTags
|
|
8
8
|
##
|
|
9
9
|
## Convert an array of @tags to plain strings
|
|
10
10
|
##
|
|
11
|
-
## @return [Array] array of strings
|
|
11
|
+
## @return [Array] array of strings without @ symbols
|
|
12
12
|
##
|
|
13
|
+
## @example Convert an array of tags to strings
|
|
14
|
+
## ['@one', '@two', 'three'].to_tags => ['one', 'two', 'three']
|
|
13
15
|
def tags_to_array
|
|
14
16
|
map(&:remove_at).map(&:strip)
|
|
15
17
|
end
|
|
@@ -18,9 +20,8 @@ module Doing
|
|
|
18
20
|
#
|
|
19
21
|
# @return [Array] Array of @tags
|
|
20
22
|
#
|
|
21
|
-
# @example
|
|
22
|
-
# ['one', '@two', 'three'].to_tags
|
|
23
|
-
# # => ['@one', '@two', '@three']
|
|
23
|
+
# @example Convert an array of strings with or without @ symbols
|
|
24
|
+
# ['one', '@two', 'three'].to_tags => ['@one', '@two', '@three']
|
|
24
25
|
def to_tags
|
|
25
26
|
map(&:add_at)
|
|
26
27
|
end
|
data/lib/doing/chronify/array.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Doing
|
|
4
4
|
# Chronify array helpers
|
|
5
|
-
|
|
5
|
+
module ChronifyArray
|
|
6
6
|
# Convert [d, h, m] to [y, d, h, m]
|
|
7
7
|
def to_years
|
|
8
8
|
d, h, m = self
|
|
@@ -56,8 +56,6 @@ module Doing
|
|
|
56
56
|
##
|
|
57
57
|
## Format [d, h, m] as string
|
|
58
58
|
##
|
|
59
|
-
## @accept [Array] Array of [days, hours, minutes]
|
|
60
|
-
##
|
|
61
59
|
## @param format [Symbol] The format, :dhm, :hm,
|
|
62
60
|
## :m, :clock, :natural
|
|
63
61
|
## @return [String] formatted string
|
|
@@ -3,3 +3,15 @@
|
|
|
3
3
|
require_relative 'array'
|
|
4
4
|
require_relative 'numeric'
|
|
5
5
|
require_relative 'string'
|
|
6
|
+
|
|
7
|
+
class ::String
|
|
8
|
+
include Doing::ChronifyString
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class ::Array
|
|
12
|
+
include Doing::ChronifyArray
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class ::Numeric
|
|
16
|
+
include Doing::ChronifyNumeric
|
|
17
|
+
end
|
|
@@ -4,11 +4,12 @@ module Doing
|
|
|
4
4
|
##
|
|
5
5
|
## Number helpers
|
|
6
6
|
##
|
|
7
|
-
|
|
7
|
+
module ChronifyNumeric
|
|
8
8
|
##
|
|
9
9
|
## Format human readable time from seconds
|
|
10
10
|
##
|
|
11
|
-
## @param
|
|
11
|
+
## @param human [Boolean] if True, don't convert
|
|
12
|
+
## hours into days
|
|
12
13
|
##
|
|
13
14
|
def format_time(human: false)
|
|
14
15
|
return [0, 0, 0] if nil?
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Doing
|
|
2
|
+
module Completion
|
|
3
|
+
module StringUtils
|
|
4
|
+
def short_desc
|
|
5
|
+
split(/[,.]/)[0].sub(/ \(.*?\)?$/, '').strip
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def ltrunc(max)
|
|
9
|
+
if length > max
|
|
10
|
+
sub(/^.*?(.{#{max - 3}})$/, '...\1')
|
|
11
|
+
else
|
|
12
|
+
self
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ltrunc!(max)
|
|
17
|
+
replace ltrunc(max)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class ::String
|
|
24
|
+
include Doing::Completion::StringUtils
|
|
25
|
+
end
|
data/lib/doing/completion.rb
CHANGED
data/lib/doing/good.rb
CHANGED
data/lib/doing/item/dates.rb
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '
|
|
4
|
-
require_relative '
|
|
5
|
-
require_relative '
|
|
6
|
-
require_relative '
|
|
3
|
+
require_relative 'dates'
|
|
4
|
+
require_relative 'tags'
|
|
5
|
+
require_relative 'state'
|
|
6
|
+
require_relative 'query'
|
|
7
7
|
|
|
8
8
|
module Doing
|
|
9
9
|
##
|
|
10
10
|
## This class describes a single WWID item
|
|
11
11
|
##
|
|
12
12
|
class Item
|
|
13
|
+
include ItemDates
|
|
14
|
+
include ItemQuery
|
|
15
|
+
include ItemState
|
|
16
|
+
include ItemTags
|
|
17
|
+
|
|
13
18
|
attr_accessor :date, :title, :section, :note
|
|
14
19
|
|
|
15
20
|
# attr_reader :id
|
|
@@ -56,7 +61,7 @@ module Doing
|
|
|
56
61
|
|
|
57
62
|
return false unless @note.equal?(other.note)
|
|
58
63
|
|
|
59
|
-
return false if match_section &&
|
|
64
|
+
return false if match_section && !@section.equal?(other.section)
|
|
60
65
|
|
|
61
66
|
true
|
|
62
67
|
end
|
data/lib/doing/item/query.rb
CHANGED
data/lib/doing/item/state.rb
CHANGED
data/lib/doing/item/tags.rb
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doing
|
|
4
|
+
class Items < Array
|
|
5
|
+
# Get a new Items object containing only items in a
|
|
6
|
+
# specified section
|
|
7
|
+
#
|
|
8
|
+
# @param section [String] section title
|
|
9
|
+
#
|
|
10
|
+
# @return [Items] Array of items
|
|
11
|
+
#
|
|
12
|
+
def in_section(section)
|
|
13
|
+
if section =~ /^all$/i
|
|
14
|
+
dup
|
|
15
|
+
else
|
|
16
|
+
items = Items.new.concat(select { |item| !item.nil? && item.section == section })
|
|
17
|
+
items.add_section(section, log: false)
|
|
18
|
+
items
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
## Search Items for a string (title and note)
|
|
24
|
+
##
|
|
25
|
+
## @param query [String] The query
|
|
26
|
+
## @param case_type [Symbol] The case type
|
|
27
|
+
## (:smart, :sensitive, :ignore)
|
|
28
|
+
##
|
|
29
|
+
## @return [Items] array of items matching search
|
|
30
|
+
##
|
|
31
|
+
def search(query, case_type: :smart)
|
|
32
|
+
WWID.new.fuzzy_filter_items(self, query, case_type: case_type)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
## Search items by tags
|
|
37
|
+
##
|
|
38
|
+
## @param tags [Array,String] The tags by which to
|
|
39
|
+
## filter
|
|
40
|
+
## @param bool [Symbol] The bool with which to
|
|
41
|
+
## combine multiple tags
|
|
42
|
+
##
|
|
43
|
+
## @return [Items] array of items matching tag filter
|
|
44
|
+
##
|
|
45
|
+
def tagged(tags, bool: :and)
|
|
46
|
+
WWID.new.filter_items(self, opt: { tag: tags, bool: bool })
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
## Filter Items by date. String arguments will be
|
|
51
|
+
## chronified
|
|
52
|
+
##
|
|
53
|
+
## @param start [Time,String] Filter items after
|
|
54
|
+
## this date
|
|
55
|
+
## @param finish [Time,String] Filter items before
|
|
56
|
+
## this date
|
|
57
|
+
##
|
|
58
|
+
## @return [Items] array of items with dates between
|
|
59
|
+
## targets
|
|
60
|
+
##
|
|
61
|
+
def between_dates(start, finish)
|
|
62
|
+
start = start.chronify(guess: :begin, future: false) if start.is_a?(String)
|
|
63
|
+
finish = finish.chronify(guess: :end) if finish.is_a?(String)
|
|
64
|
+
WWID.new.filter_items(self, opt: { date_filter: [start, finish] })
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'filter'
|
|
4
|
+
require_relative 'modify'
|
|
5
|
+
require_relative 'sections'
|
|
6
|
+
require_relative 'util'
|
|
7
|
+
|
|
8
|
+
module Doing
|
|
9
|
+
# A collection of Item objects
|
|
10
|
+
class Items < Array
|
|
11
|
+
attr_accessor :sections
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
super
|
|
15
|
+
@sections = []
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
## Test if self includes Item
|
|
20
|
+
##
|
|
21
|
+
## @param item [Item] The item to search for
|
|
22
|
+
## @param match_section [Boolean] Section must match
|
|
23
|
+
##
|
|
24
|
+
## @return [Boolean] True if Item exists
|
|
25
|
+
##
|
|
26
|
+
def include?(item, match_section: true)
|
|
27
|
+
includes = false
|
|
28
|
+
each do |other_item|
|
|
29
|
+
if other_item.equal?(item, match_section: match_section)
|
|
30
|
+
includes = true
|
|
31
|
+
break
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
includes
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Output sections and items in Doing file format
|
|
39
|
+
def to_s
|
|
40
|
+
out = []
|
|
41
|
+
@sections.each do |section|
|
|
42
|
+
out.push(section.original)
|
|
43
|
+
items = in_section(section.title).sort_by { |i| [i.date, i.title] }
|
|
44
|
+
items.reverse! if Doing.setting('doing_file_sort').normalize_order == :desc
|
|
45
|
+
items.each { |item| out.push(item.to_s) }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
out.join("\n")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @private
|
|
52
|
+
def inspect
|
|
53
|
+
sections = @sections.map { |s| "<Section:#{s.title} #{in_section(s.title).count} items>" }.join(', ')
|
|
54
|
+
"#<Doing::Items #{count} items, #{@sections.count} sections: #{sections}>"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doing
|
|
4
|
+
class Items < Array
|
|
5
|
+
##
|
|
6
|
+
## Delete an item from the index
|
|
7
|
+
##
|
|
8
|
+
## @param item The item
|
|
9
|
+
##
|
|
10
|
+
def delete_item(item, single: false)
|
|
11
|
+
deleted = delete(item)
|
|
12
|
+
Doing.logger.count(:deleted)
|
|
13
|
+
Doing.logger.info('Entry deleted:', deleted.title) if single
|
|
14
|
+
deleted
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
## Update an item in the index with a modified item
|
|
19
|
+
##
|
|
20
|
+
## @param old_item The old item
|
|
21
|
+
## @param new_item The new item
|
|
22
|
+
##
|
|
23
|
+
def update_item(old_item, new_item)
|
|
24
|
+
s_idx = index { |item| item.equal?(old_item) }
|
|
25
|
+
|
|
26
|
+
raise ItemNotFound, 'Unable to find item in index, did it mutate?' unless s_idx
|
|
27
|
+
|
|
28
|
+
return if fetch(s_idx).equal?(new_item)
|
|
29
|
+
|
|
30
|
+
self[s_idx] = new_item
|
|
31
|
+
Doing.logger.count(:updated)
|
|
32
|
+
Doing.logger.info('Entry updated:', self[s_idx].title.trunc(60))
|
|
33
|
+
new_item
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doing
|
|
4
|
+
class Items < Array
|
|
5
|
+
# List sections, title only
|
|
6
|
+
#
|
|
7
|
+
# @return [Array] section titles
|
|
8
|
+
#
|
|
9
|
+
def section_titles
|
|
10
|
+
@sections.map(&:title)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Test if section already exists
|
|
14
|
+
#
|
|
15
|
+
# @param section [String] section title
|
|
16
|
+
#
|
|
17
|
+
# @return [Boolean] true if section exists
|
|
18
|
+
#
|
|
19
|
+
def section?(section)
|
|
20
|
+
section = section.is_a?(Section) ? section.title.downcase : section.downcase
|
|
21
|
+
@sections.map { |i| i.title.downcase }.include?(section)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
## Return the best section match for a search query
|
|
26
|
+
##
|
|
27
|
+
## @param frag The search query
|
|
28
|
+
## @param distance The distance apart characters can be (fuzziness)
|
|
29
|
+
##
|
|
30
|
+
## @return [Section] (first) matching section object
|
|
31
|
+
##
|
|
32
|
+
def guess_section(frag, distance: 2)
|
|
33
|
+
section = nil
|
|
34
|
+
re = frag.to_rx(distance: distance, case_type: :ignore)
|
|
35
|
+
@sections.each do |sect|
|
|
36
|
+
next unless sect.title =~ /#{re}/i
|
|
37
|
+
|
|
38
|
+
Doing.logger.debug('Match:', %(Assuming "#{sect.title}" from "#{frag}"))
|
|
39
|
+
section = sect
|
|
40
|
+
break
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
section
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Add a new section to the sections array. Accepts
|
|
47
|
+
# either a Section object, or a title string that will
|
|
48
|
+
# be converted into a Section.
|
|
49
|
+
#
|
|
50
|
+
# @param section [Section] The section to add. A
|
|
51
|
+
# String value will be converted to
|
|
52
|
+
# Section automatically.
|
|
53
|
+
# @param log [Boolean] Add a log message
|
|
54
|
+
# notifying the user about the
|
|
55
|
+
# creation of the section.
|
|
56
|
+
#
|
|
57
|
+
# @return nothing
|
|
58
|
+
#
|
|
59
|
+
def add_section(section, log: false)
|
|
60
|
+
section = section.is_a?(Section) ? section : Section.new(section.cap_first)
|
|
61
|
+
|
|
62
|
+
return if section?(section)
|
|
63
|
+
|
|
64
|
+
@sections.push(section)
|
|
65
|
+
Doing.logger.info('New section:', %("#{section}" added)) if log
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def delete_section(section, log: false)
|
|
69
|
+
return unless section?(section)
|
|
70
|
+
|
|
71
|
+
raise DoingRuntimeError, 'Section not empty' if in_section(section).count.positive?
|
|
72
|
+
|
|
73
|
+
@sections.each do |sect|
|
|
74
|
+
next unless sect.title == section && in_section(sect).count.zero?
|
|
75
|
+
|
|
76
|
+
@sections.delete(sect)
|
|
77
|
+
Doing.logger.info('Removed section:', %("#{section}" removed)) if log
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
Doing.logger.error('Not found:', %("#{section}" not found))
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|