Highlights:

* notmuch-emacs-mua without arguments runs (notmuch-hello)

* runs emacs(1) in case emacsclient(1) fails to connect to running emacs

* takes -nw option

* handles mailto:

* --from option when sending non-mailto: way

* -i includes file --body[= ]string inserts string
---
 notmuch-emacs-mua | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 200 insertions(+)
 create mode 100755 notmuch-emacs-mua

diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua
new file mode 100755
index 0000000..b1696f7
--- /dev/null
+++ b/notmuch-emacs-mua
@@ -0,0 +1,200 @@
+#!/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 at nikula.org>
+#          Tomi Ollila <tomi.ollila at iki.fi>
+#
+
+set -eu
+
+# "expand" '\' to '\\' & '"' to '\"'
+escape_optarg ()
+{
+    OPTARG=${OPTARG//\\/\\\\}; OPTARG=${OPTARG//\"/\\\"}
+}
+
+# ditto, in case there is '\n' sequence in the source, otherwise
+# "expand" only trailing '\'s to '\\'s
+escape_body_optarg ()
+{
+    case ${OPTARG} in
+       *'\"'*) OPTARG=${OPTARG//\\/\\\\} ;;
+       *'\') OPTARG=$( printf %s "${OPTARG}" | sed 's/\(\\*\)$/\1\1/' )
+    esac
+    OPTARG=${OPTARG//\"/\\\"}
+}
+
+unset ALTERNATE_EDITOR
+exec_mua ()
+{
+    if "${EMACSCLIENT:=emacsclient}" --eval t >/dev/null 2>&1
+    then
+       emacs=$EMACSCLIENT
+       # close stdout in case no -nw (and no --print)
+       test -n "$W$X" || exec >/dev/null
+    else
+       emacs=${EMACS:-emacs}
+    fi
+    ${X:-exec} "$emacs" $W --eval "$*"
+    exit
+    ${X:-exec "$emacs" $W --eval} "$*"
+}
+
+X=
+W=
+
+SUBJECT= TO= CC= BCC= BODY= FROM= IB=
+
+while
+    # first, handle "long" options which cannot be handled by getopts
+    case ${1-} in
+       -nw)
+           W=-nw
+           shift
+           continue
+           ;;
+       mailto:*)
+           oIFS=$IFS; IFS=; OPTARG="$*" IFS=$oIFS
+           escape_optarg
+           exec_mua "(progn (require 'notmuch) (browse-url-mail \"$OPTARG\"))"
+           exit
+    esac
+
+    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=*|--from=*)
+                   OPTARG=${opt#--*=}
+                   opt=${opt%%=*}
+                   ;;
+               # Long options with argument in next arg.
+               --subject  |--to  |--cc  |--bcc  |--body  |--from  )
+                   if [[ $# < 2 ]]; then
+                       echo "$0: option '${opt}' requires an argument." >&2
+                       exit 1
+                   fi
+                   OPTARG=$2
+                   OPTIND=$((OPTIND + 1))
+                   ;;
+               # Long options without arguments.
+               --help|--nw|--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-emacs-mua
+           ;;
+       --from)
+           escape_optarg
+           FROM=${OPTARG}
+           ;;
+       --subject|s)
+           escape_optarg
+           SUBJECT=${SUBJECT:+$SUBJECT }${OPTARG}
+           ;;
+       --to)
+           escape_optarg
+           TO=${TO:+$TO, }${OPTARG}
+           ;;
+       --cc|c)
+           escape_optarg
+           CC=${CC:+$CC, }${OPTARG}
+           ;;
+       --bcc|b)
+           escape_optarg
+           BCC=${BCC:+$BCC, }${OPTARG}
+           ;;
+       i)
+           escape_optarg
+           if [[ ! -f ${OPTARG} ]]; then
+               echo "$0: '${OPTARG}': no such file" >&2
+               exit 1
+           fi
+           IB=${IB}$'\n'"  (insert-file \"${OPTARG}\")"
+           IB=${IB}$'\n'"  (if /= (point) (line-beginning-position) (insert 
\"\\n\"))"
+           ;;
+       --body)
+           escape_body_optarg
+           IB=${IB}$'\n'"  (insert \"${OPTARG}\\n\")"
+           ;;
+       --nw)
+           W=-nw
+           ;;
+       --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
+    arg=${arg//\\/\\\\}; arg=${arg//\"/\\\"}
+    TO=${TO:+$TO, }${arg}
+done
+
+NL=$'\n'
+ELISP="\
+${CC:+$NL  (message-goto-cc) (insert \"$CC\")}\
+${BCC:+$NL  (message-goto-bcc) (insert \"$BCC\")}\
+${IB:+$NL  (message-goto-body)$IB}"
+
+if [[ $TO == '' && $SUBJECT == '' && $ELISP == '' ]]
+then
+    exec_mua "(progn (require 'notmuch) (notmuch-hello))"
+else
+    [[ $FROM != '' ]] && OH="(list (cons 'From \"$FROM\"))" || OH=nil
+    [[ $TO != '' ]] && TO=\"$TO\" || TO=nil
+    [[ $SUBJECT != '' ]] && SUBJECT=\"$SUBJECT\" || SUBJECT=nil
+    exec_mua "$NL(progn (require 'notmuch)
+  (notmuch-mua-mail $TO $SUBJECT
+       $OH nil (notmuch-mua-get-switch-function))\
+$ELISP$NL  (set-buffer-modified-p nil) (message-goto-to))"
+fi
-- 
1.9.0

Reply via email to