[DRAFT PATCH] modified notmuch-emacs-mua

Subject: [DRAFT PATCH] modified notmuch-emacs-mua

Date: Fri, 11 Jul 2014 00:12:59 +0300

To: notmuch@notmuchmail.org, jani@nikula.org, david@tethera.net, jrollins@finestructure.net

Cc: tomi.ollila@iki.fi

From: Tomi Ollila


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@nikula.org>
+#          Tomi Ollila <tomi.ollila@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


Thread: