[PATCH] cli: add a tool for starting new message in the emacs ui
Jani Nikula
jani at nikula.org
Wed Mar 19 14:54:15 PDT 2014
On Wed, 19 Mar 2014, Tomi Ollila <tomi.ollila at iki.fi> wrote:
> On Wed, Mar 19 2014, Jani Nikula <jani at nikula.org> wrote:
>
>> Add a tool to start composing an email in the Notmuch Emacs UI with
>> the specified subject, recipients, and message body.
>>
>> ---
>>
>> I need something like this to script some mails, particularly with the
>> mutt compatible options, but I also think notmuch must have long
>> options. I then got a little carried away with figuring out how to
>> support both. I think it turned out pretty neat, except due to some
>> subtlety it only works with bash.
>>
>> I didn't integrate this in the man build or install or anything,
>> because I wanted to get feedback first on whether we want to have this
>> at all. Or if it should live in contrib or something.
>>
>> BR,
>> Jani.
>> ---
>
> Quick glance to the code and some thoughts.
Thanks!
>
>> doc/man1/notmuch-emacs-mua.rst | 50 ++++++++++++++++++
>> notmuch-emacs-mua | 113 +++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 163 insertions(+)
>> create mode 100644 doc/man1/notmuch-emacs-mua.rst
>> create mode 100755 notmuch-emacs-mua
>>
>> diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst
>> new file mode 100644
>> index 000000000000..6e63818492fb
>> --- /dev/null
>> +++ b/doc/man1/notmuch-emacs-mua.rst
>> @@ -0,0 +1,50 @@
>> +=================
>> +notmuch-emacs-mua
>> +=================
>> +
>> +SYNOPSIS
>> +========
>> +
>> +**notmuch-emacs-mua** [options ...] [<to-address> ...]
>> +
>> +DESCRIPTION
>> +===========
>> +
>> +Start composing an email in the Notmuch Emacs UI with the specified
>> +subject, recipients, and message body.
>> +
>> +For **notmuch-emacs-mua** to work, you need **emacsclient** and an
>> +already running Emacs with a server.
>> +
>> +Supported options for **notmuch-emacs-mua** include
>> +
>> + ``-h, --help``
>> + Display help.
>> +
>> + ``-s, --subject=``\ <subject>
>> + Specify the subject of the message.
>> +
>> + ``--to=``\ <to-address>
>> + Specify a recipient (To).
>> +
>> + ``-c, --cc=``\ <cc-address>
>> + Specify a carbon-copy (Cc) recipient.
>> +
>> + ``-b, --bcc=``\ <bcc-address>
>> + Specify a blind-carbon-copy (Bcc) recipient.
>> +
>> + ``-i, --body=``\ <file>
>> + Specify a file to include into the body of the message.
>> +
>> + ``--print``
>> + Output the resulting elisp to stdout instead of evaluating it.
>> +
>> +The supported positional parameters and short options are a compatible
>> +subset of the **mutt** MUA command-line options.
>> +
>> +Options may be specified multiple times.
>> +
>> +SEE ALSO
>> +========
>> +
>> +**notmuch(1)**, **emacsclient(1)**, **mutt(1)**
>
> It would be convenient to the user to have the manual embedded in
> the script in case no args are given or so (or that is convenient
> to me ;) and no namual page at all...
If this is to become part of notmuch, I think a separate man page is in
order. Otherwise, agreed (and even had that in an earlier version).
>
>> diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua
>> new file mode 100755
>> index 000000000000..a482fe1a8eca
>> --- /dev/null
>> +++ b/notmuch-emacs-mua
>> @@ -0,0 +1,113 @@
>> +#!/bin/bash
>
> #!/usr/bin/env bash
Agreed.
>
>> +#
>> +# notmuch-emacs-mua - start composing a mail on the command line
>> +#
>> +# Copyright © 2014 Jani Nikula
>> +#
>> +# This program is free software: you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License as published by
>> +# the Free Software Foundation, either version 3 of the License, or
>> +# (at your option) any later version.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program. If not, see http://www.gnu.org/licenses/ .
>> +#
>> +# Authors: Jani Nikula <jani at nikula.org>
>> +#
>> +
>> +set -e
>
> set -eu would be nice IMO...
>
> ... then initialize all vars to empty strings, like PRINT_ONLY=
> ... and in cases not possible syntax ${1-} can be used.
Agreed.
>
>> +
>> +# The crux of it all: construct an elisp progn and eval it.
>> +ELISP="(progn (notmuch-mua-new-mail)"
>
> ELISP="(progn (require 'notmuch) (notmuch-mua-new-mail)"
Right.
>
>> +
>> +while getopts :s:c:b:i:h opt; do
>> + # Handle errors and long options.
>> + case "${opt}" in
>> + :)
>> + echo "$0: short option -${OPTARG} requires an argument." >&2
>> + exit 1
>> + ;;
>> + \?)
>> + opt=$1
>> + if [ "${OPTARG}" != "-" ]; then
>> + echo "$0: unknown short option -${OPTARG}." >&2
>> + exit 1
>> + fi
>> +
>> + case "${opt}" in
>> + # Long options with arguments.
>> + --subject=*|--to=*|--cc=*|--bcc=*|--body=*)
>> + OPTARG=${opt#--*=}
>> + opt=${opt%%=*}
>> + ;;
>> + # Long options without arguments.
>> + --help|--print)
>> + ;;
>> + *)
>> + echo "$0: unknown long option ${opt}, or argument mismatch." >&2
>> + exit 1
>> + ;;
>> + esac
>> + # getopts does not do this for what it considers errors.
>> + OPTIND=$((OPTIND + 1))
>> + ;;
>> + esac
>> +
>> + case "${opt}" in
>> + --help|h)
>> + exec man notmuch-search
>> + ;;
>> + --subject|s)
>> + ELISP="${ELISP} (message-goto-subject) (insert \"${OPTARG}\")"
>> + ;;
>> + --to)
>> + ELISP="${ELISP} (message-goto-to) (insert \"${OPTARG}, \")"
>> + ;;
>> + --cc|c)
>> + ELISP="${ELISP} (message-goto-cc) (insert \"${OPTARG}, \")"
>> + ;;
>> + --bcc|b)
>> + ELISP="${ELISP} (message-goto-bcc) (insert \"${OPTARG}, \")"
>> + ;;
>> + --body|i)
>> + ELISP="${ELISP} (message-goto-body) (cd \"${PWD}\") (insert-file \"${OPTARG}\")"
>> + ;;
>> + --print)
>> + PRINT_ONLY=1
>> + ;;
>> + *)
>> + # We should never end up here.
>> + echo "$0: internal error (option ${opt})." >&2
>> + exit 1
>> + ;;
>> + esac
>> +
>> + shift $((OPTIND - 1))
>> + OPTIND=1
>> +done
>> +
>> +# Positional parameters.
>> +while [ $# -gt 0 ]; do
>> + ELISP="${ELISP} (message-goto-to) (insert \"${1}, \")"
>> + shift
>> +done
>
> for arg; do
for arg in $@; ?
> ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")"
> done
>
> I tried to address Austin's comment on IRC with
> printf -v qarg %q "$arg" -- that has problem if there is whitespace
> in arg. maybe printf -v qarg '%q ' "$arg" -- then there is always one
> trailing ws (and spaces are always prefixed w/ \ -- (insert "foo\ bar")
> just makes the ' ' disappear (which is not good...).
>
> maybe arg=${arg//\\/\\\\}; arg=${arg//"/\\"};
>
> ${parameter/pattern/string} -- Pattern substition in bash manual.
I'm inclined to go with "don't do that then" ;)
>
>
>> +# End progn.
>> +ELISP="${ELISP})"
>> +
>> +if [ -n "$PRINT_ONLY" ]; then
>> + echo ${ELISP}
>> + exit 0
>> +fi
>> +
>> +# Evaluate the progn.
>> +emacsclient --eval "${ELISP}" &>/dev/null
>
> emacsclient --eval "${ELISP}" >/dev/null 2>&1
>
> (why do you want to redirect stdout & stderr to devnull ?)
Okay, maybe it could be just stdout (which will be the eval result, in
this case nil).
>
>> +if [ $? -ne 0 ]; then
>> + echo "$0: emacsclient failed" >&2
>> + exit 1
>> +fi
>> --
>> 1.9.0
More information about the notmuch
mailing list