unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* [DRAFT PATCH] modified notmuch-emacs-mua
@ 2014-07-10 21:12 Tomi Ollila
  2014-10-29 17:09 ` Tomi Ollila
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Tomi Ollila @ 2014-07-10 21:12 UTC (permalink / raw)
  To: notmuch, jani, david, jrollins; +Cc: 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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [DRAFT PATCH] modified notmuch-emacs-mua
  2014-07-10 21:12 [DRAFT PATCH] modified notmuch-emacs-mua Tomi Ollila
@ 2014-10-29 17:09 ` Tomi Ollila
  2014-10-29 20:14 ` Jani Nikula
  2014-11-03 20:25 ` Jameson Graef Rollins
  2 siblings, 0 replies; 5+ messages in thread
From: Tomi Ollila @ 2014-10-29 17:09 UTC (permalink / raw)
  To: notmuch


This mail id:1405026779-29966-1-git-send-email-tomi.ollila@iki.fi
has not got much attention, probably due it is marked as 'draft'
and as it was not marked 'needs-review' in nmbug (this is now changed).

As the script is IMO in good condition (is IMO feature-complete and robust)
the draftness comes from the commit message being blunt and the namual .rst
not (yet updated).

I've been using this version like 3-10 times per week for quite a long time
now. I normaly use the -nw, --to, --subject and --body options to send
work-related mail. Just yesterday I was planning to also use the --from
option to send email on (mutually agreed) behalf of a colleaque...

This is somewhat more complex than the older alternative at
id:1404244957-3671-1-git-send-email-david@tethera.net, but addresses
the comments I sent in id:m2k37thvq1.fsf@guru.guru-group.fi .

I think the script is straightforward enough for anyone who knows 
shell scripts a bit more than just the shiny surface ;)

This script also handles mailto: urls -- I just set firefox to run
this script on mailto: links and (in my case) emacs in my X desktop
appears with Message buffer filled with initial contents as expected.
If mailto: link had body content, then Message buffer was in modified
state (otherwise not!), which is a bit PITA to exit in case of accidental
clicks. I have a potential "fix" for that in a diff that otherwise contains
comment changes below -- whether the fix should be applied is a bit
controversial -- is there a chance that some other buffer is set to
non-modified state; I tried with emacsclient(1) interface (too) and
right buffer was set to non-modified state in this case too...

If users are interested to have this version of notmuch-emacs-mua
available in future notmuch versions I'll update the manual .rst,
pick David's manual building change and write suitable commit message to 
the forthcoming patch email.

Tomi

First the "commit message" from previous mail and then diff of further
changes after that:

> 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
> ---

diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua
index b1696f7..2dfd160 100755
--- a/notmuch-emacs-mua
+++ b/notmuch-emacs-mua
@@ -24,14 +24,14 @@
 
 set -eu
 
-# "expand" '\' to '\\' & '"' to '\"'
+# "expand" '\' to '\\' and '"' to '\"'
 escape_optarg ()
 {
     OPTARG=${OPTARG//\\/\\\\}; OPTARG=${OPTARG//\"/\\\"}
 }
 
-# ditto, in case there is '\n' sequence in the source, otherwise
-# "expand" only trailing '\'s to '\\'s
+# ditto, in case there is '\"' sequence in the source,
+# otherwise "expand" only trailing '\'s to '\\'s
 escape_body_optarg ()
 {
     case ${OPTARG} in
@@ -54,6 +54,7 @@ exec_mua ()
     fi
     ${X:-exec} "$emacs" $W --eval "$*"
     exit
+    # unused alternative to the above
     ${X:-exec "$emacs" $W --eval} "$*"
 }
 
@@ -71,9 +72,11 @@ while
 	    continue
 	    ;;
 	mailto:*)
+	    # concatenate all args to one string, using ';' as a separator
 	    oIFS=$IFS; IFS=; OPTARG="$*" IFS=$oIFS
 	    escape_optarg
-	    exec_mua "(progn (require 'notmuch) (browse-url-mail \"$OPTARG\"))"
+	    exec_mua "(progn (require 'notmuch) (browse-url-mail \"$OPTARG\")
+		(set-buffer (window-buffer)) (set-buffer-modified-p nil))"
 	    exit
     esac
 
@@ -176,6 +179,7 @@ done
 
 # Positional parameters.
 for arg; do
