Re: [PATCH v4 01/16] add util/search-path.{c, h} to test for executables in $PATH
[notmuch-archives.git] / 48 / c1e542a175bf201ac0257a3e49fad15326a810
1 Return-Path: <too@guru-group.fi>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 119C6431FBC\r
6         for <notmuch@notmuchmail.org>; Sat,  7 Mar 2015 02:37:21 -0800 (PST)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: 2.438\r
10 X-Spam-Level: **\r
11 X-Spam-Status: No, score=2.438 tagged_above=-999 required=5\r
12         tests=[DNS_FROM_AHBL_RHSBL=2.438] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id BFXoDf4rNSqF for <notmuch@notmuchmail.org>;\r
16         Sat,  7 Mar 2015 02:37:15 -0800 (PST)\r
17 Received: from guru.guru-group.fi (guru.guru-group.fi [46.183.73.34])\r
18         by olra.theworths.org (Postfix) with ESMTP id 91162431FAE\r
19         for <notmuch@notmuchmail.org>; Sat,  7 Mar 2015 02:37:15 -0800 (PST)\r
20 Received: by guru.guru-group.fi (Postfix, from userid 501)\r
21         id 6DC5C100293; Sat,  7 Mar 2015 12:36:49 +0200 (EET)\r
22 From: Tomi Ollila <tomi.ollila@iki.fi>\r
23 To: notmuch@notmuchmail.org\r
24 Subject: [PATCH] notmuch-emacs-mua: more options, some fixes\r
25 Date: Sat,  7 Mar 2015 12:36:45 +0200\r
26 Message-Id: <1425724605-392-1-git-send-email-tomi.ollila@iki.fi>\r
27 X-Mailer: git-send-email 2.0.0\r
28 Cc: tomi.ollila@iki.fi\r
29 X-BeenThere: notmuch@notmuchmail.org\r
30 X-Mailman-Version: 2.1.13\r
31 Precedence: list\r
32 List-Id: "Use and development of the notmuch mail system."\r
33         <notmuch.notmuchmail.org>\r
34 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
35         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
36 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
37 List-Post: <mailto:notmuch@notmuchmail.org>\r
38 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
39 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
40         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
41 X-List-Received-Date: Sat, 07 Mar 2015 10:37:22 -0000\r
42 \r
43 Two new options added:\r
44    --from: specify alternate From: header\r
45    --bodytext: possibility to give body content from command line\r
46 \r
47 Non-forking escape() functionality, also escaping \ (backslash) characters.\r
48 \r
49 Without content arguments start emacs/emacsclient and run (notmuch-hello),\r
50 in this case without assigning anything to message-exit-actions.\r
51 \r
52 Point is now positioned at the end of the content given last on command\r
53 line, unless to: or subject: is missing -- in which case point is\r
54 positioned at one of these headers (is both missing, at to:)\r
55 \r
56 The -nw option is now given to emacs in case --no-window-system command\r
57 line option is provided (--no-window-system used to work with emacsclient\r
58 only).\r
59 \r
60 In case EMACS or EMACSCLIENT environment variable was defined but being\r
61 empty (null string), use emacs/emacsclient as command instead (null string\r
62 as executable name gives confusing error message). Also $EMACS/$EMACSCLIENT\r
63 executable name is now quoted to *NOT* split it to separate command line\r
64 arguments on any $IFS variables there might be.\r
65 \r
66 Reorganized content argument handling to combine the content of same option\r
67 given multiple times and make it look more readable when --print option is\r
68 used. --body option also now checks the existence of the file to be\r
69 included and if the file included does not end with newline trailing\r
70 newline is inserted to the message buffer.\r
71 \r
72 As bash supports [[ ]] command and it's special expansion (or lack thereof)\r
73 of variables (and ==, && and || inside) the few [ ]'s there were are now\r
74 changed to this more advanced format.\r
75 ---\r
76 \r
77 The changes *NOT* taken from my 2 draft patches (*)\r
78 \r
79 1) no -nw hacking\r
80 \r
81 2) no mailto: handling\r
82 \r
83 (*) id:1421776424-24304-1-git-send-email-tomi.ollila@iki.fi (later, linking\r
84 previous)\r
85 \r
86 \r
87  doc/man1/notmuch-emacs-mua.rst |   8 ++-\r
88  notmuch-emacs-mua              | 123 ++++++++++++++++++++++++++++++-----------\r
89  2 files changed, 99 insertions(+), 32 deletions(-)\r
90 \r
91 diff --git a/doc/man1/notmuch-emacs-mua.rst b/doc/man1/notmuch-emacs-mua.rst\r
92 index eb47098..29f7e0c 100644\r
93 --- a/doc/man1/notmuch-emacs-mua.rst\r
94 +++ b/doc/man1/notmuch-emacs-mua.rst\r
95 @@ -22,6 +22,9 @@ Supported options for **notmuch-emacs-mua** include\r
96          Use emacsclient, rather than emacs. This will start\r
97          an emacs daemon process if necessary.\r
98  \r
99 +    ``--from=``\ <from>\r
100 +        Specify alternate sender (From) of the message.\r
101 +\r
102      ``-s, --subject=``\ <subject>\r
103          Specify the subject of the message.\r
104  \r
105 @@ -37,6 +40,9 @@ Supported options for **notmuch-emacs-mua** include\r
106      ``-i, --body=``\ <file>\r
107          Specify a file to include into the body of the message.\r
108  \r
109 +    ``--bodytext=``\ <text>\r
110 +        Specify text content to be inserted into the body of the message.\r
111 +\r
112      ``--no-window-system``\r
113          Even if a window system is available, use the current terminal\r
114  \r
115 @@ -60,4 +66,4 @@ Name of emacsclient comment to invoke\r
116  SEE ALSO\r
117  ========\r
118  \r
119 -**notmuch(1)**, **emacsclient(1)**, **mutt(1)**\r
120 +**notmuch(1)**, **emacs(1)**, **emacsclient(1)**, **mutt(1)**\r
121 diff --git a/notmuch-emacs-mua b/notmuch-emacs-mua\r
122 index b8cbc82..17365b9 100755\r
123 --- a/notmuch-emacs-mua\r
124 +++ b/notmuch-emacs-mua\r
125 @@ -1,4 +1,5 @@\r
126  #!/usr/bin/env bash\r
127 +# -*- mode: shell-script; sh-basic-offset: 4; tab-width: 8 -*-\r
128  #\r
129  # notmuch-emacs-mua - start composing a mail on the command line\r
130  #\r
131 @@ -18,25 +19,47 @@\r
132  # along with this program.  If not, see http://www.gnu.org/licenses/ .\r
133  #\r
134  # Authors: Jani Nikula <jani@nikula.org>\r
135 +#          Tomi Ollila <tomi.ollila@iki.fi>\r
136  #\r
137  \r
138  set -eu\r
139  \r
140 +# escape: "expand" '\' to '\\' & '"' to '\"'\r
141 +# Calling convention: escape -v var "$arg" (like in bash printf).\r
142  escape ()\r
143  {\r
144 -    echo "${1//\"/\\\"}"\r
145 +    local arg=${3//\\/\\\\}\r
146 +    eval $2='${arg//\"/\\\"}'\r
147  }\r
148  \r
149 -EMACS=${EMACS-emacs}\r
150 -EMACSCLIENT=${EMACSCLIENT-emacsclient}\r
151 +EMACS=${EMACS:-emacs}\r
152 +EMACSCLIENT=${EMACSCLIENT:-emacsclient}\r
153  \r
154  PRINT_ONLY=\r
155  USE_EMACSCLIENT=\r
156 -CLIENT_TYPE="-c"\r
157 +EMACSCLIENT_TYPE='-c'\r
158 +EMACS_NW=\r
159  \r
160 -# The crux of it all: construct an elisp progn and eval it.\r
161 -ELISP="(prog1 'done (require 'notmuch) (notmuch-mua-new-mail)"\r
162 -ELISP="${ELISP} (setq message-exit-actions (list #'save-buffers-kill-terminal))"\r
163 +exec_mua ()\r
164 +{\r
165 +    if [[ -n $PRINT_ONLY ]]; then\r
166 +       echo "$1"\r
167 +       exit\r
168 +    fi\r
169 +\r
170 +    if [[ -n $USE_EMACSCLIENT ]]; then\r
171 +       # Evaluate the progn.\r
172 +       exec "${EMACSCLIENT}" ${EMACSCLIENT_TYPE} -a '' --eval "$1"\r
173 +    else\r
174 +       exec "${EMACS}" ${EMACS_NW} --eval "$1"\r
175 +    fi\r
176 +    exit not reached\r
177 +}\r
178 +\r
179 +SUBJECT= TO= CC= BCC= BODY= FROM=\r
180 +\r
181 +unset message_goto # Final elisp function to execute, when defined.\r
182 +cddone=false\r
183  \r
184  while getopts :s:c:b:i:hC opt; do\r
185      # Handle errors and long options.\r
186 @@ -47,14 +70,14 @@ while getopts :s:c:b:i:hC opt; do\r
187             ;;\r
188         \?)\r
189             opt=$1\r
190 -           if [ "${OPTARG}" != "-" ]; then\r
191 +           if [[ ${OPTARG} != '-' ]]; then\r
192                 echo "$0: unknown short option -${OPTARG}." >&2\r
193                 exit 1\r
194             fi\r
195  \r
196             case "${opt}" in\r
197                 # Long options with arguments.\r
198 -               --subject=*|--to=*|--cc=*|--bcc=*|--body=*)\r
199 +               --subject=*|--to=*|--cc=*|--bcc=*|--body=*|--from=*|--bodytext=*)\r
200                     OPTARG=${opt#--*=}\r
201                     opt=${opt%%=*}\r
202                     ;;\r
203 @@ -71,9 +94,7 @@ while getopts :s:c:b:i:hC opt; do\r
204             ;;\r
205      esac\r
206  \r
207 -\r
208 -    OPTARG="${OPTARG-none}"\r
209 -    OPTARG="$(escape "${OPTARG}")"\r
210 +    escape -v OPTARG "${OPTARG-}"\r
211  \r
212      case "${opt}" in\r
213         --help|h)\r
214 @@ -82,26 +103,48 @@ while getopts :s:c:b:i:hC opt; do\r
215         --client|C)\r
216             USE_EMACSCLIENT="yes"\r
217             ;;\r
218 +       --from)\r
219 +           FROM=${OPTARG}\r
220 +           ;;\r
221         --subject|s)\r
222 -           ELISP="${ELISP} (message-goto-subject) (insert \"${OPTARG}\")"\r
223 +           SUBJECT=${SUBJECT:+$SUBJECT }${OPTARG}\r
224 +           message_goto='(message-goto-subject)'\r
225             ;;\r
226         --to)\r
227 -           ELISP="${ELISP} (message-goto-to) (insert \"${OPTARG}, \")"\r
228 +           TO=${TO:+$TO, }${OPTARG}\r
229 +           message_goto='(message-goto-to)'\r
230             ;;\r
231         --cc|c)\r
232 -           ELISP="${ELISP} (message-goto-cc) (insert \"${OPTARG}, \")"\r
233 +           CC=${CC:+$CC, }${OPTARG}\r
234 +           message_goto='(message-goto-cc)'\r
235             ;;\r
236         --bcc|b)\r
237 -           ELISP="${ELISP} (message-goto-bcc) (insert \"${OPTARG}, \")"\r
238 +           BCC=${BCC:+$BCC, }${OPTARG}\r
239 +           message_goto='(message-goto-bcc)'\r
240             ;;\r
241         --body|i)\r
242 -           ELISP="${ELISP} (message-goto-body) (cd \"${PWD}\") (insert-file \"${OPTARG}\")"\r
243 +           if [[ ! -f ${OPTARG} ]]; then\r
244 +               echo "$0: '${OPTARG}': no such file" >&2\r
245 +               exit 1\r
246 +           fi\r
247 +           if [[ $cddone == 'false' ]]; then\r
248 +               BODY=${BODY}$'\n'"  (cd \"${PWD}\")"\r
249 +               cddone=true\r
250 +           fi\r
251 +           BODY=${BODY}$'\n'"  (insert-file \"${OPTARG}\")"\r
252 +           BODY=${BODY}$'\n'"  (if (/= (point) (line-beginning-position)) (insert \"\\n\"))"\r
253 +           unset message_goto\r
254 +           ;;\r
255 +       --bodytext)\r
256 +           BODY=${BODY}$'\n'"  (insert \"${OPTARG}\\n\")"\r
257 +           unset message_goto\r
258             ;;\r
259         --print)\r
260             PRINT_ONLY=1\r
261             ;;\r
262         --no-window-system)\r
263 -           CLIENT_TYPE="-t"\r
264 +           EMACSCLIENT_TYPE='-t'\r
265 +           EMACS_NW='-nw'\r
266             ;;\r
267         *)\r
268             # We should never end up here.\r
269 @@ -116,21 +159,39 @@ done\r
270  \r
271  # Positional parameters.\r
272  for arg; do\r
273 -    arg="$(escape "${arg}")"\r
274 -    ELISP="${ELISP} (message-goto-to) (insert \"${arg}, \")"\r
275 +    escape -v _arg "${arg}"\r
276 +    TO=${TO:+$TO, }${_arg}\r
277 +    message_goto='(message-goto-to)'\r
278  done\r
279  \r
280 -# End progn.\r
281 -ELISP="${ELISP})"\r
282 +# The newlines are here for better user experience when --print option is used.\r
283 +NL=$'\n'\r
284 +ELISP="\\r
285 +${CC:+$NL  (message-goto-cc) (insert \"$CC\")}\\r
286 +${BCC:+$NL  (message-goto-bcc) (insert \"$BCC\")}\\r
287 +${BODY:+$NL  (message-goto-body)$BODY}"\r
288  \r
289 -if [ -n "$PRINT_ONLY" ]; then\r
290 -    echo ${ELISP}\r
291 -    exit 0\r
292 -fi\r
293 -\r
294 -if [ -n "$USE_EMACSCLIENT" ]; then\r
295 -    # Evaluate the progn.\r
296 -    exec ${EMACSCLIENT} ${CLIENT_TYPE} -a '' --eval "${ELISP}"\r
297 +if [[ $TO == '' && $SUBJECT == '' && $ELISP == '' ]]\r
298 +then\r
299 +    exec_mua "(prog1 'done (require 'notmuch) (notmuch-hello))"\r
300  else\r
301 -    exec ${EMACS} --eval "${ELISP}"\r
302 +    [[ $FROM != '' ]] && OH="(list (cons 'From \"$FROM\"))" || OH=nil\r
303 +\r
304 +    if [[ $SUBJECT == '' ]]; then\r
305 +       SUBJECT=nil\r
306 +       message_goto='(message-goto-subject)'\r
307 +    else\r
308 +       SUBJECT=\"$SUBJECT\"\r
309 +    fi\r
310 +    if [[ $TO == '' ]]; then\r
311 +       TO=nil\r
312 +       message_goto='(message-goto-to)'\r
313 +    else\r
314 +       TO=\"$TO\"\r
315 +    fi\r
316 +    exec_mua "(prog1 'done (require 'notmuch)\r
317 +  (setq message-exit-actions (list #'save-buffers-kill-terminal))\r
318 +  (notmuch-mua-mail ${TO} ${SUBJECT}\r
319 +       ${OH} nil (notmuch-mua-get-switch-function))\\r
320 +${ELISP}${NL}  (set-buffer-modified-p nil)${message_goto+ $message_goto})"\r
321  fi\r
322 -- \r
323 2.1.0\r
324 \r