doing 1.0.92 → 2.0.5.pre
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/AUTHORS +19 -0
- data/CHANGELOG.md +596 -0
- data/COMMANDS.md +1181 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +110 -0
- data/LICENSE +23 -0
- data/README.md +15 -699
- data/Rakefile +79 -0
- data/_config.yml +1 -0
- data/bin/doing +1012 -486
- data/doing.fish +278 -0
- data/doing.gemspec +34 -0
- data/doing.rdoc +1759 -0
- data/example_plugin.rb +209 -0
- data/generate_completions.sh +4 -0
- data/img/doing-colors.jpg +0 -0
- data/img/doing-printf-wrap-800.jpg +0 -0
- data/img/doing-show-note-formatting-800.jpg +0 -0
- data/lib/completion/_doing.zsh +151 -0
- data/lib/completion/doing.bash +416 -0
- data/lib/completion/doing.fish +278 -0
- data/lib/doing/array.rb +8 -0
- data/lib/doing/cli_status.rb +66 -0
- data/lib/doing/colors.rb +136 -0
- data/lib/doing/configuration.rb +312 -0
- data/lib/doing/errors.rb +102 -0
- data/lib/doing/hash.rb +31 -0
- data/lib/doing/hooks.rb +59 -0
- data/lib/doing/item.rb +155 -0
- data/lib/doing/log_adapter.rb +342 -0
- data/lib/doing/markdown_document_listener.rb +174 -0
- data/lib/doing/note.rb +59 -0
- data/lib/doing/pager.rb +95 -0
- data/lib/doing/plugin_manager.rb +208 -0
- data/lib/doing/plugins/export/csv_export.rb +48 -0
- data/lib/doing/plugins/export/html_export.rb +83 -0
- data/lib/doing/plugins/export/json_export.rb +140 -0
- data/lib/doing/plugins/export/markdown_export.rb +85 -0
- data/lib/doing/plugins/export/taskpaper_export.rb +34 -0
- data/lib/doing/plugins/export/template_export.rb +141 -0
- data/lib/doing/plugins/import/cal_to_json.scpt +0 -0
- data/lib/doing/plugins/import/calendar_import.rb +76 -0
- data/lib/doing/plugins/import/doing_import.rb +144 -0
- data/lib/doing/plugins/import/timing_import.rb +78 -0
- data/lib/doing/string.rb +347 -0
- data/lib/doing/symbol.rb +16 -0
- data/lib/doing/time.rb +18 -0
- data/lib/doing/util.rb +186 -0
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +1868 -2356
- data/lib/doing/wwidfile.rb +117 -0
- data/lib/doing.rb +44 -4
- data/lib/examples/commands/wiki.rb +81 -0
- data/lib/examples/plugins/hooks.rb +22 -0
- data/lib/examples/plugins/say_export.rb +202 -0
- data/lib/examples/plugins/templates/wiki.css +169 -0
- data/lib/examples/plugins/templates/wiki.haml +27 -0
- data/lib/examples/plugins/templates/wiki_index.haml +18 -0
- data/lib/examples/plugins/wiki_export.rb +87 -0
- data/lib/templates/doing-markdown.erb +5 -0
- data/man/doing.1 +964 -0
- data/man/doing.1.html +711 -0
- data/man/doing.1.ronn +600 -0
- data/package-lock.json +3 -0
- data/rdoc_to_mmd.rb +42 -0
- data/rdocfixer.rb +13 -0
- data/scripts/generate_bash_completions.rb +210 -0
- data/scripts/generate_fish_completions.rb +201 -0
- data/scripts/generate_zsh_completions.rb +164 -0
- metadata +82 -7
- data/lib/doing/helpers.rb +0 -191
- data/lib/doing/markdown_export.rb +0 -16
data/example_plugin.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# title: Export plugin example
|
4
|
+
# description: Speak the most recent entry (macOS)
|
5
|
+
# author: Brett Terpstra
|
6
|
+
# url: https://brettterpstra.com
|
7
|
+
|
8
|
+
# Example
|
9
|
+
#
|
10
|
+
# doing show -o sayit
|
11
|
+
#
|
12
|
+
# ## Configuration
|
13
|
+
#
|
14
|
+
# Change what the plugin says by generating a template with
|
15
|
+
# `doing template --type say`, saving it to a file, and
|
16
|
+
# putting the path to that file in `export_templates->say` in
|
17
|
+
# .doingrc.
|
18
|
+
#
|
19
|
+
# export_templates:
|
20
|
+
# say: /path/to/template.txt
|
21
|
+
#
|
22
|
+
# Use a different voice by adding a `say_voice` key to your
|
23
|
+
# .doingrc. Use `say -v ?` to see available voices.
|
24
|
+
#
|
25
|
+
# say_voice: Zarvox
|
26
|
+
|
27
|
+
module Doing
|
28
|
+
##
|
29
|
+
## @brief Plugin class
|
30
|
+
##
|
31
|
+
class SayExport
|
32
|
+
include Doing::Util
|
33
|
+
|
34
|
+
#-------------------------------------------------------
|
35
|
+
## Plugin Settings. A plugin must have a self.settings
|
36
|
+
## method that returns a hash with plugin settings.
|
37
|
+
##
|
38
|
+
## trigger: (required) Regular expression to match
|
39
|
+
## FORMAT when used with `--output FORMAT`. Registered
|
40
|
+
## name of plugin must be able to match the trigger, but
|
41
|
+
## alternatives can be included
|
42
|
+
##
|
43
|
+
## templates: (optional) Array of templates this plugin
|
44
|
+
## can export (plugin must have :template method)
|
45
|
+
##
|
46
|
+
## Each template is a hash containing:
|
47
|
+
## - name: display name for template
|
48
|
+
## - trigger: regular expression for
|
49
|
+
## `template --type FORMAT`
|
50
|
+
##
|
51
|
+
## If a template is included, a config key will
|
52
|
+
## automatically be added for the user to override
|
53
|
+
## The config key will be available at:
|
54
|
+
##
|
55
|
+
## wwid.config['export_templates'][PLUGIN_NAME]
|
56
|
+
##
|
57
|
+
## config: (optional) A Hash which will be
|
58
|
+
## added to the main configuration in the plugins section.
|
59
|
+
## Options defined here are included when config file is
|
60
|
+
## created or updated with `config --update`. Use this to
|
61
|
+
## add new configuration keys, not to override existing
|
62
|
+
## ones.
|
63
|
+
##
|
64
|
+
## The configuration keys will be available at:
|
65
|
+
##
|
66
|
+
## wwid.config['plugins'][PLUGIN_NAME][KEY]
|
67
|
+
##
|
68
|
+
## @brief Method to return plugin settings (required)
|
69
|
+
##
|
70
|
+
## @return Hash of settings for this plugin
|
71
|
+
##
|
72
|
+
def self.settings
|
73
|
+
{
|
74
|
+
trigger: 'say(?:it)?',
|
75
|
+
templates: [
|
76
|
+
{ name: 'say', trigger: 'say(?:it)?' }
|
77
|
+
],
|
78
|
+
config: {
|
79
|
+
'say_voice' => 'Fiona'
|
80
|
+
}
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
#-------------------------------------------------------
|
86
|
+
## Output a template. Only required if template(s) are
|
87
|
+
## included in settings. The method should return a
|
88
|
+
## string (not output it to the STDOUT).
|
89
|
+
##
|
90
|
+
## @brief Method to return template (optional)
|
91
|
+
##
|
92
|
+
## @param trigger The trigger passed to the
|
93
|
+
## template function. When this
|
94
|
+
## method defines multiple
|
95
|
+
## templates, the trigger can be
|
96
|
+
## used to determine which one is
|
97
|
+
## output.
|
98
|
+
##
|
99
|
+
## @return (String) template contents
|
100
|
+
##
|
101
|
+
def self.template(trigger)
|
102
|
+
return unless trigger =~ /^say(it)?$/
|
103
|
+
|
104
|
+
'On %date, you were %title, recorded in section %section%took'
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
##
|
109
|
+
## @brief Render data received from an output
|
110
|
+
## command
|
111
|
+
##
|
112
|
+
## @param wwid The wwid object with config
|
113
|
+
## and public methods
|
114
|
+
## @param items An array of items to be output
|
115
|
+
## { <Date>date, <String>title,
|
116
|
+
## <String>section, <Array>note }
|
117
|
+
## @param variables Additional variables including
|
118
|
+
## flags passed to command
|
119
|
+
## (variables[:options])
|
120
|
+
##
|
121
|
+
## @return (String) Rendered output
|
122
|
+
##
|
123
|
+
def self.render(wwid, items, variables: {})
|
124
|
+
return if items.nil? || items.empty?
|
125
|
+
|
126
|
+
# the :options key includes the flags passed to the
|
127
|
+
# command that called the plugin use `puts
|
128
|
+
# variables.inspect` to see properties and methods
|
129
|
+
# when run
|
130
|
+
opt = variables[:options]
|
131
|
+
|
132
|
+
# This plugin just grabs the last item in the `items`
|
133
|
+
# list (which could be the oldest or newest, depending
|
134
|
+
# on the sort order of the command that called the
|
135
|
+
# plugin). Most of the time you'll want to use :each
|
136
|
+
# or :map to generate output.
|
137
|
+
i = items[-1]
|
138
|
+
|
139
|
+
# Format the item. Items are a hash with 4 keys: date,
|
140
|
+
# title, section (parent section), and note. Start
|
141
|
+
# time is in item.date. The wwid object has some
|
142
|
+
# methods for calculation and formatting, including
|
143
|
+
# wwid.item.end_date to convert the @done timestamp to
|
144
|
+
# an end date.
|
145
|
+
if opt[:times]
|
146
|
+
interval = i.interval
|
147
|
+
|
148
|
+
if interval
|
149
|
+
took = '. You finished on '
|
150
|
+
finished_at = i.end_date
|
151
|
+
took += finished_at.strftime('%A %B %e at %I:%M%p')
|
152
|
+
|
153
|
+
d, h, m = wwid.format_time(interval)
|
154
|
+
took += ' and it took'
|
155
|
+
took += " #{d.to_i} days" if d.to_i.positive?
|
156
|
+
took += " #{h.to_i} hours" if h.to_i.positive?
|
157
|
+
took += " #{m.to_i} minutes" if m.to_i.positive?
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
date = i.date.strftime('%A %B %e at %I:%M%p')
|
162
|
+
title = i.title.gsub(/@/, 'hashtag ')
|
163
|
+
tpl = template('say')
|
164
|
+
|
165
|
+
if wwid.config['export_templates'].key?('say')
|
166
|
+
cfg_tpl = wwid.config['export_templates']['say']
|
167
|
+
tpl = cfg_tpl unless cfg_tpl.nil? || cfg_tpl.empty?
|
168
|
+
end
|
169
|
+
output = tpl.dup
|
170
|
+
output.gsub!(/%date/, date)
|
171
|
+
output.gsub!(/%title/, title)
|
172
|
+
output.gsub!(/%section/, i.section)
|
173
|
+
output.gsub!(/%took/, took || '')
|
174
|
+
|
175
|
+
# Debugging output
|
176
|
+
# warn "Saying: #{output}"
|
177
|
+
|
178
|
+
# To provide results on the command line after the
|
179
|
+
# command runs, use Doing.logger, which responds to
|
180
|
+
# :debug, :info, :warn, and :error. e.g.:
|
181
|
+
#
|
182
|
+
# Doing.logger.info("This plugin has run")
|
183
|
+
# Doing.logger.error("This message will be displayed even if run in --quiet mode.")
|
184
|
+
#
|
185
|
+
# Results are
|
186
|
+
# provided on STDERR unless doing is run with
|
187
|
+
# `--stdout` or non-interactively.
|
188
|
+
Doing.logger.info('Spoke the last entry. Did you hear it?')
|
189
|
+
|
190
|
+
# This export runs a command for fun, most plugins won't
|
191
|
+
voice = wwid.config['plugins']['say']['say_voice'] || 'Alex'
|
192
|
+
`say -v "#{voice}" "#{output}"`
|
193
|
+
|
194
|
+
# Return the result (don't output to terminal with puts or print)
|
195
|
+
output
|
196
|
+
end
|
197
|
+
|
198
|
+
# Register the plugin with doing.
|
199
|
+
# Doing::Plugins.register 'NAME', TYPE, Class
|
200
|
+
#
|
201
|
+
# Name should be lowercase, no spaces
|
202
|
+
#
|
203
|
+
# TYPE is :import or :export
|
204
|
+
#
|
205
|
+
# Class is the plugin class (e.g. Doing::SayExport), or
|
206
|
+
# self if called within the class
|
207
|
+
Doing::Plugins.register 'say', :export, self
|
208
|
+
end
|
209
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,151 @@
|
|
1
|
+
#compdef doing
|
2
|
+
|
3
|
+
local ret=1 state
|
4
|
+
|
5
|
+
_arguments \
|
6
|
+
':subcommand:->subcommand' \
|
7
|
+
'*::options:->options' && ret=0
|
8
|
+
|
9
|
+
case $state in
|
10
|
+
subcommand)
|
11
|
+
local -a subcommands
|
12
|
+
subcommands=(
|
13
|
+
'help:Shows a list of commands or help for one command'
|
14
|
+
'now:Add an entry'
|
15
|
+
'note:Add a note to the last entry'
|
16
|
+
'meanwhile:Finish any running @meanwhile tasks and optionally create a new one'
|
17
|
+
'later:Add an item to the Later section'
|
18
|
+
'done:Add a completed item with @done(date). No argument finishes last entry.'
|
19
|
+
'finish:Mark last X entries as @done'
|
20
|
+
'tag:Tag last entry'
|
21
|
+
'mark:Mark last entry as highlighted'
|
22
|
+
'show:List all entries'
|
23
|
+
'grep:Search for entries'
|
24
|
+
'recent:List recent entries'
|
25
|
+
'today:List entries from today'
|
26
|
+
'yesterday:List entries from yesterday'
|
27
|
+
'last:Show the last entry'
|
28
|
+
'sections:List sections'
|
29
|
+
'choose:Select a section to display from a menu'
|
30
|
+
'add_section:Add a new section to the "doing" file'
|
31
|
+
'view:Display a user-created view'
|
32
|
+
'views:List available custom views'
|
33
|
+
'archive:Move entries in between sections'
|
34
|
+
'open:Open the "doing" file in an editor'
|
35
|
+
'config:Edit the configuration file'
|
36
|
+
'undo:Undo the last change to the doing_file'
|
37
|
+
)
|
38
|
+
_describe -t subcommands 'doing subcommand' subcommands && ret=0
|
39
|
+
;;
|
40
|
+
|
41
|
+
options)
|
42
|
+
age=({-a,--age=}"[Age (oldest/newest) (default: newest)]")
|
43
|
+
app=({-a,--app=}"[Edit entry with specified app (default: none)")
|
44
|
+
archive=({-a,--archive}"[Archive previous @meanwhile entry]")
|
45
|
+
back="--back=[Backdate start time (4pm|20m|2h|yesterday noon) (default: none)]"
|
46
|
+
boolean=({-b,--boolean=}"[Tag boolean (AND,OR,NONE) (default: OR)]")
|
47
|
+
bool=({-b,--bool=}"[Tag boolean (default: AND)]")
|
48
|
+
count=({-c,--count=}"[How many recent entries to tag (default: 1)]")
|
49
|
+
count=({-c,--count=}"[Max count to show (default: 0)]")
|
50
|
+
date=({-d,--date}"[Include date (default: enabled)]")
|
51
|
+
editor=( {-e,--editor}"[Edit entry with $EDITOR]")
|
52
|
+
finish=({-f,--finish_last}"[Timed entry, marks last entry in section as @done]")
|
53
|
+
file=({-f,--file=}"[Specify alternate doing file (default: none)]")
|
54
|
+
noarchive="--no-archive[Don't archive previous @meanwhile entry]"
|
55
|
+
nodate="--no-date[Don't include date]"
|
56
|
+
noeditor="--no-editor[Don't edit entry with $EDITOR]"
|
57
|
+
note=({-n,--note=}"[Note (default: none)]")
|
58
|
+
notimes="--no-times[Don't show time intervals on @done tasks.]"
|
59
|
+
nototals="--no-totals[Don't show intervals with totals at the end of output]"
|
60
|
+
output=({-o,--output=}"[Output to export format (csv|html) (default: none)]")
|
61
|
+
remove=({-r,--remove}"[Replace/Remove last entry's note]")
|
62
|
+
section=({-s,--section=}"[Section (default: Currently)]")
|
63
|
+
sort=({-s,--sort=}"[Sort order (asc/desc) (default: asc)]")
|
64
|
+
times=({-t,--times}"[Show time intervals on @done tasks (default: enabled)]")
|
65
|
+
took=({-t,--took=}"[Set completion date to start date plus XX(mhd) or (HH:MM) (default: none)]")
|
66
|
+
totals="--totals[Show intervals with totals at the end of output]"
|
67
|
+
|
68
|
+
case $words[1] in
|
69
|
+
now)
|
70
|
+
args=( $back $noeditor $editor $note $section $finish )
|
71
|
+
;;
|
72
|
+
|
73
|
+
note)
|
74
|
+
args=( $section $editor $remove )
|
75
|
+
;;
|
76
|
+
|
77
|
+
meanwhile)
|
78
|
+
args=( $back $noeditor $editor $note $section $archive $noarchive )
|
79
|
+
;;
|
80
|
+
|
81
|
+
later)
|
82
|
+
args=( $back $noeditor $editor $note $app )
|
83
|
+
;;
|
84
|
+
|
85
|
+
done)
|
86
|
+
args=( $back $took $section $remove $date $nodate $archive $editor $noeditor )
|
87
|
+
;;
|
88
|
+
|
89
|
+
finish)
|
90
|
+
args=( $back $took $section $date $nodate $archive $editor $noeditor )
|
91
|
+
;;
|
92
|
+
|
93
|
+
tag)
|
94
|
+
args=( $section $count $date $remove )
|
95
|
+
;;
|
96
|
+
|
97
|
+
mark)
|
98
|
+
args=( $section $remove )
|
99
|
+
;;
|
100
|
+
|
101
|
+
show)
|
102
|
+
args=( $boolean $count $age $sort $output $times $notimes $totals $nototals )
|
103
|
+
;;
|
104
|
+
|
105
|
+
grep)
|
106
|
+
args=( $section $output $times $notimes $totals $nototals )
|
107
|
+
;;
|
108
|
+
|
109
|
+
recent)
|
110
|
+
args=( $section $times $notimes $totals $nototals )
|
111
|
+
;;
|
112
|
+
|
113
|
+
today)
|
114
|
+
args=( $output $times $notimes $totals $nototals )
|
115
|
+
;;
|
116
|
+
|
117
|
+
yesterday)
|
118
|
+
args=( $output $times $notimes $totals $nototals )
|
119
|
+
;;
|
120
|
+
|
121
|
+
view)
|
122
|
+
args=( $section $count $output $times $notimes $totals $nototals )
|
123
|
+
;;
|
124
|
+
|
125
|
+
archive)
|
126
|
+
args=( $keep $to $bool )
|
127
|
+
;;
|
128
|
+
|
129
|
+
open)
|
130
|
+
args=(
|
131
|
+
"-a [open with app name (default:none)"
|
132
|
+
"-b [open with app bundle id (default: none)"
|
133
|
+
"-e [open with $EDITOR]"
|
134
|
+
)
|
135
|
+
;;
|
136
|
+
|
137
|
+
config)
|
138
|
+
args=( $editor )
|
139
|
+
;;
|
140
|
+
|
141
|
+
undo)
|
142
|
+
args=( $file )
|
143
|
+
;;
|
144
|
+
|
145
|
+
esac
|
146
|
+
|
147
|
+
_arguments $args && ret=0
|
148
|
+
;;
|
149
|
+
esac
|
150
|
+
|
151
|
+
return ret
|