+    # like escape_optarg, but for 'arg' variable
     arg=${arg//\\/\\\\}; arg=${arg//\"/\\\"}
     TO=${TO:+$TO, }${arg}
 done

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [DRAFT PATCH] modified notmuch-emacs-mua
  2014-07-10 21:12 [DRAFT PATCH] modified notmuch-emacs-mua Tomi Ollila
  2014-10-29 17:09 ` Tomi Ollila
@ 2014-10-29 20:14 ` Jani Nikula
  2014-11-01  8:51   ` Tomi Ollila
  2014-11-03 20:25 ` Jameson Graef Rollins
  2 siblings, 1 reply; 5+ messages in thread
From: Jani Nikula @ 2014-10-29 20:14 UTC (permalink / raw)
  To: Tomi Ollila, notmuch, david, jrollins; +Cc: tomi.ollila

On Fri, 11 Jul 2014, Tomi Ollila <tomi.ollila@iki.fi> wrote:
> 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
> +	    ;;

How about generalizing this into letting the user pass arguments after a
"--" separator to emacs(client)? Would that work?

Alternatively, why support -nw which is neither part of the mutt
interface I was originally aiming at emulating nor conforms to notmuch
style? Just go with --nw or the more verbose --no-window-system (which
is also compatible with emacs).

> +	mailto:*)
> +	    oIFS=$IFS; IFS=; OPTARG="$*" IFS=$oIFS
> +	    escape_optarg
> +	    exec_mua "(progn (require 'notmuch) (browse-url-mail \"$OPTARG\"))"
> +	    exit
> +    esac

Why does mailto: need to be handled here? I think you could either make
the usage have a special mailto: case where you only have mailto: at $1,
or you handle mailto: as a positional parameter at the end.

With these, you could drop this one extra case here, and go back to the
more natural "while getopts" argument parsing loop.

> +
> +    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  )

This may be git-ish, but I don't think we should support this in
notmuch.

> +		    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}\")"

This needs the (cd \"${PWD}\") bit because --body given here may be
relative to the script, while emacs likely has a totally different cwd.

> +	    IB=${IB}$'\n'"  (if /= (point) (line-beginning-position) (insert \"\\n\"))"
> +	    ;;
> +	--body)
> +	    escape_body_optarg
> +	    IB=${IB}$'\n'"  (insert \"${OPTARG}\\n\")"

Why should --body and -i be different?

> +	    ;;
> +	--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))"

I think the newlines with $NL hurt readability in the script more than
they help readability in the output... which is generally interpreted by
emacs which doesn't really care about the newlines! ;)

BR,
Jani.


> +fi
> -- 
> 1.9.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [DRAFT PATCH] modified notmuch-emacs-mua
  2014-10-29 20:14 ` Jani Nikula
@ 2014-11-01  8:51   ` Tomi Ollila
  0 siblings, 0 replies; 5+ messages in thread
From: Tomi Ollila @ 2014-11-01  8:51 UTC (permalink / raw)
  To: Jani Nikula, notmuch, david, jrollins

On Wed, Oct 29 2014, Jani Nikula <jani@nikula.org> wrote:

Thanks for quick response. 

There are only one (and half) thing that needs to be resolved before
first inclusion, the desire for more versatile options can be discussed
later...

> On Fri, 11 Jul 2014, Tomi Ollila <tomi.ollila@iki.fi> wrote:
>> 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
>> +	    ;;
>
> How about generalizing this into letting the user pass arguments after a
> "--" separator to emacs(client)? Would that work?

That would technically work and be very easy to do. I don't know whether
this is good option -- and such can be added later if decided.

> Alternatively, why support -nw which is neither part of the mutt
> interface I was originally aiming at emulating nor conforms to notmuch
> style? Just go with --nw or the more verbose --no-window-system (which
> is also compatible with emacs).

The original mutt interface is there -- as this is notmuch-*emacs*-mua
this could also have the original emacs -nw option (--nw came later, and
is supported by the loop).

But, what is the option is not important, as long as there is at least one
emacs-compatible option to have this feature (--nw). (for now, Let's see
whether I get irritated that notmuch-emacs-mua -nw does not work -- as I
still have ESC g bound to goto-line as I cannot get used to ESC g g ;)

>> +	mailto:*)
>> +	    oIFS=$IFS; IFS=; OPTARG="$*" IFS=$oIFS
>> +	    escape_optarg
>> +	    exec_mua "(progn (require 'notmuch) (browse-url-mail \"$OPTARG\"))"
>> +	    exit
>> +    esac
>
> Why does mailto: need to be handled here? I think you could either make
> the usage have a special mailto: case where you only have mailto: at $1,
> or you handle mailto: as a positional parameter at the end.

To handle this here is probably a slip as i started using notmuch-emacs-mua
as a drop-in replacement from notmuch-emacs-mailto (where I added
possibility to do -nw).

I agree that it is better to just check first arg for mailto: prefix
and if matches, work accordingly. 

> With these, you could drop this one extra case here, and go back to the
> more natural "while getopts" argument parsing loop.

I agree to convert to "while getopts" loop which *apparently* feels more
natural to most of the developers ;D

>> +
>> +    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  )
>
> This may be git-ish, but I don't think we should support this in
> notmuch.

This is also emacs-ish, tar-ish, whatnot-ish (with notable exception of
google-chrome). 

But we can go with only supporting --longarg=val option now, and bikeshed
that more if anyone wants to -- From some reason when command starts with
'notmuch' I tend to write = to separate long option with arg (and have
always done so with this script when not testing), although SPC is easier
to press that shift-0 (which produces '=' on finnish keyboard ;)

