-
-
Notifications
You must be signed in to change notification settings - Fork 91
Hooks
Hooks allow you to register commands and script to run when doing performs certain actions. You can register the following events:
-
post_config
-- Runs after the main configuration is read, before any local.doingrc
configurations -
post_local_config
-- Runs after local configurations are read and merged into the configuration object -
post_read
-- Runs after the contents of the doing file are parsed -
pre_entry_add
-- Runs when an entry is prepared but before it's added -
post_entry_added
-- Runs after an entry has been added to the index, allows modification -
post_entry_updated
-- Runs when an existing entry is modified -
post_entry_removed
-- Runs after an entry has been deleted -
pre_export
-- Runs when an export is ready but before output, allows modification -
pre_write
-- Runs prior to writing the index to a file, allows modification -
post_write
-- Runs after the contents of the doing file are changed. Does not run unless a modification is made
To register a hook, simply place a Ruby file in your plugins folder. This folder is located at ~/.config/doing/plugins
by default, but you can specify another location in your config using the plugin_path
key.
The ruby file should contain a call to register the hook. Pass a block to perform when the associated event is triggered.
The register method takes an optional priority:
argument containing an integer. If multiple hooks are registered, they will be executed in order of priority, lowest to highest.
Doing::Hooks.register :post_read, priority: 20 do { |wwid| ... }
The following runs a shell script called after_doing.sh
whenever a change is made to the doing file (post_write
event):
# frozen_string_literal: true
Doing::Hooks.register :post_write do |filename|
res = `/bin/bash ~/scripts/after_doing.sh`.strip
Doing.logger.debug('Hooks:', res)
end
That's all there is to it. As an example, I use the above shell script to update my iTerm status bar and my Touch Bar (BetterTouchTool widget) with my current task whenever the file changes. Any time I add or complete an entry, my status bars update.
The post_config hook receives the Doing::WWID object. This contains the @config hash and has access to all of the WWID methods. Changes made to the object within the block will carry through to the current doing operation.
If you modify the configuration variable, the changes will be incorporated into the current operation but will not be saved. If you want to save the modified configuration, use wwid.write_config to save it to a file. This will overwrite your current configuration with whatever you've done to the wwid.configuration object, so be careful. You can provide a filename argument to wwid.write to write to a different file than the primary config, e.g. (wwid.write_config(File.expand_path('~/configuration.yml'))
).
Doing::Hooks.register :post_config do |wwid|
wwid.config['new config key'] = 'My new value'
end
The post_local_config hook runs after local .doingrc
files are merged into the configuration. Keys from these files are not written out to any configurations by default, so performing any destructive file write operations in this hook is discouraged.
Doing::Hooks.register :post_config do |wwid|
wwid.config['new config key'] = 'My new value'
end
The post_read hook receives the current Doing::WWID object. This includes the @content object. wwid.content
acts like an Array of items. Each item has values for date(Date), title(String), section(String), and note(Note < Array). Additionally, there's a wwid.content.sections
attribute containing an array of section titles.
The items found in wwid.content have a variety of methods for testing whether they match search strings or tag filters (see the #tags?
and #search
methods), as well as for adding tags and modifying them. Modifications made to items by your hook will be passed on and saved when the file writes out at the end of a command. Not all commands write to disk, though; commands like show
and view
never save changes.
Doing::Hooks.register :post_read do |wwid|
Doing.logger.info('Hook:', wwid.content.keys)
end
Called before every item is added, and receives the WWID object and the new entry, which can be modified before it's added.
Doing::Hooks.register :post_entry_add do |wwid, entry|
if entry.tags?('hooked')
entry.tag('addhook')
end
end
Or make entry of a note optional when adding new items without one:
Hooks.register :pre_entry_add do |wwid, entry|
if entry.note.empty?
res = Doing::Prompt.yn('Want to add a note?', default_response: false)
if res
note = Doing::Prompt.enter_text('Enter note')
entry.note.add(note) unless note.empty?
end
end
end
Called after adding a new entry, receives the WWID object and a copy of the added entry.
Hooks.register :post_entry_added do |wwid, entry|
# Do something with the new entry, such as setting an environment variable
# that you can use in your prompt. Changes to the entry variable will not be
# saved.
end
Called after an existing entry is modified, receives the WWID object and the modified entry (which can be modified)
Hooks.register :post_entry_updated do |wwid, entry|
# entry (Item) can be modified and changes will be saved
end
Called after removing an entry, receives the WWID object and a copy of the removed entry
Called before any output operation, receives the WWID object, the output format, and the array of entries (which can be modified, but modifications will only affect the output, not the doing file content)
The pre_write hook receives the WWID object and the filename that is going to be written. Modifications made to the WWID.content object at this point will be written out to filename
(and thus permanently saved).
Doing::Hooks.register :pre_write do |wwid, filename|
return unless filename == wwid.config['doing_file']
wwid.content.each do |section, content|
content[:items].each do |i|
# If any item has @test AND @todo tags, add @hooktest
if i.tags?(['test', 'todo'], :and)
i.tag('hooktest')
end
end
end
end
The post_write hook receives the filename that was saved to.
If you want to see what changed, you can use WWID.new.get_diff(filename)
. Note that this does a line-by-line diff between the current Doing file and the most recent backup, so it can be slow and will introduce a couple of seconds wait after any command that updates the doing file. :get_diff
returns an Items object (which is an array of Items, each with date, title, note, and section, plus its own ).
Doing::Hooks.register :post_write do |filename|
`~/scripts/btt_stats.rb refresh doing`
# This is what I use to update things like my
# BetterTouchTool widgets and my iTerm status bar.
end