From f504327ac4c95a9853f9cb3100749a19033b48f1 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 28 Mar 2023 20:57:07 +0300 Subject: [PATCH 1/5] mu4e: restore support for function bookmarks Fixes 2446. --- mu4e/mu4e-bookmarks.el | 4 +--- mu4e/mu4e-search.el | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mu4e/mu4e-bookmarks.el b/mu4e/mu4e-bookmarks.el index c6a8947c..5cfc7a06 100644 --- a/mu4e/mu4e-bookmarks.el +++ b/mu4e/mu4e-bookmarks.el @@ -53,11 +53,9 @@ Each of the list elements is a plist with at least: `:name' - the name of the query -`:query' - the query expression string (not a function) +`:query' - the query expression string or function `:key' - the shortcut key (single character) -Note that the :query parameter can be a function/lambda. - Optionally, you can add the following: - `:favorite' - if t, monitor the results of this query, and make diff --git a/mu4e/mu4e-search.el b/mu4e/mu4e-search.el index 91ea88fc..c5eb12db 100644 --- a/mu4e/mu4e-search.el +++ b/mu4e/mu4e-search.el @@ -203,6 +203,7 @@ the search." (or expr (mu4e-ask-bookmark (if edit "Select bookmark: " "Bookmark: ")))) + (expr (if (functionp expr) (funcall expr) expr)) (fav (mu4e--bookmark-query (mu4e-bookmark-favorite)))) ;; reset baseline when searching for the favorite bookmark query (when (and fav (string= fav expr)) From 81ee182f05442cb2077d44b4438bda1edea08c00 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 28 Mar 2023 20:58:11 +0300 Subject: [PATCH 2/5] mu: mu-view: don't insist on absolute path Make it absolute so make_from_path can deal with it. --- mu/mu-cmd.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mu/mu-cmd.cc b/mu/mu-cmd.cc index 3f8a7c9c..0f4af1a7 100644 --- a/mu/mu-cmd.cc +++ b/mu/mu-cmd.cc @@ -156,7 +156,12 @@ handle_msg(const std::string& fname, const Options& opts) { using Format = Options::View::Format; - auto message{Message::make_from_path(fname, message_options(opts.view))}; + // make absolute. + const auto fpath{to_string_opt_gchar(g_canonicalize_filename(fname.c_str(), NULL))}; + if (!fpath) + return Err(Error::Code::File, "invalid file '%s'", fname.c_str()); + + auto message{Message::make_from_path(*fpath, message_options(opts.view))}; if (!message) return Err(message.error()); From 39101cf583bbf81a8f78e25981733fee2a8bbf39 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 28 Mar 2023 22:26:56 +0300 Subject: [PATCH 3/5] mu-find: brush off --format=links unit test Enable it by default, and modernize it a little bit --- lib/utils/mu-test-utils.hh | 8 ++++-- mu/tests/test-mu-cmd.cc | 59 +++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/lib/utils/mu-test-utils.hh b/lib/utils/mu-test-utils.hh index c59b9d5a..ffb0662c 100644 --- a/lib/utils/mu-test-utils.hh +++ b/lib/utils/mu-test-utils.hh @@ -1,5 +1,5 @@ /* -** Copyright (C) 2008-2022 Dirk-Jan C. Binnema +** Copyright (C) 2008-2023 Dirk-Jan C. Binnema ** ** 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 @@ -21,6 +21,7 @@ #define MU_TEST_UTILS_HH__ #include +#include namespace Mu { @@ -29,7 +30,10 @@ namespace Mu { * * @return a random dir name, g_free when it's no longer needed */ -char* test_mu_common_get_random_tmpdir(); +char* test_mu_common_get_random_tmpdir(void); +static inline std::string test_random_tmpdir() { + return to_string_gchar(test_mu_common_get_random_tmpdir()); +} /** * mu wrapper for g_test_init diff --git a/mu/tests/test-mu-cmd.cc b/mu/tests/test-mu-cmd.cc index d70cc80d..4d19806d 100644 --- a/mu/tests/test-mu-cmd.cc +++ b/mu/tests/test-mu-cmd.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -33,6 +34,7 @@ #include "mu-query.hh" #include "utils/mu-result.hh" #include "utils/mu-utils.hh" +#include "utils/mu-utils-file.hh" using namespace Mu; @@ -227,59 +229,59 @@ test_mu_find_03() g_free(cmdline); } -G_GNUC_UNUSED static void +static void test_mu_find_links(void) { - gchar *cmdline, *output, *erroutput, *tmpdir; - - tmpdir = test_mu_common_get_random_tmpdir(); - - cmdline = g_strdup_printf("%s find --muhome=%s --format=links --linksdir=%s " - "mime:message/rfc822", - MU_PROGRAM, - DBPATH.c_str(), - tmpdir); - + char *output, *erroutput; + const auto tmpdir{test_random_tmpdir()}; + auto cmdline = format("%s find --muhome=%s --format=links --linksdir=%s " + "mime:message/rfc822", MU_PROGRAM, DBPATH.c_str(), tmpdir.c_str()); if (g_test_verbose()) - g_print("cmdline: %s\n", cmdline); + g_print("cmdline: %s\n", cmdline.c_str()); - g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + g_assert(g_spawn_command_line_sync(cmdline.c_str(), &output, &erroutput, NULL, NULL)); /* there should be no errors */ g_assert_cmpuint(newlines_in_output(output), ==, 0); g_assert_cmpuint(newlines_in_output(erroutput), ==, 0); g_free(output); g_free(erroutput); + output = erroutput = NULL; + + /* furthermore, two symlinks should be there */ + const auto f1{format("%s/cur/3419760385_rfc822.1", tmpdir.c_str())}; + const auto f2{format("%s/cur/3419760386_rfc822.2", tmpdir.c_str())}; + + g_assert_cmpuint(determine_dtype(f1.c_str(), true), ==, DT_LNK); + g_assert_cmpuint(determine_dtype(f2.c_str(), true), ==, DT_LNK); /* now we try again, we should get a line of error output, * when we find the first target file already exists */ if (g_test_verbose()) - g_print("cmdline: %s\n", cmdline); + g_print("cmdline: %s\n", cmdline.c_str()); - g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + g_assert(g_spawn_command_line_sync(cmdline.c_str(), &output, &erroutput, NULL, NULL)); g_assert_cmpuint(newlines_in_output(output), ==, 0); g_assert_cmpuint(newlines_in_output(erroutput), ==, 1); g_free(output); g_free(erroutput); + output = erroutput = NULL; /* now we try again with --clearlinks, and the we should be * back to 0 errors */ - g_free(cmdline); - cmdline = g_strdup_printf("%s find --muhome=%s --format=links --linksdir=%s --clearlinks " - "mime:message/rfc822", - MU_PROGRAM, - DBPATH.c_str(), - tmpdir); - g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + cmdline = format("%s find --muhome=%s --format=links --linksdir=%s --clearlinks " + "mime:message/rfc822", MU_PROGRAM, DBPATH.c_str(), tmpdir.c_str()); + + g_assert(g_spawn_command_line_sync(cmdline.c_str(), &output, &erroutput, NULL, NULL)); if (g_test_verbose()) - g_print("cmdline: %s\n", cmdline); + g_print("cmdline: %s\n", cmdline.c_str()); g_assert_cmpuint(newlines_in_output(output), ==, 0); g_assert_cmpuint(newlines_in_output(erroutput), ==, 0); g_free(output); g_free(erroutput); - g_free(cmdline); - g_free(tmpdir); + g_assert_cmpuint(determine_dtype(f1.c_str(), true), ==, DT_LNK); + g_assert_cmpuint(determine_dtype(f2.c_str(), true), ==, DT_LNK); } /* some more tests */ @@ -837,11 +839,8 @@ main(int argc, char* argv[]) g_test_add_func("/mu-cmd/test-mu-find-file", test_mu_find_file); g_test_add_func("/mu-cmd/test-mu-find-mime", test_mu_find_mime); - /* recently, this test breaks _sometimes_ when run on Travis; but it - * seems related to the setup there, as nothing has changed in the code. - * turn off for now. */ - /* g_test_add_func ("/mu-cmd/test-mu-find-links", - * test_mu_find_links); */ + + g_test_add_func ("/mu-cmd/test-mu-find-links", test_mu_find_links); g_test_add_func("/mu-cmd/test-mu-find-text-in-rfc822", test_mu_find_text_in_rfc822); From e6d6f5014d4cae7452e7063cd7fa86f507a412bf Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Wed, 29 Mar 2023 09:06:24 +0300 Subject: [PATCH 4/5] mu4e: handle functionp queries in mu4e--make-query-items --- mu4e/mu4e-query-items.el | 1 + 1 file changed, 1 insertion(+) diff --git a/mu4e/mu4e-query-items.el b/mu4e/mu4e-query-items.el index e8d9eb8a..3eb05693 100644 --- a/mu4e/mu4e-query-items.el +++ b/mu4e/mu4e-query-items.el @@ -175,6 +175,7 @@ bookmark or maildir." (query (if (equal type 'maildirs) (format "maildir:\"%s\"" maildir) (plist-get item :query))) + (query (if (functionp query) (funcall query) query)) (name (plist-get item :name)) ;; it is possible that the user has a rewrite function (effective-query (funcall mu4e-query-rewrite-function query)) From fdc08349515a3e0ef1f176169b47ff1ea14ac9af Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 28 Mar 2023 22:28:48 +0300 Subject: [PATCH 5/5] mu4e-server: attempt to avoid tramp error Try to ensure default-directory is local; it seems tramp can screw up shell-command-to-string. --- mu4e/mu4e-server.el | 66 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/mu4e/mu4e-server.el b/mu4e/mu4e-server.el index cb0546ac..65ad3209 100644 --- a/mu4e/mu4e-server.el +++ b/mu4e/mu4e-server.el @@ -396,22 +396,23 @@ As per issue #2198." (defun mu4e--version-check () ;; sanity-check 1 - (unless (and mu4e-mu-binary (file-executable-p mu4e-mu-binary)) - (mu4e-error - "Cannot find mu, please set `mu4e-mu-binary' to the mu executable path")) - ;; sanity-check 2 - (let ((version (let ((s (shell-command-to-string - (concat mu4e-mu-binary " --version")))) - (and (string-match "version \\([.0-9]+\\)" s) - (match-string 1 s))))) - (if (not (string= version mu4e-mu-version)) + (let ((default-directory temporary-file-directory)) ;;ensure it's local. + (unless (and mu4e-mu-binary (file-executable-p mu4e-mu-binary)) (mu4e-error - (concat - "Found mu version %s, but mu4e needs version %s" - "; please set `mu4e-mu-binary' " - "accordingly") - version mu4e-mu-version) - (mu4e-message "Found mu version %s" version)))) + "Cannot find mu, please set `mu4e-mu-binary' to the mu executable path")) + ;; sanity-check 2 + (let ((version (let ((s (shell-command-to-string + (concat mu4e-mu-binary " --version")))) + (and (string-match "version \\([.0-9]+\\)" s) + (match-string 1 s))))) + (if (not (string= version mu4e-mu-version)) + (mu4e-error + (concat + "Found mu version %s, but mu4e needs version %s" + "; please set `mu4e-mu-binary' " + "accordingly") + version mu4e-mu-version) + (mu4e-message "Found mu version %s" version))))) (defun mu4e-server-repl () "Start a mu4e-server repl. @@ -433,24 +434,23 @@ You cannot run the repl when mu4e is running (or vice-versa)." (defun mu4e--server-start () "Start the mu server process." (mu4e--version-check) - (let ((default-directory temporary-file-directory)) ;;ensure it's local. - ;; kill old/stale servers, if any. - (mu4e--kill-stale) - (let* ((process-connection-type nil) ;; use a pipe - (args (mu4e--server-args))) - (setq mu4e--server-buf "") - (mu4e-log 'misc "* invoking '%s' with parameters %s" mu4e-mu-binary - (mapconcat (lambda (arg) (format "'%s'" arg)) args " ")) - (setq mu4e--server-process (apply 'start-process - mu4e--server-name mu4e--server-name - mu4e-mu-binary args)) - ;; register a function for (:info ...) sexps - (unless mu4e--server-process - (mu4e-error "Failed to start the mu4e backend")) - (set-process-query-on-exit-flag mu4e--server-process nil) - (set-process-coding-system mu4e--server-process 'binary 'utf-8-unix) - (set-process-filter mu4e--server-process 'mu4e--server-filter) - (set-process-sentinel mu4e--server-process 'mu4e--server-sentinel)))) + ;; kill old/stale servers, if any. + (mu4e--kill-stale) + (let* ((process-connection-type nil) ;; use a pipe + (args (mu4e--server-args))) + (setq mu4e--server-buf "") + (mu4e-log 'misc "* invoking '%s' with parameters %s" mu4e-mu-binary + (mapconcat (lambda (arg) (format "'%s'" arg)) args " ")) + (setq mu4e--server-process (apply 'start-process + mu4e--server-name mu4e--server-name + mu4e-mu-binary args)) + ;; register a function for (:info ...) sexps + (unless mu4e--server-process + (mu4e-error "Failed to start the mu4e backend")) + (set-process-query-on-exit-flag mu4e--server-process nil) + (set-process-coding-system mu4e--server-process 'binary 'utf-8-unix) + (set-process-filter mu4e--server-process 'mu4e--server-filter) + (set-process-sentinel mu4e--server-process 'mu4e--server-sentinel))) (defun mu4e--server-kill () "Kill the mu server process."