doing 2.1.38 → 2.1.39
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/Rakefile +7 -1
- data/bin/commands/now.rb +2 -4
- data/bin/commands/on.rb +4 -2
- data/bin/commands/show.rb +3 -0
- data/bin/doing +33 -35
- data/docs/doc/Array.html +1 -1
- 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 +1 -1
- data/docs/doc/Doing/Completion.html +1 -1
- data/docs/doc/Doing/Configuration.html +1 -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 +64 -1
- data/docs/doc/Doing/Items.html +1 -1
- data/docs/doc/Doing/Logger.html +1 -1
- data/docs/doc/Doing/Note.html +1 -1
- data/docs/doc/Doing/Pager.html +1 -1
- data/docs/doc/Doing/Plugins.html +1 -1
- data/docs/doc/Doing/Prompt.html +1 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/TemplateString.html +1 -1
- data/docs/doc/Doing/Types.html +1 -1
- data/docs/doc/Doing/Util/Backup.html +1 -1
- data/docs/doc/Doing/Util.html +1 -1
- data/docs/doc/Doing/WWID.html +1 -1
- data/docs/doc/Doing.html +2 -2
- 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/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 +1 -1
- data/docs/doc/Symbol.html +1 -1
- data/docs/doc/Time.html +1 -1
- data/docs/doc/TrueClass.html +1 -1
- data/docs/doc/_index.html +1 -1
- data/docs/doc/file.README.html +2 -2
- data/docs/doc/index.html +2 -2
- data/docs/doc/method_list.html +159 -151
- data/docs/doc/top-level-namespace.html +1 -1
- data/doing.rdoc +6 -1
- data/lib/completion/_doing.zsh +1 -1
- data/lib/completion/doing.bash +2 -2
- data/lib/completion/doing.fish +1 -0
- data/lib/doing/chronify/string.rb +3 -1
- data/lib/doing/item.rb +151 -53
- data/lib/doing/items.rb +1 -1
- data/lib/doing/prompt.rb +6 -8
- data/lib/doing/string/tags.rb +8 -2
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +7 -2
- metadata +2 -2
@@ -206,7 +206,7 @@
|
|
206
206
|
</div>
|
207
207
|
|
208
208
|
<div id="footer">
|
209
|
-
Generated on
|
209
|
+
Generated on Sun Mar 13 05:08:08 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.39
|
9
9
|
|
10
10
|
=== Global Options
|
11
11
|
=== --config_file arg
|
@@ -2283,6 +2283,11 @@ Show elapsed time on entries without @done tag
|
|
2283
2283
|
|
2284
2284
|
|
2285
2285
|
|
2286
|
+
===== -e|--editor
|
2287
|
+
Edit matching entries with vim
|
2288
|
+
|
2289
|
+
|
2290
|
+
|
2286
2291
|
===== -h|--[no-]hilite
|
2287
2292
|
Highlight search matches in output. Only affects command line output
|
2288
2293
|
|
data/lib/completion/_doing.zsh
CHANGED
@@ -174,7 +174,7 @@ function _doing() {
|
|
174
174
|
args=( {'(--archive)-a','(-a)--archive'}"[Archive selected items]" "--after[Select entries newer than date]:DATE_STRING:" "--resume[Copy selection as a new entry with current time and no @done tag]" "--before[Select entries older than date]:DATE_STRING:" {'(--cancel)-c','(-c)--cancel'}"[Cancel selected items]" "--case[Case sensitivity for search string matching ((c)ase-sensitive]:TYPE:" {'(--delete)-d','(-d)--delete'}"[Delete selected items]" {'(--editor)-e','(-e)--editor'}"[Edit selected item(s)]" {'(--finish)-f','(-f)--finish'}"[Add @done with current time to selected item(s)]" "--flag[Add flag to selected item(s)]" "--force[Perform action without confirmation]" "--from[Date range]:DATE_OR_RANGE:" {'(--move)-m','(-m)--move'}"[Move selected items to section]:SECTION:" "--menu[Use --no-menu to skip the interactive menu]" "--not[Select items that *dont* match search/tag filterst* match search/tag filters]" {'(--output)-o','(-o)--output'}"[Output entries to format]:FORMAT:" {'(--query)-q','(-q)--query'}"[Initial search query for filtering]:QUERY:" {'(--remove)-r','(-r)--remove'}"[Reverse -c]" {'(--section)-s','(-s)--section'}"[Select from a specific section]:SECTION:" "--save_to[Save selected entries to file using --output format]:FILE:" "--search[Filter entries using a search query]:QUERY:" {'(--tag)-t','(-t)--tag'}"[Tag selected entries]:TAG:" "--val[Perform a tag value query]:QUERY:" {'(--exact)-x','(-x)--exact'}"[Force exact search string matching]" )
|
175
175
|
;;
|
176
176
|
show)
|
177
|
-
args=( {'(--age)-a','(-a)--age'}"[Age]:AGE:" "--after[Show entries newer than date]:DATE_STRING:" "--before[Show entries older than date]:DATE_STRING:" "--bool[Boolean used to combine multiple tags]:BOOLEAN:" {'(--count)-c','(-c)--count'}"[Max count to show]:MAX:" "--case[Case sensitivity for search string matching ((c)ase-sensitive]:TYPE:" "--config_template[Output using a template from configuration]:TEMPLATE_KEY:" "--duration[Show elapsed time on entries without @done tag]" "--from[Date range]:DATE_OR_RANGE:" {'(--hilite)-h','(-h)--hilite'}"[Highlight search matches in output]" {'(--interactive)-i','(-i)--interactive'}"[Select from a menu of matching entries to perform additional operations]" {'(--menu)-m','(-m)--menu'}"[Select section or tag to display from a menu]" "--not[Show items that *dont* match search/tag filterst* match search/tag filters]" {'(--output)-o','(-o)--output'}"[Output to export format]:FORMAT:" "--only_timed[Only show items with recorded time intervals]" {'(--sort)-s','(-s)--sort'}"[Sort order]:ORDER:" "--search[Filter entries using a search query]:QUERY:" {'(--times)-t','(-t)--times'}"[Show time intervals on @done tasks]" "--tag[Filter entries by tag]:TAG:" "--tag_order[Tag sort direction]:DIRECTION:" "--tag_sort[Sort tags by]:KEY:" "--template[Override output format with a template string containing %placeholders]:TEMPLATE_STRING:" "--totals[Show time totals at the end of output]" "--val[Perform a tag value query]:QUERY:" {'(--exact)-x','(-x)--exact'}"[Force exact search string matching]" )
|
177
|
+
args=( {'(--age)-a','(-a)--age'}"[Age]:AGE:" "--after[Show entries newer than date]:DATE_STRING:" "--before[Show entries older than date]:DATE_STRING:" "--bool[Boolean used to combine multiple tags]:BOOLEAN:" {'(--count)-c','(-c)--count'}"[Max count to show]:MAX:" "--case[Case sensitivity for search string matching ((c)ase-sensitive]:TYPE:" "--config_template[Output using a template from configuration]:TEMPLATE_KEY:" "--duration[Show elapsed time on entries without @done tag]" {'(--editor)-e','(-e)--editor'}"[Edit matching entries with vim]" "--from[Date range]:DATE_OR_RANGE:" {'(--hilite)-h','(-h)--hilite'}"[Highlight search matches in output]" {'(--interactive)-i','(-i)--interactive'}"[Select from a menu of matching entries to perform additional operations]" {'(--menu)-m','(-m)--menu'}"[Select section or tag to display from a menu]" "--not[Show items that *dont* match search/tag filterst* match search/tag filters]" {'(--output)-o','(-o)--output'}"[Output to export format]:FORMAT:" "--only_timed[Only show items with recorded time intervals]" {'(--sort)-s','(-s)--sort'}"[Sort order]:ORDER:" "--search[Filter entries using a search query]:QUERY:" {'(--times)-t','(-t)--times'}"[Show time intervals on @done tasks]" "--tag[Filter entries by tag]:TAG:" "--tag_order[Tag sort direction]:DIRECTION:" "--tag_sort[Sort tags by]:KEY:" "--template[Override output format with a template string containing %placeholders]:TEMPLATE_STRING:" "--totals[Show time totals at the end of output]" "--val[Perform a tag value query]:QUERY:" {'(--exact)-x','(-x)--exact'}"[Force exact search string matching]" )
|
178
178
|
;;
|
179
179
|
since)
|
180
180
|
args=( "--bool[Boolean used to combine multiple tags]:BOOLEAN:" "--case[Case sensitivity for search string matching ((c)ase-sensitive]:TYPE:" "--config_template[Output using a template from configuration]:TEMPLATE_KEY:" "--duration[Show elapsed time on entries without @done tag]" "--not[Since items that *dont* match search/tag filterst* match search/tag filters]" {'(--output)-o','(-o)--output'}"[Output to export format]:FORMAT:" "--only_timed[Only show items with recorded time intervals]" {'(--section)-s','(-s)--section'}"[Section]:NAME:" "--search[Filter entries using a search query]:QUERY:" {'(--times)-t','(-t)--times'}"[Show time intervals on @done tasks]" "--tag[Filter entries by tag]:TAG:" "--tag_order[Tag sort direction]:DIRECTION:" "--tag_sort[Sort tags by]:KEY:" "--template[Override output format with a template string containing %placeholders]:TEMPLATE_STRING:" "--totals[Show time totals at the end of output]" "--val[Perform a tag value query]:QUERY:" {'(--exact)-x','(-x)--exact'}"[Force exact search string matching]" )
|
data/lib/completion/doing.bash
CHANGED
@@ -276,9 +276,9 @@ local words=$(doing sections)
|
|
276
276
|
IFS="$OLD_IFS"
|
277
277
|
|
278
278
|
if [[ "$token" == --* ]]; then
|
279
|
-
COMPREPLY=( $( compgen -W '--age --after --before --bool --count --case --config_template --duration --from --hilite --interactive --menu --not --output --only_timed --sort --search --times --tag --tag_order --tag_sort --template --totals --val --exact' -- $token ) )
|
279
|
+
COMPREPLY=( $( compgen -W '--age --after --before --bool --count --case --config_template --duration --editor --from --hilite --interactive --menu --not --output --only_timed --sort --search --times --tag --tag_order --tag_sort --template --totals --val --exact' -- $token ) )
|
280
280
|
elif [[ "$token" == -* ]]; then
|
281
|
-
COMPREPLY=( $( compgen -W '-a -c -h -i -m -o -s -t -x --age --after --before --bool --count --case --config_template --duration --from --hilite --interactive --menu --not --output --only_timed --sort --search --times --tag --tag_order --tag_sort --template --totals --val --exact' -- $token ) )
|
281
|
+
COMPREPLY=( $( compgen -W '-a -c -e -h -i -m -o -s -t -x --age --after --before --bool --count --case --config_template --duration --editor --from --hilite --interactive --menu --not --output --only_timed --sort --search --times --tag --tag_order --tag_sort --template --totals --val --exact' -- $token ) )
|
282
282
|
else
|
283
283
|
local nocasematchWasOff=0
|
284
284
|
shopt nocasematch >/dev/null || nocasematchWasOff=1
|
data/lib/completion/doing.fish
CHANGED
@@ -447,6 +447,7 @@ complete -c doing -l count -s c -f -r -n '__fish_doing_using_command show' -d Ma
|
|
447
447
|
complete -c doing -l case -f -r -n '__fish_doing_using_command show' -d Case\ sensitivity\ for\ search\ string\ matching\ \[\(c\)ase-sensitive
|
448
448
|
complete -c doing -l config_template -f -r -n '__fish_doing_using_command show' -d Output\ using\ a\ template\ from\ configuration
|
449
449
|
complete -c doing -l duration -f -n '__fish_doing_using_command show' -d Show\ elapsed\ time\ on\ entries\ without\ @done\ tag
|
450
|
+
complete -c doing -l editor -s e -f -n '__fish_doing_using_command show' -d Edit\ matching\ entries\ with\ vim
|
450
451
|
complete -c doing -l from -f -r -n '__fish_doing_using_command show' -d Date\ range
|
451
452
|
complete -c doing -l hilite -s h -f -n '__fish_doing_using_command show' -d Highlight\ search\ matches\ in\ output
|
452
453
|
complete -c doing -l interactive -s i -f -n '__fish_doing_using_command show' -d Select\ from\ a\ menu\ of\ matching\ entries\ to\ perform\ additional\ operations
|
@@ -196,7 +196,9 @@ module Doing
|
|
196
196
|
finish = dates[-1].chronify(guess: inclusive ? :end : :begin, future: true)
|
197
197
|
end
|
198
198
|
|
199
|
-
raise Errors::InvalidTimeExpression,
|
199
|
+
raise Errors::InvalidTimeExpression, "Unrecognized date string (#{dates[0]})" if start.nil?
|
200
|
+
|
201
|
+
raise Errors::InvalidTimeExpression, "Unrecognized date string (#{dates[-1]})" if finish.nil?
|
200
202
|
|
201
203
|
else
|
202
204
|
if date_string.strip =~ time_rx
|
data/lib/doing/item.rb
CHANGED
@@ -180,8 +180,14 @@ module Doing
|
|
180
180
|
|
181
181
|
remove = options.fetch(:remove, false)
|
182
182
|
tags.each do |tag|
|
183
|
+
if tag =~ /^(\S+)\((.*?)\)$/
|
184
|
+
m = Regexp.last_match
|
185
|
+
tag = m[1]
|
186
|
+
options[:value] ||= m[2]
|
187
|
+
end
|
188
|
+
|
183
189
|
bool = remove ? :and : :not
|
184
|
-
if tags?(tag, bool)
|
190
|
+
if tags?(tag, bool) || options[:value]
|
185
191
|
@title = @title.tag(tag, **options).strip
|
186
192
|
remove ? removed.push(tag) : added.push(tag)
|
187
193
|
end
|
@@ -201,6 +207,16 @@ module Doing
|
|
201
207
|
@title.scan(/(?<= |\A)@([^\s(]+)/).map { |tag| tag[0] }.sort.uniq
|
202
208
|
end
|
203
209
|
|
210
|
+
##
|
211
|
+
## Return all tags including parenthetical values
|
212
|
+
##
|
213
|
+
## @return [Array<Array>] Array of array pairs,
|
214
|
+
## [[tag1, value], [tag2, value]]
|
215
|
+
##
|
216
|
+
def tags_with_values
|
217
|
+
@title.scan(/(?<= |\A)@([^\s(]+)(?:\((.*?)\))?/).map { |tag| [tag[0], tag[1]] }.sort.uniq
|
218
|
+
end
|
219
|
+
|
204
220
|
##
|
205
221
|
## convert tags on item to an array with @ symbols removed
|
206
222
|
##
|
@@ -557,6 +573,12 @@ module Doing
|
|
557
573
|
false
|
558
574
|
end
|
559
575
|
|
576
|
+
def tag_pattern?(tags)
|
577
|
+
query = tags.to_query
|
578
|
+
|
579
|
+
no_tags?(query[:must_not]) && all_tags?(query[:must]) && any_tags?(query[:should])
|
580
|
+
end
|
581
|
+
|
560
582
|
def tag_value(tag)
|
561
583
|
res = @title.match(/@#{tag.sub(/^@/, '').wildcard_to_rx}\((.*?)\)/)
|
562
584
|
res ? res[1] : nil
|
@@ -592,6 +614,7 @@ module Doing
|
|
592
614
|
|
593
615
|
queries.each do |q|
|
594
616
|
parts = split_value_query(q)
|
617
|
+
|
595
618
|
return false unless tag_value_matches?(parts[2], parts[3], parts[4], parts[1])
|
596
619
|
end
|
597
620
|
true
|
@@ -607,78 +630,153 @@ module Doing
|
|
607
630
|
true
|
608
631
|
end
|
609
632
|
|
633
|
+
def duration_matches?(value, comp)
|
634
|
+
return false if interval.nil?
|
635
|
+
|
636
|
+
val = value.chronify_qty
|
637
|
+
case comp
|
638
|
+
when /^<$/
|
639
|
+
interval < val
|
640
|
+
when /^<=$/
|
641
|
+
interval <= val
|
642
|
+
when /^>$/
|
643
|
+
interval > val
|
644
|
+
when /^>=$/
|
645
|
+
interval >= val
|
646
|
+
when /^!=/
|
647
|
+
interval != val
|
648
|
+
when /^=/
|
649
|
+
interval == val
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
def date_matches?(value, comp)
|
654
|
+
time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/i
|
655
|
+
value = "#{@date.strftime('%Y-%m-%d')} #{value}" if value =~ time_rx
|
656
|
+
|
657
|
+
val = value.chronify(guess: :begin)
|
658
|
+
raise InvalidTimeExpression, "Unrecognized date/time expression (#{value})" if val.nil?
|
659
|
+
|
660
|
+
case comp
|
661
|
+
when /^<$/
|
662
|
+
@date < val
|
663
|
+
when /^<=$/
|
664
|
+
@date <= val
|
665
|
+
when /^>$/
|
666
|
+
@date > val
|
667
|
+
when /^>=$/
|
668
|
+
@date >= val
|
669
|
+
when /^!=/
|
670
|
+
@date != val
|
671
|
+
when /^=/
|
672
|
+
@date == val
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
def value_string_matches?(tag_val, comp, value)
|
677
|
+
case comp
|
678
|
+
when /\^=/
|
679
|
+
tag_val =~ /^#{value.wildcard_to_rx}/i
|
680
|
+
when /\$=/
|
681
|
+
tag_val =~ /#{value.wildcard_to_rx}$/i
|
682
|
+
when %r{==}
|
683
|
+
tag_val =~ /^#{value.wildcard_to_rx}$/i
|
684
|
+
else
|
685
|
+
tag_val =~ /#{value.wildcard_to_rx}/i
|
686
|
+
end
|
687
|
+
end
|
688
|
+
|
689
|
+
def value_number_matches?(tag_val, comp, value)
|
690
|
+
case comp
|
691
|
+
when /^<$/
|
692
|
+
tag_val < value
|
693
|
+
when /^<=$/
|
694
|
+
tag_val <= value
|
695
|
+
when /^>$/
|
696
|
+
tag_val > value
|
697
|
+
when /^>=$/
|
698
|
+
tag_val >= value
|
699
|
+
when /^!=/
|
700
|
+
tag_val != value
|
701
|
+
when /^=/
|
702
|
+
tag_val == value
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
706
|
+
##
|
707
|
+
## Test if a tag's value matches a given value. Value
|
708
|
+
## can be a date string, a text string, or a
|
709
|
+
## number/percentage. Type of comparison is determined
|
710
|
+
## by the comparitor and the objects being compared.
|
711
|
+
##
|
712
|
+
## @param tag [String] The tag name from which
|
713
|
+
## to get the value
|
714
|
+
## @param comp [String] The comparator (e.g. >=
|
715
|
+
## or *=)
|
716
|
+
## @param value [String] The value to test
|
717
|
+
## against
|
718
|
+
## @param negate [Boolean] Negate the response
|
719
|
+
##
|
720
|
+
## @return True if tag value matches, False otherwise.
|
721
|
+
##
|
610
722
|
def tag_value_matches?(tag, comp, value, negate)
|
611
|
-
|
612
|
-
|
613
|
-
return false if interval.nil?
|
614
|
-
|
615
|
-
val = value.chronify_qty
|
616
|
-
is_match = case comp
|
617
|
-
when /^<$/
|
618
|
-
interval < val
|
619
|
-
when /^<=$/
|
620
|
-
interval <= val
|
621
|
-
when /^>$/
|
622
|
-
interval > val
|
623
|
-
when /^>=$/
|
624
|
-
interval >= val
|
625
|
-
when /^!=/
|
626
|
-
interval != val
|
627
|
-
when /^=/
|
628
|
-
interval == val
|
629
|
-
end
|
630
|
-
comp =~ /!/ || negate ? !is_match : is_match
|
631
|
-
elsif all_tags?([tag])
|
723
|
+
# If tag matches existing tag
|
724
|
+
if tags?(tag, :and)
|
632
725
|
tag_val = tag_value(tag)
|
633
726
|
|
727
|
+
# If the tag value is not a date and contains alpha
|
728
|
+
# characters and comparison is ==, or comparison is
|
729
|
+
# a string comparitor (*= ^= $=)
|
634
730
|
if (value.chronify.nil? && value =~ /[a-z]/i && comp =~ /^!?==?$/) || comp =~ /[$*^]=/
|
635
|
-
is_match =
|
636
|
-
when /\^=/
|
637
|
-
tag_val =~ /^#{value.wildcard_to_rx}/i
|
638
|
-
when /\$=/
|
639
|
-
tag_val =~ /#{value.wildcard_to_rx}$/i
|
640
|
-
when %r{==}
|
641
|
-
tag_val =~ /^#{value.wildcard_to_rx}$/i
|
642
|
-
else
|
643
|
-
tag_val =~ /#{value.wildcard_to_rx}/i
|
644
|
-
end
|
731
|
+
is_match = value_string_matches?(tag_val, comp, value)
|
645
732
|
|
646
733
|
comp =~ /!/ || negate ? !is_match : is_match
|
647
734
|
else
|
735
|
+
# Convert values to either a number or a date
|
648
736
|
tag_val = number_or_date(tag_val)
|
649
737
|
val = number_or_date(value)
|
650
738
|
|
739
|
+
# Fail if either value is nil
|
651
740
|
return false if val.nil? || tag_val.nil?
|
652
741
|
|
742
|
+
# Fail unless both values are of the same class (float or date)
|
653
743
|
return false unless val.class == tag_val.class
|
654
744
|
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
when /^<=$/
|
659
|
-
tag_val <= val
|
660
|
-
when /^>$/
|
661
|
-
tag_val > val
|
662
|
-
when /^>=$/
|
663
|
-
tag_val >= val
|
664
|
-
when /^!=/
|
665
|
-
tag_val != val
|
666
|
-
when /^=/
|
667
|
-
tag_val == val
|
668
|
-
end
|
669
|
-
negate.nil? ? matches : !matches
|
745
|
+
is_match = value_number_matches?(tag_val, comp, val)
|
746
|
+
|
747
|
+
negate.nil? ? is_match : !is_match
|
670
748
|
end
|
749
|
+
# If tag name matches a trigger for elapsed time test
|
750
|
+
elsif tag =~ /^(elapsed|dur(ation)?|int(erval)?)$/i
|
751
|
+
is_match = duration_matches?(value, comp)
|
752
|
+
|
753
|
+
comp =~ /!/ || negate ? !is_match : is_match
|
754
|
+
# Else if tag name matches a trigger for start date
|
755
|
+
elsif tag =~ /^(d(ate)?|t(ime)?)$/i
|
756
|
+
is_match = date_matches?(value, comp)
|
757
|
+
|
758
|
+
comp =~ /!/ || negate ? !is_match : is_match
|
759
|
+
# Else if tag name matches a trigger for all text
|
760
|
+
elsif tag =~ /^text$/i
|
761
|
+
is_match = value_string_matches?([@title, @note.to_s(prefix: '')].join(' '), comp, value)
|
762
|
+
|
763
|
+
comp =~ /!/ || negate ? !is_match : is_match
|
764
|
+
# Else if tag name matches a trigger for title
|
765
|
+
elsif tag =~ /^title$/i
|
766
|
+
is_match = value_string_matches?(@title, comp, value)
|
767
|
+
|
768
|
+
comp =~ /!/ || negate ? !is_match : is_match
|
769
|
+
# Else if tag name matches a trigger for note
|
770
|
+
elsif tag =~ /^note$/i
|
771
|
+
is_match = value_string_matches?(@note.to_s(prefix: ''), comp, value)
|
772
|
+
|
773
|
+
comp =~ /!/ || negate ? !is_match : is_match
|
774
|
+
# Else if item contains tag being tested
|
671
775
|
else
|
672
776
|
false
|
673
777
|
end
|
674
778
|
end
|
675
779
|
|
676
|
-
def tag_pattern?(tags)
|
677
|
-
query = tags.to_query
|
678
|
-
|
679
|
-
no_tags?(query[:must_not]) && all_tags?(query[:must]) && any_tags?(query[:should])
|
680
|
-
end
|
681
|
-
|
682
780
|
def split_tags(tags)
|
683
781
|
tags.to_tags.tags_to_array
|
684
782
|
end
|
data/lib/doing/items.rb
CHANGED
@@ -179,7 +179,7 @@ module Doing
|
|
179
179
|
out = []
|
180
180
|
@sections.each do |section|
|
181
181
|
out.push(section.original)
|
182
|
-
items = in_section(section.title).sort_by
|
182
|
+
items = in_section(section.title).sort_by { |i| [i.date, i.title] }
|
183
183
|
items.reverse! if Doing.setting('doing_file_sort').normalize_order == :desc
|
184
184
|
items.each { |item| out.push(item.to_s) }
|
185
185
|
end
|
data/lib/doing/prompt.rb
CHANGED
@@ -58,14 +58,12 @@ module Doing
|
|
58
58
|
comp = proc { |s| completions.grep(/^#{Regexp.escape(s)}/) }
|
59
59
|
Readline.completion_append_character = ' '
|
60
60
|
Readline.completion_proc = comp
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
prompt_text << yellow(' to cancel')
|
68
|
-
puts prompt_text.join('')
|
61
|
+
puts format(['%<promptcolor>s%<prompt>s %<textcolor>sEnter a blank line',
|
62
|
+
'(%<keycolor>sreturn twice%<textcolor>s)',
|
63
|
+
'to end editing and save,',
|
64
|
+
'%<keycolor>sCTRL-C%<textcolor>s to cancel%<reset>s'].join(' '),
|
65
|
+
{ promptcolor: boldgreen, prompt: prompt.sub(/:?$/, ':'),
|
66
|
+
textcolor: yellow, keycolor: boldwhite, reset: reset })
|
69
67
|
|
70
68
|
res = []
|
71
69
|
|
data/lib/doing/string/tags.rb
CHANGED
@@ -117,14 +117,20 @@ module Doing
|
|
117
117
|
else
|
118
118
|
Doing.logger.debug('Skipped:', "not tagged #{"@#{tag}".cyan}")
|
119
119
|
end
|
120
|
-
elsif title =~ /@#{tag}(?=[ (]|$)/
|
120
|
+
elsif title =~ /@#{tag}(?=[ (]|$)/ && !value.good?
|
121
121
|
Doing.logger.debug('Skipped:', "already tagged #{"@#{tag}".cyan}")
|
122
122
|
return title
|
123
123
|
else
|
124
124
|
add = tag
|
125
125
|
add += "(#{value})" unless value.nil?
|
126
|
+
|
126
127
|
title.chomp!
|
127
|
-
|
128
|
+
|
129
|
+
if value && title =~ /@#{tag}(?=[ (]|$)/
|
130
|
+
title.sub!(/@#{tag}(\(.*?\))?/, "@#{add}")
|
131
|
+
else
|
132
|
+
title += " @#{add}"
|
133
|
+
end
|
128
134
|
|
129
135
|
title.dedup_tags!
|
130
136
|
title.chomp!
|
data/lib/doing/version.rb
CHANGED
data/lib/doing/wwid.rb
CHANGED
@@ -665,7 +665,7 @@ module Doing
|
|
665
665
|
##
|
666
666
|
def filter_items(items = Items.new, opt: {})
|
667
667
|
logger.benchmark(:filter_items, :start)
|
668
|
-
time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/
|
668
|
+
time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/i
|
669
669
|
|
670
670
|
if items.nil? || items.empty?
|
671
671
|
section = opt[:section] ? guess_section(opt[:section]) : 'All'
|
@@ -1292,9 +1292,14 @@ module Doing
|
|
1292
1292
|
next
|
1293
1293
|
end
|
1294
1294
|
|
1295
|
-
|
1296
1295
|
tag = tag.strip
|
1297
1296
|
|
1297
|
+
if tag =~ /^(\S+)\((.*?)\)$/
|
1298
|
+
m = Regexp.last_match
|
1299
|
+
tag = m[1]
|
1300
|
+
opt[:value] ||= m[2]
|
1301
|
+
end
|
1302
|
+
|
1298
1303
|
if tag =~ /^done$/ && opt[:date] && item.should_time?
|
1299
1304
|
max_elapsed = Doing.setting('interaction.confirm_longer_than', 0)
|
1300
1305
|
max_elapsed = max_elapsed.chronify_qty if max_elapsed.is_a?(String)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.39
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03-
|
11
|
+
date: 2022-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: github-markup
|