* [PATCH] notmuch-emacs-mua: more options, some fixes
@ 2015-03-07 10:36 Tomi Ollila
2015-03-07 14:12 ` Jani Nikula
0 siblings, 1 reply; 2+ messages in thread
From: Tomi Ollila @ 2015-03-07 10:36 UTC (permalink / raw)
To: notmuch; +Cc: tomi.ollila
Two new options added:
--from: specify alternate From: header
--bodytext: possibility to give body content from command line
Non-forking escape() functionality, also escaping \ (backslash) characters.
Without content arguments start emacs/emacsclient and run (notmuch-hello),
in this case without assigning anything to message-exit-actions.
Point is now positioned at the end of the content given last on command
line, unless to: or subject: is missing -- in which case point is
positioned at one of these headers (is both missing, at to:)
The -nw option is now given to emacs in case --no-window-system command
line option is provided (--no-window-system used to work with emacsclient
only).
In case EMACS or EMACSCLIENT environment variable was defined but being
empty (null string), use emacs/emacsclient as command instead (null string
as executable name gives confusing error message). Also $EMACS/$EMACSCLIENT
executable name is now quoted to *NOT* split it to separate command line
arguments on any $IFS variables there might be.
Reorganized content argument handling to combine the content of same option
given multiple times and make it look more readable when --print option is
used. --body option also now checks the existence of the file to be
included and if the file included does not end with newline trailing
newline is inserted to the message buffer.
As bash supports [[ ]] command and it's special expansion (or lack thereof)
of variables (and ==, && and || inside) the few [ ]'s there were are now
changed to this more advanced format.
---
The changes *NOT* taken from my 2 draft patches (*)
1) no -nw hacking
2) no mailto: handling
(*) id:1421776424-24304-1-git-send-email-tomi.ollila@iki.fi (later, linking
previous)
doc/man1/notmuch-emacs-mua.rst | 8 ++-
notmuch-emacs-mua | 123 ++++++++++++++++++++++++++++++-----------
2 files changed, 99 insertions(+), 32 deletions(-)
diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst
index eb47098..29f7e0c 100644
--- a/doc/man1/notmuch-emacs-mua.rst
+++ b/doc/man1/notmuch-emacs-mua.rst
@@ -22,6 +22,9 @@ Supported options for **notmuch-emacs-mua** include
Use emacsclient, rather than emacs. This will start
an emacs daemon process if necessary.
+ ``--from=``\ <from>
+ Specify alternate sender (From) of the message.
+
``-s, --subject=``\ <subject>
Specify the subject of the message.
@@ -37,6 +40,9 @@ Supported options for **notmuch-emacs-mua** include
``-i, --body=``\ <file>
Specify a file to include into the body of the message.
+ ``--bodytext=``\ <text>
+ Specify text content to be inserted into the body of the message.
+
``--no-window-system``
Even if a window system is available, use the current terminal
@@ -60,4 +66,4 @@ Name of emacsclient comment to invoke
SEE ALSO
========
-**notmuch(1)**, **emacsclient(1)**, **mutt(1)**
+**notmuch(1)**, **emacs(1)**, **emacsclient(1)**, **mutt(1)**
diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua
index b8cbc82..17365b9 100755
--- a/notmuch-emacs-mua
+++ b/notmuch-emacs-mua
@@ -1,4 +1,5 @@
#!/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
#
@@ -18,25 +19,47 @@
# 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
+# escape: "expand" '\' to '\\' & '"' to '\"'
+# Calling convention: escape -v var "$arg" (like in bash printf).
escape ()
{
- echo "${1//\"/\\\"}"
+ local arg=${3//\\/\\\\}
+ eval $2='${arg//\"/\\\"}'
}
-EMACS=${EMACS-emacs}
-EMACSCLIENT=${EMACSCLIENT-emacsclient}
+EMACS=${EMACS:-emacs}
+EMACSCLIENT=${EMACSCLIENT:-emacsclient}
PRINT_ONLY=
USE_EMACSCLIENT=
-CLIENT_TYPE="-c"
+EMACSCLIENT_TYPE='-c'
+EMACS_NW=
-# 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))"
+exec_mua ()
+{
+ if [[ -n $PRINT_ONLY ]]; then
+ echo "$1"
+ exit
+ fi
+
+ if [[ -n $USE_EMACSCLIENT ]]; then
+ # Evaluate the progn.
+ exec "${EMACSCLIENT}" ${EMACSCLIENT_TYPE} -a '' --eval "$1"
+ else
+ exec "${EMACS}" ${EMACS_NW} --eval "$1"
+ fi
+ exit not reached
+}
+
+SUBJECT= TO= CC= BCC= BODY= FROM=
+
+unset message_goto # Final elisp function to execute, when defined.
+cddone=false
while getopts :s:c:b:i:hC opt; do
# Handle errors and long options.
@@ -47,14 +70,14 @@ while getopts :s:c:b:i:hC opt; do
;;
\?)
opt=$1
- if [ "${OPTARG}" != "-" ]; then
+ 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=*)
+ --subject=*|--to=*|--cc=*|--bcc=*|--body=*|--from=*|--bodytext=*)
OPTARG=${opt#--*=}
opt=${opt%%=*}
;;
@@ -71,9 +94,7 @@ while getopts :s:c:b:i:hC opt; do
;;
esac
-
- OPTARG="${OPTARG-none}"
- OPTARG="$(escape "${OPTARG}")"
+ escape -v OPTARG "${OPTARG-}"
case "${opt}" in
--help|h)
@@ -82,26 +103,48 @@ while getopts :s:c:b:i:hC opt; do
--client|C)
USE_EMACSCLIENT="yes"
;;
+ --from)
+ FROM=${OPTARG}
+ ;;
--subject|s)
- ELISP="${ELISP} (message-goto-subject) (insert \"${OPTARG}\")"
+ SUBJECT=${SUBJECT:+$SUBJECT }${OPTARG}
+ message_goto='(message-goto-subject)'
;;
--to)
- ELISP="${ELISP} (message-goto-to) (insert \"${OPTARG}, \")"
+ TO=${TO:+$TO, }${OPTARG}
+ message_goto='(message-goto-to)'
;;
--cc|c)
- ELISP="${ELISP} (message-goto-cc) (insert \"${OPTARG}, \")"
+ CC=${CC:+$CC, }${OPTARG}
+ message_goto='(message-goto-cc)'
;;
--bcc|b)
- ELISP="${ELISP} (message-goto-bcc) (insert \"${OPTARG}, \")"
+ BCC=${BCC:+$BCC, }${OPTARG}
+ message_goto='(message-goto-bcc)'
;;
--body|i)
- ELISP="${ELISP} (message-goto-body) (cd \"${PWD}\") (insert-file \"${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)
+ BODY=${BODY}$'\n'" (insert \"${OPTARG}\\n\")"
+ unset message_goto
;;
--print)
PRINT_ONLY=1
;;
--no-window-system)
- CLIENT_TYPE="-t"
+ EMACSCLIENT_TYPE='-t'
+ EMACS_NW='-nw'
;;
*)
# We should never end up here.
@@ -116,21 +159,39 @@ done
# Positional parameters.
for arg; do
- arg="$(escape "${arg}")"
- ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")"
+ escape -v _arg "${arg}"
+ TO=${TO:+$TO, }${_arg}
+ message_goto='(message-goto-to)'
done
-# End progn.
-ELISP="${ELISP})"
+# The newlines are here for better user experience when --print option is used.
+NL=$'\n'
+ELISP="\
+${CC:+$NL (message-goto-cc) (insert \"$CC\")}\
+${BCC:+$NL (message-goto-bcc) (insert \"$BCC\")}\
+${BODY:+$NL (message-goto-body)$BODY}"
-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}"
+if [[ $TO == '' && $SUBJECT == '' && $ELISP == '' ]]
+then
+ exec_mua "(prog1 'done (require 'notmuch) (notmuch-hello))"
else
- exec ${EMACS} --eval "${ELISP}"
+ [[ $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 "(prog1 'done (require 'notmuch)
+ (setq message-exit-actions (list #'save-buffers-kill-terminal))
+ (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.1.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] notmuch-emacs-mua: more options, some fixes
2015-03-07 10:36 [PATCH] notmuch-emacs-mua: more options, some fixes Tomi Ollila
@ 2015-03-07 14:12 ` Jani Nikula
0 siblings, 0 replies; 2+ messages in thread
From: Jani Nikula @ 2015-03-07 14:12 UTC (permalink / raw)
To: Tomi Ollila, notmuch; +Cc: tomi.ollila
On Sat, 07 Mar 2015, Tomi Ollila <tomi.ollila@iki.fi> wrote:
> Two new options added:
> --from: specify alternate From: header
> --bodytext: possibility to give body content from command line
>
> Non-forking escape() functionality, also escaping \ (backslash) characters.
>
> Without content arguments start emacs/emacsclient and run (notmuch-hello),
> in this case without assigning anything to message-exit-actions.
>
> Point is now positioned at the end of the content given last on command
> line, unless to: or subject: is missing -- in which case point is
> positioned at one of these headers (is both missing, at to:)
>
> The -nw option is now given to emacs in case --no-window-system command
> line option is provided (--no-window-system used to work with emacsclient
> only).
>
> In case EMACS or EMACSCLIENT environment variable was defined but being
> empty (null string), use emacs/emacsclient as command instead (null string
> as executable name gives confusing error message). Also $EMACS/$EMACSCLIENT
> executable name is now quoted to *NOT* split it to separate command line
> arguments on any $IFS variables there might be.
>
> Reorganized content argument handling to combine the content of same option
> given multiple times and make it look more readable when --print option is
> used. --body option also now checks the existence of the file to be
> included and if the file included does not end with newline trailing
> newline is inserted to the message buffer.
>
> As bash supports [[ ]] command and it's special expansion (or lack thereof)
> of variables (and ==, && and || inside) the few [ ]'s there were are now
> changed to this more advanced format.
As I mentioned on IRC, I think there are too many changes here for one
patch. One change at a time! In particular because I'm not sure if all
of this is really needed... like message_goto and point placement
handling. Starts to feel like all of this would be better handled with a
dedicated function in emacs!
BR,
Jani.
> ---
>
> The changes *NOT* taken from my 2 draft patches (*)
>
> 1) no -nw hacking
>
> 2) no mailto: handling
>
> (*) id:1421776424-24304-1-git-send-email-tomi.ollila@iki.fi (later, linking
> previous)
>
>
> doc/man1/notmuch-emacs-mua.rst | 8 ++-
> notmuch-emacs-mua | 123 ++++++++++++++++++++++++++++++-----------
> 2 files changed, 99 insertions(+), 32 deletions(-)
>
> diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst
> index eb47098..29f7e0c 100644
> --- a/doc/man1/notmuch-emacs-mua.rst
> +++ b/doc/man1/notmuch-emacs-mua.rst
> @@ -22,6 +22,9 @@ Supported options for **notmuch-emacs-mua** include
> Use emacsclient, rather than emacs. This will start
> an emacs daemon process if necessary.
>
> + ``--from=``\ <from>
> + Specify alternate sender (From) of the message.
> +
> ``-s, --subject=``\ <subject>
> Specify the subject of the message.
>
> @@ -37,6 +40,9 @@ Supported options for **notmuch-emacs-mua** include
> ``-i, --body=``\ <file>
> Specify a file to include into the body of the message.
>
> + ``--bodytext=``\ <text>
> + Specify text content to be inserted into the body of the message.
> +
> ``--no-window-system``
> Even if a window system is available, use the current terminal
>
> @@ -60,4 +66,4 @@ Name of emacsclient comment to invoke
> SEE ALSO
> ========
>
> -**notmuch(1)**, **emacsclient(1)**, **mutt(1)**
> +**notmuch(1)**, **emacs(1)**, **emacsclient(1)**, **mutt(1)**
> diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua
> index b8cbc82..17365b9 100755
> --- a/notmuch-emacs-mua
> +++ b/notmuch-emacs-mua
> @@ -1,4 +1,5 @@
> #!/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
> #
> @@ -18,25 +19,47 @@
> # 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
>
> +# escape: "expand" '\' to '\\' & '"' to '\"'
> +# Calling convention: escape -v var "$arg" (like in bash printf).
> escape ()
> {
> - echo "${1//\"/\\\"}"
> + local arg=${3//\\/\\\\}
> + eval $2='${arg//\"/\\\"}'
> }
>
> -EMACS=${EMACS-emacs}
> -EMACSCLIENT=${EMACSCLIENT-emacsclient}
> +EMACS=${EMACS:-emacs}
> +EMACSCLIENT=${EMACSCLIENT:-emacsclient}
>
> PRINT_ONLY=
> USE_EMACSCLIENT=
> -CLIENT_TYPE="-c"
> +EMACSCLIENT_TYPE='-c'
> +EMACS_NW=
>
> -# 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))"
> +exec_mua ()
> +{
> + if [[ -n $PRINT_ONLY ]]; then
> + echo "$1"
> + exit
> + fi
> +
> + if [[ -n $USE_EMACSCLIENT ]]; then
> + # Evaluate the progn.
> + exec "${EMACSCLIENT}" ${EMACSCLIENT_TYPE} -a '' --eval "$1"
> + else
> + exec "${EMACS}" ${EMACS_NW} --eval "$1"
> + fi
> + exit not reached
> +}
> +
> +SUBJECT= TO= CC= BCC= BODY= FROM=
> +
> +unset message_goto # Final elisp function to execute, when defined.
> +cddone=false
>
> while getopts :s:c:b:i:hC opt; do
> # Handle errors and long options.
> @@ -47,14 +70,14 @@ while getopts :s:c:b:i:hC opt; do
> ;;
> \?)
> opt=$1
> - if [ "${OPTARG}" != "-" ]; then
> + 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=*)
> + --subject=*|--to=*|--cc=*|--bcc=*|--body=*|--from=*|--bodytext=*)
> OPTARG=${opt#--*=}
> opt=${opt%%=*}
> ;;
> @@ -71,9 +94,7 @@ while getopts :s:c:b:i:hC opt; do
> ;;
> esac
>
> -
> - OPTARG="${OPTARG-none}"
> - OPTARG="$(escape "${OPTARG}")"
> + escape -v OPTARG "${OPTARG-}"
>
> case "${opt}" in
> --help|h)
> @@ -82,26 +103,48 @@ while getopts :s:c:b:i:hC opt; do
> --client|C)
> USE_EMACSCLIENT="yes"
> ;;
> + --from)
> + FROM=${OPTARG}
> + ;;
> --subject|s)
> - ELISP="${ELISP} (message-goto-subject) (insert \"${OPTARG}\")"
> + SUBJECT=${SUBJECT:+$SUBJECT }${OPTARG}
> + message_goto='(message-goto-subject)'
> ;;
> --to)
> - ELISP="${ELISP} (message-goto-to) (insert \"${OPTARG}, \")"
> + TO=${TO:+$TO, }${OPTARG}
> + message_goto='(message-goto-to)'
> ;;
> --cc|c)
> - ELISP="${ELISP} (message-goto-cc) (insert \"${OPTARG}, \")"
> + CC=${CC:+$CC, }${OPTARG}
> + message_goto='(message-goto-cc)'
> ;;
> --bcc|b)
> - ELISP="${ELISP} (message-goto-bcc) (insert \"${OPTARG}, \")"
> + BCC=${BCC:+$BCC, }${OPTARG}
> + message_goto='(message-goto-bcc)'
> ;;
> --body|i)
> - ELISP="${ELISP} (message-goto-body) (cd \"${PWD}\") (insert-file \"${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)
> + BODY=${BODY}$'\n'" (insert \"${OPTARG}\\n\")"
> + unset message_goto
> ;;
> --print)
> PRINT_ONLY=1
> ;;
> --no-window-system)
> - CLIENT_TYPE="-t"
> + EMACSCLIENT_TYPE='-t'
> + EMACS_NW='-nw'
> ;;
> *)
> # We should never end up here.
> @@ -116,21 +159,39 @@ done
>
> # Positional parameters.
> for arg; do
> - arg="$(escape "${arg}")"
> - ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")"
> + escape -v _arg "${arg}"
> + TO=${TO:+$TO, }${_arg}
> + message_goto='(message-goto-to)'
> done
>
> -# End progn.
> -ELISP="${ELISP})"
> +# The newlines are here for better user experience when --print option is used.
> +NL=$'\n'
> +ELISP="\
> +${CC:+$NL (message-goto-cc) (insert \"$CC\")}\
> +${BCC:+$NL (message-goto-bcc) (insert \"$BCC\")}\
> +${BODY:+$NL (message-goto-body)$BODY}"
>
> -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}"
> +if [[ $TO == '' && $SUBJECT == '' && $ELISP == '' ]]
> +then
> + exec_mua "(prog1 'done (require 'notmuch) (notmuch-hello))"
> else
> - exec ${EMACS} --eval "${ELISP}"
> + [[ $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 "(prog1 'done (require 'notmuch)
> + (setq message-exit-actions (list #'save-buffers-kill-terminal))
> + (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.1.0
>
> _______________________________________________
> notmuch mailing list
> notmuch@notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-03-07 14:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-07 10:36 [PATCH] notmuch-emacs-mua: more options, some fixes Tomi Ollila
2015-03-07 14:12 ` Jani Nikula
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).