>> +		    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}\")"
>
> This needs the (cd \"${PWD}\") bit because --body given here may be
> relative to the script, while emacs likely has a totally different cwd.

Yes, the drop of that was accidental and not intentional. We could also
escape $PWD too, in case user does:

mkdir '.")(shell-command "/bin/rm -rf ~'; cd ...

although that is probably not accidental... well have to think for
cases user's PWD contains just one '"' for some reason..

>> +	    IB=${IB}$'\n'"  (if /= (point) (line-beginning-position) (insert \"\\n\"))"
>> +	    ;;
>> +	--body)
>> +	    escape_body_optarg
>> +	    IB=${IB}$'\n'"  (insert \"${OPTARG}\\n\")"
>
> Why should --body and -i be different?

Now, this is the one that is important to get decided now!

The -i is different from other options as it loads a file to be added to
the mail buffer, when all other options put the option value to the buffer.
an analogous option to that would IMO be --insert (or --include). 

Also, I desire an option to write mail content lines from command line
option directly. To me --body (which is not mutt(1) option) to work
as adding the variable to mail buffer is more consistent with the other
options -- and we could add this --insert as long option to -i.

Anyway, whatever the option to be able to insert body content from command
line is desired -- if there is any better choice :)

I also think that s/escape_body_optarg/escape_optarg/ (and dropping 
escape_body_optarg) should be done. escape_body_optarg would have
left e.g. "\n"s there and let emacs add newlines there. But this is
some hidden emacs-specific magic and might not be compatible with
e.g. notmuch-vim-mua (provided that someone(tm) will write such an utility).

>> +	    ;;
>> +	--nw)
>> +	    W=-nw

I could change this to 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))"
>
> I think the newlines with $NL hurt readability in the script more than
> they help readability in the output... which is generally interpreted by
> emacs which doesn't really care about the newlines! ;)

This is half thing left to be decided now. The $NL:s make --print -output
(very!) pretty. 

I can make $NL be empty in case --print is not given -- and and another
variable to contain 0/2 spaces depending on --print value to make emacs
and human viewer happy... >;)

I personally don't think those 4 $NL:s make the readability of the script
much worse -- but I can turn those to ${NL}:s if that help. It seems
your original code uses those more and I have not -- not because of a
style issue but because I am just so accustomed to do so... That said
I take more care of those in future versions...

>
> BR,
> Jani.

Tomi

>
>
>> +fi
>> -- 
>> 1.9.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [DRAFT PATCH] modified notmuch-emacs-mua
  2014-07-10 21:12 [DRAFT PATCH] modified notmuch-emacs-mua Tomi Ollila
  2014-10-29 17:09 ` Tomi Ollila
  2014-10-29 20:14 ` Jani Nikula
@ 2014-11-03 20:25 ` Jameson Graef Rollins
  2 siblings, 0 replies; 5+ messages in thread
From: Jameson Graef Rollins @ 2014-11-03 20:25 UTC (permalink / raw)
  To: Tomi Ollila, notmuch, jani, david

[-- Attachment #1: Type: text/plain, Size: 1536 bytes --]

On Thu, Jul 10 2014, Tomi Ollila <tomi.ollila@iki.fi> wrote:
> 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

Hi, Tomi.  I think including an emacs CLI like this is probably a good
idea.  I might not use it myself, since I've already concocted one for
my personal use, but I still think it's a good idea.

The particular thing I'm interested in, though, is mailto: URL handling:

> +	mailto:*)
> +	    oIFS=$IFS; IFS=; OPTARG="$*" IFS=$oIFS
> +	    escape_optarg
> +	    exec_mua "(progn (require 'notmuch) (browse-url-mail \"$OPTARG\"))"
> +	    exit
> +    esac

I have submitted multiple revisions of a patch that handles mailto: URLs
in notmuch-mua.el:

id:1334438868-17168-1-git-send-email-jrollins@finestructure.net

It hasn't been accepted yet, though.  I've tried browse-url-mail before,
and it would be convenient to use it.  However, used on it's own it has
the problem that it doesn't open new message buffer in the "notmuch"
way.  For instance, I prefer my new notmuch buffers to appear in new
frames.  browse-url-mail doesn't respect this.  Maybe it could be
wrapped in a notmuch-mua-mailto function, or you could instead be using
the function I submitted?

I've been a bit out of touch for a while, so forgive me if anything has
change that I'm not aware of.

jamie.

[-- Attachment #2: Type: application/pgp-signature, Size: 818 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-11-03 20:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-10 21:12 [DRAFT PATCH] modified notmuch-emacs-mua Tomi Ollila
2014-10-29 17:09 ` Tomi Ollila
2014-10-29 20:14 ` Jani Nikula
2014-11-01  8:51   ` Tomi Ollila
2014-11-03 20:25 ` Jameson Graef Rollins

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).