sexp and strings

2022-06-12 Thread erik colson
Hi,

I would like to define a squery in my notmuch configuration which would
ease a query I often use.  The query is

  tag:/d/

where d are decimal numbers.
Now I would like to shorten this to

  D d

wherefor I was thinking of using a macro like:

  D=(macro (dossier) ((tag (regex ,dossier

But this doesn't seem to do the job.
Any ideas how I can achieve this ?

thx
-- 
erik colson
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 1/4] test: add new corpus of duplicate messages

2022-06-12 Thread David Bremner
This corpus will be used to test a new --duplicate option for notmuch-show
---
 test/corpora/duplicate/msg-1-1:2, |  85 ++
 test/corpora/duplicate/msg-1-2:2, | 113 ++
 test/corpora/duplicate/msg-2-1:2, |  43 +++
 test/corpora/duplicate/msg-2-2:2, | 140 +++
 test/corpora/duplicate/msg-3-1:2, | 183 +
 test/corpora/duplicate/msg-3-2:2, | 184 ++
 test/corpora/duplicate/msg-3-3:2, | 178 +
 test/corpora/duplicate/msg-3-4:2, | 184 ++
 test/corpora/duplicate/msg-3-5:2, | 179 +
 9 files changed, 1289 insertions(+)
 create mode 100644 test/corpora/duplicate/msg-1-1:2,
 create mode 100644 test/corpora/duplicate/msg-1-2:2,
 create mode 100644 test/corpora/duplicate/msg-2-1:2,
 create mode 100644 test/corpora/duplicate/msg-2-2:2,
 create mode 100644 test/corpora/duplicate/msg-3-1:2,
 create mode 100644 test/corpora/duplicate/msg-3-2:2,
 create mode 100644 test/corpora/duplicate/msg-3-3:2,
 create mode 100644 test/corpora/duplicate/msg-3-4:2,
 create mode 100644 test/corpora/duplicate/msg-3-5:2,

diff --git a/test/corpora/duplicate/msg-1-1:2, 
b/test/corpora/duplicate/msg-1-1:2,
new file mode 100644
index ..bc7da06d
--- /dev/null
+++ b/test/corpora/duplicate/msg-1-1:2,
@@ -0,0 +1,85 @@
+Return-path: 

+Envelope-to: da...@tethera.net
+Delivery-date: Wed, 28 Nov 2012 18:41:46 -0400
+Received: from [199.188.72.155] (helo=yantan.tethera.net)
+   by tesseract.cs.unb.ca with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)
+   (Exim 4.72)
+   (envelope-from 
)
+   id 1TdqKA-00017j-3c
+   for da...@tethera.net; Wed, 28 Nov 2012 18:41:46 -0400
+Received: from wagner.debian.org ([217.196.43.132])
+   by yantan.tethera.net with esmtp (Exim 4.72)
+   (envelope-from 
)
+   id 1TdqK9-00072z-AF
+   for da...@tethera.net; Wed, 28 Nov 2012 18:41:45 -0400
+Received: from localhost ([::1] helo=wagner.debian.org)
+   by wagner.debian.org with esmtp (Exim 4.72)
+   (envelope-from 
)
+   id 1TdqK8-0007GZ-67
+   for da...@tethera.net; Wed, 28 Nov 2012 22:41:44 +
+Received: from vasks.debian.org ([217.196.43.140])
+   by wagner.debian.org with esmtp (Exim 4.72)
+   (envelope-from )
+   id 1TdqIc-0006jm-OC; Wed, 28 Nov 2012 22:40:11 +
+Received: from gladky-anton-guest by vasks.debian.org with local (Exim 4.72)
+   (envelope-from )
+   id 1TdqIc-0003j1-DE; Wed, 28 Nov 2012 22:40:10 +
+Date: Wed, 28 Nov 2012 22:40:10 +
+From: Anton Gladky 
+To: 691...@bugs.debian.org, cont...@bugs.debian.org,
+   691896-submit...@bugs.debian.org
+Message-ID: 

+X-PTS-Approved: Yes
+X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on wagner.debian.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM
+   autolearn=ham version=3.3.1
+Subject: [87ea161] Fix for Bug#691896 committed to git
+X-BeenThere: debian-science-maintain...@lists.alioth.debian.org
+X-Mailman-Version: 2.1.13
+Precedence: list
+List-Id: Mailing list for maintainer discussions and BTS messages
+   
+List-Unsubscribe: 
,
+   

+List-Archive: 

+List-Post: 
+List-Help: 

+List-Subscribe: 
,
+   

+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+Sender: 
debian-science-maintainers-bounces+david=tethera@lists.alioth.debian.org
+Errors-To: 
debian-science-maintainers-bounces+david=tethera@lists.alioth.debian.org
+X-SA-Exim-Connect-IP: ::1
+X-SA-Exim-Mail-From: 
debian-science-maintainers-bounces+david=tethera@lists.alioth.debian.org
+X-SA-Exim-Scanned: No (on wagner.debian.org); SAEximRunCond expanded to false
+X-Spam-Score: 1.3
+X-Spam_bar: +
+
+
+tags 691896 + pending
+thanks
+
+Hello,
+
+ The following change has been committed for this bug by
+ Anton Gladky  on Wed, 31 Oct 2012 08:16:42 +0100.
+ The fix will be in the next upload. 
+
+Minor fixes in README.Debian. (Closes: #691896)
+
+
+
+
+You can check the diff of the fix at:
+
+;a=commitdiff;h=87ea161
+
+
+
+-- 
+debian-science-maintainers mailing list
+debian-science-maintain...@lists.alioth.debian.org
+http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-science-maintainers
diff --git 

[PATCH 4/4] WIP/emacs: replace message with different duplicate

2022-06-12 Thread David Bremner
---
 emacs/notmuch-query.el  |  4 +++-
 emacs/notmuch-show.el   | 11 +++
 test/T450-emacs-show.sh | 12 
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-query.el b/emacs/notmuch-query.el
index 5c7f4f8d..865e3ccf 100644
--- a/emacs/notmuch-query.el
+++ b/emacs/notmuch-query.el
@@ -25,7 +25,7 @@
 
 ;;; Basic query function
 
-(defun notmuch-query-get-threads (search-terms)
+(defun notmuch-query-get-threads (search-terms  duplicate)
   "Return a list of threads of messages matching SEARCH-TERMS.
 
 A thread is a forest or list of trees. A tree is a two element
@@ -34,6 +34,8 @@ is a possibly empty forest of replies."
   (let ((args '("show" "--format=sexp" "--format-version=5")))
 (when notmuch-show-process-crypto
   (setq args (append args '("--decrypt=true"
+(when duplicate
+  (setq args (append args (list (format "--duplicate=%d" duplicate)
 (setq args (append args search-terms))
 (apply #'notmuch-call-notmuch-sexp args)))
 
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 203ca7f0..833543b0 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1082,6 +1082,17 @@ is t, hide the part initially and show the button."
 (defvar notmuch-show-previous-subject "")
 (make-variable-buffer-local 'notmuch-show-previous-subject)
 
+(defun notmuch-show-replace-msg (duplicate)
+  (interactive "Nduplicate: ")
+  (save-excursion
+(let* ((extent (notmuch-show-message-extent))
+  (id (notmuch-show-get-message-id))
+  (depth (notmuch-show-get-depth))
+  (inhibit-read-only t)
+  (new-msg (notmuch-query-get-threads (list id) duplicate)))
+  (delete-region (car extent) (cdr extent))
+  (notmuch-show-insert-msg new-msg depth
+
 (defun notmuch-show-insert-msg (msg depth)
   "Insert the message MSG at depth DEPTH in the current thread."
   (let* ((headers (plist-get msg :headers))
diff --git a/test/T450-emacs-show.sh b/test/T450-emacs-show.sh
index 678efd8b..6141873d 100755
--- a/test/T450-emacs-show.sh
+++ b/test/T450-emacs-show.sh
@@ -271,4 +271,16 @@ when we detect the word "attachment" and there's no 
attach? :p
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
+add_email_corpus duplicate
+
+ID3=87r2ecrr6x@zephyr.silentflame.com
+test_begin_subtest "duplicate=3"
+test_emacs "(notmuch-show \"id:${ID3}\")
+  (notmuch-show-replace-msg 3)
+  (test-visible-output \"OUTPUT\")"
+output=$(grep "Subject:" OUTPUT)
+file=$(notmuch search --output=files id:${ID3} | head -n 3 | tail -n 1)
+subject=$(grep '^Subject:' $file)
+test_expect_equal "$output" "$subject"
+
 test_done
-- 
2.35.2

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


WIP: allow display of duplicate messages with notmuch show / notmuch-emacs

2022-06-12 Thread David Bremner
This is alpha quality, so in particular there is no key binding for
the new function #'notmuch-show-replace-msg, which redraws with a
different duplicate. On the other hand it's the first progress in a
long time towards a better ui for duplicate messages, and it turns out
not to be as hard as I thought.

What isn't here at all is some kind of indicator in the UI that
duplicates exist for a given message. That should be doable because we
have the list of filenames in the sexp / json output.




___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 3/4] WIP: support show --duplicate for structured output

2022-06-12 Thread David Bremner
---
 mime-node.c   | 32 +++-
 notmuch-client.h  |  4 +++-
 notmuch-reply.c   |  2 +-
 notmuch-show.c|  2 +-
 test/T520-show.sh | 24 
 5 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/mime-node.c b/mime-node.c
index d29c4e48..890c8a0d 100644
--- a/mime-node.c
+++ b/mime-node.c
@@ -78,13 +78,14 @@ mime_node_get_message_crypto_status (mime_node_t *node)
 
 notmuch_status_t
 mime_node_open (const void *ctx, notmuch_message_t *message,
+   int duplicate,
_notmuch_crypto_t *crypto, mime_node_t **root_out)
 {
 const char *filename = notmuch_message_get_filename (message);
 mime_node_context_t *mctx;
 mime_node_t *root;
 notmuch_status_t status;
-int fd;
+int fd = -1;
 
 root = talloc_zero (ctx, mime_node_t);
 if (root == NULL) {
@@ -103,20 +104,33 @@ mime_node_open (const void *ctx, notmuch_message_t 
*message,
 talloc_set_destructor (mctx, _mime_node_context_free);
 
 /* Fast path */
-fd = open (filename, O_RDONLY);
+if (duplicate <= 0)
+   fd = open (filename, O_RDONLY);
 if (fd == -1) {
-   /* Slow path - for some reason the first file in the list is
-* not available anymore. This is clearly a problem in the
+   /* Slow path - Either we are trying to open a specific file, or
+* for some reason the first file in the list is
+* not available anymore. The latter is clearly a problem in the
 * database, but we are not going to let this problem be a
 * show stopper */
notmuch_filenames_t *filenames;
+   int i=1;
+
for (filenames = notmuch_message_get_filenames (message);
 notmuch_filenames_valid (filenames);
-notmuch_filenames_move_to_next (filenames)) {
-   filename = notmuch_filenames_get (filenames);
-   fd = open (filename, O_RDONLY);
-   if (fd != -1)
-   break;
+notmuch_filenames_move_to_next (filenames), i++) {
+   if (i>= duplicate) {
+   filename = notmuch_filenames_get (filenames);
+   fd = open (filename, O_RDONLY);
+   if (fd != -1) {
+   break;
+   } else {
+   if (duplicate > 0) {
+   fprintf (stderr, "Error opening %s: %s\n", filename, 
strerror (errno));
+   status = NOTMUCH_STATUS_FILE_ERROR;
+   goto DONE;
+   }
+   }
+   }
}
 
talloc_free (filenames);
diff --git a/notmuch-client.h b/notmuch-client.h
index f8f987e7..faea52b7 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -389,7 +389,8 @@ struct mime_node {
 };
 
 /* Construct a new MIME node pointing to the root message part of
- * message. If crypto->verify is true, signed child parts will be
+ * message. Use the duplicate-th filename if that parameter is
+ * positive. If crypto->verify is true, signed child parts will be
  * verified. If crypto->decrypt is NOTMUCH_DECRYPT_TRUE, encrypted
  * child parts will be decrypted using either stored session keys or
  * asymmetric crypto.  If crypto->decrypt is NOTMUCH_DECRYPT_AUTO,
@@ -407,6 +408,7 @@ struct mime_node {
  */
 notmuch_status_t
 mime_node_open (const void *ctx, notmuch_message_t *message,
+   int duplicate,
_notmuch_crypto_t *crypto, mime_node_t **node_out);
 
 /* Return a new MIME node for the requested child part of parent.
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 9fca22db..ee50bb22 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -663,7 +663,7 @@ do_reply (notmuch_database_t *notmuch,
 notmuch_messages_move_to_next (messages)) {
message = notmuch_messages_get (messages);
 
-   if (mime_node_open (notmuch, message, >crypto, ))
+   if (mime_node_open (notmuch, message, 0, >crypto, ))
return 1;
 
reply = create_reply_message (notmuch, message,
diff --git a/notmuch-show.c b/notmuch-show.c
index 7b57aab3..ccaf9fa0 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -1018,7 +1018,7 @@ show_message (void *ctx,
session_key_count_error = notmuch_message_count_properties (message, 
"session-key",

_keys);
 
-status = mime_node_open (local, message, &(params->crypto), );
+status = mime_node_open (local, message, params->duplicate, 
&(params->crypto), );
 if (status)
goto DONE;
 part = mime_node_seek_dfs (root, (params->part < 0 ? 0 : params->part));
diff --git a/test/T520-show.sh b/test/T520-show.sh
index 12bde6c7..a19b4d57 100755
--- a/test/T520-show.sh
+++ b/test/T520-show.sh
@@ -45,4 +45,28 @@ if [ $NOTMUCH_HAVE_SFSEXP -eq 1 ]; then
 
 fi
 
+add_email_corpus duplicate
+
+ID1=debian/2.6.1.dfsg-4-1-g87ea161@87ea161e851dfb1ea324af00e4ecfccc18875e15
+test_begin_subtest "format json, subject, --duplicate=1"

[PATCH 2/4] CLI/show: WIP support --duplicate for raw output

2022-06-12 Thread David Bremner
---
 notmuch-client.h |  1 +
 notmuch-show.c   | 21 -
 test/T210-raw.sh | 11 +++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index 9f57ac5e..f8f987e7 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -75,6 +75,7 @@ typedef struct notmuch_show_params {
 bool entire_thread;
 bool omit_excluded;
 bool output_body;
+int duplicate;
 int part;
 _notmuch_crypto_t crypto;
 bool include_html;
diff --git a/notmuch-show.c b/notmuch-show.c
index 6a54d9c1..7b57aab3 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -23,6 +23,20 @@
 #include "sprinter.h"
 #include "zlib-extra.h"
 
+static const char *
+_get_filename (notmuch_message_t *message, int index) {
+notmuch_filenames_t *filenames = notmuch_message_get_filenames (message);
+int i=1;
+
+for (;
+notmuch_filenames_valid (filenames);
+notmuch_filenames_move_to_next (filenames), i++) {
+   if (i >= index)
+   return notmuch_filenames_get (filenames);
+}
+return NULL;
+}
+
 static const char *
 _get_tags_as_string (const void *ctx, notmuch_message_t *message)
 {
@@ -925,7 +939,7 @@ format_part_raw (unused (const void *ctx), unused 
(sprinter_t *sp),
char buf[4096];
notmuch_status_t ret = NOTMUCH_STATUS_FILE_ERROR;
 
-   filename = notmuch_message_get_filename (node->envelope_file);
+   filename = _get_filename (node->envelope_file, params->duplicate);
if (filename == NULL) {
fprintf (stderr, "Error: Cannot get message filename.\n");
goto DONE;
@@ -1266,6 +1280,7 @@ notmuch_show_command (notmuch_database_t *notmuch, int 
argc, char *argv[])
 sprinter_t *sprinter;
 notmuch_show_params_t params = {
.part = -1,
+   .duplicate = 0,
.omit_excluded = true,
.output_body = true,
.crypto = { .decrypt = NOTMUCH_DECRYPT_AUTO },
@@ -1306,6 +1321,7 @@ notmuch_show_command (notmuch_database_t *notmuch, int 
argc, char *argv[])
{ .opt_bool = , .name = "verify" },
{ .opt_bool = _body, .name = "body" },
{ .opt_bool = _html, .name = "include-html" },
+   { .opt_int = , .name = "duplicate" },
{ .opt_inherit = notmuch_shared_options },
{ }
 };
@@ -1324,6 +1340,9 @@ notmuch_show_command (notmuch_database_t *notmuch, int 
argc, char *argv[])
 /* specifying a part implies single message display */
 single_message = params.part >= 0;
 
+/* specifying a duplicate also implies single message display */
+single_message = single_message || (params.duplicate>0);
+
 if (format == NOTMUCH_FORMAT_NOT_SPECIFIED) {
/* if part was requested and format was not specified, use format=raw */
if (params.part >= 0)
diff --git a/test/T210-raw.sh b/test/T210-raw.sh
index e1d50bf9..f4990b6d 100755
--- a/test/T210-raw.sh
+++ b/test/T210-raw.sh
@@ -64,4 +64,15 @@ for pow in {10..20}; do
 test_expect_success "notmuch show --format=raw subject:$size > /dev/null"
 done
 
+add_email_corpus duplicate
+ID3=87r2ecrr6x@zephyr.silentflame.com 
+test_begin_subtest "raw content, duplicate files"
+rm -f OUTPUT.raw
+for dup in {1..5}; do
+notmuch show --format=raw --duplicate=${dup} --format=raw id:${ID3} | 
md5sum | cut -f1 -d' '  >> OUTPUT.raw
+done
+sort OUTPUT.raw > OUTPUT
+notmuch search --output=files id:${ID3} | xargs md5sum | cut -f1 -d ' ' | sort 
> EXPECTED
+test_expect_equal_file_nonempty EXPECTED OUTPUT
+
 test_done
-- 
2.35.2

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org