doing 1.0.91 → 2.0.3.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHORS +19 -0
  3. data/CHANGELOG.md +590 -0
  4. data/COMMANDS.md +1181 -0
  5. data/Gemfile +2 -0
  6. data/Gemfile.lock +110 -0
  7. data/LICENSE +23 -0
  8. data/README.md +15 -699
  9. data/Rakefile +79 -0
  10. data/_config.yml +1 -0
  11. data/bin/doing +1012 -486
  12. data/doing.fish +278 -0
  13. data/doing.gemspec +34 -0
  14. data/doing.rdoc +1759 -0
  15. data/example_plugin.rb +209 -0
  16. data/generate_completions.sh +4 -0
  17. data/img/doing-colors.jpg +0 -0
  18. data/img/doing-printf-wrap-800.jpg +0 -0
  19. data/img/doing-show-note-formatting-800.jpg +0 -0
  20. data/lib/completion/_doing.zsh +151 -0
  21. data/lib/completion/doing.bash +416 -0
  22. data/lib/completion/doing.fish +278 -0
  23. data/lib/doing/array.rb +8 -0
  24. data/lib/doing/cli_status.rb +66 -0
  25. data/lib/doing/colors.rb +136 -0
  26. data/lib/doing/configuration.rb +310 -0
  27. data/lib/doing/errors.rb +102 -0
  28. data/lib/doing/hash.rb +31 -0
  29. data/lib/doing/hooks.rb +59 -0
  30. data/lib/doing/item.rb +155 -0
  31. data/lib/doing/log_adapter.rb +342 -0
  32. data/lib/doing/markdown_document_listener.rb +174 -0
  33. data/lib/doing/note.rb +59 -0
  34. data/lib/doing/pager.rb +95 -0
  35. data/lib/doing/plugin_manager.rb +208 -0
  36. data/lib/doing/plugins/export/csv_export.rb +48 -0
  37. data/lib/doing/plugins/export/html_export.rb +83 -0
  38. data/lib/doing/plugins/export/json_export.rb +140 -0
  39. data/lib/doing/plugins/export/markdown_export.rb +85 -0
  40. data/lib/doing/plugins/export/taskpaper_export.rb +34 -0
  41. data/lib/doing/plugins/export/template_export.rb +141 -0
  42. data/lib/doing/plugins/import/cal_to_json.scpt +0 -0
  43. data/lib/doing/plugins/import/calendar_import.rb +76 -0
  44. data/lib/doing/plugins/import/doing_import.rb +144 -0
  45. data/lib/doing/plugins/import/timing_import.rb +78 -0
  46. data/lib/doing/string.rb +346 -0
  47. data/lib/doing/symbol.rb +16 -0
  48. data/lib/doing/time.rb +18 -0
  49. data/lib/doing/util.rb +186 -0
  50. data/lib/doing/version.rb +1 -1
  51. data/lib/doing/wwid.rb +1831 -2358
  52. data/lib/doing/wwidfile.rb +117 -0
  53. data/lib/doing.rb +44 -4
  54. data/lib/examples/commands/wiki.rb +80 -0
  55. data/lib/examples/plugins/hooks.rb +22 -0
  56. data/lib/examples/plugins/say_export.rb +202 -0
  57. data/lib/examples/plugins/templates/wiki.css +169 -0
  58. data/lib/examples/plugins/templates/wiki.haml +27 -0
  59. data/lib/examples/plugins/templates/wiki_index.haml +18 -0
  60. data/lib/examples/plugins/wiki_export.rb +87 -0
  61. data/lib/templates/doing-markdown.erb +5 -0
  62. data/man/doing.1 +964 -0
  63. data/man/doing.1.html +711 -0
  64. data/man/doing.1.ronn +600 -0
  65. data/package-lock.json +3 -0
  66. data/rdoc_to_mmd.rb +42 -0
  67. data/rdocfixer.rb +13 -0
  68. data/scripts/generate_bash_completions.rb +210 -0
  69. data/scripts/generate_fish_completions.rb +201 -0
  70. data/scripts/generate_zsh_completions.rb +164 -0
  71. metadata +82 -6
  72. data/lib/doing/helpers.rb +0 -191
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.fmt_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
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+
3
+ scripts/generate_fish_completions.rb > lib/completion/doing.fish
4
+ scripts/generate_bash_completions.rb > lib/completion/doing.bash
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