* [PATCH] cli: add a tool for starting new message in the emacs ui @ 2014-03-19 19:25 Jani Nikula 2014-03-19 21:24 ` Tomi Ollila 0 siblings, 1 reply; 17+ messages in thread From: Jani Nikula @ 2014-03-19 19:25 UTC (permalink / raw) To: notmuch 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. --- 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)** 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 +# +# 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@nikula.org> +# + +set -e + +# The crux of it all: construct an elisp progn and eval it. +ELISP="(progn (notmuch-mua-new-mail)" + +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 + +# End progn. +ELISP="${ELISP})" + +if [ -n "$PRINT_ONLY" ]; then + echo ${ELISP} + exit 0 +fi + +# Evaluate the progn. +emacsclient --eval "${ELISP}" &>/dev/null +if [ $? -ne 0 ]; then + echo "$0: emacsclient failed" >&2 + exit 1 +fi -- 1.9.0 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH] cli: add a tool for starting new message in the emacs ui 2014-03-19 19:25 [PATCH] cli: add a tool for starting new message in the emacs ui Jani Nikula @ 2014-03-19 21:24 ` Tomi Ollila 2014-03-19 21:54 ` Jani Nikula 0 siblings, 1 reply; 17+ messages in thread From: Tomi Ollila @ 2014-03-19 21:24 UTC (permalink / raw) To: Jani Nikula, notmuch On Wed, Mar 19 2014, Jani Nikula <jani@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. > 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... > 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 > +# > +# 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@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. > + > +# 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)" > + > +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 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. > +# 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 ?) > +if [ $? -ne 0 ]; then > + echo "$0: emacsclient failed" >&2 > + exit 1 > +fi > -- > 1.9.0 ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] cli: add a tool for starting new message in the emacs ui 2014-03-19 21:24 ` Tomi Ollila @ 2014-03-19 21:54 ` Jani Nikula 2014-03-20 10:31 ` Tomi Ollila 0 siblings, 1 reply; 17+ messages in thread From: Jani Nikula @ 2014-03-19 21:54 UTC (permalink / raw) To: Tomi Ollila, notmuch On Wed, 19 Mar 2014, Tomi Ollila <tomi.ollila@iki.fi> wrote: > On Wed, Mar 19 2014, Jani Nikula <jani@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@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 ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] cli: add a tool for starting new message in the emacs ui 2014-03-19 21:54 ` Jani Nikula @ 2014-03-20 10:31 ` Tomi Ollila 2014-04-06 15:43 ` [PATCH v2] " Jani Nikula 0 siblings, 1 reply; 17+ messages in thread From: Tomi Ollila @ 2014-03-20 10:31 UTC (permalink / raw) To: Jani Nikula, notmuch On Wed, Mar 19 2014, Jani Nikula <jani@nikula.org> wrote: > On Wed, 19 Mar 2014, Tomi Ollila <tomi.ollila@iki.fi> wrote: >> On Wed, Mar 19 2014, Jani Nikula <jani@nikula.org> wrote: >> >>> + >>> +# Positional parameters. >>> +while [ $# -gt 0 ]; do >>> + ELISP="${ELISP} (message-goto-to) (insert \"${1}, \")" >>> + shift >>> +done >> >> for arg; do > > for arg in $@; ? Yes, that is less obfuscated version of that, whichever you feel more comfortable with... for more discussion about the alternatives here see: http://www.in-ulm.de/~mascheck/various/bourne_args/ (but don't look that -- it is unnecessary and only causes headache ;D) >> maybe arg=${arg//\\/\\\\}; arg=${arg//"/\\"}; >> >> ${parameter/pattern/string} -- Pattern substition in bash manual. > > I'm inclined to go with "don't do that then" ;) $ bash -c 'arg=${0//\\/\\\\}; echo ${arg//\"/\\\"}' 'this"is\a test' this\"is\\a test $ zsh -c 'arg=${0//\\/\\\\}; echo ${arg//\"/\\\"}' 'this"is\a test' this\"is\a test $ ksh -c 'arg=${0//\\/\\\\}; echo ${arg//\"/\\\"}' 'this"is\a test' this\"is\\a test Interestigly zsh on Scientific Linux 6.2 fails here (zsh 4.3.10) -- I tried various tricks and none helped. Hmm also zsh 4.3.17 on Ubuntu 12.04 fails. zsh 5.0.2 on Fedora 20 works OK. ksh & bash installed on all these 3 systems work OK (and also bash 3.2.51... on Mac OS X). IMO this quoting should be done -- so I can send you email with: $ notmuch-emacs-mua '"Jani Nikula" <jani@nikula.org>' Tomi ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2] cli: add a tool for starting new message in the emacs ui 2014-03-20 10:31 ` Tomi Ollila @ 2014-04-06 15:43 ` Jani Nikula 2014-04-07 3:59 ` Jameson Graef Rollins 2014-07-01 20:02 ` [PATCH] " David Bremner 0 siblings, 2 replies; 17+ messages in thread From: Jani Nikula @ 2014-04-06 15:43 UTC (permalink / raw) To: notmuch, Tomi Ollila Add a tool to start composing an email in the Notmuch Emacs UI with the specified subject, recipients, and message body. --- doc/man1/notmuch-emacs-mua.rst | 50 +++++++++++++++++ notmuch-emacs-mua | 122 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 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)** diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua new file mode 100755 index 000000000000..7f94271d8a44 --- /dev/null +++ b/notmuch-emacs-mua @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# +# 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@nikula.org> +# + +set -eu + +escape () +{ + echo "${1//\"/\\\"}" +} + +PRINT_ONLY= + +# The crux of it all: construct an elisp progn and eval it. +ELISP="(progn (require 'notmuch) (notmuch-mua-new-mail)" + +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 + + OPTARG="$(escape "${OPTARG}")" + + case "${opt}" in + --help|h) + exec man notmuch-emacs-mua + ;; + --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. +for arg; do + arg="$(escape "${arg}")" + ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")" +done + +# End progn. +ELISP="${ELISP})" + +if [ -n "$PRINT_ONLY" ]; then + echo ${ELISP} + exit 0 +fi + +# Evaluate the progn. +emacsclient --eval "${ELISP}" >/dev/null +if [ $? -ne 0 ]; then + echo "$0: emacsclient failed" >&2 + exit 1 +fi -- 1.9.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v2] cli: add a tool for starting new message in the emacs ui 2014-04-06 15:43 ` [PATCH v2] " Jani Nikula @ 2014-04-07 3:59 ` Jameson Graef Rollins 2014-07-01 20:02 ` [PATCH] " David Bremner 1 sibling, 0 replies; 17+ messages in thread From: Jameson Graef Rollins @ 2014-04-07 3:59 UTC (permalink / raw) To: Jani Nikula, notmuch, Tomi Ollila [-- Attachment #1: Type: text/plain, Size: 592 bytes --] On Sun, Apr 06 2014, Jani Nikula <jani@nikula.org> wrote: > Add a tool to start composing an email in the Notmuch Emacs UI with > the specified subject, recipients, and message body. Hey, Jani. You might be interested in checking out a patch I submitted a while back to support "mailto:" urls in notmuch-mua.el: id:1327865624-7673-1-git-send-email-jrollins@finestructure.net That, combined with your new ui interface would make handling mailto: urls in say browsers very convenient, e.g.: ELISP="(notmuch-mua-mailto \"$URL\")" for: notmuch-emacs-mua mailto:foo@example.com jamie. [-- Attachment #2: Type: application/pgp-signature, Size: 818 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH] cli: add a tool for starting new message in the emacs ui 2014-04-06 15:43 ` [PATCH v2] " Jani Nikula 2014-04-07 3:59 ` Jameson Graef Rollins @ 2014-07-01 20:02 ` David Bremner 2014-07-04 17:36 ` Tomi Ollila 2015-01-18 16:21 ` David Bremner 1 sibling, 2 replies; 17+ messages in thread From: David Bremner @ 2014-07-01 20:02 UTC (permalink / raw) To: notmuch From: Jani Nikula <jani@nikula.org> Add a tool to start composing an email in the Notmuch Emacs UI with the specified subject, recipients, and message body. --- I added the necessary lines to conf.py to get the man pages built and installed I'd be happier with this if it could start emacs. I tried adding "-a ''" to the emacsclient invokation, but that doesn't quite work; the message-mode buffer is created in emacs but no frame is displayed. It could be a peculiarity of my emacs setup, of course. doc/conf.py | 4 ++ doc/man1/notmuch-emacs-mua.rst | 50 +++++++++++++++++ notmuch-emacs-mua | 122 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 doc/man1/notmuch-emacs-mua.rst create mode 100755 notmuch-emacs-mua diff --git a/doc/conf.py b/doc/conf.py index 70ba1b8..8ee19f4 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -74,6 +74,10 @@ man_pages = [ u'creates a plain-text dump of the tags of each message', [u'Carl Worth and many others'], 1), +('man1/notmuch-emacs-mua','notmuch-emacs-mua', + u'send mail with notmuch and emacs', + [u'Carl Worth and many others'], 1), + ('man5/notmuch-hooks','notmuch-hooks', u'hooks for notmuch', [u'Carl Worth and many others'], 5), diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst new file mode 100644 index 0000000..6e63818 --- /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)** diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua new file mode 100755 index 0000000..7f94271 --- /dev/null +++ b/notmuch-emacs-mua @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# +# 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@nikula.org> +# + +set -eu + +escape () +{ + echo "${1//\"/\\\"}" +} + +PRINT_ONLY= + +# The crux of it all: construct an elisp progn and eval it. +ELISP="(progn (require 'notmuch) (notmuch-mua-new-mail)" + +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 + + OPTARG="$(escape "${OPTARG}")" + + case "${opt}" in + --help|h) + exec man notmuch-emacs-mua + ;; + --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. +for arg; do + arg="$(escape "${arg}")" + ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")" +done + +# End progn. +ELISP="${ELISP})" + +if [ -n "$PRINT_ONLY" ]; then + echo ${ELISP} + exit 0 +fi + +# Evaluate the progn. +emacsclient --eval "${ELISP}" >/dev/null +if [ $? -ne 0 ]; then + echo "$0: emacsclient failed" >&2 + exit 1 +fi -- 2.0.0.rc2 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH] cli: add a tool for starting new message in the emacs ui 2014-07-01 20:02 ` [PATCH] " David Bremner @ 2014-07-04 17:36 ` Tomi Ollila 2015-01-18 16:21 ` David Bremner 1 sibling, 0 replies; 17+ messages in thread From: Tomi Ollila @ 2014-07-04 17:36 UTC (permalink / raw) To: David Bremner, notmuch, Jani Nikula On Tue, Jul 01 2014, David Bremner <david@tethera.net> wrote: > From: Jani Nikula <jani@nikula.org> > > Add a tool to start composing an email in the Notmuch Emacs UI with > the specified subject, recipients, and message body. > --- > > I added the necessary lines to conf.py to get the man pages built and > installed > > I'd be happier with this if it could start emacs. I tried adding "-a > ''" to the emacsclient invokation, but that doesn't quite work; the > message-mode buffer is created in emacs but no frame is displayed. It > could be a peculiarity of my emacs setup, of course. Ah, this -a '' is new acquaintance to me -- I tried -a emacs and that obviously did not work. It would have been nicer is there is option to just run emacs instead... (that's what I did in that mailto: patch). But there are plenty of other options, which needs at least be discussed, is some tolerable subset can be agreed. First, this will "fail" $ emacs --daemon $ emacsclient --eval '(progn (require 'notmuch) (notmuch-hello))' The window is "nowhere" $ emacsclient -nw can be used to "attach" to the emacs session and then one can switch to the ``notmuch-hello`` -window -- but, someone may use such a supported setup using emacs/emacsclient This "problem" could be tacled so that if emasclient is to be used, option (to be added) ``-nw`` is not given and stdout (or stderr) is a tty (test -t 1 / test -t 2), after running emacsclient print a message to the output with content something like: "connected to running emacs ... if the access to that emacs is hidden you can run ``emacsclient -nw`` to find it..." Ok. Using emacsclient could be opportunistic -- in case using it fails emacs(1) were used instead. The code checking this could be (*): unset ALTERNATE_EDITOR if "${EMACSCLIENT:=emacsclient}" --eval t >/dev/null 2>&1 then exec >/dev/null # (ok, use stderr for msg, or change this :D) editor=$EMACSCLIENT else editor=${EMACS:-emacs} fi (*) to save my time, copied from id:1404237992-9456-1-git-send-email-tomi.ollila@iki.fi When running emacs there is question whether to run it in background or foreground. Probably the only always working option is to run in foreground (unless adding an option) -- backgrounding would be possible only when all of these apply: 1) user did not give ``-nw`` option 2) DISPLAY is not null or unset 3) emacs(1) does have X support! 3 cannot be determined trivially. If backgrounding were supported the only way I see it can be done is: bg () { perl -e 'use POSIX; exit if fork; POSIX::setsid(); exec @ARGV' "$@" } Ok, then about the tool: > doc/conf.py | 4 ++ > doc/man1/notmuch-emacs-mua.rst | 50 +++++++++++++++++ > notmuch-emacs-mua | 122 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 176 insertions(+) > create mode 100644 doc/man1/notmuch-emacs-mua.rst > create mode 100755 notmuch-emacs-mua > > diff --git a/doc/conf.py b/doc/conf.py > index 70ba1b8..8ee19f4 100644 > --- a/doc/conf.py > +++ b/doc/conf.py > @@ -74,6 +74,10 @@ man_pages = [ > u'creates a plain-text dump of the tags of each message', > [u'Carl Worth and many others'], 1), > > +('man1/notmuch-emacs-mua','notmuch-emacs-mua', > + u'send mail with notmuch and emacs', > + [u'Carl Worth and many others'], 1), > + > ('man5/notmuch-hooks','notmuch-hooks', > u'hooks for notmuch', > [u'Carl Worth and many others'], 5), > diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst > new file mode 100644 > index 0000000..6e63818 > --- /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. -i option is consistent with mutt(1). mutt(1) does not have --body option. therefore I'd suggest that --body takes the body content from command line instead from file. If there is to be long-option along with -i it could be --include or --insert.. > + > + ``--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)** > diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua > new file mode 100755 > index 0000000..7f94271 > --- /dev/null > +++ b/notmuch-emacs-mua > @@ -0,0 +1,122 @@ > +#!/usr/bin/env bash > +# > +# 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@nikula.org> > +# > + > +set -eu > + > +escape () > +{ > + echo "${1//\"/\\\"}" > +} This has 3 issues: 1) This does not quote '\' which can be used to execute arbitrary code (is that a feature) 2) echo may escape things differently in other bashes 3) running subshell just to this escape all args is not required, there are bash builtins to do that during same process. If one wants to use function, escape -v var arg syntax could be deviced with escape () { local var=${3//\"/\\\"}; var=${var//\\/\\\\} eval $2=\$var } > +PRINT_ONLY= > + Tomi ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH] cli: add a tool for starting new message in the emacs ui 2014-07-01 20:02 ` [PATCH] " David Bremner 2014-07-04 17:36 ` Tomi Ollila @ 2015-01-18 16:21 ` David Bremner 2015-01-18 21:07 ` Tomi Ollila ` (3 more replies) 1 sibling, 4 replies; 17+ messages in thread From: David Bremner @ 2015-01-18 16:21 UTC (permalink / raw) To: notmuch From: Jani Nikula <jani@nikula.org> Add a tool to start composing an email in the Notmuch Emacs UI with the specified subject, recipients, and message body. --- This version fixes my complaint about the previous version not starting emacs. It does this by starting a new "frame", either at the window system level, or in the current terminal. The traditional "-nw" short form of the argument "--no-window-system" seems maybe more work to parse than it's worth. doc/conf.py | 4 ++ doc/man1/notmuch-emacs-mua.rst | 53 ++++++++++++++++++ notmuch-emacs-mua | 122 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 doc/man1/notmuch-emacs-mua.rst create mode 100755 notmuch-emacs-mua diff --git a/doc/conf.py b/doc/conf.py index fb49f6e..8fbc854 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -78,6 +78,10 @@ man_pages = [ u'creates a plain-text dump of the tags of each message', [u'Carl Worth and many others'], 1), +('man1/notmuch-emacs-mua','notmuch-emacs-mua', + u'send mail with notmuch and emacs', + [u'Carl Worth and many others'], 1), + ('man5/notmuch-hooks','notmuch-hooks', u'hooks for notmuch', [u'Carl Worth and many others'], 5), diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst new file mode 100644 index 0000000..bf8c3aa --- /dev/null +++ b/doc/man1/notmuch-emacs-mua.rst @@ -0,0 +1,53 @@ +================= +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. + + ``--no-window-system`` + Even if a window system is available, use the current terminal + + ``--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)** diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua new file mode 100755 index 0000000..fdf4024 --- /dev/null +++ b/notmuch-emacs-mua @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# +# 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@nikula.org> +# + +set -eu + +escape () +{ + echo "${1//\"/\\\"}" +} + +PRINT_ONLY= +CLIENT_TYPE="-c" + +# The crux of it all: construct an elisp progn and eval it. +ELISP="(prog1 'done (require 'notmuch) (notmuch-mua-new-mail)" + +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|--no-window-system) + ;; + *) + 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 + + OPTARG="$(escape "${OPTARG}")" + + case "${opt}" in + --help|h) + exec man notmuch-emacs-mua + ;; + --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 + ;; + --no-window-system) + CLIENT_TYPE="-t" + ;; + *) + # We should never end up here. + echo "$0: internal error (option ${opt})." >&2 + exit 1 + ;; + esac + + shift $((OPTIND - 1)) + OPTIND=1 +done + +# Positional parameters. +for arg; do + arg="$(escape "${arg}")" + ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")" +done + +# End progn. +ELISP="${ELISP})" + +if [ -n "$PRINT_ONLY" ]; then + echo ${ELISP} + exit 0 +fi + +# Evaluate the progn. +exec emacsclient ${CLIENT_TYPE} -a '' --eval "${ELISP}" -- 2.1.4 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH] cli: add a tool for starting new message in the emacs ui 2015-01-18 16:21 ` David Bremner @ 2015-01-18 21:07 ` Tomi Ollila 2015-01-19 16:32 ` Tomi Ollila ` (2 subsequent siblings) 3 siblings, 0 replies; 17+ messages in thread From: Tomi Ollila @ 2015-01-18 21:07 UTC (permalink / raw) To: David Bremner, notmuch On Sun, Jan 18 2015, David Bremner <david@tethera.net> wrote: > From: Jani Nikula <jani@nikula.org> > > Add a tool to start composing an email in the Notmuch Emacs UI with > the specified subject, recipients, and message body. > --- > > This version fixes my complaint about the previous version not > starting emacs. It does this by starting a new "frame", either at the > window system level, or in the current terminal. The traditional > "-nw" short form of the argument "--no-window-system" seems maybe more > work to parse than it's worth. Well, id:1405026779-29966-1-git-send-email-tomi.ollila@iki.fi (*) had -nw parsing, but I can live without... But more than that one important feature has to be agreed before initial interface is locked down -- how to provide body content from command line without resorting to temporary files. In (*) --body was adding those lines instead of reading file and I later suggested that --include or --insert could do the same as -i ... but I am open to any solution that gives me opportunity to provide body *content* from command line. Tomi > > doc/conf.py | 4 ++ > doc/man1/notmuch-emacs-mua.rst | 53 ++++++++++++++++++ > notmuch-emacs-mua | 122 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 179 insertions(+) > create mode 100644 doc/man1/notmuch-emacs-mua.rst > create mode 100755 notmuch-emacs-mua > > diff --git a/doc/conf.py b/doc/conf.py > index fb49f6e..8fbc854 100644 > --- a/doc/conf.py > +++ b/doc/conf.py > @@ -78,6 +78,10 @@ man_pages = [ > u'creates a plain-text dump of the tags of each message', > [u'Carl Worth and many others'], 1), > > +('man1/notmuch-emacs-mua','notmuch-emacs-mua', > + u'send mail with notmuch and emacs', > + [u'Carl Worth and many others'], 1), > + > ('man5/notmuch-hooks','notmuch-hooks', > u'hooks for notmuch', > [u'Carl Worth and many others'], 5), > diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst > new file mode 100644 > index 0000000..bf8c3aa > --- /dev/null > +++ b/doc/man1/notmuch-emacs-mua.rst > @@ -0,0 +1,53 @@ > +================= > +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. > + > + ``--no-window-system`` > + Even if a window system is available, use the current terminal > + > + ``--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)** > diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua > new file mode 100755 > index 0000000..fdf4024 > --- /dev/null > +++ b/notmuch-emacs-mua > @@ -0,0 +1,122 @@ > +#!/usr/bin/env bash > +# > +# 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@nikula.org> > +# > + > +set -eu > + > +escape () > +{ > + echo "${1//\"/\\\"}" > +} > + > +PRINT_ONLY= > +CLIENT_TYPE="-c" > + > +# The crux of it all: construct an elisp progn and eval it. > +ELISP="(prog1 'done (require 'notmuch) (notmuch-mua-new-mail)" > + > +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|--no-window-system) > + ;; > + *) > + 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 > + > + OPTARG="$(escape "${OPTARG}")" > + > + case "${opt}" in > + --help|h) > + exec man notmuch-emacs-mua > + ;; > + --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 > + ;; > + --no-window-system) > + CLIENT_TYPE="-t" > + ;; > + *) > + # We should never end up here. > + echo "$0: internal error (option ${opt})." >&2 > + exit 1 > + ;; > + esac > + > + shift $((OPTIND - 1)) > + OPTIND=1 > +done > + > +# Positional parameters. > +for arg; do > + arg="$(escape "${arg}")" > + ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")" > +done > + > +# End progn. > +ELISP="${ELISP})" > + > +if [ -n "$PRINT_ONLY" ]; then > + echo ${ELISP} > + exit 0 > +fi > + > +# Evaluate the progn. > +exec emacsclient ${CLIENT_TYPE} -a '' --eval "${ELISP}" > -- > 2.1.4 ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] cli: add a tool for starting new message in the emacs ui 2015-01-18 16:21 ` David Bremner 2015-01-18 21:07 ` Tomi Ollila @ 2015-01-19 16:32 ` Tomi Ollila 2015-01-20 17:53 ` [DRAFT PATCH v2] modified notmuch-emacs-mua v2 Tomi Ollila 2015-02-22 20:34 ` [PATCH] cli: add a tool for starting new message in the emacs ui David Bremner 3 siblings, 0 replies; 17+ messages in thread From: Tomi Ollila @ 2015-01-19 16:32 UTC (permalink / raw) To: David Bremner, Jani Nikula, notmuch On Sun, Jan 18 2015, David Bremner <david@tethera.net> wrote: > From: Jani Nikula <jani@nikula.org> > > Add a tool to start composing an email in the Notmuch Emacs UI with > the specified subject, recipients, and message body. > --- I've given this quite a lot of thought today (while commuting on the bus), and at some (late) moment of time I started to think about security (command line options are visible in ps(1) output), and based on that the naive user option --body taking content from a file is tol^H^H^Hgood idea after all. Therefore, the current command line interface gets +1 from me. I'll use this as a base for further work after this is committed to the repository. (I am now on a terminal unsuitable for yet another review round; I'll do that tomorrow) Tomi > > This version fixes my complaint about the previous version not > starting emacs. It does this by starting a new "frame", either at the > window system level, or in the current terminal. The traditional > "-nw" short form of the argument "--no-window-system" seems maybe more > work to parse than it's worth. > > doc/conf.py | 4 ++ > doc/man1/notmuch-emacs-mua.rst | 53 ++++++++++++++++++ > notmuch-emacs-mua | 122 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 179 insertions(+) > create mode 100644 doc/man1/notmuch-emacs-mua.rst > create mode 100755 notmuch-emacs-mua > > diff --git a/doc/conf.py b/doc/conf.py > index fb49f6e..8fbc854 100644 > --- a/doc/conf.py > +++ b/doc/conf.py > @@ -78,6 +78,10 @@ man_pages = [ > u'creates a plain-text dump of the tags of each message', > [u'Carl Worth and many others'], 1), > > +('man1/notmuch-emacs-mua','notmuch-emacs-mua', > + u'send mail with notmuch and emacs', > + [u'Carl Worth and many others'], 1), > + > ('man5/notmuch-hooks','notmuch-hooks', > u'hooks for notmuch', > [u'Carl Worth and many others'], 5), > diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst > new file mode 100644 > index 0000000..bf8c3aa > --- /dev/null > +++ b/doc/man1/notmuch-emacs-mua.rst > @@ -0,0 +1,53 @@ > +================= > +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. > + > + ``--no-window-system`` > + Even if a window system is available, use the current terminal > + > + ``--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)** > diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua > new file mode 100755 > index 0000000..fdf4024 > --- /dev/null > +++ b/notmuch-emacs-mua > @@ -0,0 +1,122 @@ > +#!/usr/bin/env bash > +# > +# 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@nikula.org> > +# > + > +set -eu > + > +escape () > +{ > + echo "${1//\"/\\\"}" > +} > + > +PRINT_ONLY= > +CLIENT_TYPE="-c" > + > +# The crux of it all: construct an elisp progn and eval it. > +ELISP="(prog1 'done (require 'notmuch) (notmuch-mua-new-mail)" > + > +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|--no-window-system) > + ;; > + *) > + 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 > + > + OPTARG="$(escape "${OPTARG}")" > + > + case "${opt}" in > + --help|h) > + exec man notmuch-emacs-mua > + ;; > + --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 > + ;; > + --no-window-system) > + CLIENT_TYPE="-t" > + ;; > + *) > + # We should never end up here. > + echo "$0: internal error (option ${opt})." >&2 > + exit 1 > + ;; > + esac > + > + shift $((OPTIND - 1)) > + OPTIND=1 > +done > + > +# Positional parameters. > +for arg; do > + arg="$(escape "${arg}")" > + ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")" > +done > + > +# End progn. > +ELISP="${ELISP})" > + > +if [ -n "$PRINT_ONLY" ]; then > + echo ${ELISP} > + exit 0 > +fi > + > +# Evaluate the progn. > +exec emacsclient ${CLIENT_TYPE} -a '' --eval "${ELISP}" > -- > 2.1.4 > > _______________________________________________ > notmuch mailing list > notmuch@notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch ^ permalink raw reply [flat|nested] 17+ messages in thread
* [DRAFT PATCH v2] modified notmuch-emacs-mua v2 2015-01-18 16:21 ` David Bremner 2015-01-18 21:07 ` Tomi Ollila 2015-01-19 16:32 ` Tomi Ollila @ 2015-01-20 17:53 ` Tomi Ollila 2015-01-20 18:58 ` David Bremner 2015-02-22 20:34 ` [PATCH] cli: add a tool for starting new message in the emacs ui David Bremner 3 siblings, 1 reply; 17+ messages in thread From: Tomi Ollila @ 2015-01-20 17:53 UTC (permalink / raw) To: David Bremner, notmuch, Jani Nikula; +Cc: tomi.ollila This is second draft patch of (first being) id:1405026779-29966-1-git-send-email-tomi.ollila@iki.fi I saw potential problem with only supporting emacsclient(1) in the version David sent: id:1421598115-4889-1-git-send-email-david@tethera.net (no emacs server running and no tty -- new X client not started) therefore I started to modify that part -- and soon adding all features I'd like to see there. As I expect some bikeshedding to continue I skip doc update for the time being (to avoid unnecessary work), therefore calling this as "draft patch". This implIments many of my first draft features: mailto: is handled if given as first argument (not yet all the nice stuff Jameson suggested, we'll perhaps get there later...) --from option when sending non-mailto: way And, -nw (*) in a new way... The -i and --body are done as in initial Jani's version ( also as in id:1421598115-4889-1-git-send-email-david@tethera.net ) Also, --long SPC value is not implemented, format is --long=value In case emacsclient(1) is used and no --no-window-system, '-c' arg is given to emacsclient like in the version David sent. (this means that if emacs is not running on X, user may get this message: "emacsclient: could not get terminal name" -- we need to document user to give -nw (--no-window-system) option then) Other "new" things: Option --bodytext to give body content from command line (not documented yet, but I'll add privacy warning when updating NaMual page. Final cursor position goes based on last option given from command line, unless to: or subject: is missing -- cursor is positioned after these headers in this case. (*) -nw works so that the 'n' is given to getopts and it expects an argument; the argument is checked being w (this means -nw and -n w are accepted). this also gives interesting output when one attempts to use plain '-n' (error message shows next arg concatenated into this or... "./notmuch-emacs-mua: short option -n requires an argument." -- OK, forgot to handle this special case at this time...) Anyway, I'd rather have -nw and some peculiarity than no -nw at all ;) Tomi --- notmuch-emacs-mua | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100755 notmuch-emacs-mua diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua new file mode 100755 index 000000000000..42275cd1a563 --- /dev/null +++ b/notmuch-emacs-mua @@ -0,0 +1,217 @@ +#!/usr/bin/env bash +# -*- mode: shell-script; sh-basic-offset: 4; tab-width: 8 -*- +# +# 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@nikula.org> +# Tomi Ollila <tomi.ollila@iki.fi> +# + +set -eu + +# Cannot use [[ ]] until we know we have bash. +case ${BASH_VERSION-} in '') + echo "Not BASH!" >&2 + exit 1 +esac + +# escape: "expand" '\' to '\\' & '"' to '\"' +# Calling convention: escape -v var "$arg" (like in bash printf). +escape () +{ + local arg=${3//\\/\\\\} + eval $2='${arg//\"/\\\"}' +} + +unset ALTERNATE_EDITOR +exec_mua () +{ + if "${EMACSCLIENT:=emacsclient}" --eval t >/dev/null 2>&1 + then + emacs=$EMACSCLIENT + # Close stdout in case no --no-window-system (and no --print). + test -n "$W$X" || exec >/dev/null + # W/ emacsclient, use '-c' in case no --no-window-system. + [[ -n $W ]] || W=-c + else + emacs=${EMACS:-emacs} + fi + ${X:-exec} "${emacs}" $W --eval "(prog1 'done $*)" + exit +} + +X= # This is chaged to 'echo' when --print is used. +W= # This is changed to '-nw' when --no-window-system is used. + +SUBJECT= TO= CC= BCC= BODY= FROM= + +unset message_goto # Final elisp function to execute, when defined. +cddone=false + +# "Short circuit" mailto handling. +case ${1-} in mailto:*) + oIFS=$IFS; IFS= + escape -v OPTARG "$*" + IFS=$oIFS + exec_mua "(require 'notmuch) (browse-url-mail \"$OPTARG\")" + exit +esac + +while getopts :s:c:b:i:n: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=*|--from=*|--bodytext=*) + OPTARG=${opt#--*=} + opt=${opt%%=*} + ;; + # Long options without arguments. + --help|--print|--no-window-system) + ;; + *) + 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 + + escape -v OPTARG "${OPTARG}" + + case "${opt}" in + --help|h) + exec man notmuch-emacs-mua + ;; + --from) + escape -v FROM "${OPTARG}" + ;; + --subject|s) + escape -v OPTARG "${OPTARG}" + SUBJECT=${SUBJECT:+$SUBJECT }${OPTARG} + message_goto='(message-goto-subject)' + ;; + --to) + escape -v OPTARG "${OPTARG}" + TO=${TO:+$TO, }${OPTARG} + message_goto='(message-goto-to)' + ;; + --cc|c) + escape -v OPTARG "${OPTARG}" + CC=${CC:+$CC, }${OPTARG} + message_goto='(message-goto-cc)' + ;; + --bcc|b) + escape -v OPTARG "${OPTARG}" + BCC=${BCC:+$BCC, }${OPTARG} + message_goto='(message-goto-bcc)' + ;; + --body|i) + escape -v OPTARG "${OPTARG}" + if [[ ! -f ${OPTARG} ]]; then + echo "$0: '${OPTARG}': no such file" >&2 + exit 1 + fi + if [[ $cddone == 'false' ]]; then + BODY=${BODY}$'\n'" (cd \"${PWD}\")" + cddone=true + fi + BODY=${BODY}$'\n'" (insert-file \"${OPTARG}\")" + BODY=${BODY}$'\n'" (if (/= (point) (line-beginning-position)) (insert \"\\n\"))" + unset message_goto + ;; + --bodytext) + escape -v OPTARG "${OPTARG}" + BODY=${BODY}$'\n'" (insert \"${OPTARG}\\n\")" + unset message_goto + ;; + --no-window-system) + W=-nw + ;; + n) # -nw !!! + if [[ $OPTARG == 'w' ]]; then + W=-nw + else + echo "$0: unknown option -n${OPTARG}, or argument mismatch." >&2 + exit 1 + fi + ;; + --print) + X=echo + ;; + *) + # We should never end up here. + echo "$0: internal error (option ${opt})." >&2 + exit 1 + ;; + esac + + shift $((OPTIND - 1)) + OPTIND=1 +done + +# Positional parameters. +for arg; do + escape -v arg "${arg}" + TO=${TO:+$TO, }${arg} + message_goto='(message-goto-to)' +done + +# The newlines are here for --print (only) output. +NL=$'\n' +ELISP="\ +${CC:+$NL (message-goto-cc) (insert \"$CC\")}\ +${BCC:+$NL (message-goto-bcc) (insert \"$BCC\")}\ +${BODY:+$NL (message-goto-body)$BODY}" + +if [[ $TO == '' && $SUBJECT == '' && $ELISP == '' ]] +then + exec_mua "(require 'notmuch) (notmuch-hello)" +else + [[ $FROM != '' ]] && OH="(list (cons 'From \"$FROM\"))" || OH=nil + + if [[ $SUBJECT == '' ]]; then + SUBJECT=nil + message_goto='(message-goto-subject)' + else + SUBJECT=\"$SUBJECT\" + fi + if [[ $TO == '' ]]; then + TO=nil + message_goto='(message-goto-to)' + else + TO=\"$TO\" + fi + exec_mua "(require 'notmuch) + (notmuch-mua-mail ${TO} ${SUBJECT} + ${OH} nil (notmuch-mua-get-switch-function))\ +${ELISP}${NL} (set-buffer-modified-p nil)${message_goto+ $message_goto}" +fi -- 2.0.0 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [DRAFT PATCH v2] modified notmuch-emacs-mua v2 2015-01-20 17:53 ` [DRAFT PATCH v2] modified notmuch-emacs-mua v2 Tomi Ollila @ 2015-01-20 18:58 ` David Bremner 2015-01-21 9:38 ` Tomi Ollila 0 siblings, 1 reply; 17+ messages in thread From: David Bremner @ 2015-01-20 18:58 UTC (permalink / raw) To: Tomi Ollila, notmuch, Jani Nikula; +Cc: tomi.ollila Tomi Ollila <tomi.ollila@iki.fi> writes: > This is second draft patch of (first being) > > id:1405026779-29966-1-git-send-email-tomi.ollila@iki.fi > > I saw potential problem with only supporting emacsclient(1) in > the version David sent: > id:1421598115-4889-1-git-send-email-david@tethera.net > > (no emacs server running and no tty -- new X client not started) > I don't understand what use case is failing for you. I think I tested all 4 combinations of DISPLAY set and unset and emacs server running and not running. Do you somehow want to run the notmuch-emacs-mua script from a process not attached to a terminal (from cron?). > In case emacsclient(1) is used and no --no-window-system, '-c' arg is > given to emacsclient like in the version David sent. > > (this means that if emacs is not running on X, user may get this message: > "emacsclient: could not get terminal name" -- we need to document user > to give -nw (--no-window-system) option then) As I wrote above, I'm missing what the tradeoff is. The version I sent works fine (at least for me) in the case where DISPLAY is not set and --no-window-system is not given (i.e. it's implied if DISPLAY is not set). d ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [DRAFT PATCH v2] modified notmuch-emacs-mua v2 2015-01-20 18:58 ` David Bremner @ 2015-01-21 9:38 ` Tomi Ollila 2015-01-21 16:50 ` David Bremner 0 siblings, 1 reply; 17+ messages in thread From: Tomi Ollila @ 2015-01-21 9:38 UTC (permalink / raw) To: David Bremner, notmuch, Jani Nikula On Tue, Jan 20 2015, David Bremner <david@tethera.net> wrote: > Tomi Ollila <tomi.ollila@iki.fi> writes: > >> This is second draft patch of (first being) >> >> id:1405026779-29966-1-git-send-email-tomi.ollila@iki.fi >> >> I saw potential problem with only supporting emacsclient(1) in >> the version David sent: >> id:1421598115-4889-1-git-send-email-david@tethera.net >> >> (no emacs server running and no tty -- new X client not started) >> > > I don't understand what use case is failing for you. I think I tested > all 4 combinations of DISPLAY set and unset and emacs server running and > not running. Do you somehow want to run the notmuch-emacs-mua script > from a process not attached to a terminal (from cron?). It seems that you have done good testing and I just failed to test using exactly the same options you have: emacsclient -c -a '' .zshrc Works as one'd expect to work successfully in all cases, DISPLAY set/unset and emacs-server running or not (now deleting 6 lines of text below that was based on wrong assumtions...) // 6 lines of text deleted ... :) // So, the question goes into deciding whether the magic of starting emacs server to the user if it is not running -- something that many users would not anticipate/desire (I am one of those)... Running emacs via emacsclient has subtle differences to just running emacs the "regular" way -- while testing I just had problems exiting the emacsclient session without exiting the whole emacs -- I exited the whole emacs and next time paid attention to minibuffer message saying c-x 5 0 exits the session... Now that I got the tests work as David would have expected me to do those, the frame emacs started looked different that my emacs frames have when starting "normally" -- there was extra toolbar in the frame (I have inhibited all menu and toolbars in my normal setup). Just that it behaves differently is suspicious. Therefore, IMO it is clearer to run "regular" emacs unless user is explicitly running emacs-server and can anticipate the behaviour differences when running emacsclient there. >> In case emacsclient(1) is used and no --no-window-system, '-c' arg is >> given to emacsclient like in the version David sent. >> >> (this means that if emacs is not running on X, user may get this message: >> "emacsclient: could not get terminal name" -- we need to document user >> to give -nw (--no-window-system) option then) > > As I wrote above, I'm missing what the tradeoff is. The version I sent > works fine (at least for me) in the case where DISPLAY is not set and > --no-window-system is not given (i.e. it's implied if DISPLAY is not > set). Ok, my tests failed colossally here. Sorry. First, I forgot to have -a '' there (for comparison) and secondly I closed stdout before running emacsclient (bug in the script). That's what you get after almost 3 hours of vigorous hacking there; the manual test coverage is probably not the best possible... > > d Tomi ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [DRAFT PATCH v2] modified notmuch-emacs-mua v2 2015-01-21 9:38 ` Tomi Ollila @ 2015-01-21 16:50 ` David Bremner 0 siblings, 0 replies; 17+ messages in thread From: David Bremner @ 2015-01-21 16:50 UTC (permalink / raw) To: Tomi Ollila, notmuch, Jani Nikula Tomi Ollila <tomi.ollila@iki.fi> writes: > > So, the question goes into deciding whether the magic of starting emacs > server to the user if it is not running -- something that many users would > not anticipate/desire (I am one of those)... > Yes, this objection I understand, and even anticipated a bit when sending the patch. So no problem from my side to make this an option. We could even even use "notmuch config get" to retrieve the users preference, although maybe that is overcomplicating things. d ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH] cli: add a tool for starting new message in the emacs ui 2015-01-18 16:21 ` David Bremner ` (2 preceding siblings ...) 2015-01-20 17:53 ` [DRAFT PATCH v2] modified notmuch-emacs-mua v2 Tomi Ollila @ 2015-02-22 20:34 ` David Bremner 2015-03-06 7:06 ` David Bremner 3 siblings, 1 reply; 17+ messages in thread From: David Bremner @ 2015-02-22 20:34 UTC (permalink / raw) To: David Bremner, notmuch From: Jani Nikula <jani@nikula.org> Add a tool to start composing an email in the Notmuch Emacs UI with the specified subject, recipients, and message body. --- doc/conf.py | 4 ++ doc/man1/notmuch-emacs-mua.rst | 63 +++++++++++++++++++ notmuch-emacs-mua | 136 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 doc/man1/notmuch-emacs-mua.rst create mode 100755 notmuch-emacs-mua diff --git a/doc/conf.py b/doc/conf.py index fb49f6e..8fbc854 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -78,6 +78,10 @@ man_pages = [ u'creates a plain-text dump of the tags of each message', [u'Carl Worth and many others'], 1), +('man1/notmuch-emacs-mua','notmuch-emacs-mua', + u'send mail with notmuch and emacs', + [u'Carl Worth and many others'], 1), + ('man5/notmuch-hooks','notmuch-hooks', u'hooks for notmuch', [u'Carl Worth and many others'], 5), diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst new file mode 100644 index 0000000..eb47098 --- /dev/null +++ b/doc/man1/notmuch-emacs-mua.rst @@ -0,0 +1,63 @@ +================= +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. + +Supported options for **notmuch-emacs-mua** include + + ``-h, --help`` + Display help. + + ``-C, --client`` + Use emacsclient, rather than emacs. This will start + an emacs daemon process if necessary. + + ``-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. + + ``--no-window-system`` + Even if a window system is available, use the current terminal + + ``--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. + +ENVIRONMENT VARIABLES +===================== + +``EMACS`` +Name of emacs command to invoke + +``EMACSCLIENT`` +Name of emacsclient comment to invoke + +SEE ALSO +======== + +**notmuch(1)**, **emacsclient(1)**, **mutt(1)** diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua new file mode 100755 index 0000000..b8cbc82 --- /dev/null +++ b/notmuch-emacs-mua @@ -0,0 +1,136 @@ +#!/usr/bin/env bash +# +# 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@nikula.org> +# + +set -eu + +escape () +{ + echo "${1//\"/\\\"}" +} + +EMACS=${EMACS-emacs} +EMACSCLIENT=${EMACSCLIENT-emacsclient} + +PRINT_ONLY= +USE_EMACSCLIENT= +CLIENT_TYPE="-c" + +# The crux of it all: construct an elisp progn and eval it. +ELISP="(prog1 'done (require 'notmuch) (notmuch-mua-new-mail)" +ELISP="${ELISP} (setq message-exit-actions (list #'save-buffers-kill-terminal))" + +while getopts :s:c:b:i:hC 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|--no-window-system|--client) + ;; + *) + 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 + + + OPTARG="${OPTARG-none}" + OPTARG="$(escape "${OPTARG}")" + + case "${opt}" in + --help|h) + exec man notmuch-emacs-mua + ;; + --client|C) + USE_EMACSCLIENT="yes" + ;; + --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 + ;; + --no-window-system) + CLIENT_TYPE="-t" + ;; + *) + # We should never end up here. + echo "$0: internal error (option ${opt})." >&2 + exit 1 + ;; + esac + + shift $((OPTIND - 1)) + OPTIND=1 +done + +# Positional parameters. +for arg; do + arg="$(escape "${arg}")" + ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")" +done + +# End progn. +ELISP="${ELISP})" + +if [ -n "$PRINT_ONLY" ]; then + echo ${ELISP} + exit 0 +fi + +if [ -n "$USE_EMACSCLIENT" ]; then + # Evaluate the progn. + exec ${EMACSCLIENT} ${CLIENT_TYPE} -a '' --eval "${ELISP}" +else + exec ${EMACS} --eval "${ELISP}" +fi -- 2.1.4 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH] cli: add a tool for starting new message in the emacs ui 2015-02-22 20:34 ` [PATCH] cli: add a tool for starting new message in the emacs ui David Bremner @ 2015-03-06 7:06 ` David Bremner 0 siblings, 0 replies; 17+ messages in thread From: David Bremner @ 2015-03-06 7:06 UTC (permalink / raw) To: notmuch David Bremner <david@tethera.net> writes: > From: Jani Nikula <jani@nikula.org> > > Add a tool to start composing an email in the Notmuch Emacs UI with > the specified subject, recipients, and message body. Both Jani and Tomi expressed, if not satisfaction, at least exhaustion with this version, so I pushed to master. d ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2015-03-06 7:08 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-03-19 19:25 [PATCH] cli: add a tool for starting new message in the emacs ui Jani Nikula 2014-03-19 21:24 ` Tomi Ollila 2014-03-19 21:54 ` Jani Nikula 2014-03-20 10:31 ` Tomi Ollila 2014-04-06 15:43 ` [PATCH v2] " Jani Nikula 2014-04-07 3:59 ` Jameson Graef Rollins 2014-07-01 20:02 ` [PATCH] " David Bremner 2014-07-04 17:36 ` Tomi Ollila 2015-01-18 16:21 ` David Bremner 2015-01-18 21:07 ` Tomi Ollila 2015-01-19 16:32 ` Tomi Ollila 2015-01-20 17:53 ` [DRAFT PATCH v2] modified notmuch-emacs-mua v2 Tomi Ollila 2015-01-20 18:58 ` David Bremner 2015-01-21 9:38 ` Tomi Ollila 2015-01-21 16:50 ` David Bremner 2015-02-22 20:34 ` [PATCH] cli: add a tool for starting new message in the emacs ui David Bremner 2015-03-06 7:06 ` David Bremner
Code repositories for project(s) associated with this public inbox https://yhetil.org/notmuch.git/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).