doing 2.1.14 → 2.1.15
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/.irbrc +1 -0
- data/.yardoc/checksums +11 -9
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +3 -2
- data/README.md +56 -19
- data/bin/doing +4 -3
- data/docs/doc/Array.html +117 -3
- 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 +5 -2
- 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 +106 -2
- 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 +1 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/TemplateString.html +2 -2
- data/docs/doc/Doing/Util/Backup.html +1 -1
- data/docs/doc/Doing/Util.html +1 -1
- data/docs/doc/Doing/WWID.html +35 -65
- data/docs/doc/Doing.html +3 -3
- 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 +279 -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 +767 -115
- data/docs/doc/Symbol.html +1 -1
- data/docs/doc/Time.html +1 -1
- data/docs/doc/_index.html +14 -9
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +41 -15
- data/docs/doc/index.html +41 -15
- data/docs/doc/method_list.html +357 -293
- data/docs/doc/top-level-namespace.html +2 -2
- data/docs/index.md +56 -19
- data/doing.gemspec +1 -0
- data/doing.rdoc +3 -3
- data/example_plugin.rb +2 -4
- data/lib/completion/_doing.zsh +3 -3
- data/lib/completion/doing.bash +4 -4
- data/lib/completion/doing.fish +2 -2
- data/lib/doing/array_chronify.rb +57 -0
- data/lib/doing/configuration.rb +4 -1
- data/lib/doing/item.rb +32 -0
- data/lib/doing/log_adapter.rb +1 -1
- data/lib/doing/numeric_chronify.rb +40 -0
- data/lib/doing/plugins/export/dayone_export.rb +1 -1
- data/lib/doing/plugins/export/json_export.rb +2 -2
- data/lib/doing/plugins/export/template_export.rb +47 -90
- data/lib/doing/string.rb +97 -33
- data/lib/doing/string_chronify.rb +83 -13
- data/lib/doing/time.rb +4 -4
- data/lib/doing/util_backup.rb +1 -1
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +58 -83
- data/lib/doing.rb +30 -27
- data/lib/examples/plugins/say_export.rb +1 -4
- metadata +26 -2
@@ -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="Hash.html" title="Hash (class)">Hash</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>
|
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="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="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>
|
90
90
|
|
91
91
|
|
92
92
|
</p>
|
@@ -102,7 +102,7 @@
|
|
102
102
|
</div>
|
103
103
|
|
104
104
|
<div id="footer">
|
105
|
-
Generated on
|
105
|
+
Generated on Mon Jan 17 08:01:48 2022 by
|
106
106
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
107
107
|
0.9.26 (ruby-3.0.1).
|
108
108
|
</div>
|
data/docs/index.md
CHANGED
@@ -1,53 +1,90 @@
|
|
1
1
|
# doing
|
2
2
|
|
3
|
-
**A command line tool for remembering what you were doing and tracking what
|
3
|
+
**A command line tool for remembering what you were doing and tracking what
|
4
|
+
you've done.**
|
4
5
|
|
5
|
-
_If you're one of the rare people like me who find this useful, feel free to
|
6
|
+
_If you're one of the rare people like me who find this useful, feel free to
|
7
|
+
[buy me some coffee][donate]._
|
6
8
|
|
7
9
|
|
8
10
|
|
9
|
-
The current version of `doing` is 2.1.
|
11
|
+
The current version of `doing` is 2.1.13.
|
10
12
|
|
11
|
-
Find all of the documentation in the [doing wiki]
|
13
|
+
Find all of the documentation in the [doing wiki][wiki].
|
12
14
|
|
13
|
-
See [what's new in Doing 2.0]
|
15
|
+
See [what's new in Doing 2.0][doing 2].
|
14
16
|
|
15
|
-
Check out some craziness with Doing in the [iTerm status bar]
|
17
|
+
Check out some craziness with Doing in the [iTerm status bar][status bar] and
|
18
|
+
the [Mac Touch Bar/menu bar][touch bar].
|
16
19
|
|
17
20
|
## What and why
|
18
21
|
|
19
|
-
`doing` is a basic CLI for adding and listing "what was I doing" reminders in a
|
22
|
+
`doing` is a basic CLI for adding and listing "what was I doing" reminders in a
|
23
|
+
[TaskPaper-formatted](https://www.taskpaper.com) text file. It allows for
|
24
|
+
multiple sections/categories and flexible output formatting.
|
20
25
|
|
21
|
-
While I'm working, I have hourly reminders to record what I'm working on, and I
|
26
|
+
While I'm working, I have hourly reminders to record what I'm working on, and I
|
27
|
+
try to remember to punch in quick notes if I'm unexpectedly called away from a
|
28
|
+
project. I can do this just by typing `doing now tracking down the CG bug`.
|
22
29
|
|
23
|
-
If there's something I want to look at later but doesn't need to be added to a
|
30
|
+
If there's something I want to look at later but doesn't need to be added to a
|
31
|
+
task list or tracker, I can type `doing later check out the pinboard bookmarks
|
32
|
+
from macdrifter`. When I get back to my computer --- or just need a refresher
|
33
|
+
after a distraction --- I can type `doing last` to see what the last thing on
|
34
|
+
my plate was. I can also type `doing recent` (or just `doing`) to get a list of
|
35
|
+
the last few entries. `doing today` gives me everything since midnight for the
|
36
|
+
current day, making it easy to see what I've accomplished over a sleepless
|
37
|
+
night.
|
24
38
|
|
25
|
-
Doing has over 30 commands for tracking your status, recording your time, and
|
39
|
+
Doing has over 30 commands for tracking your status, recording your time, and
|
40
|
+
analyzing the results.
|
26
41
|
|
27
|
-
See [the wiki]
|
42
|
+
See [the wiki][wiki] for installation and usage instructions.
|
28
43
|
|
29
44
|
## Launchbar/Alfred
|
30
45
|
|
31
|
-
The LaunchBar action requires that `doing` be available in
|
46
|
+
The LaunchBar action requires that `doing` be available in
|
47
|
+
`/usr/local/bin/doing`. If it's not (because you're using RVM or similar),
|
48
|
+
you'll need to symlink it there. Running the action with Return will show the
|
49
|
+
latest 9 items from Currently, along with any time intervals recorded, and
|
50
|
+
includes a submenu of Timers for each tag.
|
32
51
|
|
33
|
-
Pressing Spacebar and typing allows you to add a new entry to currently. You an
|
52
|
+
Pressing Spacebar and typing allows you to add a new entry to currently. You an
|
53
|
+
also trigger a custom show command by typing "show [section/tag]" and hitting
|
54
|
+
return. Include any command line flags at the end of the string, and if you add
|
55
|
+
text in parenthesis, it will be processed as a note on the entry.
|
34
56
|
|
35
|
-
Point of interest, the LaunchBar Action makes use of the `-o json` flag for
|
57
|
+
Point of interest, the LaunchBar Action makes use of the `-o json` flag for
|
58
|
+
outputting JSON to the action's script for parsing.
|
36
59
|
|
37
60
|
|
38
61
|
|
39
|
-
See the [doing project on BrettTerpstra.com]
|
62
|
+
See the [doing project on BrettTerpstra.com][bt doing] for the download.
|
40
63
|
|
41
64
|
|
42
65
|
|
43
66
|
|
44
|
-
Evan Lovely has
|
67
|
+
Evan Lovely has created an [Alfred workflow][] as well.
|
45
68
|
|
46
69
|
## Contributing
|
47
70
|
|
48
|
-
If you [create a plugin]
|
49
|
-
|
50
|
-
|
71
|
+
If you [create a plugin][], custom command, or hook you can share, please
|
72
|
+
[let me know][contact]. If I get a few plugin contributions, I'll set up a
|
73
|
+
second repository for them.
|
74
|
+
|
75
|
+
Feel free to fork [the repository][github] on GitHub and make pull requests
|
76
|
+
with changes. Please target the `develop` branch with pull requests.
|
77
|
+
|
78
|
+
[bt doing]: https://brettterpstra.com/projects/doing/
|
79
|
+
[donate]: http://brettterpstra.com/donate/
|
80
|
+
[github]: https://github.com/ttscoff/doing/
|
81
|
+
[wiki]: https://github.com/ttscoff/doing/wiki
|
82
|
+
[doing 2]: https://brettterpstra.com/2021/11/20/doing-2-dot-0/
|
83
|
+
[status bar]: https://brettterpstra.com/2021/10/15/see-what-youre-doing-in-the-iterm-status-bar/
|
84
|
+
[touch bar]: https://brettterpstra.com/2021/07/21/crazy-bettertouchtool-touch-bar-simulator/
|
85
|
+
[create a plugin]: https://github.com/ttscoff/doing/wiki/Creating-Plugins
|
86
|
+
[contact]: https://brettterpstra.com/contact/
|
87
|
+
[alfred workflow]: http://www.evanlovely.com/blog/technology/alfred-for-terpstras-doing/
|
51
88
|
|
52
89
|
|
53
90
|
|
data/doing.gemspec
CHANGED
@@ -41,6 +41,7 @@ spec = Gem::Specification.new do |s|
|
|
41
41
|
s.add_runtime_dependency('tty-which', '~> 0.5', '>= 0.5.0')
|
42
42
|
s.add_runtime_dependency('tty-markdown', '~> 0.7', '>= 0.7.0')
|
43
43
|
s.add_runtime_dependency('tty-reader', '~> 0.9', '>= 0.9.0')
|
44
|
+
s.add_runtime_dependency('tty-screen', '~> 0.8', '>= 0.8.1')
|
44
45
|
s.add_runtime_dependency('parslet', '~> 2.0', '>= 2.0.0')
|
45
46
|
s.add_runtime_dependency('plist', '~> 3.6', '>= 3.6.0')
|
46
47
|
# s.add_runtime_dependency('amatch', '~> 0.4', '>= 0.4.0')
|
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.15
|
9
9
|
|
10
10
|
=== Global Options
|
11
11
|
=== --config_file arg
|
@@ -557,7 +557,7 @@ Section
|
|
557
557
|
[Default Value] None
|
558
558
|
|
559
559
|
|
560
|
-
===== -t|--took INTERVAL
|
560
|
+
===== -t|--took|--for INTERVAL
|
561
561
|
|
562
562
|
Set completion date to start date plus interval (XX[mhd] or HH:MM).
|
563
563
|
If used without the --back option, the start date will be moved back to allow
|
@@ -645,7 +645,7 @@ Finish the last X entries matching search filter, surround with slashes for rege
|
|
645
645
|
[Default Value] None
|
646
646
|
|
647
647
|
|
648
|
-
===== -t|--took INTERVAL
|
648
|
+
===== -t|--took|--for INTERVAL
|
649
649
|
|
650
650
|
Set the completed date to the start date plus XX[hmd]
|
651
651
|
|
data/example_plugin.rb
CHANGED
@@ -152,11 +152,9 @@ module Doing
|
|
152
152
|
finished_at = i.end_date
|
153
153
|
took += finished_at.strftime('%A %B %e at %I:%M%p')
|
154
154
|
|
155
|
-
|
155
|
+
|
156
156
|
took += ' and it took'
|
157
|
-
took +=
|
158
|
-
took += " #{h.to_i} hours" if h.to_i.positive?
|
159
|
-
took += " #{m.to_i} minutes" if m.to_i.positive?
|
157
|
+
took += interval.time_string(format: :natural)
|
160
158
|
end
|
161
159
|
end
|
162
160
|
|
data/lib/completion/_doing.zsh
CHANGED
@@ -106,13 +106,13 @@ function _doing() {
|
|
106
106
|
args=( {-d,--dump}"[DEPRECATED]" {-u,--update}"[DEPRECATED]" )
|
107
107
|
;;
|
108
108
|
done)
|
109
|
-
args=( {-a,--archive}"[Immediately archive the entry]" "(--ask)--ask}[Prompt for note via multi-line input]" "(--at=)--at=}[Set finish date to specific date/time]" "(--started=)--started=}[Backdate start date by interval or set to time [4pm|20m|2h|"yesterday noon"]]" "(--date)--date}[Include date]" {-e,--editor}"[Edit entry with vim]" {-n,--note=}"[Include a note]" {-r,--remove}"[Remove @done tag]" {-s,--section=}"[Section]"
|
109
|
+
args=( {-a,--archive}"[Immediately archive the entry]" "(--ask)--ask}[Prompt for note via multi-line input]" "(--at=)--at=}[Set finish date to specific date/time]" "(--started=)--started=}[Backdate start date by interval or set to time [4pm|20m|2h|"yesterday noon"]]" "(--date)--date}[Include date]" {-e,--editor}"[Edit entry with vim]" {-n,--note=}"[Include a note]" {-r,--remove}"[Remove @done tag]" {-s,--section=}"[Section]" "(--for=)--for=}[Set completion date to start date plus interval]" {-u,--unfinished}"[Finish last entry not already marked @done]" )
|
110
110
|
;;
|
111
111
|
did)
|
112
|
-
args=( {-a,--archive}"[Immediately archive the entry]" "(--ask)--ask}[Prompt for note via multi-line input]" "(--at=)--at=}[Set finish date to specific date/time]" "(--started=)--started=}[Backdate start date by interval or set to time [4pm|20m|2h|"yesterday noon"]]" "(--date)--date}[Include date]" {-e,--editor}"[Edit entry with vim]" {-n,--note=}"[Include a note]" {-r,--remove}"[Remove @done tag]" {-s,--section=}"[Section]"
|
112
|
+
args=( {-a,--archive}"[Immediately archive the entry]" "(--ask)--ask}[Prompt for note via multi-line input]" "(--at=)--at=}[Set finish date to specific date/time]" "(--started=)--started=}[Backdate start date by interval or set to time [4pm|20m|2h|"yesterday noon"]]" "(--date)--date}[Include date]" {-e,--editor}"[Edit entry with vim]" {-n,--note=}"[Include a note]" {-r,--remove}"[Remove @done tag]" {-s,--section=}"[Section]" "(--for=)--for=}[Set completion date to start date plus interval]" {-u,--unfinished}"[Finish last entry not already marked @done]" )
|
113
113
|
;;
|
114
114
|
finish)
|
115
|
-
args=( {-a,--archive}"[Archive entries]" "(--at=)--at=}[Set finish date to specific date/time]" "(--auto)--auto}[Auto-generate finish dates from next entrys start times start time]" {-b,--back=}"[Backdate completed date to date string [4pm|20m|2h|yesterday noon]]" "(--bool=)--bool=}[Boolean]" "(--case=)--case=}[Case sensitivity for search string matching [(c)ase-sensitive]" "(--date)--date}[Include date]" {-i,--interactive}"[Select item(s) to finish from a menu of matching entries]" "(--not)--not}[Finish items that *dont* match search/tag filterst* match search/tag filters]" {-r,--remove}"[Remove done tag]" {-s,--section=}"[Section]" "(--search=)--search=}[Finish the last X entries matching search filter]"
|
115
|
+
args=( {-a,--archive}"[Archive entries]" "(--at=)--at=}[Set finish date to specific date/time]" "(--auto)--auto}[Auto-generate finish dates from next entrys start times start time]" {-b,--back=}"[Backdate completed date to date string [4pm|20m|2h|yesterday noon]]" "(--bool=)--bool=}[Boolean]" "(--case=)--case=}[Case sensitivity for search string matching [(c)ase-sensitive]" "(--date)--date}[Include date]" {-i,--interactive}"[Select item(s) to finish from a menu of matching entries]" "(--not)--not}[Finish items that *dont* match search/tag filterst* match search/tag filters]" {-r,--remove}"[Remove done tag]" {-s,--section=}"[Section]" "(--search=)--search=}[Finish the last X entries matching search filter]" "(--for=)--for=}[Set the completed date to the start date plus XX[hmd]]" "(--tag=)--tag=}[Finish the last X entries containing TAG]" {-u,--unfinished}"[Finish last entry]" "(--val=)--val=}[Perform a tag value query]" {-x,--exact}"[Force exact search string matching]" )
|
116
116
|
;;
|
117
117
|
grep)
|
118
118
|
args=( "(--after=)--after=}[Search entries newer than date]" "(--before=)--before=}[Search entries older than date]" "(--bool=)--bool=}[Combine multiple tags or value queries using AND]" "(--case=)--case=}[Case sensitivity for search string matching [(c)ase-sensitive]" {-d,--delete}"[Delete matching entries]" "(--duration)--duration}[Show elapsed time on entries without @done tag]" {-e,--editor}"[Edit matching entries with vim]" "(--from=)--from=}[Date range to show]" {-i,--interactive}"[Display an interactive menu of results to perform further operations]" "(--not)--not}[Show items that *dont* match search stringt* match search string]" {-o,--output=}"[Output to export format]" "(--only_timed)--only_timed}[Only show items with recorded time intervals]" {-s,--section=}"[Section]" {-t,--times}"[Show time intervals on @done tasks]" "(--tag_sort=)--tag_sort=}[Sort tags by]" "(--totals)--totals}[Show intervals with totals at the end of output]" "(--val=)--val=}[Perform a tag value query]" {-x,--exact}"[Force exact string matching]" )
|
data/lib/completion/doing.bash
CHANGED
@@ -81,9 +81,9 @@ _doing_config() {
|
|
81
81
|
_doing_done() {
|
82
82
|
|
83
83
|
if [[ "$token" == --* ]]; then
|
84
|
-
COMPREPLY=( $( compgen -W '--archive --ask --at --started --date --editor --note --remove --section --
|
84
|
+
COMPREPLY=( $( compgen -W '--archive --ask --at --started --date --editor --note --remove --section --for --unfinished' -- $token ) )
|
85
85
|
elif [[ "$token" == -* ]]; then
|
86
|
-
COMPREPLY=( $( compgen -W '-a -e -n -r -s -
|
86
|
+
COMPREPLY=( $( compgen -W '-a -e -n -r -s -u --archive --ask --at --started --date --editor --note --remove --section --for --unfinished' -- $token ) )
|
87
87
|
|
88
88
|
fi
|
89
89
|
}
|
@@ -91,9 +91,9 @@ _doing_done() {
|
|
91
91
|
_doing_finish() {
|
92
92
|
|
93
93
|
if [[ "$token" == --* ]]; then
|
94
|
-
COMPREPLY=( $( compgen -W '--archive --at --auto --back --bool --case --date --interactive --not --remove --section --search --
|
94
|
+
COMPREPLY=( $( compgen -W '--archive --at --auto --back --bool --case --date --interactive --not --remove --section --search --for --tag --unfinished --val --exact' -- $token ) )
|
95
95
|
elif [[ "$token" == -* ]]; then
|
96
|
-
COMPREPLY=( $( compgen -W '-a -b -i -r -s -
|
96
|
+
COMPREPLY=( $( compgen -W '-a -b -i -r -s -u -x --archive --at --auto --back --bool --case --date --interactive --not --remove --section --search --for --tag --unfinished --val --exact' -- $token ) )
|
97
97
|
|
98
98
|
fi
|
99
99
|
}
|
data/lib/completion/doing.fish
CHANGED
@@ -155,7 +155,7 @@ complete -c doing -l editor -s e -f -n '__fish_doing_using_command done did' -d
|
|
155
155
|
complete -c doing -l note -s n -f -r -n '__fish_doing_using_command done did' -d Include\ a\ note
|
156
156
|
complete -c doing -l remove -s r -f -n '__fish_doing_using_command done did' -d Remove\ @done\ tag
|
157
157
|
complete -c doing -l section -s s -f -r -n '__fish_doing_using_command done did' -d Section
|
158
|
-
complete -c doing -l
|
158
|
+
complete -c doing -l for -f -r -n '__fish_doing_using_command done did' -d Set\ completion\ date\ to\ start\ date\ plus\ interval
|
159
159
|
complete -c doing -l unfinished -s u -f -n '__fish_doing_using_command done did' -d Finish\ last\ entry\ not\ already\ marked\ @done
|
160
160
|
complete -c doing -l archive -s a -f -n '__fish_doing_using_command finish' -d Archive\ entries
|
161
161
|
complete -c doing -l at -f -r -n '__fish_doing_using_command finish' -d Set\ finish\ date\ to\ specific\ date/time
|
@@ -169,7 +169,7 @@ complete -c doing -l not -f -n '__fish_doing_using_command finish' -d Finish\
|
|
169
169
|
complete -c doing -l remove -s r -f -n '__fish_doing_using_command finish' -d Remove\ done\ tag
|
170
170
|
complete -c doing -l section -s s -f -r -n '__fish_doing_using_command finish' -d Section
|
171
171
|
complete -c doing -l search -f -r -n '__fish_doing_using_command finish' -d Finish\ the\ last\ X\ entries\ matching\ search\ filter
|
172
|
-
complete -c doing -l
|
172
|
+
complete -c doing -l for -f -r -n '__fish_doing_using_command finish' -d Set\ the\ completed\ date\ to\ the\ start\ date\ plus\ XX\[hmd\]
|
173
173
|
complete -c doing -l tag -f -r -n '__fish_doing_using_command finish' -d Finish\ the\ last\ X\ entries\ containing\ TAG
|
174
174
|
complete -c doing -l unfinished -s u -f -n '__fish_doing_using_command finish' -d Finish\ last\ entry
|
175
175
|
complete -c doing -l val -f -r -n '__fish_doing_using_command finish' -d Perform\ a\ tag\ value\ query
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doing
|
4
|
+
# Chronify array helpers
|
5
|
+
class ::Array
|
6
|
+
##
|
7
|
+
## Format [d, h, m] as string
|
8
|
+
##
|
9
|
+
## @param time [Array] Array of [days, hours,
|
10
|
+
## minutes]
|
11
|
+
## @param format [Symbol] The format, :dhm, :hm, :m, :clock, :natural
|
12
|
+
## @return [String] formatted string
|
13
|
+
##
|
14
|
+
def time_string(format: :dhm)
|
15
|
+
raise InvalidArgument, 'Invalid array, must be [d,h,m]' unless count == 3
|
16
|
+
|
17
|
+
d, h, m = self
|
18
|
+
case format
|
19
|
+
when :clock
|
20
|
+
format('%<d>02d:%<h>02d:%<m>02d', d: d, h: h, m: m)
|
21
|
+
when :dhm
|
22
|
+
output = []
|
23
|
+
output.push(format('%<d>dd', d: d)) if d.positive?
|
24
|
+
output.push(format('%<h>dh', h: h)) if h.positive?
|
25
|
+
output.push(format('%<m>dm', m: m)) if m.positive?
|
26
|
+
output.join(' ')
|
27
|
+
when :hm
|
28
|
+
h += d * 24 if d.positive?
|
29
|
+
format('%<h> 4dh %<m>02dm', h: h, m: m)
|
30
|
+
when :m
|
31
|
+
h += d * 24 if d.positive?
|
32
|
+
m += h * 60 if h.positive?
|
33
|
+
format('%<m> 4dm', m: m)
|
34
|
+
when :natural
|
35
|
+
human = []
|
36
|
+
human.push(format('%<d>d %<s>s', d: d, s: 'day'.to_p(d))) if d.positive?
|
37
|
+
human.push(format('%<h>d %<s>s', h: h, s: 'hour'.to_p(h))) if h.positive?
|
38
|
+
human.push(format('%<m>d %<s>s', m: m, s: 'minute'.to_p(m))) if m.positive?
|
39
|
+
human.join(', ')
|
40
|
+
when :speech
|
41
|
+
human = []
|
42
|
+
human.push(format('%<d>d %<s>s', d: d, s: 'day'.to_p(d))) if d.positive?
|
43
|
+
human.push(format('%<h>d %<s>s', h: h, s: 'hour'.to_p(h))) if h.positive?
|
44
|
+
human.push(format('%<m>d %<s>s', m: m, s: 'minute'.to_p(m))) if m.positive?
|
45
|
+
last = human.pop
|
46
|
+
case human.count
|
47
|
+
when 2
|
48
|
+
human.join(', ') + ", and #{last}"
|
49
|
+
when 1
|
50
|
+
"#{human[0]} and #{last}"
|
51
|
+
when 0
|
52
|
+
last
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/doing/configuration.rb
CHANGED
@@ -101,7 +101,10 @@ module Doing
|
|
101
101
|
'distance' => 3,
|
102
102
|
'case' => 'smart' # sensitive, ignore, smart
|
103
103
|
},
|
104
|
-
'include_notes' => true
|
104
|
+
'include_notes' => true,
|
105
|
+
'interaction' => {
|
106
|
+
'confirm_longer_than' => '5h'
|
107
|
+
}
|
105
108
|
}
|
106
109
|
|
107
110
|
def initialize(file = nil, options: {})
|
data/lib/doing/item.rb
CHANGED
@@ -57,6 +57,25 @@ module Doing
|
|
57
57
|
@end_date ||= Time.parse(Regexp.last_match(1)) if @title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/
|
58
58
|
end
|
59
59
|
|
60
|
+
def calculate_end_date(opt)
|
61
|
+
if opt[:took]
|
62
|
+
if @date + opt[:took] > Time.now
|
63
|
+
@date = Time.now - opt[:took]
|
64
|
+
Time.now
|
65
|
+
else
|
66
|
+
@date + opt[:took]
|
67
|
+
end
|
68
|
+
elsif opt[:back]
|
69
|
+
if opt[:back].is_a? Integer
|
70
|
+
@date + opt[:back]
|
71
|
+
else
|
72
|
+
@date + (opt[:back] - @date)
|
73
|
+
end
|
74
|
+
else
|
75
|
+
Time.now
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
60
79
|
# Generate a hash that represents the entry
|
61
80
|
#
|
62
81
|
# @return [String] entry hash
|
@@ -112,6 +131,19 @@ module Doing
|
|
112
131
|
(start_a >= start_b && start_a <= end_b) || (end_a >= start_b && end_a <= end_b) || (start_a < start_b && end_a > end_b)
|
113
132
|
end
|
114
133
|
|
134
|
+
##
|
135
|
+
## Updates the title of the Item by expanding natural
|
136
|
+
## language dates within configured date tags (tags
|
137
|
+
## whose value is expected to be a date)
|
138
|
+
##
|
139
|
+
## @param additional_tags An array of additional
|
140
|
+
## tag names to consider
|
141
|
+
## dates
|
142
|
+
##
|
143
|
+
def expand_date_tags(additional_tags = nil)
|
144
|
+
@title.expand_date_tags(additional_tags)
|
145
|
+
end
|
146
|
+
|
115
147
|
##
|
116
148
|
## Add (or remove) tags from the title of the item
|
117
149
|
##
|
data/lib/doing/log_adapter.rb
CHANGED
@@ -52,7 +52,7 @@ module Doing
|
|
52
52
|
COUNT_KEYS.each { |key| @counters[key] = { tag: [], count: 0 } }
|
53
53
|
@results = []
|
54
54
|
@logdev = $stderr
|
55
|
-
@max_length =
|
55
|
+
@max_length = TTY::Screen.columns - 5 || 85
|
56
56
|
self.log_level = level
|
57
57
|
@prev_level = level
|
58
58
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doing
|
4
|
+
##
|
5
|
+
## Number helpers
|
6
|
+
##
|
7
|
+
class ::Numeric
|
8
|
+
##
|
9
|
+
## Format human readable time from seconds
|
10
|
+
##
|
11
|
+
## @param seconds [Integer] Seconds
|
12
|
+
##
|
13
|
+
def format_time(human: false)
|
14
|
+
return [0, 0, 0] if nil?
|
15
|
+
|
16
|
+
seconds = dup.to_i
|
17
|
+
minutes = (seconds / 60).to_i
|
18
|
+
hours = (minutes / 60).to_i
|
19
|
+
if human
|
20
|
+
minutes = (minutes % 60).to_i
|
21
|
+
[0, hours, minutes]
|
22
|
+
else
|
23
|
+
days = (hours / 24).to_i
|
24
|
+
hours = (hours % 24).to_i
|
25
|
+
minutes = (minutes % 60).to_i
|
26
|
+
[days, hours, minutes]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
## Format seconds as natural language time string
|
32
|
+
##
|
33
|
+
## @param format [Symbol] The format to output
|
34
|
+
## (:dhm, :hm, :m, :clock, :natural)
|
35
|
+
##
|
36
|
+
def time_string(format: :dhm)
|
37
|
+
format_time(human: true).time_string(format: format)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -84,7 +84,7 @@ module Doing
|
|
84
84
|
interval ||= false
|
85
85
|
human_time = false
|
86
86
|
if interval
|
87
|
-
d, h, m = wwid.
|
87
|
+
d, h, m = wwid.get_interval(i, formatted: false).format_time
|
88
88
|
human_times = []
|
89
89
|
human_times << format('%<d>d day%<p>s', d: d, p: d == 1 ? '' : 's') if d > 0
|
90
90
|
human_times << format('%<h>d hour%<p>s', h: h, p: h == 1 ? '' : 's') if h > 0
|
@@ -56,7 +56,7 @@ module Doing
|
|
56
56
|
end_date: end_date,
|
57
57
|
title: title.strip, #+ " #{note}"
|
58
58
|
note: note.instance_of?(Array) ? note.to_s : note,
|
59
|
-
time:
|
59
|
+
time: interval.time_string(format: :clock),
|
60
60
|
tags: tags
|
61
61
|
}
|
62
62
|
|
@@ -68,7 +68,7 @@ module Doing
|
|
68
68
|
new_item = {
|
69
69
|
'id' => index + 1,
|
70
70
|
'content' => title.strip, #+ " #{note}"
|
71
|
-
'title' => title.strip + " (#{
|
71
|
+
'title' => title.strip + " (#{interval.time_string(format: :clock)})",
|
72
72
|
'start' => i.date.strftime('%F %T'),
|
73
73
|
'type' => 'box',
|
74
74
|
'style' => 'color:#4c566b;background-color:#d8dee9;'
|
@@ -5,6 +5,7 @@
|
|
5
5
|
# author: Brett Terpstra
|
6
6
|
# url: https://brettterpstra.com
|
7
7
|
module Doing
|
8
|
+
# Template Export
|
8
9
|
class TemplateExport
|
9
10
|
include Doing::Color
|
10
11
|
include Doing::Util
|
@@ -32,7 +33,7 @@ module Doing
|
|
32
33
|
|
33
34
|
placeholders = {}
|
34
35
|
|
35
|
-
if
|
36
|
+
if !item.note.empty? && wwid.config['include_notes']
|
36
37
|
note = item.note.map(&:strip).delete_if(&:empty?)
|
37
38
|
note.map! { |line| "#{line.sub(/^\t*/, '')} " }
|
38
39
|
|
@@ -42,122 +43,74 @@ module Doing
|
|
42
43
|
line.simple_wrap(width)
|
43
44
|
# line.chomp.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n")
|
44
45
|
end
|
45
|
-
note
|
46
|
+
note.delete_if(&:empty?)
|
46
47
|
end
|
47
48
|
else
|
48
49
|
note = []
|
49
50
|
end
|
50
51
|
|
51
|
-
# output.sub!(/%(\d+)?date/) do
|
52
|
-
# pad = Regexp.last_match(1).to_i
|
53
|
-
# format("%#{pad}s", item.date.strftime(opt[:format]))
|
54
|
-
# end
|
55
52
|
placeholders['date'] = item.date.strftime(opt[:format])
|
56
53
|
|
57
54
|
interval = wwid.get_interval(item, record: true, formatted: false) if opt[:times]
|
58
55
|
if interval
|
59
|
-
case opt[:interval_format].to_sym
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
interval = format('%<d>02d:%<h>02d:%<m>02d', d: d, h: h, m: m)
|
66
|
-
end
|
56
|
+
interval = case opt[:interval_format].to_sym
|
57
|
+
when :human
|
58
|
+
interval.time_string(format: :hm)
|
59
|
+
else
|
60
|
+
interval.time_string(format: :clock)
|
61
|
+
end
|
67
62
|
end
|
68
63
|
|
69
64
|
interval ||= ''
|
70
|
-
# output.sub!(/%interval/, interval)
|
71
65
|
placeholders['interval'] = interval
|
72
66
|
|
73
67
|
duration = item.duration if opt[:duration]
|
74
68
|
if duration
|
75
|
-
case opt[:interval_format].to_sym
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
duration = format('%<d>02d:%<h>02d:%<m>02d', d: d, h: h, m: m)
|
82
|
-
end
|
69
|
+
duration = case opt[:interval_format].to_sym
|
70
|
+
when :human
|
71
|
+
duration.time_string(format: :hm)
|
72
|
+
else
|
73
|
+
duration.time_string(format: :clock)
|
74
|
+
end
|
83
75
|
end
|
84
76
|
duration ||= ''
|
85
|
-
# output.sub!(/%duration/, duration)
|
86
77
|
placeholders['duration'] = duration
|
87
78
|
|
88
|
-
|
89
|
-
# pad = Regexp.last_match(1) || 13
|
90
|
-
# format("%#{pad}s", item.date.relative_date)
|
91
|
-
# end
|
92
|
-
placeholders['shortdate'] = format("%13s", item.date.relative_date)
|
93
|
-
# output.sub!(/%section/, item.section) if item.section
|
79
|
+
placeholders['shortdate'] = format('%13s', item.date.relative_date)
|
94
80
|
placeholders['section'] = item.section || ''
|
95
81
|
placeholders['title'] = item.title
|
96
|
-
|
97
|
-
# title_rx = /(?mi)%(?<width>-?\d+)?(?:(?<ichar>[ _t])(?<icount>\d+))?(?<prefix>.[ _t]?)?title(?<after>.*?)$/
|
98
|
-
# title_color = Doing::Color.reset + output.match(/(?mi)^(.*?)(%.*?title)/)[1].last_color
|
99
|
-
|
100
|
-
# title_offset = Doing::Color.uncolor(output).match(title_rx).begin(0)
|
101
|
-
|
102
|
-
# output.sub!(title_rx) do
|
103
|
-
# m = Regexp.last_match
|
104
|
-
|
105
|
-
# after = m['after']
|
106
|
-
# pad = m['width'].to_i
|
107
|
-
# indent = ''
|
108
|
-
# if m['ichar']
|
109
|
-
# char = m['ichar'] =~ /t/ ? "\t" : ' '
|
110
|
-
# indent = char * m['icount'].to_i
|
111
|
-
# end
|
112
|
-
# prefix = m['prefix']
|
113
|
-
# if opt[:wrap_width]&.positive? || pad.positive?
|
114
|
-
# width = pad.positive? ? pad : opt[:wrap_width]
|
115
|
-
# item.title.wrap(width, pad: pad, indent: indent, offset: title_offset, prefix: prefix, color: title_color, after: after, reset: reset)
|
116
|
-
# # flag + item.title.gsub(/(.{#{opt[:wrap_width]}})(?=\s+|\Z)/, "\\1\n ").sub(/\s*$/, '') + reset
|
117
|
-
# else
|
118
|
-
# format("%s%#{pad}s%s", prefix, item.title.sub(/\s*$/, ''), after)
|
119
|
-
# end
|
120
|
-
# end
|
121
|
-
|
122
|
-
|
123
|
-
|
124
82
|
placeholders['note'] = note
|
125
83
|
placeholders['idnote'] = note.empty? ? '' : "\n#{note.map { |l| "\t\t#{l.strip} " }.join("\n")}"
|
126
84
|
placeholders['odnote'] = note.empty? ? '' : "\n#{note.map { |l| "#{l.strip} " }.join("\n")}"
|
127
|
-
placeholders['chompnote'] = note.empty? ? '' : note.map { |l| l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ') }.join(' ')
|
128
|
-
|
129
|
-
# if note.empty?
|
130
|
-
# output.gsub!(/%(chomp|[io]d|(\^.)?(([ _t]|[^a-z0-9])?\d+)?(.[ _t]?)?)?note/, '')
|
131
|
-
# else
|
132
|
-
# output.sub!(/%note/, "\n#{note.map { |l| "\t#{l.strip} " }.join("\n")}")
|
133
|
-
# output.sub!(/%idnote/, "\n#{note.map { |l| "\t\t#{l.strip} " }.join("\n")}")
|
134
|
-
# output.sub!(/%odnote/, "\n#{note.map { |l| "#{l.strip} " }.join("\n")}")
|
135
|
-
# output.sub!(/(?mi)%(?:\^(?<mchar>.))?(?:(?<ichar>[ _t]|[^a-z0-9])?(?<icount>\d+))?(?<prefix>.[ _t]?)?note/) do
|
136
|
-
# m = Regexp.last_match
|
137
|
-
# mark = m['mchar'] || ''
|
138
|
-
# indent = if m['ichar']
|
139
|
-
# char = m['ichar'] =~ /t/ ? "\t" : ' '
|
140
|
-
# char * m['icount'].to_i
|
141
|
-
# else
|
142
|
-
# ''
|
143
|
-
# end
|
144
|
-
# prefix = m['prefix'] || ''
|
145
|
-
# "\n#{note.map { |l| "#{mark}#{indent}#{prefix}#{l.strip} " }.join("\n")}"
|
146
|
-
# end
|
147
|
-
|
148
|
-
# output.sub!(/%chompnote/) do
|
149
|
-
# note.map { |l| l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ') }.join(' ')
|
150
|
-
# end
|
151
|
-
# end
|
152
85
|
|
153
|
-
|
154
|
-
|
155
|
-
|
86
|
+
chompnote = []
|
87
|
+
unless note.empty?
|
88
|
+
chompnote = note.map do |l|
|
89
|
+
l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
placeholders['chompnote'] = chompnote.join(' ')
|
156
93
|
|
157
|
-
|
94
|
+
template = opt[:template].dup
|
95
|
+
note_rx = /(?i-m)(?x:^([\s\S]*?)
|
96
|
+
(%(?:[io]d|(?:\^[\s\S])?
|
97
|
+
(?:(?:[ _t]|[^a-z0-9])?\d+)?
|
98
|
+
(?:[\s\S][ _t]?)?)?note)
|
99
|
+
([\s\S]*?)$)/
|
100
|
+
template.sub!(note_rx, '\1\3\2')
|
101
|
+
output = Doing::TemplateString.new(template,
|
102
|
+
color: flag,
|
103
|
+
placeholders: placeholders,
|
104
|
+
reset: reset,
|
105
|
+
tags_color: opt[:tags_color],
|
106
|
+
wrap_width: opt[:wrap_width]).colored
|
107
|
+
|
108
|
+
output.gsub!(/(?<!\\)%(\S)?hr(_under)?/) do
|
158
109
|
o = ''
|
159
|
-
|
160
|
-
|
110
|
+
TTY::Screen.columns.to_i.times do
|
111
|
+
char = Regexp.last_match(2).nil? ? '-' : '_'
|
112
|
+
char = Regexp.last_match(1).nil? ? char : Regexp.last_match(1)
|
113
|
+
o += char
|
161
114
|
end
|
162
115
|
o
|
163
116
|
end
|
@@ -170,7 +123,11 @@ module Doing
|
|
170
123
|
end
|
171
124
|
|
172
125
|
# Doing.logger.debug('Template Export:', "#{items.count} items output to template #{opt[:template]}")
|
173
|
-
|
126
|
+
if opt[:totals]
|
127
|
+
out += wwid.tag_times(format: wwid.config['timer_format'].to_sym,
|
128
|
+
sort_by_name: opt[:sort_tags],
|
129
|
+
sort_order: opt[:tag_order])
|
130
|
+
end
|
174
131
|
out
|
175
132
|
end
|
176
133
|
|