Hooks in Csup are very different from hooks in Sup.
In Sup, a hook is a piece of Ruby code that Sup evaluates and executes, with some variable context, as if this code were part of Sup itself.
In Csup, a hook is an executable program that is entirely separate from Csup.
A hook is typically a shell script, but could be written in any language, Ruby
being another obvious choice. Hooks live in the directory ~/.csup/hooks
,
and should be marked as executable using chmod +x
.
In order for Csup hooks to work properly, you must change the default shell from dash to bash. Run this command:
sudo dpkg-reconfigure dash
When you are asked whether you want dash to be the default shell, select "No".
On some systems, the above command will not work, so you'll have to change the symbolic link for the shell using these commands:
cd /bin
sudo ln -sf bash sh
When Csup executes a hook, it passes any required parameters and data as one or more lines to the hook's standard input. Csup then reads whatever the hook sends to its standard output, and uses that as the "value" of the hook.
Here is the list of hooks that Csup currently supports.
before-poll
Csup calls this hook just before it calls notmuch new
. This gives the hook the opportunity
to fetch mail, perhaps using fetchmail
. If successful, the hook should return
an exit status of 0; otherwise it should return a non-zero exit status. If the hook
needs to show the user a message about what it did, it should write this message
as a single line to standard output.
If you have already defined a pre-new
hook for Notmuch, you will probably
want to have this hook do nothing but return a zero exit code.
See Notmuch Hook Setup for
more information about the Notmuch pre-new
hook.
Here is a sample ~/.csup/hooks/before-poll
hook:
#!/bin/sh
#fetchmail >>/tmp/fetchmail.log # Do nothing because we already have pre-new
exit 0 # always return 0 because fetchmail returns non-zero if no messages
mime-decode
Csup calls this hook to convert mime-encoded content (typically HTML) to plain text for displaying in a thread view. Csup sends the hook a line containing the content type, followed by the raw content data. If the hook recognizes the content type as something that could be sensibly converted to plain text, it should pass the remainder of the input to the appropriate decoding program, and return the exit status of the decoding program. Otherwise the hook should ignore the content, and return a non-zero exit status.
Here is a sample ~/.csup/hooks/mime-decode
hook:
#!/bin/sh
read type
case $type in
text/html)
cat - | w3m -T text/html -dump
;;
text/plain)
cat
;;
*)
exit 1
;;
esac
mime-view
Csup calls this hook when the user wants to view mime-encoded content (typically PDF or image) in an external program. Csup sends the hook a line containing the content type, followed by the raw content data. If the hook recognizes the content type, is should pass the remainder of the input to the appropriate viewing program, and return the exit status of the viewing program. Otherwise the hook should ignore the content, and return a non-zero exit status.
Here is a sample ~/.csup/hooks/mime-view
hook for Linux Mint that uses
xviewer
to view images, and xreader
to view PDF files. Note that it takes special
care to ensure that the temporary file it creates is always
deleted on exit.
#!/bin/sh
view () {
viewer=$1
t=$(mktemp) || exit 1
trap "rm -f -- '$t'" EXIT
cat >$t
$viewer $t
status=$?
rm -f -- "$t"
trap - EXIT
exit $status
}
read type
case $type in
*/pdf)
view xreader
;;
image/*)
view xviewer
;;
*)
exit 1
;;
esac
signature
Csup calls this hook, if it exists, to fetch signature lines to append
to sent emails. If the hook does not exist, Csup will use
the contents of the signature file named in the signature
part
of the sender's account information in ~/.csup/config.yaml
Here is a ~/.csup/hooks/signature
hook that outputs a random fortune
to be used as a signature.
#!/bin/sh
/usr/games/fortune
forward-attribution
When forwarding or replying to a message, csup mentions the origin of the message by adding attributions to it. The default attribution for forwarding looks like this:
--- Begin forwarded message from John Doe ---
headers and body of the message
--- End forwarded message ---
The forward attribution can be customized in the forward-attribution
hook.
Csup sends the hook a line containing the message's author, followed
by a line containing the message's timestamp (number of seconds since the Epoch).
The hook responds by outputting two lines: the text of the begin line
and the text of the end line.
Here is a sample ~/.csup/hooks/forward-attribution
hook:
#!/usr/bin/env ruby
name = STDIN.gets.strip
timestamp = STDIN.gets.strip.to_i
t = Time.at(timestamp)
puts "--- Start of amazing forwarded message from #{name} of #{t.strftime('%B %H, %Y at %H:%M')} ---"
puts "--- End of amazing forwarded message from #{name} of #{t.strftime('%B %H, %Y at %H:%M')} ---"
attribution
The default attribution for replies looks like this:
Excerpts from Joe Blogg's message of 1 Jan 1999:
The attribution for replies can be customized in the attribution
hook.
As with the forward-attribution
hook,
Csup sends the hook a line containing the message's author, followed
by a line containing the message's timestamp (number of seconds since the Epoch).
The hook responds by outputting the text of the quote line (can be multi-line).
Here is a sample ~/.csup/hooks/attribution
hook:
#!/usr/bin/env ruby
name = STDIN.gets.strip
timestamp = STDIN.gets.strip.to_i
t = Time.at(timestamp)
puts "The Great and Powerful #{name} wrote the following on #{t.strftime('%B %H, %Y at %H:%M')}:"
goto
The g
command in thread view mode looks for a URL in the line under
the cursor, and if it finds one, it sends it to the goto hook. The hook
reads one line containing the URL, then invokes the appropriate browser
program to view the URL.
Here is a sample ~/.csup/hooks/goto
hook:
#!/bin/sh
# The goto hook reads a URL from standard input, then
# runs the appropriate viewer for that URL.
read url
xdg-open "$url"