├── .dir-locals.el ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── feature-request.md │ ├── guile.md │ ├── misc.md │ ├── mu-bug-report.md │ └── mu4e-bug-report.md ├── issue_template.md └── workflows │ └── build-and-test.yml ├── .gitignore ├── .mailmap ├── AUTHORS ├── COPYING ├── IDEAS.org ├── Makefile ├── NEWS.org ├── README.org ├── autogen.sh ├── build-aux ├── date.py ├── meson-install-info.sh └── version.texi.in ├── contrib ├── mu-completion.zsh ├── mu-sexp-convert └── mu.spec ├── guile ├── compile-scm.in ├── examples │ ├── contacts-export │ ├── msg-graphs │ ├── mu-biff │ └── org2mu4e ├── fdl.texi ├── meson.build ├── mu-guile-message.cc ├── mu-guile-message.hh ├── mu-guile-message.x ├── mu-guile.cc ├── mu-guile.hh ├── mu-guile.texi ├── mu-guile.x ├── mu.scm ├── mu │ ├── README │ ├── contact.scm │ ├── message.scm │ ├── part.scm │ ├── plot.scm │ ├── script.scm │ └── stats.scm ├── scripts │ ├── find-dups.scm │ ├── histogram.scm │ └── msgs-count.scm └── tests │ ├── meson.build │ ├── test-mu-guile.cc │ └── test-mu-guile.scm ├── lib ├── meson.build ├── message │ ├── meson.build │ ├── mu-contact.cc │ ├── mu-contact.hh │ ├── mu-document.cc │ ├── mu-document.hh │ ├── mu-fields.cc │ ├── mu-fields.hh │ ├── mu-flags.cc │ ├── mu-flags.hh │ ├── mu-message-file.cc │ ├── mu-message-file.hh │ ├── mu-message-part.cc │ ├── mu-message-part.hh │ ├── mu-message.cc │ ├── mu-message.hh │ ├── mu-mime-object.cc │ ├── mu-mime-object.hh │ ├── mu-priority.cc │ ├── mu-priority.hh │ ├── test-mu-message.cc │ └── tests │ │ └── meson.build ├── mu-config.cc ├── mu-config.hh ├── mu-contacts-cache.cc ├── mu-contacts-cache.hh ├── mu-indexer.cc ├── mu-indexer.hh ├── mu-maildir.cc ├── mu-maildir.hh ├── mu-query-macros.cc ├── mu-query-macros.hh ├── mu-query-match-deciders.cc ├── mu-query-match-deciders.hh ├── mu-query-parser.cc ├── mu-query-parser.hh ├── mu-query-processor.cc ├── mu-query-results.hh ├── mu-query-threads.cc ├── mu-query-threads.hh ├── mu-query-xapianizer.cc ├── mu-query.cc ├── mu-query.hh ├── mu-scanner.cc ├── mu-scanner.hh ├── mu-script.cc ├── mu-script.hh ├── mu-server.cc ├── mu-server.hh ├── mu-store.cc ├── mu-store.hh ├── mu-xapian-db.cc ├── mu-xapian-db.hh ├── tests │ ├── bench-indexer.cc │ ├── meson.build │ ├── test-mu-container.cc │ ├── test-mu-maildir.cc │ ├── test-mu-msg-fields.cc │ ├── test-mu-msg.cc │ ├── test-mu-store-query.cc │ ├── test-mu-store.cc │ └── test-query.cc └── utils │ ├── meson.build │ ├── mu-async-queue.hh │ ├── mu-command-handler.cc │ ├── mu-command-handler.hh │ ├── mu-error.cc │ ├── mu-error.hh │ ├── mu-html-to-text.cc │ ├── mu-lang-detector.cc │ ├── mu-lang-detector.hh │ ├── mu-logger.cc │ ├── mu-logger.hh │ ├── mu-option.cc │ ├── mu-option.hh │ ├── mu-readline.cc │ ├── mu-readline.hh │ ├── mu-regex.cc │ ├── mu-regex.hh │ ├── mu-result.hh │ ├── mu-sexp.cc │ ├── mu-sexp.hh │ ├── mu-test-utils.cc │ ├── mu-test-utils.hh │ ├── mu-unbroken.hh │ ├── mu-utils-file.cc │ ├── mu-utils-file.hh │ ├── mu-utils.cc │ ├── mu-utils.hh │ └── tests │ ├── meson.build │ └── test-utils.cc ├── man ├── author.inc ├── bugs.inc ├── common-options.inc ├── copyright.inc.in ├── exit-code.inc ├── macros.inc ├── meson.build ├── mu-add.1.org ├── mu-bookmarks.5.org ├── mu-cfind.1.org ├── mu-easy.7.org ├── mu-extract.1.org ├── mu-find.1.org ├── mu-help.1.org ├── mu-index.1.org ├── mu-info.1.org ├── mu-init.1.org ├── mu-mkdir.1.org ├── mu-move.1.org ├── mu-query.7.org ├── mu-remove.1.org ├── mu-server.1.org ├── mu-verify.1.org ├── mu-view.1.org ├── mu.1.org ├── muhome.inc └── prefooter.inc ├── meson.build ├── meson_options.txt ├── mu ├── meson.build ├── mu-cmd-add.cc ├── mu-cmd-cfind.cc ├── mu-cmd-extract.cc ├── mu-cmd-find.cc ├── mu-cmd-index.cc ├── mu-cmd-info.cc ├── mu-cmd-init.cc ├── mu-cmd-mkdir.cc ├── mu-cmd-move.cc ├── mu-cmd-remove.cc ├── mu-cmd-script.cc ├── mu-cmd-server.cc ├── mu-cmd-verify.cc ├── mu-cmd-view.cc ├── mu-cmd.cc ├── mu-cmd.hh ├── mu-memcheck.in ├── mu-options.cc ├── mu-options.hh ├── mu.cc └── tests │ ├── gmime-test.c │ ├── meson.build │ └── test-mu-query.cc ├── mu4e ├── fdl.texi ├── htmlxref.cnf ├── meson.build ├── mu4e-about.org ├── mu4e-actions.el ├── mu4e-bookmarks.el ├── mu4e-compose.el ├── mu4e-config.el.in ├── mu4e-contacts.el ├── mu4e-context.el ├── mu4e-contrib.el ├── mu4e-draft.el ├── mu4e-folders.el ├── mu4e-headers.el ├── mu4e-helpers.el ├── mu4e-icalendar.el ├── mu4e-lists.el ├── mu4e-main.el ├── mu4e-mark.el ├── mu4e-message.el ├── mu4e-mime-parts.el ├── mu4e-modeline.el ├── mu4e-notification.el ├── mu4e-obsolete.el ├── mu4e-org.el ├── mu4e-pkg.el.in ├── mu4e-query-items.el ├── mu4e-search.el ├── mu4e-server.el ├── mu4e-speedbar.el ├── mu4e-thread.el ├── mu4e-transient.el ├── mu4e-update.el ├── mu4e-vars.el ├── mu4e-view.el ├── mu4e-window.el ├── mu4e.el ├── mu4e.texi └── texinfo-klare.css ├── testdata ├── cjk │ └── cur │ │ ├── test1 │ │ ├── test2 │ │ ├── test3 │ │ └── test4 ├── testdir │ ├── cur │ │ ├── 1220863042.12663_1.mindcrime!2,S │ │ ├── 1220863060.12663_3.mindcrime!2,S │ │ ├── 1220863087.12663_15.mindcrime!2,PS │ │ ├── 1220863087.12663_19.mindcrime!2,S │ │ ├── 1220863087.12663_5.mindcrime!2,S │ │ ├── 1220863087.12663_7.mindcrime!2,RS │ │ ├── 1252168370_3.14675.cthulhu!2,S │ │ ├── 1283599333.1840_11.cthulhu!2, │ │ ├── 1305664394.2171_402.cthulhu!2, │ │ ├── encrypted!2,S │ │ ├── multimime!2,FS │ │ ├── multirecip!2,S │ │ ├── signed!2,S │ │ ├── signed-encrypted!2,S │ │ └── special!2,Sabc │ ├── new │ │ ├── 1220863087.12663_21.mindcrime │ │ ├── 1220863087.12663_23.mindcrime │ │ ├── 1220863087.12663_25.mindcrime │ │ └── 1220863087.12663_9.mindcrime │ └── tmp │ │ └── 1220863087.12663.ignore ├── testdir2 │ ├── Foo │ │ ├── cur │ │ │ ├── arto.eml │ │ │ ├── fraiche.eml │ │ │ └── mail5 │ │ ├── new │ │ │ └── .noindex │ │ └── tmp │ │ │ └── .noindex │ ├── bar │ │ ├── .noupdate │ │ ├── cur │ │ │ ├── 181736.eml │ │ │ ├── mail1 │ │ │ ├── mail2 │ │ │ ├── mail3 │ │ │ ├── mail4 │ │ │ ├── mail5 │ │ │ ├── mail6 │ │ │ └── mail7 │ │ ├── new │ │ │ └── .noindex │ │ └── tmp │ │ │ └── .noindex │ └── wom_bat │ │ └── cur │ │ ├── atomic │ │ ├── rfc822.1 │ │ └── rfc822.2 └── testdir4 │ ├── 1220863042.12663_1.mindcrime!2,S │ ├── 1220863087.12663_19.mindcrime!2,S │ ├── 1252168370_3.14675.cthulhu!2,S │ ├── 1283599333.1840_11.cthulhu!2, │ ├── 1305664394.2171_402.cthulhu!2, │ ├── 181736.eml │ ├── encrypted!2,S │ ├── mail1 │ ├── mail5 │ ├── multimime!2,FS │ ├── signed!2,S │ ├── signed-bad!2,S │ ├── signed-encrypted!2,S │ └── special!2,Sabc └── thirdparty ├── CLI11.hpp ├── fmt ├── LICENSE ├── args.h ├── base.h ├── chrono.h ├── color.h ├── compile.h ├── core.h ├── format-inl.h ├── format.h ├── os.h ├── ostream.h ├── printf.h ├── ranges.h ├── std.h └── xchar.h ├── tabulate.hpp └── tl ├── expected.hpp └── optional.hpp /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ;;; -*- no-byte-compile: t; -*- 2 | ((nil . ((tab-width . 8) 3 | (fill-column . 80) 4 | ;; (commment-fill-column . 80) 5 | (emacs-lisp-docstring-fill-column . 65) 6 | (bug-reference-url-format . "https://github.com/djcb/mu/issues/%s"))) 7 | (c-mode . ((c-file-style . "linux") 8 | (indent-tabs-mode . t) 9 | (mode . bug-reference-prog))) 10 | (c-ts-mode . ((indent-tabs-mode . t) 11 | (c-ts-mode-indent-style . linux) 12 | (c-ts-mode-indent-offset . 8) 13 | (mode . bug-reference-prog))) 14 | (c++-mode . ((c-file-style . "linux") 15 | (fill-column . 100) 16 | ;; (comment-fill-column . 80) 17 | (mode . bug-reference-prog))) 18 | (c++-ts-mode . ((indent-tabs-mode . t) 19 | (c-ts-mode-indent-style . linux) 20 | (c-ts-mode-indent-offset . 8) 21 | (mode . bug-reference-prog))) 22 | (emacs-lisp-mode . ((indent-tabs-mode . nil) 23 | (mode . bug-reference-prog))) 24 | (lisp-data-mode . ((indent-tabs-mode . nil))) 25 | (texinfo-mode . ((mode . bug-reference-prog))) 26 | (org-mode . ((mode . bug-reference)))) 27 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | #-*-mode:conf-*- 2 | # editorconfig file (see EditorConfig.org), with some 3 | # lowest-denominator settings that should work for many editors. 4 | 5 | 6 | root = true # this is the top-level 7 | 8 | [*] 9 | end_of_line = lf 10 | insert_final_newline = true 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | 14 | # The "best" answer is "tabs-for-indentation; spaces for alignment". 15 | 16 | [*.{cc,cpp,hh,hpp}] 17 | indent_style = tab 18 | indent_size = 8 19 | max_line_length = 90 20 | 21 | [*.{c,h}] 22 | indent_style = tab 23 | indent_size = 8 24 | max_line_length = 80 25 | 26 | [configure.ac] 27 | indent_style = tab 28 | indent_size = 4 29 | max_line_length = 100 30 | 31 | [Makefile.am] 32 | indent_style = tab 33 | indent_size = 8 34 | max_line_length = 100 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for mu or mu4e 4 | title: "[RFE]" 5 | labels: rfe, new 6 | assignees: '' 7 | --- 8 | 9 | Note, please see the IDEAS.org file in repository root for existing ideas; maybe 10 | it's already there. 11 | 12 | **Is your feature request related to a problem? Please describe.** 13 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 14 | 15 | **Describe the solution you'd like** 16 | A clear and concise description of what you want to happen. 17 | 18 | **Describe alternatives you've considered** 19 | A clear and concise description of any alternative solutions or features you've considered. 20 | 21 | **Additional context** 22 | Add any other context or screenshots about the feature request here. 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/guile.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Guile 3 | about: mu-guile related item 4 | title: "[guile]" 5 | labels: new, guile 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the item** 11 | 12 | A clear and concise description of what you expected or wished to happen and 13 | what actually happened while using `mu-guile`. 14 | 15 | Note: `mu-guile` has been deprecated for quite some time, and will be removed in 16 | the future. 17 | 18 | **To Reproduce** 19 | Steps to reproduce the behavior. 20 | 21 | **Environment** 22 | Please describe the versions of OS, Emacs, mu/mu4e etc. you are using. 23 | 24 | **Checklist** 25 | - [ ] you are running either the latest 1.12.x release, or `master` 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/misc.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Misc 3 | about: Miscellaneous items you want to share 4 | title: "[misc]" 5 | labels: new 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Note**: for questions, please use the mailing-list: https://groups.google.com/g/mu-discuss 11 | 12 | **Describe the issue** 13 | A clear and concise description, i.e. what you expected/desired to happen and what actually happened. 14 | 15 | **Environment** 16 | If applicable, please describe the versions of OS, Emacs, mu etc. you are using. 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/mu-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Mu Bug Report 3 | about: Create a report to help us improve 4 | title: "[mu bug]" 5 | labels: bug, mu, new 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | 11 | Give the bug a good title. 12 | 13 | Please provide a clear and concise description of what you expected to happen 14 | and what actually happened, and follow the steps below. 15 | 16 | **How to Reproduce** 17 | 18 | Include the exact steps of what you were doing (commands executed etc.). Include 19 | any relevant logs and outputs. 20 | 21 | Does the problem happen each time? Sometimes? 22 | 23 | If this is about a specific (kind of) message, please attach an example message 24 | (anonymized as needed) 25 | 26 | **Environment** 27 | Please describe the versions of OS, Emacs, mu etc. you are using. 28 | 29 | **Checklist** 30 | - [ ] you are running either the latest 1.10.x/1.12.x release or `master` (otherwise, please upgrade). 31 | 32 | Thank you! 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/mu4e-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Mu4e Bug Report 3 | about: Create a report to help us improve mu4e 4 | title: "[mu4e bug]" 5 | labels: bug, mu4e, new 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | 11 | Give the bug a good title. 12 | 13 | Please provide a clear and concise description of what you expected to happen 14 | and what actually happened, and follow the steps below. 15 | 16 | **How to Reproduce** 17 | 18 | Include the exact steps of what you were doing (commands executed etc.). Include 19 | any relevant logs and outputs: 20 | 21 | - Best start from `emacs -Q`, and load a minimal `mu4e` setup; describe the steps 22 | that lead up to the bug. 23 | - Does the problem happen each time? Sometimes? 24 | 25 | - Try some small variations of what you were doing. Does it make a difference? 26 | 27 | - If this is about a specific (kind of) message, attach an example message. 28 | (Open the message, press `.` (`mu4e-view-raw-message`), then `C-x C-w` and 29 | attach. Anonymize as needed, all that matters is that the issue still 30 | reproduces. 31 | 32 | **Environment** 33 | 34 | Please describe the versions of OS, Emacs, mu/mu4e etc. you are using. 35 | 36 | **Checklist** 37 | 38 | - [ ] you are running either an 1.10.x/1.12.x release or `master` (otherwise please upgrade) 39 | - [ ] you can reproduce the problem without 3rd party extensions (including Doom/Evil, various extensions etc.) 40 | - [ ] you have read all of the above 41 | 42 | Please make sure you all items in the checklist are set/met before filing the ticket. 43 | 44 | Thank you! 45 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | # Important! Before filing an issue, please consider the following: 2 | 3 | * Ensure your mu/mu4e setup is no older than the latest stable release (1.6.x). 4 | 5 | * Disable any third-party mu4e extensions; this includes customizations like the ones in "Doom" / 6 | "Evil" etc. 7 | 8 | * If a problem occurs with a certain (type of) message, attach an (anonymized) example of 9 | such a message 10 | 11 | * Please provide some minimal steps to reproduce 12 | 13 | * Please follow the below template 14 | 15 | Thanks! 16 | 17 | ## Expected or desired behavior 18 | 19 | Please describe the behavior you expect or want 20 | 21 | ## Actual behavior 22 | 23 | Please describe the behavior you are actually seeing. 24 | 25 | For bug-reports, if applicable, include error messages, emacs stack traces, example messages 26 | etc. Try to be as specific as possible - when do you see this happening? Does it happen always? 27 | Sometimes? How often? 28 | 29 | ## Steps to reproduce 30 | 31 | For bug-reports, please describe in as much detail as possible how one can reproduce the problem. 32 | 33 | If there's a problem with a specific (type of) message, please attach such a message to the report. 34 | 35 | ## Versions of mu, mu4e/emacs, operating system etc. 36 | 37 | ## Any other detail 38 | 39 | E.g. are you using the gnus-based message view? 40 | -------------------------------------------------------------------------------- /.github/workflows/build-and-test.yml: -------------------------------------------------------------------------------- 1 | name: Build & run tests 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | build: 9 | runs-on: ${{ matrix.os }} 10 | timeout-minutes: 30 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | os: 15 | - ubuntu-latest 16 | - macos-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - if: contains(matrix.os, 'ubuntu') 22 | name: ubuntu-deps 23 | run: | 24 | sudo apt update 25 | sudo apt-get install meson ninja-build libglib2.0-dev libxapian-dev libgmime-3.0-dev libcld2-dev pkg-config guile-3.0-dev emacs texinfo 26 | 27 | - if: contains(matrix.os, 'macos') 28 | name: macos-deps 29 | run: | 30 | brew install meson ninja libgpg-error libtool pkg-config glib gmime xapian guile emacs texinfo 31 | 32 | - name: configure 33 | run: ./autogen.sh # '-Db_sanitize=address' 34 | 35 | - name: build 36 | run: make 37 | 38 | - name: test 39 | run: make test-verbose-if-fail 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | www/mu 2 | mug 3 | /mu/mu 4 | /mu/mu-help-strings.h 5 | mug2 6 | .desktop 7 | *html 8 | .deps 9 | .libs 10 | autom4te* 11 | Makefile 12 | Makefile.in 13 | INSTALL 14 | aclocal.m4 15 | config.* 16 | configure 17 | install-sh 18 | depcomp 19 | libtool 20 | ltmain.sh 21 | 22 | # Added automatically by `autoreconf` 23 | m4/libtool.m4 24 | m4/ltoptions.m4 25 | m4/ltsugar.m4 26 | m4/ltversion.m4 27 | m4/lt~obsolete.m4 28 | 29 | missing 30 | nohup.out 31 | vgdump 32 | stamp-h1 33 | GPATH 34 | GRTAGS 35 | GSYMS 36 | GTAGS 37 | *.lo 38 | *.o 39 | *.la 40 | *.x 41 | *.go 42 | *.gz 43 | *.bz2 44 | \#* 45 | *.aux 46 | *.cp 47 | *.fn 48 | *.info 49 | *.ky 50 | *.log 51 | *.pg 52 | *.toc 53 | *.tp 54 | *.vr 55 | *.elc 56 | *.gcda 57 | *.gcno 58 | *.trs 59 | *.exe 60 | *.lib 61 | aminclude_static.am 62 | elisp-comp 63 | elc-stamp 64 | dummy.cc 65 | msg2pdf 66 | gmime-test 67 | test-mu-cmd 68 | test-mu-cmd-cfind 69 | test-mu-contacts 70 | test-mu-container 71 | test-mu-date 72 | test-mu-flags 73 | test-mu-maildir 74 | test-mu-msg 75 | test-mu-msg-fields 76 | test-mu-query 77 | test-mu-runtime 78 | test-mu-store 79 | test-mu-str 80 | test-mu-threads 81 | test-mu-util 82 | test-parser 83 | test-tokenizer 84 | test-utils 85 | tokenize 86 | test-command-parser 87 | test-mu-utils 88 | test-sexp-parser 89 | test-scanner 90 | /guile/tests/test-mu-guile 91 | 92 | mu4e-config.el 93 | mu4e.pdf 94 | texinfo.tex 95 | texi.texi 96 | *.tex 97 | *.pdf 98 | /www/auto/* 99 | configure.lineno 100 | /test.xml 101 | /mu4e/mdate-sh 102 | /mu4e/mu4e-about.el 103 | /mu4e/stamp-vti 104 | /mu4e/version.texi 105 | /lib/doxyfile 106 | /version.texi 107 | /compile 108 | /TAGS 109 | parse 110 | 111 | *_flymake.* 112 | *_flymake_* 113 | /perf.data 114 | perf.data 115 | perf.data.old 116 | *vgdump 117 | /lib/asan.log* 118 | /man/mu-mfind.1 119 | /mu/mu-memcheck 120 | mu-*-coverage 121 | mu*tar.xz 122 | compile_commands.json 123 | /lib/utils/test-sexp 124 | /lib/utils/test-option 125 | /lib/test-mu-threader 126 | /lib/test-mu-tokenizer 127 | /lib/test-mu-parser 128 | /lib/test-mu-query-threader 129 | /lib/test-contacts 130 | /lib/test-flags 131 | /lib/test-maildir 132 | /lib/test-msg 133 | /lib/test-msg-fields 134 | /lib/test-query 135 | /lib/test-store 136 | /lib/test-threader 137 | /mu/test-cmd 138 | /mu/test-cmd-cfind 139 | /mu/test-query 140 | /mu/test-threads 141 | /lib/test-threads 142 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Dirk-Jan C. Binnema 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Dirk-Jan C. Binnema 2 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this to generate all the initial makefiles, etc. 3 | 4 | echo "*** meson build setup" 5 | 6 | test -f mu/mu.cc || { 7 | echo "*** Run this script from the top-level mu source directory" 8 | exit 1 9 | } 10 | BUILDDIR=build 11 | 12 | command -v meson 2> /dev/null 13 | if [ $? != 0 ]; then 14 | echo "*** 'meson' not found, please install it ***" 15 | exit 1 16 | fi 17 | 18 | # we could remove build/ but let's avoid rm -rf risks... 19 | if test -d ${BUILDDIR}; then 20 | meson setup --reconfigure ${BUILDDIR} $@ || exit 1 21 | else 22 | meson setup ${BUILDDIR} $@ || exit 1 23 | fi 24 | 25 | echo "*** Now run either 'ninja -C ${BUILDDIR}' or 'make' to build mu" 26 | echo "*** Check the Makefile for other useful targets" 27 | -------------------------------------------------------------------------------- /build-aux/date.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | Script to get date strings, since the MacOS 'date' is not quite up to GNU 5 | standards 6 | 7 | E.g.. 8 | date.py 2023-10-14 "The year-month is %y %m" 9 | """ 10 | 11 | import sys 12 | from datetime import datetime 13 | 14 | date=datetime.strptime(sys.argv[1],'%Y-%m-%d') 15 | print(date.strftime(sys.argv[2])) 16 | -------------------------------------------------------------------------------- /build-aux/meson-install-info.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | infodir=$1 4 | infofile=$2 5 | 6 | # Meson post-install script to update info metadata 7 | 8 | # If DESTDIR is set, do _not_ install-info, since it's only a temporary 9 | # install 10 | if test -z "${DESTDIR}"; then 11 | install-info --info-dir "${infodir}" "${infodir}/${infofile}" 12 | gzip --best --force "${infodir}/${infofile}" 13 | fi 14 | -------------------------------------------------------------------------------- /build-aux/version.texi.in: -------------------------------------------------------------------------------- 1 | @set UPDATED @UPDATED@ 2 | @set UPDATED-MONTH @UPDATEDMONTH@ 3 | @set UPDATED-YEAR @UPDATEDYEAR@ 4 | @set EDITION @VERSION@ 5 | @set VERSION @VERSION@ 6 | -------------------------------------------------------------------------------- /contrib/mu-completion.zsh: -------------------------------------------------------------------------------- 1 | #compdef mu 2 | 3 | ## Copyright (C) 2011-2012 Dirk-Jan C. Binnema 4 | ## 5 | ## This program is free software; you can redistribute it and/or modify 6 | ## it under the terms of the GNU General Public License as published by 7 | ## the Free Software Foundation; either version 3 of the License, or 8 | ## (at your option) any later version. 9 | ## 10 | ## This program is distributed in the hope that it will be useful, 11 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | ## GNU General Public License for more details. 14 | ## 15 | ## You should have received a copy of the GNU General Public License 16 | ## along with this program; if not, write to the Free Software Foundation, 17 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | # zsh completion for mu. Install this by copying/linking to this file somewhere in 20 | # your $fpath; the link/copy must have a name starting with an underscore "_" 21 | 22 | # main dispatcher function 23 | _mu() { 24 | if (( CURRENT > 2 )) ; then 25 | local cmd=${words[2]} 26 | curcontext="${curcontext%:*:*}:mu-$cmd" 27 | (( CURRENT-- )) 28 | shift words 29 | _call_function ret _mu_$cmd 30 | return ret 31 | else 32 | _mu_commands 33 | fi 34 | } 35 | 36 | 37 | 38 | _mu_commands() { 39 | local -a mu_commands 40 | mu_commands=( 41 | 'index:scan your maildirs and import their metadata in the database' 42 | 'find:search for messages in the database' 43 | 'view:display specific messages' 44 | 'cfind:search for contacts (name + email) in the database' 45 | 'extract:extract message-parts (attachments) and save or open them' 46 | 'mkdir:create maildirs' 47 | # below are not generally very useful, so let's not auto-complete them 48 | # 'add: add a message to the database.' 49 | # 'remove:remove a message from the database.' 50 | # 'server:sart the mu server' 51 | ) 52 | 53 | _describe -t command 'command' mu_commands 54 | } 55 | 56 | _mu_common_options=( 57 | '--debug[output information useful for debugging mu]' 58 | '--quiet[do not give any non-critical information]' 59 | '--nocolor[do not use colors in some of the output]' 60 | '--version[display mu version and copyright information]' 61 | '--log-stderr[log to standard error]' 62 | ) 63 | 64 | _mu_db_options=( 65 | '--muhome[use some non-default location for the mu database]:directory:_files' 66 | ) 67 | 68 | _mu_find_options=( 69 | '--fields[fields to display in the output]' 70 | '--sortfield[field to sort the output by]' 71 | '--descending[sort in descending order]' 72 | '--summary[include a summary of the message]' 73 | '--summary-len[number of lines to use for the summary]' 74 | '--bookmark[use a named bookmark]' 75 | '--output[set the kind of output for the query]' 76 | ) 77 | 78 | _mu_view_options=( 79 | '--summary[only show a summary of the message]' 80 | '--summary-len[number of lines to use for the summary]' 81 | ) 82 | 83 | 84 | _mu_view() { 85 | _arguments -s : \ 86 | $_mu_common_options \ 87 | $_mu_view_options 88 | } 89 | 90 | _mu_extract() { 91 | _files 92 | } 93 | 94 | _mu_find() { 95 | _arguments -s : \ 96 | $_mu_common_options \ 97 | $_mu_db_options \ 98 | $_mu_find_options 99 | } 100 | 101 | _mu_index() { 102 | _arguments -s : \ 103 | $_mu_db_options \ 104 | $_mu_common_options 105 | }mu 106 | 107 | _mu_cleanup() { 108 | _arguments -s : \ 109 | $_mu_db_options \ 110 | $_mu_common_options 111 | } 112 | 113 | 114 | _mu_mkdir() { 115 | _arguments -s : \ 116 | '--mode=[file mode for the new Maildir]:file mode: ' \ 117 | $_mu_common_options 118 | } 119 | 120 | _mu "$@" 121 | 122 | # Local variables: 123 | # mode: sh 124 | # End: 125 | -------------------------------------------------------------------------------- /guile/compile-scm.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ## Copyright (C) 2021 Dirk-Jan C. Binnema 3 | ## 4 | ## This program is free software; you can redistribute it and/or modify 5 | ## it under the terms of the GNU General Public License as published by 6 | ## the Free Software Foundation; either version 3 of the License, or 7 | ## (at your option) any later version. 8 | ## 9 | ## This program is distributed in the hope that it will be useful, 10 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ## GNU General Public License for more details. 13 | ## 14 | ## You should have received a copy of the GNU General Public License 15 | ## along with this program; if not, write to the Free Software Foundation, 16 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | @abs_builddir@/build-env @guild@ compile "$@" 19 | 20 | # Local-Variables: 21 | # mode: sh 22 | # End: 23 | -------------------------------------------------------------------------------- /guile/examples/contacts-export: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec guile -e main -s $0 $@ 3 | !# 4 | 5 | ;; 6 | ;; Copyright (C) 2012 Dirk-Jan C. Binnema 7 | ;; 8 | ;; This program is free software; you can redistribute it and/or modify it 9 | ;; under the terms of the GNU General Public License as published by the 10 | ;; Free Software Foundation; either version 3, or (at your option) any 11 | ;; later version. 12 | ;; 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | ;; 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program; if not, write to the Free Software Foundation, 21 | ;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | 23 | 24 | (use-modules (ice-9 getopt-long) (ice-9 format)) 25 | (use-modules (srfi srfi-1)) 26 | (use-modules (mu)) 27 | 28 | (define (sort-by-freq c1 c2) 29 | (< (mu:frequency c1) (mu:frequency c2))) 30 | 31 | (define (sort-by-newness c1 c2) 32 | (< (mu:last-seen c1) (mu:last-seen c2))) 33 | 34 | (define (main args) 35 | (let* ((optionspec '( (muhome (value #t)) 36 | (sort-by (value #t)) 37 | (revert (value #f)) 38 | (format (value #t)) 39 | (limit (value #t)) 40 | (help (single-char #\h) (value #f)))) 41 | (options (getopt-long args optionspec)) 42 | (msg (string-append 43 | "usage: contacts-export [--help] [--muhome=] " 44 | "--format= " 45 | "--sort-by= [--revert] [--limit=]\n")) 46 | (help (option-ref options 'help #f)) 47 | (muhome (option-ref options 'muhome #f)) 48 | (sort-by (or (option-ref options 'sort-by #f) "frequency")) 49 | (revert (option-ref options 'revert #f)) 50 | (form (or (option-ref options 'format #f) "plain")) 51 | (limit (string->number (option-ref options 'limit "1000000")))) 52 | (if help 53 | (begin 54 | (display msg) 55 | (exit 0)) 56 | (begin 57 | (setlocale LC_ALL "") 58 | (mu:initialize muhome) 59 | (let* ((sort-func 60 | (cond 61 | ((string= sort-by "frequency") sort-by-freq) 62 | ((string= sort-by "newness") sort-by-newness) 63 | (else (begin (display msg) (exit 1))))) 64 | (contacts '())) 65 | ;; make a list of all contacts 66 | (mu:for-each-contact 67 | (lambda (c) (set! contacts (cons c contacts)))) 68 | 69 | ;; should we sort it? 70 | (if sort-by 71 | (set! contacts (sort! contacts 72 | (if revert (negate sort-func) sort-func)))) 73 | 74 | ;; should we limit the number? 75 | (if (and limit (< limit (length contacts))) 76 | (set! contacts (take! contacts limit))) 77 | ;; export! 78 | (for-each 79 | (lambda (c) 80 | (format #t "~a\n" (mu:contact->string c form))) 81 | contacts)))))) 82 | 83 | ;; Local Variables: 84 | ;; mode: scheme 85 | ;; End: 86 | -------------------------------------------------------------------------------- /guile/examples/mu-biff: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec guile -e main -s $0 $@ 3 | !# 4 | 5 | ;; 6 | ;; Copyright (C) 2012 Dirk-Jan C. Binnema 7 | ;; 8 | ;; This program is free software; you can redistribute it and/or modify it 9 | ;; under the terms of the GNU General Public License as published by the 10 | ;; Free Software Foundation; either version 3, or (at your option) any 11 | ;; later version. 12 | ;; 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | ;; 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program; if not, write to the Free Software Foundation, 21 | ;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | 23 | ;; script to list the message matching which are newer than 24 | ;; minutes 25 | 26 | ;; use it, eg. like: 27 | ;; $ mu-biff --newer-than=`date +%s --date='5 minutes ago'` "maildir:/inbox" 28 | 29 | 30 | (use-modules (ice-9 getopt-long) (ice-9 format)) 31 | (use-modules (mu)) 32 | 33 | (define (main args) 34 | (let* ((optionspec '((muhome (value #t)) 35 | (newer-than (value #t)) 36 | (help (single-char #\h) (value #f)))) 37 | (options (getopt-long args optionspec)) 38 | (msg (string-append 39 | "usage: mu-biff [--help] [--muhome=]" 40 | " [--newer-than=] ")) 41 | (help (option-ref options 'help #f)) 42 | (newer-than (string->number (option-ref options 'newer-than "0"))) 43 | (muhome (option-ref options 'muhome #f)) 44 | (query (string-concatenate (option-ref options '() '())))) 45 | (if help 46 | (begin (display msg) (newline) (exit 0)) 47 | (begin 48 | (mu:initialize muhome) 49 | (mu:for-each-message 50 | (lambda (msg) 51 | (if (> (mu:timestamp msg) newer-than) 52 | (format #t "~a ~a\n" 53 | (mu:from msg) 54 | (mu:subject msg)))) 55 | query))))) 56 | 57 | ;; Local Variables: 58 | ;; mode: scheme 59 | ;; End: 60 | -------------------------------------------------------------------------------- /guile/examples/org2mu4e: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec guile -e main -s $0 $@ 3 | !# 4 | 5 | ;; 6 | ;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema 7 | ;; 8 | ;; This program is free software; you can redistribute it and/or modify it 9 | ;; under the terms of the GNU General Public License as published by the 10 | ;; Free Software Foundation; either version 3, or (at your option) any 11 | ;; later version. 12 | ;; 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | ;; 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program; if not, write to the Free Software Foundation, 21 | ;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | 23 | (use-modules (ice-9 getopt-long) (ice-9 format)) 24 | (use-modules (mu)) 25 | 26 | (define (display-org-header query) 27 | "Print the header for the org-file for QUERY." 28 | (format #t "* Messages matching '~a'\n\n" query)) 29 | 30 | (define (org-mu4e-link msg) 31 | "Create a link for this message understandable by org-mu4e." 32 | (let* ((subject ;; cleanup subject 33 | (string-map 34 | (lambda (kar) 35 | (if (member kar '(#\] #\[)) #\space kar)) 36 | (or (mu:subject msg) "No subject")))) 37 | (format #f "[[mu4e:msgid:~a][~s]]" 38 | (mu:message-id msg) subject))) 39 | 40 | (define (display-org-entry msg tag) 41 | "Write an org entry for MSG." 42 | (format #t "** ~a ~a\n\t~s\n\t~s\n" 43 | (org-mu4e-link msg) 44 | (if tag (string-concatenate `(":" ,tag "::")) "") 45 | (or (mu:from msg) "?") 46 | (let ((body (mu:body msg))) 47 | (if (not body) ;; get a 'summary' of the body text 48 | "" 49 | (string-map 50 | (lambda (c) 51 | (if (or (char=? c #\newline) (char=? c #\return)) 52 | #\space 53 | c)) 54 | (substring body 0 (min (string-length body) 100))))))) 55 | 56 | (define (main args) 57 | (let* ((optionspec '( (muhome (value #t)) 58 | (tag (value #t)) 59 | (help (single-char #\h) (value #f)))) 60 | (options (getopt-long args optionspec)) 61 | (msg (string-append 62 | "usage: mu4e-org [--help] [--muhome=] [--tag=] ")) 63 | (help (option-ref options 'help #f)) 64 | (tag (option-ref options 'tag #f)) 65 | (muhome (option-ref options 'muhome #f)) 66 | (query (string-concatenate (option-ref options '() '())))) 67 | (if help 68 | (begin (display msg) (exit 0)) 69 | (begin 70 | (mu:initialize muhome) 71 | (display-org-header query) 72 | (mu:for-each-message 73 | (lambda (msg) (display-org-entry msg tag)) 74 | query))))) 75 | 76 | ;; Local Variables: 77 | ;; mode: scheme 78 | ;; End: 79 | -------------------------------------------------------------------------------- /guile/mu-guile-message.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2011-2020 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_GUILE_MESSAGE_H__ 21 | #define MU_GUILE_MESSAGE_H__ 22 | 23 | /** 24 | * Initialize this mu guile module. 25 | * 26 | * @param data 27 | q * 28 | * @return 29 | */ 30 | extern "C" { 31 | void* mu_guile_message_init(void* data); 32 | } 33 | 34 | #endif /*MU_GUILE_MESSAGE_HH__*/ 35 | -------------------------------------------------------------------------------- /guile/mu-guile-message.x: -------------------------------------------------------------------------------- 1 | /* cpp arguments: mu-guile-message.cc -DHAVE_CONFIG_H -I. -I.. -I../lib -I/usr/local/include/guile/3.0 -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/sysprof-4 -I/usr/include/libmount -I/usr/include/blkid -pthread -fno-strict-aliasing -Wall -Wextra -Wundef -Wwrite-strings -Wpointer-arith -Wmissing-declarations -Wredundant-decls -Wno-unused-parameter -Wno-missing-field-initializers -Wformat=2 -Wcast-align -Wformat-nonliteral -Wformat-security -Wsign-compare -Wstrict-aliasing -Wshadow -Winline -Wpacked -Wmissing-format-attribute -Wmissing-noreturn -Winit-self -Wmissing-include-dirs -Wunused-but-set-variable -Warray-bounds -Wreturn-type -Wno-overloaded-virtual -Wswitch-enum -Wswitch-default -Wno-error=unused-parameter -Wno-error=missing-field-initializers -Wno-error=overloaded-virtual -Wno-redundant-decls -Wno-missing-declarations -Wno-suggest-attribute=noreturn -O2 -Wno-inline */ 2 | scm_c_define_gsubr (s_get_field, 2, 0, 0, (scm_t_subr) get_field);; 3 | scm_c_define_gsubr (s_get_contacts, 2, 0, 0, (scm_t_subr) get_contacts);; 4 | scm_c_define_gsubr (s_get_parts, 1, 1, 0, (scm_t_subr) get_parts);; 5 | scm_c_define_gsubr (s_get_header, 2, 0, 0, (scm_t_subr) get_header);; 6 | scm_c_define_gsubr (s_for_each_message, 3, 0, 0, (scm_t_subr) for_each_message);; 7 | -------------------------------------------------------------------------------- /guile/mu-guile.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2011-2020 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef __MU_GUILE_H__ 21 | #define __MU_GUILE_H__ 22 | 23 | #include 24 | #include 25 | 26 | #pragma GCC diagnostic push 27 | #pragma GCC diagnostic ignored "-Wredundant-decls" 28 | #include 29 | #pragma GCC diagnostic pop 30 | 31 | /** 32 | * get the singleton Store instance 33 | */ 34 | Mu::Store& mu_guile_store(); 35 | 36 | /** 37 | * whether mu-guile is initialized 38 | * 39 | * @return TRUE if MuGuile is Initialized, FALSE otherwise 40 | */ 41 | gboolean mu_guile_initialized(); 42 | 43 | /** 44 | * raise a guile error (based on a GError) 45 | * 46 | * @param func_name function name 47 | * @param err the error 48 | * 49 | * @return SCM_UNSPECIFIED 50 | */ 51 | SCM mu_guile_g_error(const char* func_name, GError* err); 52 | 53 | /** 54 | * raise a guile error 55 | * 56 | * @param func_name function 57 | * @param status err code 58 | * @param fmt format string for error msg 59 | * @param args params for format string 60 | * 61 | * @return SCM_UNSPECIFIED 62 | */ 63 | SCM mu_guile_error(const char* func_name, int status, const char* fmt, SCM args); 64 | 65 | /** 66 | * convert a string into an SCM -- . It assumes str is in UTF8 encoding, and 67 | * replace characters with '?' if needed. 68 | * 69 | * @param str a string 70 | * 71 | * @return a guile string or #f for empty 72 | */ 73 | SCM mu_guile_scm_from_string(const std::string& str); 74 | 75 | /** 76 | * Initialize this mu guile module. 77 | * 78 | * @param data 79 | * 80 | * @return 81 | */ 82 | extern "C" { 83 | void* mu_guile_init(void* data); 84 | } 85 | #endif /*__MU_GUILE_H__*/ 86 | -------------------------------------------------------------------------------- /guile/mu-guile.x: -------------------------------------------------------------------------------- 1 | /* cpp arguments: mu-guile.cc -DHAVE_CONFIG_H -I. -I.. -I../lib -I/usr/local/include/guile/3.0 -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/sysprof-4 -I/usr/include/libmount -I/usr/include/blkid -pthread -fno-strict-aliasing -Wall -Wextra -Wundef -Wwrite-strings -Wpointer-arith -Wmissing-declarations -Wredundant-decls -Wno-unused-parameter -Wno-missing-field-initializers -Wformat=2 -Wcast-align -Wformat-nonliteral -Wformat-security -Wsign-compare -Wstrict-aliasing -Wshadow -Winline -Wpacked -Wmissing-format-attribute -Wmissing-noreturn -Winit-self -Wmissing-include-dirs -Wunused-but-set-variable -Warray-bounds -Wreturn-type -Wno-overloaded-virtual -Wswitch-enum -Wswitch-default -Wno-error=unused-parameter -Wno-error=missing-field-initializers -Wno-error=overloaded-virtual -Wno-redundant-decls -Wno-missing-declarations -Wno-suggest-attribute=noreturn -O2 -Wno-inline */ 2 | scm_c_define_gsubr (s_mu_initialize, 0, 1, 0, (scm_t_subr) mu_initialize); scm_c_export (s_mu_initialize, __null );; 3 | scm_c_define_gsubr (s_mu_initialized_p, 0, 0, 0, (scm_t_subr) mu_initialized_p); scm_c_export (s_mu_initialized_p, __null );; 4 | scm_c_define_gsubr (s_log_func, 1, 0, 1, (scm_t_subr) log_func);; 5 | -------------------------------------------------------------------------------- /guile/mu/contact.scm: -------------------------------------------------------------------------------- 1 | (define-module (mu contact) :use-module(mu)) 2 | (display "(mu contact) is deprecated, please remove from (use-modules ...)") 3 | (newline) 4 | 5 | -------------------------------------------------------------------------------- /guile/mu/message.scm: -------------------------------------------------------------------------------- 1 | (define-module (mu message) :use-module (mu)) 2 | (display "(mu message) is deprecated, please remove from (use-modules ...)") 3 | (newline) 4 | 5 | -------------------------------------------------------------------------------- /guile/mu/part.scm: -------------------------------------------------------------------------------- 1 | (define-module (mu part) :use-module (mu)) 2 | (display "(mu part) is deprecated, please remove from (use-modules ...)") 3 | (newline) 4 | 5 | -------------------------------------------------------------------------------- /guile/mu/plot.scm: -------------------------------------------------------------------------------- 1 | ;; 2 | ;; Copyright (C) 2011-2022 Dirk-Jan C. Binnema 3 | ;; 4 | ;; This program is free software; you can redistribute it and/or modify it 5 | ;; under the terms of the GNU General Public License as published by the 6 | ;; Free Software Foundation; either version 3, or (at your option) any 7 | ;; later version. 8 | ;; 9 | ;; This program is distributed in the hope that it will be useful, 10 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ;; GNU General Public License for more details. 13 | ;; 14 | 15 | ;; You should have received a copy of the GNU General Public License 16 | ;; along with this program; if not, write to the Free Software Foundation, 17 | ;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | (define-module (mu plot) 20 | :use-module (mu) 21 | :use-module (ice-9 popen) 22 | :export ( mu:plot ;; alias for mu:plot-histogram 23 | mu:plot-histogram 24 | )) 25 | 26 | (define (export-pairs pairs) 27 | "Write a temporary file with the list of PAIRS in table format, and 28 | return the file name." 29 | (let* ((output (mkstemp "/tmp/mu-guile-XXXXXX" "w")) 30 | (datafile (port-filename output))) 31 | (for-each 32 | (lambda(pair) 33 | (display (format #f "~a ~a\n" (car pair) (cdr pair)) output)) 34 | pairs) 35 | (close output) 36 | datafile)) 37 | 38 | (define (find-program-in-path prog) 39 | "Find exutable program PROG in PATH; return the full path, or #f if 40 | not found." 41 | (let* ((path (parse-path (getenv "PATH"))) 42 | (progpath (search-path path prog))) 43 | (if (not progpath) 44 | #f 45 | (if (access? progpath X_OK) ;; is 46 | progpath 47 | #f)))) 48 | 49 | (define* (mu:plot-histogram data title x-label y-label 50 | #:optional (output "dumb") (extra-gnuplot-opts '())) 51 | "Plot DATA with TITLE, X-LABEL and X-LABEL using the gnuplot 52 | program. DATA is a list of cons-pairs (X . Y). 53 | 54 | OUTPUT is a string 55 | that determines the type of output that gnuplot produces, depending on 56 | the system. Which options are available depends on the particulars for 57 | the gnuplot installation, but typical examples would be \"dumb\" for 58 | text-only display, \"wxterm\" to write to a graphical window, or 59 | \"png\" to write a PNG-image to stdout. 60 | 61 | EXTRA-GNUPLOT-OPTS is a list 62 | of any additional options for gnuplot." 63 | (if (not (find-program-in-path "gnuplot")) 64 | (error "cannot find 'gnuplot' in path")) 65 | (when (zero? (length data)) 66 | (error "No data for plotting")) 67 | (let* ((datafile (export-pairs data)) 68 | (gnuplot (open-pipe "gnuplot -p" OPEN_WRITE)) 69 | (recipe 70 | (string-append 71 | "reset\n" 72 | "set term " (or output "dumb") "\n" 73 | "set title \"" title "\"\n" 74 | "set xlabel \"" x-label "\"\n" 75 | "set ylabel \"" y-label "\"\n" 76 | "set boxwidth 0.9\n" 77 | (string-join extra-gnuplot-opts "\n") 78 | "plot \"" datafile "\" using 2:xticlabels(1) with boxes fs solid title \"\"\n"))) 79 | (display recipe gnuplot) 80 | (close-pipe gnuplot))) 81 | 82 | ;; backward compatibility 83 | (define mu:plot mu:plot-histogram) 84 | -------------------------------------------------------------------------------- /guile/mu/script.scm: -------------------------------------------------------------------------------- 1 | ;; Copyright (C) 2012-2013 Dirk-Jan C. Binnema 2 | ;; 3 | ;; This program is free software; you can redistribute it and/or modify it 4 | ;; under the terms of the GNU General Public License as published by the 5 | ;; Free Software Foundation; either version 3, or (at your option) any 6 | ;; later version. 7 | ;; 8 | ;; This program is distributed in the hope that it will be useful, 9 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ;; GNU General Public License for more details. 12 | ;; 13 | 14 | ;; You should have received a copy of the GNU General Public License 15 | ;; along with this program; if not, write to the Free Software Foundation, 16 | ;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | (define-module (mu script) 18 | :export (mu:run-stats)) 19 | 20 | (use-modules (ice-9 getopt-long) (ice-9 optargs) (ice-9 popen) (ice-9 format)) 21 | (use-modules (mu) (mu stats) (mu plot)) 22 | 23 | (define (help-and-exit) 24 | "Show some help." 25 | (display 26 | (string-append "usage: script [--help] [--textonly] " 27 | "[--muhome=] [--query=") 28 | (newline)) 29 | (exit 0)) 30 | 31 | (define (mu:run-stats args func) 32 | "Run some statistics function. 33 | Interpret argument-list ARGS (like command-line 34 | arguments). Possible arguments are: 35 | --help (show some help and exit) 36 | --muhome (path to alternative mu home directory) 37 | --output (a string describing the output, e.g. \"dumb\", \"png\" \"wxt\") 38 | searchexpr (a search query) 39 | then call FUNC with args SEARCHEXPR and OUTPUT." 40 | (setlocale LC_ALL "") 41 | (let* ((optionspec '((muhome (value #t)) 42 | (query (value #t)) 43 | (output (value #f)) 44 | (time-unit (value #t)) ;; Ignore. 45 | (help (single-char #\h) (value #f)))) 46 | (options (getopt-long args optionspec)) 47 | (query (option-ref options 'query #f)) 48 | (help (option-ref options 'help #f)) 49 | (output (option-ref options 'output #f)) 50 | (muhome (option-ref options 'muhome #f)) 51 | (restargs (option-ref options '() #f))) 52 | (if help (help-and-exit)) 53 | (mu:initialize muhome) 54 | (func (or query "") output))) 55 | 56 | ;; Local Variables: 57 | ;; mode: scheme 58 | ;; End: 59 | -------------------------------------------------------------------------------- /guile/scripts/msgs-count.scm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec guile -e main -s $0 $@ 3 | !# 4 | ;; Copyright (C) 2022 Dirk-Jan C. Binnema 5 | ;; 6 | ;; This program is free software; you can redistribute it and/or modify it 7 | ;; under the terms of the GNU General Public License as published by the 8 | ;; Free Software Foundation; either version 3, or (at your option) any 9 | ;; later version. 10 | ;; 11 | ;; This program is distributed in the hope that it will be useful, 12 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ;; GNU General Public License for more details. 15 | ;; 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program; if not, write to the Free Software Foundation, 19 | ;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | 22 | ;; INFO: Count the number of messages matching some query 23 | ;; INFO: options: 24 | ;; INFO: --query=: limit to messages matching query 25 | ;; INFO: --muhome=: path to mu home dir (optional) 26 | 27 | (use-modules (mu) (mu script) (mu stats)) 28 | 29 | (define (count expr output) 30 | "Print the total number of messages matching the query EXPR. 31 | OUTPUT is ignored." 32 | (display (mu:count expr)) 33 | (newline)) 34 | 35 | (define (main args) 36 | (mu:run-stats args count)) 37 | 38 | ;; Local Variables: 39 | ;; mode: scheme 40 | ;; End: 41 | -------------------------------------------------------------------------------- /guile/tests/meson.build: -------------------------------------------------------------------------------- 1 | ## Copyright (C) 2024 Dirk-Jan C. Binnema 2 | ## 3 | ## This program is free software; you can redistribute it and/or modify 4 | ## it under the terms of the GNU General Public License as published by 5 | ## the Free Software Foundation; either version 3 of the License, or 6 | ## (at your option) any later version. 7 | ## 8 | ## This program is distributed in the hope that it will be useful, 9 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ## GNU General Public License for more details. 12 | ## 13 | ## You should have received a copy of the GNU General Public License 14 | ## along with this program; if not, write to the Free Software Foundation, 15 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | # 18 | # guile test; they don't work with ASAN. 19 | # 20 | if get_option('b_sanitize') == 'none' 21 | guile_load_path = join_paths(meson.project_source_root(), 'guile') 22 | guile_extensions_path = ':'.join([ 23 | join_paths(meson.project_build_root(), 'guile'), 24 | meson.current_build_dir()]) 25 | 26 | test('test-mu-guile', 27 | executable('test-mu-guile', 28 | 'test-mu-guile.cc', 29 | install: false, 30 | cpp_args: [ 31 | '-DABS_SRCDIR="' + meson.current_source_dir() + '"', 32 | '-DGUILE_LOAD_PATH="' + guile_load_path + '"', 33 | '-DGUILE_EXTENSIONS_PATH="' + guile_extensions_path + '"' 34 | ], 35 | dependencies: [glib_dep, lib_mu_dep])) 36 | else 37 | message('sanitizer build; skip guile test') 38 | endif 39 | -------------------------------------------------------------------------------- /guile/tests/test-mu-guile.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2012-2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "config.h" 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "utils/mu-test-utils.hh" 31 | #include 32 | #include 33 | 34 | using namespace Mu; 35 | 36 | static std::string test_dir; 37 | 38 | static std::string 39 | fill_database(void) 40 | { 41 | const auto cmdline = mu_format( 42 | "/bin/sh -c '" 43 | "{} init --muhome={} --maildir={} --quiet; " 44 | "{} index --muhome={} --quiet'", 45 | MU_PROGRAM, 46 | test_dir, 47 | MU_TESTMAILDIR2, 48 | MU_PROGRAM, 49 | test_dir); 50 | 51 | if (g_test_verbose()) 52 | mu_println("{}", cmdline); 53 | 54 | GError *err{}; 55 | if (!g_spawn_command_line_sync(cmdline.c_str(), NULL, NULL, NULL, &err)) { 56 | mu_printerrln("Error: {}", err ? err->message : "?"); 57 | g_clear_error(&err); 58 | g_assert(0); 59 | } 60 | 61 | return test_dir; 62 | } 63 | 64 | static void 65 | test_something(const char* what) 66 | { 67 | g_setenv("GUILE_AUTO_COMPILE", "0", TRUE); 68 | g_setenv("GUILE_LOAD_PATH", GUILE_LOAD_PATH, TRUE); 69 | g_setenv("GUILE_EXTENSIONS_PATH",GUILE_EXTENSIONS_PATH, TRUE); 70 | 71 | if (g_test_verbose()) 72 | g_print("GUILE_LOAD_PATH: %s\n", GUILE_LOAD_PATH); 73 | 74 | const auto dir = fill_database(); 75 | const auto cmdline = mu_format("{} -q -e main {}/test-mu-guile.scm " 76 | "--muhome={} --test={}", 77 | GUILE_BINARY, ABS_SRCDIR, 78 | dir, what); 79 | 80 | if (g_test_verbose()) 81 | mu_println("cmdline: {}", cmdline); 82 | 83 | GError *err{}; 84 | int status{}; 85 | if (!g_spawn_command_line_sync(cmdline.c_str(), NULL, NULL, &status, &err) || 86 | status != 0) { 87 | mu_printerrln("Error: {}", err ? err->message : "something went wrong"); 88 | g_clear_error(&err); 89 | g_assert(0); 90 | } 91 | } 92 | 93 | static void 94 | test_mu_guile_queries(void) 95 | { 96 | test_something("queries"); 97 | } 98 | 99 | static void 100 | test_mu_guile_messages(void) 101 | { 102 | test_something("message"); 103 | } 104 | 105 | static void 106 | test_mu_guile_stats(void) 107 | { 108 | test_something("stats"); 109 | } 110 | 111 | int 112 | main(int argc, char* argv[]) 113 | { 114 | int rv; 115 | TempDir tempdir; 116 | test_dir = tempdir.path(); 117 | 118 | mu_test_init(&argc, &argv); 119 | 120 | if (!set_en_us_utf8_locale()) 121 | return 0; /* don't error out... */ 122 | 123 | g_test_add_func("/guile/queries", test_mu_guile_queries); 124 | g_test_add_func("/guile/message", test_mu_guile_messages); 125 | g_test_add_func("/guile/stats", test_mu_guile_stats); 126 | 127 | rv = g_test_run(); 128 | 129 | return rv; 130 | } 131 | -------------------------------------------------------------------------------- /lib/meson.build: -------------------------------------------------------------------------------- 1 | ## Copyright (C) 2021-2023 Dirk-Jan C. Binnema 2 | ## 3 | ## This program is free software; you can redistribute it and/or modify 4 | ## it under the terms of the GNU General Public License as published by 5 | ## the Free Software Foundation; either version 3 of the License, or 6 | ## (at your option) any later version. 7 | ## 8 | ## This program is distributed in the hope that it will be useful, 9 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ## GNU General Public License for more details. 12 | ## 13 | ## You should have received a copy of the GNU General Public License 14 | ## along with this program; if not, write to the Free Software Foundation, 15 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | 18 | subdir('utils') 19 | subdir('message') 20 | 21 | lib_mu=static_library( 22 | 'mu', 23 | [ 24 | # db 25 | 'mu-config.cc', 26 | 'mu-contacts-cache.cc', 27 | 'mu-store.cc', 28 | 'mu-xapian-db.cc', 29 | # querying 30 | 'mu-query-macros.cc', 31 | 'mu-query-match-deciders.cc', 32 | 'mu-query-parser.cc', 33 | 'mu-query-processor.cc', 34 | 'mu-query-threads.cc', 35 | 'mu-query-xapianizer.cc', 36 | 'mu-query.cc', 37 | # indexing 38 | 'mu-indexer.cc', 39 | 'mu-scanner.cc', 40 | # mu4e 41 | 'mu-server.cc', 42 | # misc 43 | 'mu-maildir.cc', 44 | 'mu-script.cc' 45 | ], 46 | dependencies: [ 47 | glib_dep, 48 | gio_dep, 49 | gmime_dep, 50 | xapian_dep, 51 | guile_dep, 52 | config_h_dep, 53 | lib_mu_utils_dep, 54 | lib_mu_message_dep], 55 | install: false) 56 | 57 | lib_mu_dep = declare_dependency( 58 | link_with: lib_mu, 59 | dependencies: [ lib_mu_message_dep, thread_dep ], 60 | include_directories: 61 | include_directories(['.', '..'])) 62 | 63 | # 64 | # dev helpers 65 | # 66 | 67 | process_query = executable('process-query', [ 'mu-query-processor.cc'], 68 | install: false, 69 | cpp_args: ['-DBUILD_PROCESS_QUERY'], 70 | dependencies: [glib_dep, lib_mu_dep]) 71 | 72 | parse_query = executable( 'parse-query', [ 'mu-query-parser.cc' ], 73 | install: false, 74 | cpp_args: ['-DBUILD_PARSE_QUERY'], 75 | dependencies: [glib_dep, lib_mu_dep]) 76 | 77 | parse_query_expand = executable( 'parse-query-expand', [ 'mu-query-parser.cc' ], 78 | install: false, 79 | cpp_args: ['-DBUILD_PARSE_QUERY_EXPAND'], 80 | dependencies: [glib_dep, lib_mu_dep]) 81 | 82 | xapian_query = executable('xapianize-query', [ 'mu-query-xapianizer.cc' ], 83 | install: false, 84 | cpp_args: ['-DBUILD_XAPIANIZE_QUERY'], 85 | dependencies: [glib_dep, lib_mu_dep]) 86 | 87 | list_maildirs = executable('list-maildirs', 'mu-scanner.cc', 88 | install: false, 89 | cpp_args: ['-DBUILD_LIST_MAILDIRS'], 90 | dependencies: [glib_dep, config_h_dep, 91 | lib_mu_utils_dep]) 92 | 93 | if not get_option('tests').disabled() 94 | subdir('tests') 95 | endif 96 | -------------------------------------------------------------------------------- /lib/message/meson.build: -------------------------------------------------------------------------------- 1 | ## Copyright (C) 2022-2024 Dirk-Jan C. Binnema 2 | ## 3 | ## This program is free software; you can redistribute it and/or modify 4 | ## it under the terms of the GNU General Public License as published by 5 | ## the Free Software Foundation; either version 3 of the License, or 6 | ## (at your option) any later version. 7 | ## 8 | ## This program is distributed in the hope that it will be useful, 9 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ## GNU General Public License for more details. 12 | ## 13 | ## You should have received a copy of the GNU General Public License 14 | ## along with this program; if not, write to the Free Software Foundation, 15 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | 18 | lib_mu_message=static_library( 19 | 'mu-message', 20 | [ 21 | 'mu-message.cc', 22 | 'mu-message-file.cc', 23 | 'mu-message-part.cc', 24 | 'mu-contact.cc', 25 | 'mu-document.cc', 26 | 'mu-fields.cc', 27 | 'mu-flags.cc', 28 | 'mu-priority.cc', 29 | 'mu-mime-object.cc', 30 | ], 31 | dependencies: [ 32 | glib_dep, 33 | gmime_dep, 34 | xapian_dep, 35 | config_h_dep, 36 | lib_mu_utils_dep], 37 | install: false) 38 | 39 | lib_mu_message_dep = declare_dependency( 40 | link_with: lib_mu_message, 41 | dependencies: [ xapian_dep, gmime_dep, lib_mu_utils_dep, config_h_dep ], 42 | include_directories: 43 | include_directories(['.', '..'])) 44 | 45 | if not get_option('tests').disabled() 46 | subdir('tests') 47 | endif 48 | -------------------------------------------------------------------------------- /lib/message/mu-message-file.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2022 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_MESSAGE_FILE_HH__ 21 | #define MU_MESSAGE_FILE_HH__ 22 | 23 | #include "mu-flags.hh" 24 | #include 25 | 26 | namespace Mu { 27 | 28 | /* 29 | * The file-components, ie. 30 | * 1631819685.fb7b279bbb0a7b66.evergrey:2,RS 31 | * => { 32 | * "1631819685.fb7b279bbb0a7b66.evergrey", 33 | * ':', 34 | * "2,", 35 | * "RS" 36 | * } 37 | */ 38 | struct FileParts { 39 | std::string base; /**< basename */ 40 | char separator; /**< separator */ 41 | std::string flags_suffix; /**< suffix (with flags) */ 42 | }; 43 | 44 | /** 45 | * Get the file-parts for some message-file 46 | * 47 | * @param file path to some message file (does not have to exist) 48 | * 49 | * @return FileParts for the message file 50 | */ 51 | FileParts message_file_parts(const std::string& file); 52 | 53 | 54 | struct DirFile { 55 | std::string dir; 56 | std::string file; 57 | bool is_new; 58 | }; 59 | 60 | /** 61 | * Get information about the message file componemts 62 | * 63 | * @param path message path 64 | * 65 | * @return the components for the message file or an error. 66 | */ 67 | Result base_message_dir_file(const std::string& path); 68 | 69 | 70 | 71 | /** 72 | * Get the Maildir flags from the full path of a mailfile. The flags are as 73 | * specified in http://cr.yp.to/proto/maildir.html, plus Flag::New for new 74 | * messages, ie the ones that live in new/. The flags are logically OR'ed. Note 75 | * that the file does not have to exist; the flags are based on the path only. 76 | * 77 | * @param pathname of a mailfile; it does not have to refer to an 78 | * actual message 79 | * 80 | * @return the message flags or an error 81 | */ 82 | Result flags_from_path(const std::string& pathname); 83 | 84 | /** 85 | * get the maildir for a certain message path, ie, the path *before* 86 | * cur/ or new/ and *after* the root. 87 | * 88 | * @param path path for some message 89 | * @param root filesystem root for the maildir 90 | * 91 | * @return the maildir or an Error 92 | */ 93 | Result maildir_from_path(const std::string& path, 94 | const std::string& root); 95 | } // Mu 96 | 97 | 98 | #endif /* MU_MESSAGE_FILE_HH__ */ 99 | -------------------------------------------------------------------------------- /lib/message/mu-priority.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2022 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "mu-priority.hh" 21 | 22 | using namespace Mu; 23 | 24 | std::string 25 | Mu::to_string(Priority prio) 26 | { 27 | return std::string{priority_name(prio)}; 28 | } 29 | 30 | /* 31 | * tests... also build as runtime-tests, so we can get coverage info 32 | */ 33 | #ifdef BUILD_TESTS 34 | #include 35 | #define static_assert g_assert_true 36 | #endif /*BUILD_TESTS*/ 37 | 38 | [[maybe_unused]] static void 39 | test_priority_to_char() 40 | { 41 | static_assert(to_char(Priority::Low) == 'l'); 42 | static_assert(to_char(Priority::Normal) == 'n'); 43 | static_assert(to_char(Priority::High) == 'h'); 44 | } 45 | 46 | [[maybe_unused]] static void 47 | test_priority_from_char() 48 | { 49 | static_assert(priority_from_char('l') == Priority::Low); 50 | static_assert(priority_from_char('n') == Priority::Normal); 51 | static_assert(priority_from_char('h') == Priority::High); 52 | static_assert(priority_from_char('x') == Priority::Normal); 53 | } 54 | 55 | [[maybe_unused]] static void 56 | test_priority_name() 57 | { 58 | static_assert(priority_name(Priority::Low) == "low"); 59 | static_assert(priority_name(Priority::Normal) == "normal"); 60 | static_assert(priority_name(Priority::High) == "high"); 61 | } 62 | 63 | 64 | #ifdef BUILD_TESTS 65 | int 66 | main(int argc, char* argv[]) 67 | { 68 | g_test_init(&argc, &argv, NULL); 69 | 70 | g_test_add_func("/message/priority/to-char", test_priority_to_char); 71 | g_test_add_func("/message/priority/from-char", test_priority_from_char); 72 | g_test_add_func("/message/priority/name", test_priority_name); 73 | 74 | return g_test_run(); 75 | } 76 | #endif /*BUILD_TESTS*/ 77 | -------------------------------------------------------------------------------- /lib/message/mu-priority.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2022 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_PRIORITY_HH__ 21 | #define MU_PRIORITY_HH__ 22 | 23 | #include 24 | #include 25 | #include 26 | #include "mu-fields.hh" 27 | 28 | namespace Mu { 29 | /** 30 | * Message priorities 31 | * 32 | */ 33 | 34 | /** 35 | * The priority ids 36 | * 37 | */ 38 | enum struct Priority : char { 39 | Low = 'l', /**< Low priority */ 40 | Normal = 'n', /**< Normal priority */ 41 | High = 'h', /**< High priority */ 42 | }; 43 | 44 | /** 45 | * Sequence of all message priorities. 46 | */ 47 | static constexpr std::array AllMessagePriorities = { 48 | Priority::Low, Priority::Normal, Priority::High}; 49 | 50 | /** 51 | * Get the char for some priority 52 | * 53 | * @param id an id 54 | * 55 | * @return the char 56 | */ 57 | constexpr char 58 | to_char(Priority prio) 59 | { 60 | return static_cast(prio); 61 | } 62 | 63 | /** 64 | * Get the priority for some character; unknown ones 65 | * become Normal. 66 | * 67 | * @param c some character 68 | */ 69 | constexpr Priority 70 | priority_from_char(char c) 71 | { 72 | switch (c) { 73 | case 'l': 74 | return Priority::Low; 75 | case 'h': 76 | return Priority::High; 77 | case 'n': 78 | default: 79 | return Priority::Normal; 80 | } 81 | } 82 | 83 | /** 84 | * Get the priority from their (internal) name, i.e., low/normal/high 85 | * or shortcut. 86 | * 87 | * @param pname 88 | * 89 | * @return the priority or none 90 | */ 91 | static inline Option 92 | priority_from_name(std::string_view pname) 93 | { 94 | if (pname == "low" || pname == "l") 95 | return Priority::Low; 96 | else if (pname == "high" || pname == "h") 97 | return Priority::High; 98 | else if (pname == "normal" || pname == "n") 99 | return Priority::Normal; 100 | else 101 | return Nothing; 102 | } 103 | 104 | 105 | /** 106 | * Get the name for a given priority 107 | * 108 | * @return the name 109 | */ 110 | constexpr std::string_view 111 | priority_name(Priority prio) 112 | { 113 | switch (prio) { 114 | case Priority::Low: 115 | return "low"; 116 | case Priority::High: 117 | return "high"; 118 | case Priority::Normal: 119 | default: 120 | return "normal"; 121 | } 122 | } 123 | 124 | /** 125 | * Get the name for a given priority (backward compatibility) 126 | * 127 | * @return the name 128 | */ 129 | constexpr const char* 130 | priority_name_c_str(Priority prio) 131 | { 132 | switch (prio) { 133 | case Priority::Low: 134 | return "low"; 135 | case Priority::High: 136 | return "high"; 137 | case Priority::Normal: 138 | default: 139 | return "normal"; 140 | } 141 | } 142 | 143 | /** 144 | * Get a the message priority as a string 145 | * 146 | * @param prio priority 147 | * 148 | * @return a string 149 | */ 150 | std::string to_string(Priority prio); 151 | 152 | } // namespace Mu 153 | 154 | #endif /*MU_PRIORITY_HH_*/ 155 | -------------------------------------------------------------------------------- /lib/message/tests/meson.build: -------------------------------------------------------------------------------- 1 | ## Copyright (C) 2022-2024 Dirk-Jan C. Binnema 2 | ## 3 | ## This program is free software; you can redistribute it and/or modify 4 | ## it under the terms of the GNU General Public License as published by 5 | ## the Free Software Foundation; either version 3 of the License, or 6 | ## (at your option) any later version. 7 | ## 8 | ## This program is distributed in the hope that it will be useful, 9 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ## GNU General Public License for more details. 12 | ## 13 | ## You should have received a copy of the GNU General Public License 14 | ## along with this program; if not, write to the Free Software Foundation, 15 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | # 18 | # tests 19 | # 20 | 21 | test('test-contact', 22 | executable('test-contact', 23 | '../mu-contact.cc', 24 | install: false, 25 | cpp_args: ['-DBUILD_TESTS'], 26 | dependencies: [glib_dep, gmime_dep, lib_mu_message_dep])) 27 | 28 | test('test-document', 29 | executable('test-document', 30 | '../mu-document.cc', 31 | install: false, 32 | cpp_args: ['-DBUILD_TESTS'], 33 | dependencies: [glib_dep, gmime_dep, lib_mu_message_dep])) 34 | 35 | test('test-fields', 36 | executable('test-fields', 37 | '../mu-fields.cc', 38 | install: false, 39 | cpp_args: ['-DBUILD_TESTS'], 40 | dependencies: [glib_dep, gmime_dep, lib_mu_message_dep])) 41 | 42 | test('test-flags', 43 | executable('test-flags', 44 | '../mu-flags.cc', 45 | install: false, 46 | cpp_args: ['-DBUILD_TESTS'], 47 | dependencies: [glib_dep, gmime_dep, lib_mu_message_dep])) 48 | 49 | test('test-message', 50 | executable('test-message', 51 | '../test-mu-message.cc', 52 | install: false, 53 | dependencies: [glib_dep, gmime_dep, lib_mu_message_dep])) 54 | 55 | test('test-priority', 56 | executable('test-priority', 57 | '../mu-priority.cc', 58 | install: false, 59 | cpp_args: ['-DBUILD_TESTS'], 60 | dependencies: [glib_dep, gmime_dep, lib_mu_message_dep])) 61 | 62 | test('test-message-file', 63 | executable('test-message-file', 64 | '../mu-message-file.cc', 65 | install: false, 66 | cpp_args: ['-DBUILD_TESTS'], 67 | dependencies: [glib_dep, lib_mu_message_dep])) 68 | 69 | test('test-message-part', 70 | executable('test-message-part', 71 | '../mu-message-part.cc', 72 | install: false, 73 | cpp_args: ['-DBUILD_TESTS'], 74 | dependencies: [glib_dep, lib_mu_message_dep])) 75 | -------------------------------------------------------------------------------- /lib/mu-config.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "mu-config.hh" 21 | 22 | using namespace Mu; 23 | 24 | constexpr /*static*/ bool 25 | validate_props() 26 | { 27 | size_t id{0}; 28 | for (auto&& prop: Config::properties) { 29 | 30 | // ids must match 31 | if (static_cast(prop.id) != id) 32 | return false; 33 | ++id; 34 | } 35 | 36 | return true; 37 | } 38 | 39 | #ifdef BUILD_TESTS 40 | #define static_assert g_assert_true 41 | #endif /*BUILD_TESTS*/ 42 | 43 | [[maybe_unused]] 44 | static void 45 | test_props() 46 | { 47 | static_assert(validate_props()); 48 | } 49 | 50 | #ifdef BUILD_TESTS 51 | /* 52 | * Tests. 53 | * 54 | */ 55 | 56 | #include "utils/mu-test-utils.hh" 57 | 58 | static void 59 | test_basic() 60 | { 61 | MemDb db; 62 | Config conf_db{db}; 63 | 64 | g_assert_false(conf_db.read_only()); 65 | 66 | using Id = Config::Id; 67 | 68 | { 69 | const auto rmd = conf_db.get(); 70 | g_assert_true(rmd.empty()); 71 | } 72 | 73 | { 74 | auto res = conf_db.set("/home/djcb/Maildir"); 75 | assert_valid_result(res); 76 | 77 | const auto rmd = conf_db.get(); 78 | assert_equal(rmd, "/home/djcb/Maildir"); 79 | } 80 | 81 | { 82 | g_assert_true(Config::property().default_val == "50000"); 83 | g_assert_cmpuint(conf_db.get(),==,50000); 84 | 85 | assert_valid_result(conf_db.set(123456)); 86 | g_assert_cmpuint(conf_db.get(),==,123456); 87 | } 88 | 89 | 90 | { 91 | MemDb db2; 92 | Config conf_db2{db2}; 93 | 94 | g_assert_cmpuint(conf_db2.get(),==,50000); 95 | g_assert_true(conf_db2.get().empty()); 96 | 97 | // BatchSize is configurable; RootMaildir is not. 98 | conf_db2.import_configurable(conf_db); 99 | 100 | g_assert_cmpuint(conf_db2.get(),==,123456); 101 | g_assert_true(conf_db2.get().empty()); 102 | } 103 | } 104 | 105 | static void 106 | test_read_only() 107 | { 108 | MemDb db{true/*read-only*/}; 109 | Config conf_db{db}; 110 | 111 | auto res = conf_db.set(12345); 112 | g_assert_false(!!res); 113 | } 114 | 115 | int 116 | main(int argc, char* argv[]) 117 | { 118 | mu_test_init(&argc, &argv); 119 | 120 | g_test_add_func("/config-db/props", test_props); 121 | g_test_add_func("/config-db/basic", test_basic); 122 | g_test_add_func("/config-db/read-only", test_read_only); 123 | 124 | return g_test_run(); 125 | } 126 | #endif /*BUILD_TESTS*/ 127 | -------------------------------------------------------------------------------- /lib/mu-indexer.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2022 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_INDEXER_HH__ 21 | #define MU_INDEXER_HH__ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace Mu { 28 | 29 | class Store; 30 | 31 | /// An object abstracting the index process. 32 | class Indexer { 33 | public: 34 | /** 35 | * Construct an indexer object 36 | * 37 | * @param store the message store to use 38 | */ 39 | Indexer(Store& store); 40 | 41 | /** 42 | * DTOR 43 | */ 44 | ~Indexer(); 45 | 46 | /// A configuration object for the indexer 47 | struct Config { 48 | bool scan{true}; 49 | /**< scan for new messages */ 50 | bool cleanup{true}; 51 | /**< clean messages no longer in the file system */ 52 | bool ignore_noupdate{}; 53 | /**< ignore .noupdate files */ 54 | bool lazy_check{}; 55 | /**< whether to skip directories or message files that haven't changed since the 56 | * previous indexing operation, based on their ctime */ 57 | }; 58 | 59 | /** 60 | * Start indexing. If already underway, do nothing. This returns 61 | * immediately after starting, with the work being done in the 62 | * background, unless blocking = true 63 | * 64 | * @param conf a configuration object 65 | * 66 | * @return true if starting worked or an indexing process was already 67 | * underway; false otherwise. 68 | * 69 | */ 70 | bool start(const Config& conf, bool block=false); 71 | 72 | /** 73 | * Stop indexing. If not indexing, do nothing. 74 | * 75 | * @return true if we stopped indexing, or indexing was not underway; false otherwise. 76 | */ 77 | bool stop(); 78 | 79 | /** 80 | * Is an indexing process running? 81 | * 82 | * @return true or false. 83 | */ 84 | bool is_running() const; 85 | 86 | // Object describing current progress 87 | struct Progress { 88 | void reset() { 89 | running = false; 90 | checked = updated = removed = 0; 91 | } 92 | std::atomic running{}; /**< Is an index operation in progress? */ 93 | std::atomic checked{}; /**< Number of messages checked for changes */ 94 | std::atomic updated{}; /**< Number of messages (re)parsed/added/updated */ 95 | std::atomic removed{}; /**< Number of message removed from store */ 96 | }; 97 | 98 | /** 99 | * Get an object describing the current progress. The progress object 100 | * describes the most recent indexing job, and is reset upon a fresh 101 | * start(). 102 | * 103 | * @return a progress object. 104 | */ 105 | const Progress& progress() const; 106 | 107 | /** 108 | * Last time indexing was completed. 109 | * 110 | * @return the time or 0 111 | */ 112 | ::time_t completed() const; 113 | 114 | private: 115 | struct Private; 116 | std::unique_ptr priv_; 117 | }; 118 | 119 | } // namespace Mu 120 | #endif /* MU_INDEXER_HH__ */ 121 | -------------------------------------------------------------------------------- /lib/mu-query-macros.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | 21 | #ifndef MU_QUERY_MACROS_HH__ 22 | #define MU_QUERY_MACROS_HH__ 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "mu-config.hh" 31 | 32 | namespace Mu { 33 | 34 | class QueryMacros{ 35 | public: 36 | /** 37 | * Construct QueryMacros object 38 | * 39 | * @param conf config object ref 40 | */ 41 | QueryMacros(const Config& conf); 42 | 43 | /** 44 | * DTOR 45 | */ 46 | ~QueryMacros(); 47 | 48 | /** 49 | * Read bookmarks (ie. macros) from a bookmark-file 50 | * 51 | * @param bookmarks_file path to the bookmarks file 52 | * 53 | * @return Ok or some error 54 | */ 55 | Result load_bookmarks(const std::string& bookmarks_file); 56 | 57 | 58 | /** 59 | * Find a macro (aka 'bookmark') by its name 60 | * 61 | * @param name the name of the bookmark 62 | * 63 | * @return the macro value or Nothing if not found 64 | */ 65 | Option find_macro(const std::string& name) const; 66 | 67 | private: 68 | struct Private; 69 | std::unique_ptr priv_; 70 | }; 71 | 72 | 73 | } // namespace Mu 74 | 75 | #endif /* MU_QUERY_MACROS_HH__ */ 76 | -------------------------------------------------------------------------------- /lib/mu-query-match-deciders.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2021-2024 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_QUERY_MATCH_DECIDERS_HH__ 21 | #define MU_QUERY_MATCH_DECIDERS_HH__ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "mu-xapian-db.hh" 28 | 29 | #include "mu-query-results.hh" 30 | 31 | namespace Mu { 32 | using StringSet = std::unordered_set; 33 | 34 | struct DeciderInfo { 35 | QueryMatches matches; 36 | StringSet thread_ids; 37 | StringSet message_ids; 38 | }; 39 | 40 | /** 41 | * Make a "leader" decider, that is, a MatchDecider for either a singular or the 42 | * first query in the leader/related pair of queries. Gather information for 43 | * threading, and the subsequent "related" query. 44 | * 45 | * @param qflags query flags 46 | * @param match_info receives information about the matches. 47 | * 48 | * @return a unique_ptr to a match decider. 49 | */ 50 | std::unique_ptr make_leader_decider(QueryFlags qflags, DeciderInfo& info); 51 | 52 | /** 53 | * Make a "related" decider, that is, a MatchDecider for the second query 54 | * in the leader/related pair of queries. 55 | * 56 | * @param qflags query flags 57 | * @param match_info receives information about the matches. 58 | * 59 | * @return a unique_ptr to a match decider. 60 | */ 61 | std::unique_ptr make_related_decider(QueryFlags qflags, DeciderInfo& info); 62 | 63 | /** 64 | * Make a "thread" decider, that is, a MatchDecider that removes all but the 65 | * document excepts for the ones found during initial/related searches. 66 | * 67 | * @param qflags query flags 68 | * @param match_info receives information about the matches. 69 | * 70 | * @return a unique_ptr to a match decider. 71 | */ 72 | std::unique_ptr make_thread_decider(QueryFlags qflags, DeciderInfo& info); 73 | 74 | } // namespace Mu 75 | 76 | #endif /* MU_QUERY_MATCH_DECIDERS_HH__ */ 77 | -------------------------------------------------------------------------------- /lib/mu-query-threads.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2021 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_QUERY_THREADS__ 21 | #define MU_QUERY_THREADS__ 22 | 23 | #include "mu-query-results.hh" 24 | 25 | namespace Mu { 26 | /** 27 | * Calculate the threads for these query results; that is, determine the 28 | * thread-paths for each message, so we can let Xapian order them in the correct 29 | * order. 30 | * 31 | * Note - threads are sorted chronologically, and the messages below the top 32 | * level are always sorted in ascending orde 33 | * 34 | * @param qres query results 35 | * @param descending whether to sort the top-level in descending order 36 | */ 37 | void calculate_threads(QueryResults& qres, bool descending); 38 | 39 | } // namespace Mu 40 | 41 | #endif /*MU_QUERY_THREADS__*/ 42 | -------------------------------------------------------------------------------- /lib/mu-query.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2008-2024 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify 5 | ** it under the terms of the GNU General Public License as published by 6 | ** the Free Software Foundation; either version 3 of the License, or 7 | ** (at your option) any later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef __MU_QUERY_HH__ 21 | #define __MU_QUERY_HH__ 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace Mu { 34 | 35 | class Query { 36 | public: 37 | /** 38 | * Run a query on the store 39 | * 40 | * @param expr the search expression 41 | * @param sortfield_id the sortfield-id. Default to Date 42 | * @param flags query flags 43 | * @param maxnum maximum number of results to return. 0 for 'no limit' 44 | * 45 | * @return the query-results or an error 46 | */ 47 | Result run(const std::string& expr, 48 | Field::Id sortfield_id = Field::Id::Date, 49 | QueryFlags flags = QueryFlags::None, 50 | size_t maxnum = 0) const; 51 | 52 | /** 53 | * run a Xapian query to count the number of matches; for the syntax, please 54 | * refer to the mu-query manpage 55 | * 56 | * @param expr the search expression; use "" to match all messages 57 | * 58 | * @return the number of matches 59 | */ 60 | size_t count(const std::string& expr = "") const; 61 | 62 | /** 63 | * For debugging, get the internal string representation of the parsed 64 | * query 65 | * 66 | * @param expr a xapian search expression 67 | * @param xapian if true, show Xapian's internal representation, 68 | * otherwise, mu's. 69 | 70 | * @return the string representation of the query 71 | */ 72 | std::string parse(const std::string& expr, bool xapian) const; 73 | 74 | private: 75 | friend class Store; 76 | 77 | /** 78 | * Construct a new Query instance. 79 | * 80 | * @param store a MuStore object 81 | */ 82 | Query(const Store& store); 83 | /** 84 | * DTOR 85 | * 86 | */ 87 | ~Query(); 88 | 89 | struct Private; 90 | std::unique_ptr priv_; 91 | }; 92 | } // namespace Mu 93 | 94 | #endif /*__MU_QUERY_HH__*/ 95 | -------------------------------------------------------------------------------- /lib/mu-scanner.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2020-2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_SCANNER_HH__ 21 | #define MU_SCANNER_HH__ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace Mu { 33 | 34 | /** 35 | * @brief Maildir scanner 36 | * 37 | * Scans maildir (trees) recursively, and calls the Handler callback for 38 | * directories & files. 39 | * 40 | * It filters out (i.e., does *not* call the handler for): 41 | * - files starting with '.' 42 | * - files that do not live in a cur / new leaf maildir 43 | * - directories '.' and '..' and 'tmp' 44 | */ 45 | class Scanner { 46 | public: 47 | enum struct HandleType { 48 | /* 49 | * Mode: All 50 | */ 51 | File, 52 | EnterNewCur, /* cur/ or new/ */ 53 | EnterDir, /* some other directory */ 54 | LeaveDir, 55 | /* 56 | * Mode: Maildir 57 | */ 58 | Maildir, 59 | }; 60 | 61 | /** 62 | * Callback handler function 63 | * 64 | * path: full file-system path 65 | * statbuf: stat result or nullptr (for Mode::MaildirsOnly) 66 | * htype: HandleType. For Mode::MaildirsOnly only Maildir 67 | */ 68 | using Handler = std::function< 69 | bool(const std::string& path, struct stat* statbuf, HandleType htype)>; 70 | 71 | /** 72 | * Running mode for this Scanner 73 | */ 74 | enum struct Mode { 75 | All, /**< Vanilla */ 76 | MaildirsOnly /**< Only return maildir to handler */ 77 | }; 78 | 79 | /** 80 | * Construct a scanner object for scanning a directory, recursively. 81 | * 82 | * If handler is a directory 83 | * 84 | * @param root_dir root dir to start scanning 85 | * @param handler handler function for some direntry 86 | * @param options options to influence behavior 87 | */ 88 | Scanner(const std::string& root_dir, Handler handler, Mode mode = Mode::All); 89 | 90 | /** 91 | * DTOR 92 | */ 93 | ~Scanner(); 94 | 95 | /**# 96 | * Start the scan; this is a blocking call than runs until 97 | * finished or (from another thread) stop() is called. 98 | * 99 | * @return Ok if starting worked; an Error otherwise 100 | */ 101 | Result start(); 102 | 103 | /** 104 | * Request stopping the scan if it's running; otherwise do nothing 105 | */ 106 | void stop(); 107 | 108 | /** 109 | * Is a scan currently running? 110 | * 111 | * @return true or false 112 | */ 113 | bool is_running() const; 114 | 115 | private: 116 | struct Private; 117 | std::unique_ptr priv_; 118 | }; 119 | 120 | } // namespace Mu 121 | 122 | #endif /* MU_SCANNER_HH__ */ 123 | -------------------------------------------------------------------------------- /lib/mu-script.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2022 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | #ifndef MU_SCRIPT_HH__ 20 | #define MU_SCRIPT_HH__ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | namespace Mu { 28 | 29 | /** 30 | * Information about a script. 31 | * 32 | */ 33 | struct ScriptInfo { 34 | std::string name; /**< Name of script */ 35 | std::string path; /**< Full path to script */ 36 | std::string oneline; /**< One-line description */ 37 | std::string description; /**< More help */ 38 | }; 39 | 40 | /// Sequence of script infos. 41 | using ScriptInfos = std::vector; 42 | 43 | /** 44 | * Get information about the available scripts 45 | * 46 | * @return infos 47 | */ 48 | using ScriptPaths = std::vector; 49 | ScriptInfos script_infos(const ScriptPaths& paths); 50 | 51 | 52 | /** 53 | * Run some specific script 54 | * 55 | * @param path full path to the scripts 56 | * @param args argument vector to pass to the script 57 | * 58 | * @return Ok() or some error; however, note that this does not return after succesfully 59 | * starting a script. 60 | */ 61 | Result run_script(const std::string& path, const std::vector& args); 62 | 63 | } // namepace Mu 64 | 65 | #endif /* MU_SCRIPT_HH__ */ 66 | -------------------------------------------------------------------------------- /lib/mu-server.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2020-2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_SERVER_HH__ 21 | #define MU_SERVER_HH__ 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | /* LCOV_EXCL_START */ 31 | 32 | namespace Mu { 33 | 34 | /** 35 | * @brief Implements the mu server, as used by mu4e. 36 | */ 37 | class Server { 38 | public: 39 | enum struct OutputFlags { 40 | None = 0, 41 | Flush = 1 << 0, /**< flush output buffer after */ 42 | }; 43 | 44 | /** 45 | * Prototype for output function 46 | * 47 | * @param str a string 48 | * @param flags flags that influence the behavior 49 | */ 50 | using Output = std::function; 51 | 52 | struct Options { 53 | bool allow_temp_file; /**< temp file optimization allowed? */ 54 | }; 55 | 56 | /** 57 | * Construct a new server 58 | * 59 | * @param store a message store object 60 | * @param output callable for the server responses. 61 | */ 62 | Server(Store& store, const Options& opts, Output output); 63 | 64 | /** 65 | * DTOR 66 | */ 67 | ~Server(); 68 | 69 | /** 70 | * Invoke a call on the server. 71 | * 72 | * @param expr the s-expression to call 73 | * 74 | * @return true if we the server is still ready for more 75 | * calls, false when it should quit. 76 | */ 77 | bool invoke(const std::string& expr) noexcept; 78 | 79 | private: 80 | struct Private; 81 | std::unique_ptr priv_; 82 | }; 83 | MU_ENABLE_BITOPS(Server::OutputFlags); 84 | 85 | } // namespace Mu 86 | 87 | /* LCOV_EXCL_STOP */ 88 | 89 | #endif /* MU_SERVER_HH__ */ 90 | -------------------------------------------------------------------------------- /lib/tests/test-mu-container.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2014 Jakub Sitnicki 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "config.h" 21 | #include 22 | 23 | #include "utils/mu-test-utils.hh" 24 | #include "mu-container.hh" 25 | 26 | static gboolean 27 | container_has_children(const MuContainer* c) 28 | { 29 | return c && c->child; 30 | } 31 | 32 | static gboolean 33 | container_is_sibling_of(const MuContainer* c, const MuContainer* sibling) 34 | { 35 | const MuContainer* cur; 36 | 37 | for (cur = c; cur; cur = cur->next) { 38 | if (cur == sibling) 39 | return TRUE; 40 | } 41 | 42 | return container_is_sibling_of(sibling, c); 43 | } 44 | 45 | static void 46 | test_mu_container_splice_children_when_parent_has_no_siblings(void) 47 | { 48 | MuContainer *child, *parent, *root_set; 49 | 50 | child = mu_container_new(NULL, 0, "child"); 51 | parent = mu_container_new(NULL, 0, "parent"); 52 | parent = mu_container_append_children(parent, child); 53 | 54 | root_set = parent; 55 | root_set = mu_container_splice_children(root_set, parent); 56 | 57 | g_assert(root_set != NULL); 58 | g_assert(!container_has_children(parent)); 59 | g_assert(container_is_sibling_of(root_set, child)); 60 | 61 | mu_container_destroy(parent); 62 | mu_container_destroy(child); 63 | } 64 | 65 | int 66 | main(int argc, char* argv[]) 67 | { 68 | g_test_init(&argc, &argv, NULL); 69 | 70 | g_test_add_func("/mu-container/mu-container-splice-children-when-parent-has-no-siblings", 71 | test_mu_container_splice_children_when_parent_has_no_siblings); 72 | 73 | g_log_set_handler( 74 | NULL, 75 | (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), 76 | (GLogFunc)black_hole, 77 | NULL); 78 | 79 | return g_test_run(); 80 | } 81 | -------------------------------------------------------------------------------- /lib/tests/test-query.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2022-2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "mu-store.hh" 29 | #include "mu-query.hh" 30 | #include "utils/mu-result.hh" 31 | #include "utils/mu-utils.hh" 32 | #include "utils/mu-test-utils.hh" 33 | 34 | using namespace Mu; 35 | 36 | static void 37 | test_query() 38 | { 39 | allow_warnings(); 40 | TempDir temp_dir; 41 | 42 | auto store = Store::make_new(temp_dir.path(), std::string{MU_TESTMAILDIR}); 43 | assert_valid_result(store); 44 | 45 | auto&& idx{store->indexer()}; 46 | g_assert_true(idx.start(Indexer::Config{})); 47 | while (idx.is_running()) { 48 | g_usleep(1000); 49 | } 50 | 51 | auto dump_matches = [](const QueryResults& res) { 52 | size_t n{}; 53 | for (auto&& item : res) { 54 | if (g_test_verbose()) { 55 | std::cout << item.query_match() << '\n'; 56 | mu_debug("{:02d} {} {}", 57 | ++n, 58 | item.path().value_or(""), 59 | item.message_id().value_or("")); 60 | } 61 | } 62 | }; 63 | 64 | g_assert_cmpuint(store->size(), ==, 19); 65 | 66 | { 67 | const auto res = store->run_query("", {}, QueryFlags::None); 68 | g_assert_true(!!res); 69 | g_assert_cmpuint(res->size(), ==, 19); 70 | dump_matches(*res); 71 | 72 | g_assert_cmpuint(store->count_query(""), ==, 19); 73 | 74 | } 75 | 76 | { 77 | const auto res = store->run_query("", Field::Id::Path, QueryFlags::None, 11); 78 | g_assert_true(!!res); 79 | g_assert_cmpuint(res->size(), ==, 11); 80 | dump_matches(*res); 81 | } 82 | } 83 | 84 | int 85 | main(int argc, char* argv[]) try { 86 | 87 | mu_test_init(&argc, &argv); 88 | 89 | g_test_add_func("/query", test_query); 90 | 91 | return g_test_run(); 92 | 93 | } catch (const std::runtime_error& re) { 94 | std::cerr << re.what() << "\n"; 95 | return 1; 96 | } catch (...) { 97 | std::cerr << "caught exception\n"; 98 | return 1; 99 | } 100 | -------------------------------------------------------------------------------- /lib/utils/meson.build: -------------------------------------------------------------------------------- 1 | ## Copyright (C) 2022-2023 Dirk-Jan C. Binnema 2 | ## 3 | ## This program is free software; you can redistribute it and/or modify 4 | ## it under the terms of the GNU General Public License as published by 5 | ## the Free Software Foundation; either version 3 of the License, or 6 | ## (at your option) any later version. 7 | ## 8 | ## This program is distributed in the hope that it will be useful, 9 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ## GNU General Public License for more details. 12 | ## 13 | ## You should have received a copy of the GNU General Public License 14 | ## along with this program; if not, write to the Free Software Foundation, 15 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | thirdparty=join_paths('..', '..', 'thirdparty') 18 | 19 | srcs = [ 20 | 'mu-command-handler.cc', 21 | 'mu-html-to-text.cc', 22 | 'mu-lang-detector.cc', 23 | 'mu-logger.cc', 24 | 'mu-option.cc', 25 | 'mu-readline.cc', 26 | 'mu-sexp.cc', 27 | 'mu-utils-file.cc', 28 | 'mu-utils.cc', 29 | ] 30 | 31 | if not get_option('tests').disabled() 32 | test_srcs = [ 'mu-test-utils.cc' ] 33 | else 34 | test_srcs = [] 35 | endif 36 | 37 | lib_mu_utils=static_library('mu-utils', 38 | [ srcs, test_srcs ], dependencies: [ 39 | glib_dep, 40 | gio_dep, 41 | gio_unix_dep, 42 | config_h_dep, 43 | readline_dep, 44 | cld2_dep 45 | ], include_directories: 46 | include_directories(['.', '..', thirdparty]), 47 | install: false) 48 | 49 | lib_mu_utils_dep = declare_dependency( 50 | link_with: lib_mu_utils, 51 | compile_args: '-DFMT_HEADER_ONLY', 52 | include_directories: 53 | include_directories(['.', '..', thirdparty])) 54 | 55 | # 56 | # tools 57 | # 58 | html2text = executable('mu-html2text', 59 | 'mu-html-to-text.cc', 60 | dependencies: [ lib_mu_utils_dep, glib_dep ], 61 | cpp_args: ['-DBUILD_HTML_TO_TEXT'], 62 | install: false) 63 | 64 | if not get_option('tests').disabled() 65 | subdir('tests') 66 | endif 67 | -------------------------------------------------------------------------------- /lib/utils/mu-error.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | 21 | #if BUILD_TESTS 22 | 23 | #include "mu-error.hh" 24 | #include "mu-test-utils.hh" 25 | 26 | using namespace Mu; 27 | 28 | static void 29 | test_fill_error() 30 | { 31 | const Error err{Error::Code::Internal, "boo!"}; 32 | GError *gerr{}; 33 | 34 | err.fill_g_error(&gerr); 35 | 36 | assert_equal(gerr->message, "boo!"); 37 | g_assert_cmpint(gerr->code, ==, static_cast(err.code())); 38 | 39 | g_clear_error(&gerr); 40 | } 41 | 42 | static void 43 | test_add_hint() 44 | { 45 | Error err(Error::Code::Internal, "baa!"); 46 | err.add_hint("hello"); 47 | 48 | assert_equal(err.hint(), "hello"); 49 | } 50 | 51 | 52 | int 53 | main(int argc, char* argv[]) 54 | { 55 | mu_test_init(&argc, &argv); 56 | 57 | g_test_add_func("/error/fill-error", test_fill_error); 58 | g_test_add_func("/error/add-hint", test_add_hint); 59 | 60 | return g_test_run(); 61 | 62 | } 63 | 64 | #endif /*BUILD_TESTS*/ 65 | -------------------------------------------------------------------------------- /lib/utils/mu-lang-detector.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | #include "config.h" 20 | #include "mu-lang-detector.hh" 21 | 22 | using namespace Mu; 23 | 24 | #ifndef HAVE_CLD2 25 | // Dummy implementation 26 | Option Mu::detect_language(const std::string& txt) { return Nothing; } 27 | #else 28 | #include 29 | #include 30 | 31 | Option 32 | Mu::detect_language(const std::string& txt) 33 | { 34 | bool is_reliable; 35 | const auto lang = CLD2::DetectLanguage( 36 | txt.c_str(), txt.length(), 37 | true/*plain-text*/, 38 | &is_reliable); 39 | 40 | if (lang == CLD2::UNKNOWN_LANGUAGE || !is_reliable) 41 | return {}; 42 | 43 | Mu::Language res = { 44 | CLD2::LanguageName(lang), 45 | CLD2::LanguageCode(lang) 46 | }; 47 | if (!res.name || !res.code) 48 | return {}; 49 | else 50 | return Some(std::move(res)); 51 | } 52 | #endif /*HAVE_CLD2*/ 53 | 54 | #ifdef BUILD_TESTS 55 | #include 56 | #include "mu-test-utils.hh" 57 | 58 | static void 59 | test_lang_detector() 60 | { 61 | using Case = std::tuple; 62 | using Cases = std::vector; 63 | 64 | const Cases tests = {{ 65 | { "hello world, this is a bit of English", 66 | "ENGLISH", "en" }, 67 | { "En nu een paar Nederlandse woorden", 68 | "DUTCH", "nl" }, 69 | { "Hyvää huomenta! Puhun vähän suomea", 70 | "FINNISH", "fi" }, 71 | { "So eine Arbeit wird eigentlich nie fertig, man muß sie für " 72 | "fertig erklären, wenn man nach Zeit und Umständen das " 73 | "möglichste getan hat.", 74 | "GERMAN", "de"} 75 | }}; 76 | 77 | for (auto&& test: tests) { 78 | const auto res = detect_language(std::get<0>(test)); 79 | #ifndef HAVE_CLD2 80 | g_assert_false(!!res); 81 | #else 82 | g_assert_true(!!res); 83 | assert_equal(std::get<1>(test), res->name); 84 | assert_equal(std::get<2>(test), res->code); 85 | #endif 86 | 87 | } 88 | } 89 | 90 | int 91 | main(int argc, char* argv[]) 92 | { 93 | mu_test_init(&argc, &argv); 94 | 95 | g_test_add_func("/utils/lang-detector", test_lang_detector); 96 | 97 | return g_test_run(); 98 | } 99 | 100 | #endif /*BUILD_TESTS*/ 101 | -------------------------------------------------------------------------------- /lib/utils/mu-lang-detector.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_LANG_DETECTOR_HH__ 21 | #define MU_LANG_DETECTOR_HH__ 22 | 23 | #include 24 | #include "mu-option.hh" 25 | 26 | namespace Mu { 27 | 28 | struct Language { 29 | const char *name; /**< Language name, e.g. "Dutch" */ 30 | const char *code; /**< Language code, e.g. "nl" */ 31 | }; 32 | 33 | /** 34 | * Detect the language of text 35 | * 36 | * @param txt some text (UTF-8) 37 | * 38 | * @return either a Language or nothing; the latter 39 | * also if we cannot not reliably determine a single language 40 | */ 41 | Option detect_language(const std::string& txt); 42 | 43 | } // namespace Mu 44 | 45 | 46 | #endif /* MU_LANG_DETECTOR_HH__ */ 47 | -------------------------------------------------------------------------------- /lib/utils/mu-logger.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2020-2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_LOGGER_HH__ 21 | #define MU_LOGGER_HH__ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace Mu { 28 | 29 | /** 30 | * RAII object for handling logging (through g_(debug|warning|...)) 31 | * 32 | */ 33 | struct Logger { 34 | 35 | /** 36 | * Logging options 37 | * 38 | */ 39 | enum struct Options { 40 | None = 0, /**< Nothing specific */ 41 | StdOutErr = 1 << 1, /**< Log to stdout/stderr */ 42 | File = 1 << 2, /**< Force logging to file, even if journal available */ 43 | Debug = 1 << 3, /**< Include debug-level logs */ 44 | }; 45 | 46 | /** 47 | * Initialize the logging sub-system. 48 | * 49 | * Note that the path is only used if structured logging fails -- 50 | * practically, it goes to the file if there's no systemd/journald. 51 | * 52 | * if the environment variable MU_LOG_STDOUTERR is set, 53 | * LogOptions::StdoutErr is implied. 54 | * 55 | * @param path path to the log file 56 | * @param opts logging options 57 | */ 58 | static Result make(const std::string& path, Options opts=Options::None); 59 | 60 | /** 61 | * DTOR 62 | * 63 | */ 64 | ~Logger(); 65 | 66 | private: 67 | Logger(const std::string& path, Options opts); 68 | }; 69 | 70 | MU_ENABLE_BITOPS(Logger::Options); 71 | 72 | } // namespace Mu 73 | 74 | #endif /* MU_LOGGER_HH__ */ 75 | -------------------------------------------------------------------------------- /lib/utils/mu-option.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2022 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "mu-option.hh" 21 | #include 22 | 23 | using namespace Mu; 24 | 25 | Mu::Option 26 | Mu::to_string_opt_gchar(gchar*&& str) 27 | { 28 | auto res = to_string_opt(str); 29 | g_free(str); 30 | 31 | return res; 32 | } 33 | 34 | #if BUILD_TESTS 35 | #include "mu-test-utils.hh" 36 | 37 | static Option 38 | get_opt_int(bool b) 39 | { 40 | if (b) 41 | return Some(123); 42 | else 43 | return Nothing; 44 | } 45 | 46 | static void 47 | test_option() 48 | { 49 | { 50 | const auto oi{get_opt_int(true)}; 51 | g_assert_true(!!oi); 52 | g_assert_cmpint(oi.value(), ==, 123); 53 | } 54 | 55 | { 56 | const auto oi{get_opt_int(false)}; 57 | g_assert_false(!!oi); 58 | g_assert_false(oi.has_value()); 59 | g_assert_cmpint(oi.value_or(456), ==, 456); 60 | } 61 | } 62 | 63 | static void 64 | test_unwrap() 65 | { 66 | { 67 | auto&& oi{get_opt_int(true)}; 68 | g_assert_cmpint(unwrap(std::move(oi)), ==, 123); 69 | } 70 | 71 | auto ex{0}; 72 | try { 73 | auto&& oi{get_opt_int(false)}; 74 | unwrap(std::move(oi)); 75 | } catch(...) { 76 | ex = 1; 77 | } 78 | 79 | g_assert_cmpuint(ex, ==, 1); 80 | } 81 | 82 | static void 83 | test_opt_gchar() 84 | { 85 | auto o1{to_string_opt_gchar(g_strdup("boo!"))}; 86 | auto o2{to_string_opt_gchar(nullptr)}; 87 | 88 | g_assert_false(!!o2); 89 | g_assert_true(o1.value() == "boo!"); 90 | } 91 | 92 | 93 | 94 | int 95 | main(int argc, char* argv[]) 96 | { 97 | g_test_init(&argc, &argv, NULL); 98 | 99 | g_test_add_func("/option/option", test_option); 100 | g_test_add_func("/option/unwrap", test_unwrap); 101 | g_test_add_func("/option/opt-gchar", test_opt_gchar); 102 | 103 | return g_test_run(); 104 | } 105 | 106 | #endif /*BUILD_TESTS*/ 107 | -------------------------------------------------------------------------------- /lib/utils/mu-option.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_OPTION__ 21 | #define MU_OPTION__ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace Mu { 28 | 29 | /// Either a value of type T, or None 30 | template using Option = tl::optional; 31 | 32 | template 33 | Option 34 | Some(T&& t) 35 | { 36 | return std::move(t); 37 | } 38 | constexpr auto Nothing = tl::nullopt; // 'None' is already taken. 39 | 40 | template T 41 | unwrap(Option&& res) 42 | { 43 | if (!!res) 44 | return std::move(res.value()); 45 | else 46 | throw std::runtime_error("failure is not an option"); 47 | } 48 | 49 | 50 | /** 51 | * Maybe create a string from a const char pointer. 52 | * 53 | * @param str a char pointer or NULL 54 | * 55 | * @return option with either the string or nothing if str was NULL. 56 | */ 57 | Option 58 | static inline to_string_opt(const char* str) { 59 | if (str) 60 | return std::string{str}; 61 | else 62 | return Nothing; 63 | } 64 | 65 | /** 66 | * Like maybe_string that takes a const char*, but additionally, 67 | * g_free() the string. 68 | * 69 | * @param str char pointer or NULL (consumed) 70 | * 71 | * @return option with either the string or nothing if str was NULL. 72 | */ 73 | Option to_string_opt_gchar(char*&& str); 74 | 75 | 76 | } // namespace Mu 77 | #endif /*MU_OPTION__*/ 78 | -------------------------------------------------------------------------------- /lib/utils/mu-readline.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2020-2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | #include "config.h" 20 | 21 | #include "mu-utils.hh" 22 | #include "mu-readline.hh" 23 | 24 | #include 25 | #include 26 | 27 | #ifdef HAVE_LIBREADLINE 28 | #if defined(HAVE_READLINE_READLINE_H) 29 | #include 30 | #elif defined(HAVE_READLINE_H) 31 | #include 32 | #else /* !defined(HAVE_READLINE_H) */ 33 | extern char* readline(); 34 | #endif /* !defined(HAVE_READLINE_H) */ 35 | char* cmdline = NULL; 36 | #else /* !defined(HAVE_READLINE_READLINE_H) */ 37 | /* no readline */ 38 | #endif /* HAVE_LIBREADLINE */ 39 | 40 | #ifdef HAVE_READLINE_HISTORY 41 | #if defined(HAVE_READLINE_HISTORY_H) 42 | #include 43 | #elif defined(HAVE_HISTORY_H) 44 | #include 45 | #else /* !defined(HAVE_HISTORY_H) */ 46 | extern void add_history(); 47 | extern int write_history(); 48 | extern int read_history(); 49 | #endif /* defined(HAVE_READLINE_HISTORY_H) */ 50 | /* no history */ 51 | #endif /* HAVE_READLINE_HISTORY */ 52 | 53 | #if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY) 54 | #define HAVE_READLINE (1) 55 | #else 56 | #define HAVE_READLINE (0) 57 | #endif 58 | 59 | using namespace Mu; 60 | 61 | static bool is_a_tty{}; 62 | static std::string hist_path; 63 | static size_t max_lines{}; 64 | 65 | // LCOV_EXCL_START 66 | 67 | bool 68 | Mu::have_readline() 69 | { 70 | return HAVE_READLINE != 0; 71 | } 72 | 73 | void 74 | Mu::setup_readline(const std::string& histpath, size_t maxlines) 75 | { 76 | is_a_tty = !!::isatty(::fileno(stdout)); 77 | hist_path = histpath; 78 | max_lines = maxlines; 79 | 80 | #if HAVE_READLINE 81 | rl_bind_key('\t', rl_insert); // default (filenames) is not useful 82 | using_history(); 83 | read_history(hist_path.c_str()); 84 | 85 | if (max_lines > 0) 86 | stifle_history(max_lines); 87 | #endif /*HAVE_READLINE*/ 88 | } 89 | 90 | void 91 | Mu::shutdown_readline() 92 | { 93 | #if HAVE_READLINE 94 | if (!is_a_tty) 95 | return; 96 | 97 | write_history(hist_path.c_str()); 98 | if (max_lines > 0) 99 | history_truncate_file(hist_path.c_str(), max_lines); 100 | #endif /*HAVE_READLINE*/ 101 | } 102 | 103 | std::string 104 | Mu::read_line(bool& do_quit) 105 | { 106 | #if HAVE_READLINE 107 | if (is_a_tty) { 108 | auto buf = readline(";; mu% "); 109 | if (!buf) { 110 | do_quit = true; 111 | return {}; 112 | } 113 | std::string line{buf}; 114 | ::free(buf); 115 | return line; 116 | } 117 | #endif /*HAVE_READLINE*/ 118 | 119 | std::string line; 120 | mu_print(";; mu> "); 121 | if (!std::getline(std::cin, line)) 122 | do_quit = true; 123 | 124 | return line; 125 | } 126 | 127 | void 128 | Mu::save_line(const std::string& line) 129 | { 130 | #if HAVE_READLINE 131 | if (is_a_tty) 132 | add_history(line.c_str()); 133 | #endif /*HAVE_READLINE*/ 134 | } 135 | 136 | // LCOV_EXCL_STOP 137 | -------------------------------------------------------------------------------- /lib/utils/mu-readline.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2020 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | #include 20 | 21 | namespace Mu { 22 | 23 | /** 24 | * Setup readline when available and on tty. 25 | * 26 | * @param histpath path to the history file 27 | * @param max_lines maximum number of history to save 28 | */ 29 | void setup_readline(const std::string& histpath, size_t max_lines); 30 | 31 | /** 32 | * Shutdown readline 33 | * 34 | */ 35 | void shutdown_readline(); 36 | 37 | /** 38 | * Read a command line 39 | * 40 | * @param do_quit recceives whether we should quit. 41 | * 42 | * @return the string read or empty 43 | */ 44 | std::string read_line(bool& do_quit); 45 | 46 | /** 47 | * Save a line to history (or do nothing when readline is not active) 48 | * 49 | * @param line a line. 50 | */ 51 | void save_line(const std::string& line); 52 | 53 | 54 | /** 55 | * Do we have the non-shim readline? 56 | * 57 | * @return true or failse 58 | */ 59 | bool have_readline(); 60 | 61 | } // namespace Mu 62 | -------------------------------------------------------------------------------- /lib/utils/mu-regex.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "mu-regex.hh" 21 | #include 22 | 23 | using namespace Mu; 24 | 25 | #if BUILD_TESTS 26 | #include "mu-test-utils.hh" 27 | 28 | // No need for extensive regex test, we just rely on GRegex. 29 | 30 | static void 31 | test_regex_match() 32 | { 33 | auto rx = Regex::make("a.*b.c"); 34 | assert_valid_result(rx); 35 | 36 | assert_equal(mu_format("{}", *rx), "/a.*b.c/"); 37 | 38 | g_assert_true(rx->matches("axxxxxbqc")); 39 | g_assert_false(rx->matches("axxxxxbqqc")); 40 | 41 | { // unset matches nothing. 42 | Regex rx2; 43 | g_assert_false(rx2.matches("")); 44 | } 45 | } 46 | 47 | 48 | static void 49 | test_regex_match2() 50 | { 51 | Regex rx; 52 | { 53 | std::string foo = "h.llo"; 54 | rx = unwrap(Regex::make(foo.c_str())); 55 | } 56 | 57 | std::string hei = "hei"; 58 | 59 | g_assert_true(rx.matches("hallo")); 60 | g_assert_false(rx.matches(hei)); 61 | } 62 | 63 | 64 | static void 65 | test_regex_replace() 66 | { 67 | { 68 | auto rx = Regex::make("f.o"); 69 | assert_valid_result(rx); 70 | assert_equal(rx->replace("foobar", "cuux").value_or("error"), "cuuxbar"); 71 | } 72 | 73 | { 74 | auto rx = Regex::make("f.o", G_REGEX_MULTILINE); 75 | assert_valid_result(rx); 76 | assert_equal(rx->replace("foobar\nfoobar", "cuux").value_or("error"), 77 | "cuuxbar\ncuuxbar"); 78 | } 79 | } 80 | 81 | 82 | static void 83 | test_regex_fail() 84 | { 85 | allow_warnings(); 86 | 87 | { // unset rx can't replace / error. 88 | Regex rx; 89 | assert_equal(mu_format("{}", rx), "//"); 90 | g_assert_false(!!rx.replace("foo", "bar")); 91 | } 92 | 93 | { 94 | auto rx = Regex::make("("); 95 | g_assert_false(!!rx); 96 | 97 | } 98 | 99 | } 100 | 101 | int 102 | main(int argc, char* argv[]) 103 | { 104 | mu_test_init(&argc, &argv); 105 | 106 | g_test_add_func("/regex/match", test_regex_match); 107 | g_test_add_func("/regex/match2", test_regex_match2); 108 | g_test_add_func("/regex/replace", test_regex_replace); 109 | g_test_add_func("/regex/fail", test_regex_fail); 110 | 111 | return g_test_run(); 112 | } 113 | 114 | #endif /*BUILD_TESTS*/ 115 | -------------------------------------------------------------------------------- /lib/utils/mu-result.hh: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2019-2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #ifndef MU_RESULT_HH__ 21 | #define MU_RESULT_HH__ 22 | 23 | #include 24 | #include "utils/mu-error.hh" 25 | 26 | namespace Mu { 27 | /** 28 | * A little Rust-envy...a Result is _either_ some value of type T, _or_ a Mu::Error 29 | */ 30 | template using Result = tl::expected; 31 | 32 | /** 33 | * Ok() is not typically strictly needed (unlike Err), but imitates Rust's Ok 34 | * and it helps the reader. 35 | * 36 | * @param t the value to return 37 | * 38 | * @return a success Result 39 | */ 40 | template Result 41 | Ok(T&& t) 42 | { 43 | return std::move(t); 44 | } 45 | 46 | /** 47 | * Implementation of Ok() for void results. 48 | * 49 | * @return a success Result 50 | */ 51 | static inline Result 52 | Ok() 53 | { 54 | return {}; 55 | } 56 | 57 | /** 58 | * Return an error 59 | * 60 | * @param err the error 61 | * 62 | * @return error 63 | */ 64 | template Result 65 | Err(Error&& err) 66 | { 67 | return tl::unexpected(std::move(err)); 68 | } 69 | template Result 70 | Err(const Error& err) 71 | { 72 | return tl::unexpected(err); 73 | } 74 | 75 | static inline tl::unexpected 76 | Err(Error&& err) 77 | { 78 | return tl::unexpected(std::move(err)); 79 | } 80 | 81 | static inline tl::unexpected 82 | Err(const Error& err) 83 | { 84 | return tl::unexpected(err); 85 | } 86 | 87 | template 88 | static inline tl::unexpected 89 | Err(const Result& res) 90 | { 91 | return res.error(); 92 | } 93 | 94 | template 95 | static inline tl::unexpected 96 | Err(Result&& res) 97 | { 98 | return std::move(res.error()); 99 | } 100 | 101 | /* 102 | * convenience 103 | */ 104 | template 105 | tl::unexpected 106 | Err(Error::Code code, fmt::format_string frm, T&&... args) 107 | { 108 | return Err(Error{code, frm, std::forward(args)...}); 109 | } 110 | 111 | template 112 | tl::unexpected 113 | Err(Error::Code code, GError **err, fmt::format_string frm, T&&... args) 114 | { 115 | return Err(Error{code, err, frm, std::forward(args)...}); 116 | } 117 | 118 | 119 | template T 120 | unwrap(Result&& res) 121 | { 122 | if (!!res) 123 | return std::move(res.value()); 124 | else 125 | throw res.error(); 126 | } 127 | 128 | /** 129 | * Assert that some result has a value (for unit tests) 130 | * 131 | * @param R some result 132 | */ 133 | #define assert_valid_result(R) do { \ 134 | auto&& res__ = R; \ 135 | if(!res__) { \ 136 | mu_printerrln("{}:{}: error-result: {}", \ 137 | __FILE__, __LINE__, \ 138 | (res__).error().what()); \ 139 | g_assert_true(!!res__); \ 140 | } \ 141 | } while(0) 142 | 143 | }// namespace Mu 144 | 145 | #endif /* MU_RESULT_HH__ */ 146 | -------------------------------------------------------------------------------- /lib/utils/mu-test-utils.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2008-2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "config.h" 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #include "utils/mu-utils.hh" 33 | #include "utils/mu-test-utils.hh" 34 | #include "utils/mu-utils-file.hh" 35 | #include "utils/mu-error.hh" 36 | 37 | using namespace Mu; 38 | 39 | /* LCOV_EXCL_START*/ 40 | bool 41 | Mu::mu_test_mu_hacker() 42 | { 43 | return !!g_getenv("MU_HACKER"); 44 | } 45 | 46 | bool 47 | Mu::mu_test_mu_valgrind() 48 | { 49 | return !!g_getenv("MU_VALGRIND"); 50 | } 51 | 52 | /* LCOV_EXCL_STOP*/ 53 | 54 | 55 | const char* 56 | Mu::set_tz(const char* tz) 57 | { 58 | static const char* oldtz; 59 | 60 | oldtz = getenv("TZ"); 61 | if (tz) 62 | setenv("TZ", tz, 1); 63 | else 64 | unsetenv("TZ"); 65 | 66 | tzset(); 67 | return oldtz; 68 | } 69 | 70 | bool 71 | Mu::set_en_us_utf8_locale() 72 | { 73 | setenv("LC_ALL", "en_US.UTF-8", 1); 74 | 75 | if (auto str = setlocale(LC_ALL, "en_US.UTF-8"); !str) 76 | return false; 77 | 78 | if (strcmp(nl_langinfo(CODESET), "UTF-8") != 0) 79 | return false; 80 | 81 | return true; 82 | } 83 | 84 | static void 85 | black_hole(void) 86 | { 87 | return; /* do nothing */ 88 | } 89 | 90 | void 91 | Mu::mu_test_init(int *argc, char ***argv) 92 | { 93 | TempDir temp_dir; 94 | 95 | g_unsetenv("XAPIAN_CJK_NGRAM"); 96 | g_setenv("MU_TEST", "yes", TRUE); 97 | g_setenv("XDG_CACHE_HOME", temp_dir.path().c_str(), TRUE); 98 | 99 | setlocale(LC_ALL, ""); 100 | 101 | g_test_init(argc, argv, NULL); 102 | 103 | g_test_bug_base("https://github.com/djcb/mu/issues/"); 104 | 105 | if (!g_test_verbose()) 106 | g_log_set_handler( 107 | NULL, 108 | (GLogLevelFlags)(G_LOG_LEVEL_MASK | 109 | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), 110 | (GLogFunc)black_hole, NULL); 111 | } 112 | 113 | void 114 | Mu::allow_warnings() 115 | { 116 | g_test_log_set_fatal_handler( 117 | [](const char*, GLogLevelFlags, const char*, gpointer) { return FALSE; }, 118 | {}); 119 | } 120 | 121 | Mu::TempDir::TempDir(bool autodelete): autodelete_{autodelete} { 122 | 123 | if (auto res{make_temp_dir()}; !res) 124 | throw res.error(); 125 | else 126 | path_ = std::move(*res); 127 | 128 | mu_debug("created '{}'", path_); 129 | } 130 | 131 | Mu::TempDir::~TempDir() 132 | { 133 | if (::access(path_.c_str(), F_OK) != 0) 134 | return; /* nothing to do */ 135 | 136 | if (!autodelete_) { 137 | mu_debug("_not_ deleting {}", path_); 138 | return; 139 | } 140 | 141 | if (auto&& res{run_command0({RM_PROGRAM, "-fr", path_})}; !res) { 142 | /* LCOV_EXCL_START*/ 143 | mu_warning("error removing {}: {}", path_, format_as(res.error())); 144 | /* LCOV_EXCL_STOP*/ 145 | } else 146 | mu_debug("removed '{}'", path_); 147 | } 148 | -------------------------------------------------------------------------------- /lib/utils/tests/meson.build: -------------------------------------------------------------------------------- 1 | ## Copyright (C) 2021-2024 Dirk-Jan C. Binnema 2 | ## 3 | ## This program is free software; you can redistribute it and/or modify 4 | ## it under the terms of the GNU General Public License as published by 5 | ## the Free Software Foundation; either version 3 of the License, or 6 | ## (at your option) any later version. 7 | ## 8 | ## This program is distributed in the hope that it will be useful, 9 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ## GNU General Public License for more details. 12 | ## 13 | ## You should have received a copy of the GNU General Public License 14 | ## along with this program; if not, write to the Free Software Foundation, 15 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | 18 | ################################################################################ 19 | # tests 20 | 21 | 22 | # 23 | # tests 24 | # 25 | test('test-sexp', 26 | executable('test-sexp', '../mu-sexp.cc', 27 | install: false, 28 | cpp_args: ['-DBUILD_TESTS'], 29 | dependencies: [glib_dep, lib_mu_utils_dep])) 30 | 31 | test('test-regex', 32 | executable('test-regex', '../mu-regex.cc', 33 | install: false, 34 | cpp_args: ['-DBUILD_TESTS'], 35 | dependencies: [glib_dep, lib_mu_utils_dep])) 36 | 37 | test('test-command-handler', 38 | executable('test-command-handler', '../mu-command-handler.cc', 39 | install: false, 40 | cpp_args: ['-DBUILD_TESTS'], 41 | dependencies: [glib_dep, lib_mu_utils_dep])) 42 | 43 | test('test-utils-file', 44 | executable('test-utils-file', '../mu-utils-file.cc', 45 | install: false, 46 | cpp_args: ['-DBUILD_TESTS'], 47 | dependencies: [glib_dep, gio_unix_dep,config_h_dep, lib_mu_utils_dep])) 48 | 49 | test('test-logger', 50 | executable('test-logger', '../mu-logger.cc', 51 | install: false, 52 | cpp_args: ['-DBUILD_TESTS'], 53 | dependencies: [glib_dep, lib_mu_utils_dep,config_h_dep,thread_dep ])) 54 | 55 | test('test-option', 56 | executable('test-option', '../mu-option.cc', 57 | install: false, 58 | cpp_args: ['-DBUILD_TESTS'], 59 | dependencies: [glib_dep, lib_mu_utils_dep ])) 60 | 61 | test('test-lang-detector', 62 | executable('test-lang-detector', '../mu-lang-detector.cc', 63 | install: false, 64 | cpp_args: ['-DBUILD_TESTS'], 65 | dependencies: [ config_h_dep, glib_dep, lib_mu_utils_dep ])) 66 | 67 | test('test-html-to-text', 68 | executable('test-html-to-text', '../mu-html-to-text.cc', 69 | install: false, 70 | cpp_args: ['-DBUILD_TESTS'], 71 | dependencies: [glib_dep, lib_mu_utils_dep])) 72 | 73 | test('test-error', 74 | executable('test-error', '../mu-error.cc', 75 | install: false, 76 | cpp_args: ['-DBUILD_TESTS'], 77 | dependencies: [glib_dep, lib_mu_utils_dep])) 78 | 79 | test('test-mu-utils', 80 | executable('test-mu-utils', 81 | 'test-utils.cc', 82 | install: false, 83 | dependencies: [glib_dep, lib_mu_utils_dep])) 84 | -------------------------------------------------------------------------------- /man/author.inc: -------------------------------------------------------------------------------- 1 | * AUTHOR 2 | 3 | Dirk-Jan C. Binnema 4 | 5 | # Local Variables: 6 | # mode: org 7 | # End: 8 | -------------------------------------------------------------------------------- /man/bugs.inc: -------------------------------------------------------------------------------- 1 | * REPORTING BUGS 2 | 3 | Please report bugs at . 4 | 5 | # Local Variables: 6 | # mode: org 7 | # End: 8 | -------------------------------------------------------------------------------- /man/common-options.inc: -------------------------------------------------------------------------------- 1 | * COMMON OPTIONS 2 | 3 | ** -d, --debug 4 | Makes *mu* generate extra debug information, useful for debugging the program 5 | itself. Debug information goes to the standard logging location; see 6 | {{{man-link(mu,1)}}}. 7 | 8 | ** -q, --quiet 9 | Causes *mu* not to output informational messages and progress information to 10 | standard output, but only to the log file. Error messages will still be sent to 11 | standard error. Note that *mu index* is much faster with *--quiet*, so it is 12 | recommended you use this option when using *mu* from scripts etc. 13 | 14 | ** --log-stderr 15 | Causes *mu* to not output log messages to standard error, in addition to sending 16 | them to the standard logging location. 17 | 18 | ** --nocolor 19 | Do not use ANSI colors. The environment variable *NO_COLOR* can be used as an 20 | alternative to *--nocolor*. 21 | 22 | ** -V, --version 23 | Prints *mu* version and copyright information. 24 | 25 | ** -h, --help 26 | Lists the various command line options. 27 | 28 | # Local Variables: 29 | # mode: org 30 | # End: 31 | -------------------------------------------------------------------------------- /man/copyright.inc.in: -------------------------------------------------------------------------------- 1 | * COPYRIGHT 2 | 3 | This manpage is part of *mu* @VERSION@. 4 | 5 | Copyright © 2008-@YEAR@ Dirk-Jan C. Binnema. License GPLv3+: GNU GPL version 3 6 | or later . This is free software: you are 7 | free to change and redistribute it. There is NO WARRANTY, to the extent 8 | permitted by law. 9 | 10 | # Local Variables: 11 | # mode: org 12 | # End: 13 | -------------------------------------------------------------------------------- /man/exit-code.inc: -------------------------------------------------------------------------------- 1 | #+include: macros.inc 2 | 3 | * EXIT CODE 4 | 5 | This command returns 0 upon successful completion, or a non-zero exit code 6 | otherwise. 7 | 8 | 0. success 9 | 2. no matches found. Try a different query 10 | 11. database schema mismatch. You need to re-initialize *mu*, see {{{man-link(mu-init,1)}}} 11 | 19. failed to acquire lock. Some other program has exclusive access to the *mu* database 12 | 99. caught an exception 13 | 14 | # Local Variables: 15 | # mode: org 16 | # End: 17 | -------------------------------------------------------------------------------- /man/macros.inc: -------------------------------------------------------------------------------- 1 | #+MACRO: man-link *$1*​($2) 2 | 3 | # Local Variables: 4 | # mode: org 5 | # End: 6 | -------------------------------------------------------------------------------- /man/mu-add.1.org: -------------------------------------------------------------------------------- 1 | #+TITLE: MU ADD 2 | #+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@" 3 | #+include: macros.inc 4 | 5 | * NAME 6 | 7 | mu-add - add one or more messages to the database 8 | 9 | * SYNOPSIS 10 | 11 | *mu* [​_COMMON-OPTIONS_​] *add* [​_OPTIONS_​] _FILE_... 12 | 13 | * DESCRIPTION 14 | 15 | *mu add* is the command to add specific message files to the database. Each file 16 | must be specified with an absolute path. 17 | 18 | * ADD OPTIONS 19 | 20 | #+include: "muhome.inc" :minlevel 2 21 | 22 | #+include: "common-options.inc" :minlevel 1 23 | 24 | #+include: "exit-code.inc" :minlevel 1 25 | 26 | #+include: "prefooter.inc" :minlevel 1 27 | 28 | * SEE ALSO 29 | 30 | {{{man-link(mu,1)}}}, 31 | {{{man-link(mu-index,1)}}}, 32 | {{{man-link(mu-remove,1)}}} 33 | -------------------------------------------------------------------------------- /man/mu-bookmarks.5.org: -------------------------------------------------------------------------------- 1 | #+TITLE: MU BOOKMARKS 2 | #+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@" 3 | #+include: macros.inc 4 | 5 | * NAME 6 | 7 | mu-bookmarks - file with bookmarks (shortcuts) for *mu* search expressions 8 | 9 | * DESCRIPTION 10 | 11 | Bookmarks are named shortcuts for search queries. They allow using a convenient 12 | name for often-used queries. The bookmarks are also visible as shortcuts in the 13 | *mu* experimental user interfaces, =mug= and =mug2=. 14 | 15 | The bookmarks file is read from _/bookmarks_. On Unix this would typically 16 | be _~/.config/mu/bookmarks_, but this can be influenced using the *--muhome* 17 | parameter for {{{man-link(mu-find,1)}}}. 18 | 19 | The bookmarks file is a typical key=value *.ini*-file, which is best shown by 20 | means of an example: 21 | 22 | #+begin_example 23 | [mu] 24 | inbox=maildir:/inbox # inbox 25 | oldhat=maildir:/archive subject:hat # archived with subject containing 'hat' 26 | #+end_example 27 | 28 | The *[mu]* group header is required. For practical uses of bookmarks, see 29 | {{{man-link(mu-find,1)}}}. 30 | 31 | #+include: "author.inc" :minlevel 1 32 | 33 | #+include: "copyright.inc" :minlevel 1 34 | 35 | * SEE ALSO 36 | 37 | {{{man-link(mu,1)}}}, 38 | {{{man-link(mu-find,1)}}} 39 | -------------------------------------------------------------------------------- /man/mu-help.1.org: -------------------------------------------------------------------------------- 1 | #+TITLE: MU HELP 2 | #+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@" 3 | 4 | * NAME 5 | 6 | mu-help - show help information about mu commands. 7 | 8 | * SYNOPSIS 9 | 10 | *mu* [​_COMMON-OPTIONS_​] *help* [​_COMMAND_​] 11 | 12 | * DESCRIPTION 13 | 14 | *mu help* provides help information about *mu* commands. 15 | 16 | #+include: "common-options.inc" :minlevel 1 17 | 18 | #+include: "exit-code.inc" :minlevel 1 19 | 20 | #+include: "prefooter.inc" :minlevel 1 21 | -------------------------------------------------------------------------------- /man/mu-info.1.org: -------------------------------------------------------------------------------- 1 | #+TITLE: MU INFO 2 | #+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@" 3 | #+include: macros.inc 4 | 5 | * NAME 6 | 7 | mu-info - show information 8 | 9 | * SYNOPSIS 10 | 11 | *mu* [​_COMMON OPTIONS_​] *info* [​_TOPIC_​] 12 | 13 | * DESCRIPTION 14 | 15 | *mu info* is the *mu* command for getting information about various topics: 16 | 17 | - *mu*: general *mu* build information (default) 18 | - *store*: information about the message store 19 | - *fields*: table with all the query fields and flags 20 | - *maildirs*: list all maildirs under the store's root-maildir 21 | 22 | Note that while running (e.g. ~mu4e~), some of the *store* information can be 23 | delayed due to database caching. 24 | 25 | #+include: "common-options.inc" :minlevel 1 26 | 27 | #+include: "exit-code.inc" :minlevel 1 28 | 29 | #+include: "prefooter.inc" :minlevel 1 30 | 31 | * SEE ALSO 32 | 33 | {{{man-link(mu,1)}}} 34 | -------------------------------------------------------------------------------- /man/mu-mkdir.1.org: -------------------------------------------------------------------------------- 1 | #+TITLE: MU MKDIR 2 | #+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@" 3 | #+include: macros.inc 4 | 5 | * NAME 6 | 7 | mu-mkdir - create a new Maildir 8 | 9 | * SYNOPSIS 10 | 11 | *mu* [​_COMMON-OPTIONS_​] *mkdir* [​_OPTIONS_​] _DIR_... 12 | 13 | * DESCRIPTION 14 | 15 | *mu mkdir* is the command for creating Maildirs as per 16 | {{{man-link(maildir,5)}}}. A maildir is a a directory with subdirectories _new_, 17 | _cur_ and _tmp_. 18 | 19 | The command does not use the *mu* database. 20 | 21 | If creation fails for any reason, *no* attempt is made to remove any parts that 22 | were created. This is for safety reasons. 23 | 24 | * MKDIR OPTIONS 25 | 26 | ** --mode _mode_ 27 | Set the file access mode for the new maildir(s) as in 28 | {{{man-link(chmod,1)}}}. The default is 0755. 29 | 30 | #+include: "common-options.inc" :minlevel 1 31 | 32 | * EXAMPLE 33 | 34 | #+begin_example 35 | $ mu mkdir tom dick harry 36 | #+end_example 37 | 38 | creates three maildirs, _tom_, _dick_ and _harry_. 39 | 40 | #+include: "prefooter.inc" :minlevel 1 41 | 42 | * SEE ALSO 43 | 44 | {{{man-link(maildir,5)}}}, 45 | {{{man-link(chmod,1)}}} 46 | -------------------------------------------------------------------------------- /man/mu-remove.1.org: -------------------------------------------------------------------------------- 1 | #+TITLE: MU REMOVE 2 | #+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@" 3 | #+include: macros.inc 4 | 5 | * NAME 6 | 7 | mu-remove - remove messages from the database. 8 | 9 | * SYNOPSIS 10 | 11 | *mu* [​_COMMON-OPTIONS_​] *remove* [​_OPTIONS_​] _FILE_... 12 | 13 | * DESCRIPTION 14 | 15 | *mu remove* removes specific messages from the database, each of them specified by 16 | their filename. The files do not have to exist in the file system. 17 | 18 | * REMOVE OPTIONS 19 | 20 | #+include: "muhome.inc" :minlevel 2 21 | 22 | #+include: "common-options.inc" :minlevel 1 23 | 24 | #+include: "prefooter.inc" :minlevel 1 25 | 26 | * SEE ALSO 27 | 28 | {{{man-link(mu,1)}}}, 29 | {{{man-link(mu-index,1)}}}, 30 | {{{man-link(mu-add,1)}}} 31 | -------------------------------------------------------------------------------- /man/mu-server.1.org: -------------------------------------------------------------------------------- 1 | #+TITLE: MU-SERVER 2 | #+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@" 3 | #+include: macros.inc 4 | 5 | * NAME 6 | 7 | mu-server - the *mu* backend for the mu4e e-mail client 8 | 9 | * SYNOPSIS 10 | 11 | *mu* [​_COMMON-OPTIONS_​] *server* 12 | 13 | * DESCRIPTION 14 | 15 | *mu server* starts a simple shell in which one can query and manipulate the *mu* 16 | database. The output uses s-expressions. *mu server* is not meant for use by 17 | humans, except for debugging purposes. Instead, it is designed specifically for 18 | the *mu4e* e-mail client. 19 | 20 | #+begin_example 21 | ( :param1 value1 :param2 value2) 22 | #+end_example 23 | 24 | For example, to view a certain message, the command would be: 25 | 26 | #+begin_example 27 | (view :docid 12345) 28 | #+end_example 29 | 30 | Parameters can be sent in any order; they must be of the correct type though. 31 | See *lib/utils/mu-sexp-parser.hh* and *lib/utils/mu-sexp-parser.cc* in source-tree 32 | for the details. 33 | 34 | * OUTPUT FORMAT 35 | 36 | *mu server* accepts a number of commands, and delivers its results in the form: 37 | 38 | #+begin_example 39 | \\376\\377 40 | #+end_example 41 | 42 | \\376 (one byte 0xfe), followed by the length of the s-expression expressed as 43 | an hexadecimal number, followed by another \\377 (one byte 0xff), followed by 44 | the actual s-expression. 45 | 46 | By prefixing the expression with its length, it can be processed more 47 | efficiently. The \\376 and \\377 were chosen since they never occur in valid 48 | UTF-8 (in which the s-expressions are encoded). 49 | 50 | * SERVER OPTIONS 51 | 52 | ** --commands 53 | List available commands (and try with *--verbose*). 54 | 55 | ** --eval _expression_ 56 | Evaluate a mu4e server s-expression. 57 | 58 | ** --allow-temp-file 59 | If set, allow for the output of some commands to use temp-files rather than 60 | directly through the emacs process input/output. This is noticeably faster for 61 | commands with a lot of output, esp. when the the temp-file uses a in-memory 62 | file-system. 63 | 64 | * PERFORMANCE 65 | 66 | As an indication for the relative performance, we can simulate something ~mu4e~ 67 | does; we take overall time of 50 such requests: 68 | 69 | #+begin_src sh 70 | time build/mu/mu server --allow-temp-file --eval '(find :query "\"\"" :include-related t :threads t :maxnum 50000)' >/dev/null 71 | #+end_src 72 | (and *--allow-temp-file* for 1.11) 73 | 74 | #+ATTR_MAN: :disable-caption t 75 | | release | time (sec) | 76 | |---------------+------------| 77 | | 1.8 | 8.6s | 78 | | 1.10 | 5.7s | 79 | | 1.11 (master) | 2.8s | 80 | 81 | 82 | #+include: "muhome.inc" :minlevel 2 83 | 84 | #+include: "common-options.inc" :minlevel 1 85 | 86 | #+include: "prefooter.inc" :minlevel 1 87 | 88 | * SEE ALSO 89 | 90 | {{{man-link(mu,1)}}} 91 | -------------------------------------------------------------------------------- /man/mu-verify.1.org: -------------------------------------------------------------------------------- 1 | #+TITLE: MU VERIFY 2 | #+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@" 3 | #+include: macros.inc 4 | 5 | * NAME 6 | 7 | mu-verify - verify message signatures and display information about them 8 | 9 | * SYNOPSIS 10 | 11 | *mu* [​_COMMON-OPTIONS_​] *verify* [​_OPTIONS_​] [​_FILE_...] 12 | 13 | * DESCRIPTION 14 | 15 | *mu verify* is the *mu* command for verifying message signatures (such as PGP/GPG 16 | signatures) and displaying information about them. The sub-command works on 17 | message files, and does not require the message to be indexed in the database. 18 | 19 | If no message file is provided, the command expects the message on 20 | standard-input. 21 | 22 | * VERIFY OPTIONS 23 | 24 | ** -r, --auto-retrieve 25 | Attempt to find keys online (see the *auto-key-retrieve* option in the 26 | {{{man-link(gnupg,1)}}} documentation). 27 | 28 | ** --decrypt 29 | Attempt to decrypt the message. 30 | 31 | #+include: "common-options.inc" :minlevel 1 32 | 33 | * EXAMPLES 34 | 35 | To display aggregated (one-line) information about the verification status in a 36 | message: 37 | #+begin_example 38 | $ mu verify msgfile 39 | #+end_example 40 | 41 | To display information about all the signatures: 42 | #+begin_example 43 | $ mu verify --verbose msgfile 44 | #+end_example 45 | 46 | If you only want to use the exit code, you can use: 47 | #+begin_example 48 | $ mu verify --quiet msgfile 49 | #+end_example 50 | which does not give any output unless there is an error. 51 | 52 | #+include: "prefooter.inc" :minlevel 1 53 | 54 | * SEE ALSO 55 | 56 | {{{man-link(mu,1)}}} 57 | -------------------------------------------------------------------------------- /man/mu-view.1.org: -------------------------------------------------------------------------------- 1 | #+TITLE: MU VIEW 2 | #+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@" 3 | #+include: macros.inc 4 | 5 | * NAME 6 | 7 | mu-view - display an e-mail message file 8 | 9 | * SYNOPSIS 10 | 11 | *mu* [​_COMMON OPTIONS_​] *view* [​_OPTIONS_​] [​_FILE_...] 12 | 13 | * DESCRIPTION 14 | 15 | *mu view* is the *mu* command for displaying e-mail message files. It works on 16 | message files and does _not_ require the message to be indexed in the database. 17 | 18 | The command shows some common headers (From:, To:, Cc:, Bcc:, Subject: and 19 | Date:), the list of attachments and either the plain-text or html body of the 20 | message (if any), or its s-expression representation. 21 | 22 | If no message file is provided, the command reads the message from 23 | standard-input. 24 | 25 | * VIEW OPTIONS 26 | 27 | ** -o, --format _format_ 28 | Use the given output format, one of: 29 | 30 | - *plain*: use the plain-text body; this is the default, 31 | - *html*: use the HTML body, 32 | - *sexp*: show the S-expression representation of the message. 33 | 34 | ** --summary-len _number_ 35 | Instead of displaying the full message, output a summary based upon the first 36 | _number_ lines of the message. 37 | 38 | ** --terminate 39 | Terminate messages with \\​f (=form-feed=) characters when displaying them. This is 40 | useful when you want to further process them. 41 | 42 | ** --decrypt 43 | Attempt to decrypt encrypted message bodies. This is only possible if *mu* 44 | was built with crypto-support. 45 | 46 | ** --auto-retrieve 47 | Attempt to retrieve crypto-keys automatically from the network, when needed. 48 | 49 | #+include: "common-options.inc" :minlevel 1 50 | 51 | #+include: "prefooter.inc" :minlevel 1 52 | 53 | * SEE ALSO 54 | 55 | {{{man-link(mu,1)}}} 56 | -------------------------------------------------------------------------------- /man/muhome.inc: -------------------------------------------------------------------------------- 1 | ** --muhome 2 | Use a non-default directory to store and read the database, write the logs, etc. 3 | By default, *mu* uses the XDG Base Directory Specification (e.g. on GNU/Linux this 4 | defaults to _~/.cache/mu_ and _~/.config/mu_). Earlier versions of *mu* defaulted to 5 | _~/.mu_, which now requires *--muhome=~/.mu*. 6 | 7 | The environment variable *MUHOME* can be used as an alternative to *--muhome*. The 8 | latter has precedence. 9 | 10 | # Local Variables: 11 | # mode: org 12 | # End: 13 | -------------------------------------------------------------------------------- /man/prefooter.inc: -------------------------------------------------------------------------------- 1 | #+include: "bugs.inc" :minlevel 1 2 | 3 | #+include: "author.inc" :minlevel 1 4 | 5 | #+include: "copyright.inc" :minlevel 1 6 | 7 | # Local Variables: 8 | # mode: org 9 | # End: 10 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | ## Copyright (C) 2022-2024 Dirk-Jan C. Binnema 2 | ## 3 | ## This program is free software; you can redistribute it and/or modify 4 | ## it under the terms of the GNU General Public License as published by 5 | ## the Free Software Foundation; either version 3 of the License, or 6 | ## (at your option) any later version. 7 | ## 8 | ## This program is distributed in the hope that it will be useful, 9 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ## GNU General Public License for more details. 12 | ## 13 | ## You should have received a copy of the GNU General Public License 14 | ## along with this program; if not, write to the Free Software Foundation, 15 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | 18 | option('cld2', 19 | type : 'feature', 20 | value: 'auto', 21 | description: 'Add support for language-detection through cld2') 22 | 23 | # 24 | # emacs 25 | # 26 | 27 | option('emacs', 28 | type: 'string', 29 | value: 'emacs', 30 | description: 'name/path of the emacs executable (for byte-compilation)') 31 | 32 | option('lispdir', 33 | type: 'string', 34 | description: 'path under which to install emacs-lisp files') 35 | 36 | 37 | # 38 | # guile 39 | # 40 | 41 | option('guile', 42 | type : 'feature', 43 | value: 'auto', 44 | description: 'build the guile scripting support (requires guile-3.x)') 45 | 46 | # by default, this uses guile_dep.get_variable(pkgconfig: 'extensiondir') 47 | option('guile-extension-dir', 48 | type: 'string', 49 | description: 'custom install path for the guile extension module') 50 | 51 | # 52 | # misc 53 | # 54 | 55 | option('tests', 56 | type : 'feature', 57 | value: 'auto', 58 | description: 'build unit tests') 59 | 60 | option('readline', 61 | type: 'feature', 62 | value: 'auto', 63 | description: 'enable readline support for the mu4e repl') 64 | -------------------------------------------------------------------------------- /mu/meson.build: -------------------------------------------------------------------------------- 1 | ## Copyright (C) 2021-2023 Dirk-Jan C. Binnema 2 | ## 3 | ## This program is free software; you can redistribute it and/or modify 4 | ## it under the terms of the GNU General Public License as published by 5 | ## the Free Software Foundation; either version 3 of the License, or 6 | ## (at your option) any later version. 7 | ## 8 | ## This program is distributed in the hope that it will be useful, 9 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ## GNU General Public License for more details. 12 | ## 13 | ## You should have received a copy of the GNU General Public License 14 | ## along with this program; if not, write to the Free Software Foundation, 15 | ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | mu = executable( 18 | 'mu', [ 19 | 'mu.cc', 20 | 'mu-options.cc', 21 | 'mu-cmd-add.cc', 22 | 'mu-cmd-cfind.cc', 23 | 'mu-cmd-extract.cc', 24 | 'mu-cmd-find.cc', 25 | 'mu-cmd-info.cc', 26 | 'mu-cmd-init.cc', 27 | 'mu-cmd-index.cc', 28 | 'mu-cmd-mkdir.cc', 29 | 'mu-cmd-move.cc', 30 | 'mu-cmd-remove.cc', 31 | 'mu-cmd-script.cc', 32 | 'mu-cmd-server.cc', 33 | 'mu-cmd-verify.cc', 34 | 'mu-cmd-view.cc', 35 | 'mu-cmd.cc' 36 | ], 37 | dependencies: [ glib_dep, gmime_dep, lib_mu_dep, thread_dep, config_h_dep ], 38 | cpp_args: ['-DMU_SCRIPTS_DIR="'+ join_paths(datadir, 'mu', 'scripts') + '"'], 39 | install: true) 40 | # 41 | if not get_option('tests').disabled() 42 | subdir('tests') 43 | endif 44 | -------------------------------------------------------------------------------- /mu/mu-cmd-add.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "config.h" 21 | #include "mu-cmd.hh" 22 | 23 | using namespace Mu; 24 | 25 | Result 26 | Mu::mu_cmd_add(Mu::Store& store, const Options& opts) 27 | { 28 | for (auto&& file: opts.add.files) { 29 | const auto docid{store.add_message(file)}; 30 | if (!docid) 31 | return Err(docid.error()); 32 | else 33 | mu_debug("added message @ {}, docid={}", file, *docid); 34 | } 35 | 36 | return Ok(); 37 | } 38 | 39 | 40 | #ifdef BUILD_TESTS 41 | /* 42 | * Tests. 43 | * 44 | */ 45 | 46 | #include "utils/mu-test-utils.hh" 47 | 48 | static void 49 | test_add_ok() 50 | { 51 | auto testhome{unwrap(make_temp_dir())}; 52 | auto dbpath{runtime_path(RuntimePath::XapianDb, testhome)}; 53 | 54 | { 55 | unwrap(Store::make_new(dbpath, MU_TESTMAILDIR)); 56 | } 57 | 58 | { 59 | auto res = run_command({MU_PROGRAM, "add", mu_format("--muhome={}", testhome), 60 | MU_TESTMAILDIR "/cur/1220863042.12663_1.mindcrime!2,S"}); 61 | assert_valid_command(res); 62 | } 63 | 64 | { 65 | auto&& store = Store::make(dbpath); 66 | assert_valid_result(store); 67 | g_assert_cmpuint(store->size(),==,1); 68 | } 69 | 70 | { // re-add the same 71 | auto res = run_command({MU_PROGRAM, "add", mu_format("--muhome={}",testhome), 72 | MU_TESTMAILDIR "/cur/1220863042.12663_1.mindcrime!2,S"}); 73 | assert_valid_command(res); 74 | } 75 | 76 | { 77 | auto&& store = Store::make(dbpath); 78 | assert_valid_result(store); 79 | g_assert_cmpuint(store->size(),==,1); 80 | } 81 | 82 | 83 | remove_directory(testhome); 84 | } 85 | 86 | static void 87 | test_add_fail() 88 | { 89 | auto testhome{unwrap(make_temp_dir())}; 90 | auto dbpath{runtime_path(RuntimePath::XapianDb, testhome)}; 91 | 92 | { 93 | unwrap(Store::make_new(dbpath, MU_TESTMAILDIR2)); 94 | } 95 | 96 | { // wrong maildir 97 | auto res = run_command({MU_PROGRAM, "add", mu_format("--muhome={}", testhome), 98 | MU_TESTMAILDIR "/cur/1220863042.12663_1.mindcrime!2,S"}); 99 | assert_valid_result(res); 100 | g_assert_cmpuint(res->exit_code,!=,0); 101 | } 102 | 103 | 104 | { // non-existent 105 | auto res = run_command({MU_PROGRAM, "add", mu_format("--muhome={}", testhome), 106 | "/foo/bar/non-existent"}); 107 | assert_valid_result(res); 108 | g_assert_cmpuint(res->exit_code,!=,0); 109 | } 110 | 111 | remove_directory(testhome); 112 | } 113 | 114 | 115 | int 116 | main(int argc, char* argv[]) 117 | { 118 | mu_test_init(&argc, &argv); 119 | 120 | g_test_add_func("/cmd/add/ok", test_add_ok); 121 | g_test_add_func("/cmd/add/fail", test_add_fail); 122 | 123 | return g_test_run(); 124 | } 125 | #endif /*BUILD_TESTS*/ 126 | -------------------------------------------------------------------------------- /mu/mu-cmd-mkdir.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "config.h" 21 | #include "mu-cmd.hh" 22 | 23 | #include "mu-maildir.hh" 24 | 25 | using namespace Mu; 26 | 27 | Mu::Result 28 | Mu::mu_cmd_mkdir(const Options& opts) 29 | { 30 | for (auto&& dir: opts.mkdir.dirs) { 31 | if (auto&& res = 32 | maildir_mkdir(dir, opts.mkdir.mode); !res) 33 | return res; 34 | } 35 | 36 | return Ok(); 37 | } 38 | 39 | 40 | 41 | #ifdef BUILD_TESTS 42 | /* 43 | * Tests. 44 | * 45 | */ 46 | 47 | #include "utils/mu-test-utils.hh" 48 | 49 | static void 50 | test_mkdir_single() 51 | { 52 | auto testroot{unwrap(make_temp_dir())}; 53 | auto testdir1{join_paths(testroot, "testdir1")}; 54 | 55 | auto res = run_command({MU_PROGRAM, "mkdir", testdir1}); 56 | assert_valid_command(res); 57 | 58 | g_assert_true(check_dir(join_paths(testdir1, "cur"), true, true)); 59 | g_assert_true(check_dir(join_paths(testdir1, "new"), true, true)); 60 | g_assert_true(check_dir(join_paths(testdir1, "tmp"), true, true)); 61 | } 62 | 63 | static void 64 | test_mkdir_multi() 65 | { 66 | auto testroot{unwrap(make_temp_dir())}; 67 | auto testdir2{join_paths(testroot, "testdir2")}; 68 | auto testdir3{join_paths(testroot, "testdir3")}; 69 | 70 | auto res = run_command({MU_PROGRAM, "mkdir", testdir2, testdir3}); 71 | assert_valid_command(res); 72 | 73 | g_assert_true(check_dir(join_paths(testdir2, "cur"), true, true)); 74 | g_assert_true(check_dir(join_paths(testdir2, "new"), true, true)); 75 | g_assert_true(check_dir(join_paths(testdir3, "tmp"), true, true)); 76 | 77 | g_assert_true(check_dir(join_paths(testdir3, "cur"), true, true)); 78 | g_assert_true(check_dir(join_paths(testdir3, "new"), true, true)); 79 | g_assert_true(check_dir(join_paths(testdir3, "tmp"), true, true)); 80 | } 81 | 82 | int 83 | main(int argc, char* argv[]) try { 84 | 85 | mu_test_init(&argc, &argv); 86 | 87 | g_test_add_func("/cmd/mkdir/single", test_mkdir_single); 88 | g_test_add_func("/cmd/mkdir/multi", test_mkdir_multi); 89 | 90 | return g_test_run(); 91 | 92 | } catch (const Error& e) { 93 | mu_printerrln("{}", e.what()); 94 | return 1; 95 | } catch (...) { 96 | mu_printerrln("caught exception"); 97 | return 1; 98 | } 99 | #endif /*BUILD_TESTS*/ 100 | -------------------------------------------------------------------------------- /mu/mu-cmd-remove.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2023 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "config.h" 21 | #include "mu-cmd.hh" 22 | 23 | using namespace Mu; 24 | 25 | Result 26 | Mu::mu_cmd_remove(Mu::Store& store, const Options& opts) 27 | { 28 | for (auto&& file: opts.remove.files) { 29 | const auto res = store.remove_message(file); 30 | if (!res) 31 | return Err(Error::Code::File, "failed to remove {}", file.c_str()); 32 | else 33 | mu_debug("removed message @ {}", file); 34 | } 35 | 36 | return Ok(); 37 | } 38 | 39 | 40 | #ifdef BUILD_TESTS 41 | /* 42 | * Tests. 43 | * 44 | */ 45 | 46 | #include "utils/mu-test-utils.hh" 47 | 48 | static void 49 | test_remove_ok() 50 | { 51 | auto testhome{unwrap(make_temp_dir())}; 52 | auto dbpath{runtime_path(RuntimePath::XapianDb, testhome)}; 53 | 54 | /* create a writable copy */ 55 | const auto testmdir = join_paths(testhome, "test-maildir"); 56 | const auto testmsg = join_paths(testmdir, "/cur/1220863042.12663_1.mindcrime!2,S"); 57 | auto cres = run_command({CP_PROGRAM, "-r", MU_TESTMAILDIR, testmdir}); 58 | assert_valid_command(cres); 59 | 60 | { 61 | auto&& store = unwrap(Store::make_new(dbpath, testmdir)); 62 | auto res = store.add_message(testmsg); 63 | assert_valid_result(res); 64 | g_assert_true(store.contains_message(testmsg)); 65 | } 66 | 67 | { // remove the same 68 | auto res = run_command({MU_PROGRAM, "remove", 69 | mu_format("--muhome={}", testhome), 70 | testmsg}); 71 | assert_valid_command(res); 72 | } 73 | 74 | { 75 | auto&& store = unwrap(Store::make(dbpath)); 76 | g_assert_false(!!store.contains_message(testmsg)); 77 | g_assert_cmpuint(::access(testmsg.c_str(), F_OK), ==, 0); 78 | } 79 | 80 | remove_directory(testhome); 81 | } 82 | 83 | 84 | int 85 | main(int argc, char* argv[]) try { 86 | 87 | mu_test_init(&argc, &argv); 88 | 89 | g_test_add_func("/cmd/remove/ok", test_remove_ok); 90 | 91 | return g_test_run(); 92 | 93 | } catch (const Error& e) { 94 | mu_printerrln("{}", e.what()); 95 | return 1; 96 | } catch (...) { 97 | mu_printerrln("caught exception"); 98 | return 1; 99 | } 100 | #endif /*BUILD_TESTS*/ 101 | -------------------------------------------------------------------------------- /mu/mu-cmd-script.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2012-2022 Dirk-Jan C. Binnema 3 | ** 4 | ** This program is free software; you can redistribute it and/or modify it 5 | ** under the terms of the GNU General Public License as published by the 6 | ** Free Software Foundation; either version 3, or (at your option) any 7 | ** later version. 8 | ** 9 | ** This program is distributed in the hope that it will be useful, 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ** GNU General Public License for more details. 13 | ** 14 | ** You should have received a copy of the GNU General Public License 15 | ** along with this program; if not, write to the Free Software Foundation, 16 | ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ** 18 | */ 19 | 20 | #include "config.h" 21 | 22 | #include "mu-cmd.hh" 23 | #include "mu-script.hh" 24 | #include "utils/mu-utils.hh" 25 | 26 | using namespace Mu; 27 | 28 | Result 29 | Mu::mu_cmd_script(const Options& opts) 30 | { 31 | ScriptPaths paths = { MU_SCRIPTS_DIR }; 32 | const auto&& scriptinfos{script_infos(paths)}; 33 | auto script_it = Mu::seq_find_if(scriptinfos, [&](auto&& item) { 34 | return item.name == opts.script.name; 35 | }); 36 | 37 | if (script_it == scriptinfos.cend()) 38 | return Err(Error::Code::InvalidArgument, 39 | "cannot find script '{}'", opts.script.name); 40 | 41 | std::vector params{opts.script.params}; 42 | if (!opts.muhome.empty()) { 43 | params.emplace_back("--muhome"); 44 | params.emplace_back(opts.muhome); 45 | } 46 | 47 | // won't return unless there's an error. 48 | return run_script(script_it->path, opts.script.params); 49 | } 50 | -------------------------------------------------------------------------------- /mu/mu-memcheck.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export G_SLICE=always-malloc 4 | export G_DEBUG=gc-friendly 5 | 6 | libtool --mode=execute valgrind --tool=memcheck --leak-check=full --show-possibly-lost=no --leak-resolution=med --track-origins=yes --num-callers=20 --log-file='@abs_top_builddir@/mu-%p.vgdump' @abs_top_builddir@/mu/mu $@ 7 | -------------------------------------------------------------------------------- /mu4e/mu4e-about.org: -------------------------------------------------------------------------------- 1 | #+STARTUP:showall 2 | * About mu4e 3 | 4 | *mu4e* is an emacs e-mail client based on the [[http://djcbsoftware.nl/code/mu][mu]] email search engine. It was 5 | written & designed by /Dirk-Jan C. Binnema/, with contributions from others. 6 | 7 | *mu4e* and *mu* are free software, licensed under the terms of the [[http://www.gnu.org/licenses/gpl-3.0.html][GNU GPLv3]]. 8 | 9 | You can get the code from [[https://github.com/djcb/mu][the git repository]]; there, you can also 10 | [[https://github.com/djcb/mu/issues][file bugs and feature requests]]. 11 | 12 | *mu4e* has its own [[info:mu4e][manual]], which includes an [[info:mu4e#FAQ%20-%20Frequently%20Anticipated%20Questions][FAQ]]. If that is not enough, 13 | there's also the [[http://groups.google.com/group/mu-discuss][mu mailing list]]. 14 | 15 | [Press *q* to quit this buffer] 16 | -------------------------------------------------------------------------------- /mu4e/mu4e-config.el.in: -------------------------------------------------------------------------------- 1 | ;;; mu4e-config.el --- configuration values -*- lexical-binding: t -*- 2 | 3 | ;;; Commentary: 4 | 5 | ;; Auto-generated configuration values 6 | 7 | ;;; Code: 8 | 9 | (defconst mu4e-mu-version "@VERSION@" 10 | "Required mu binary version. 11 | mu4e's version must agree with this.") 12 | 13 | (defconst mu4e-doc-dir "@MU_DOC_DIR@" 14 | "Directory for mu4e documentation.") 15 | 16 | (provide 'mu4e-config) 17 | ;;; mu4e-config.el.in ends here 18 | -------------------------------------------------------------------------------- /mu4e/mu4e-pkg.el.in: -------------------------------------------------------------------------------- 1 | ;; -*- no-byte-compile: t; -*- 2 | (define-package "mu4e" "@VERSION@" 3 | "part of mu4e, the mu mail user agent" 4 | '((emacs "@EMACS_MIN_VERSION@")) 5 | :authors '(("Dirk-Jan C. Binnema" . "djcb@djcbsoftware.nl")) 6 | :maintainer '("Dirk-Jan C. Binnema" . "djcb@djcbsoftware.nl") 7 | :keywords '("email")) 8 | -------------------------------------------------------------------------------- /mu4e/texinfo-klare.css: -------------------------------------------------------------------------------- 1 | /* 2 | Custom CSS for HTML documents generated with Texinfo's makeinfo. 3 | Public domain 2016 sirgazil. All rights waived. 4 | */ 5 | 6 | 7 | 8 | /* NATIVE ELEMENTS */ 9 | a:link, 10 | a:visited { 11 | color: #245C8A; 12 | text-decoration: none; 13 | } 14 | 15 | a:active, 16 | a:focus, 17 | a:hover { 18 | text-decoration: underline; 19 | } 20 | 21 | abbr, 22 | acronym { 23 | cursor: help; 24 | } 25 | 26 | blockquote { 27 | color: #555753; 28 | font-style: oblique; 29 | margin: 30px 0px; 30 | padding-left: 3em; 31 | } 32 | 33 | body { 34 | background-color: white; 35 | box-shadow: 0 0 2px gray; 36 | box-sizing: border-box; 37 | color: #333; 38 | font-family: sans-serif; 39 | font-size: 16px; 40 | margin: 50px auto; 41 | max-width: 960px; 42 | padding: 50px; 43 | } 44 | 45 | code, 46 | samp, 47 | tt, 48 | var { 49 | color: purple; 50 | font-size: 0.8em; 51 | } 52 | 53 | div.example, 54 | div.lisp { 55 | margin: 0px; 56 | } 57 | 58 | dl { 59 | margin: 3em 0em; 60 | } 61 | 62 | dl dl { 63 | margin: 0em; 64 | } 65 | 66 | dt { 67 | background-color: #F5F5F5; 68 | padding: 0.5em; 69 | } 70 | 71 | h1, 72 | h2, 73 | h2.contents-heading, 74 | h3, 75 | h4 { 76 | padding: 20px 0px 0px 0px; 77 | font-weight: normal; 78 | } 79 | 80 | h1 { 81 | font-size: 2.4em; 82 | } 83 | 84 | h2 { 85 | font-size: 2.2em; 86 | font-weight: bold; 87 | } 88 | 89 | h3 { 90 | font-size: 1.8em; 91 | } 92 | 93 | h4 { 94 | font-size: 1.4em; 95 | } 96 | 97 | hr { 98 | background-color: silver; 99 | border-style: none; 100 | height: 1px; 101 | margin: 0px; 102 | } 103 | 104 | html { 105 | background-color: #F5F5F5; 106 | } 107 | 108 | img { 109 | max-width: 100%; 110 | } 111 | 112 | li { 113 | padding: 5px; 114 | } 115 | 116 | pre.display, 117 | pre.example, 118 | pre.format, 119 | pre.lisp, 120 | pre.verbatim{ 121 | overflow: auto; 122 | } 123 | 124 | pre.example, 125 | pre.lisp, 126 | pre.verbatim { 127 | background-color: #2D3743; 128 | border-color: #000; 129 | border-style: solid; 130 | border-width: thin; 131 | color: #E1E1E1; 132 | font-size: smaller; 133 | padding: 1em; 134 | } 135 | 136 | pre.menu-comment { 137 | border-color: #E4E4E4; 138 | border-bottom-style: solid; 139 | border-width: thin; 140 | font-family: sans; 141 | } 142 | 143 | table { 144 | border-collapse: collapse; 145 | margin: 40px 0px; 146 | } 147 | 148 | table.index-cp *, 149 | table.index-fn *, 150 | table.index-ky *, 151 | table.index-pg *, 152 | table.index-tp *, 153 | table.index-vr * { 154 | background-color: inherit; 155 | border-style: none; 156 | } 157 | 158 | td, 159 | th { 160 | border-color: silver; 161 | border-style: solid; 162 | border-width: thin; 163 | padding: 10px; 164 | } 165 | 166 | th { 167 | background-color: #F5F5F5; 168 | } 169 | /* END NATIVE ELEMENTS */ 170 | 171 | 172 | 173 | /* CLASSES */ 174 | .contents { 175 | margin-bottom: 4em; 176 | } 177 | 178 | .float { 179 | margin: 3em 0em; 180 | } 181 | 182 | .float-caption { 183 | font-size: smaller; 184 | text-align: center; 185 | } 186 | 187 | .float > img { 188 | display: block; 189 | margin: auto; 190 | } 191 | 192 | .footnote { 193 | font-size: smaller; 194 | margin: 5em 0em; 195 | } 196 | 197 | .footnote h3 { 198 | display: inline; 199 | font-size: small; 200 | } 201 | 202 | .header { 203 | background-color: #F2F2F2; 204 | font-size: small; 205 | padding: 0.2em 1em; 206 | } 207 | 208 | .key { 209 | color: purple; 210 | font-size: 0.8em; 211 | } 212 | 213 | .menu * { 214 | border-style: none; 215 | } 216 | 217 | .menu td { 218 | padding: 0.5em 0em; 219 | } 220 | 221 | .menu td:last-child { 222 | width: 60%; 223 | } 224 | 225 | .menu th { 226 | background-color: inherit; 227 | } 228 | /* END CLASSES */ 229 | -------------------------------------------------------------------------------- /testdata/cjk/cur/test1: -------------------------------------------------------------------------------- 1 | From: "Bob" 2 | Subject: CJK 1 3 | To: "Chase" 4 | Date: Thu, 18 Nov 2021 08:35:34 +0200 5 | Message-Id: 112342343e9dfo.fsf@builder.com 6 | User-Agent: mu4e 1.7.5; emacs 29.0.50 7 | 8 | サーバがダウンしました 9 | 10 | https://github.com/djcb/mu/issues/1428 11 | -------------------------------------------------------------------------------- /testdata/cjk/cur/test2: -------------------------------------------------------------------------------- 1 | From: "Bob" 2 | Subject: CJK 2 3 | To: "Chase" 4 | Date: Thu, 18 Nov 2021 08:35:34 +0200 5 | Message-Id: 271r2342343e9dfo.fsf@builder.com 6 | User-Agent: mu4e 1.7.5; emacs 29.0.50 7 | 8 | スポンサーシップ募集 9 | 10 | https://github.com/djcb/mu/issues/1428 11 | -------------------------------------------------------------------------------- /testdata/cjk/cur/test3: -------------------------------------------------------------------------------- 1 | From: "Bob" 2 | Subject: CJK 3 3 | To: "Chase" 4 | Date: Thu, 18 Nov 2021 08:35:34 +0200 5 | Message-Id: 3871r2342343e9dfo.fsf@builder.com 6 | User-Agent: mu4e 1.7.5; emacs 29.0.50 7 | 8 | サービス開始について 9 | 10 | https://github.com/djcb/mu/issues/1428 11 | -------------------------------------------------------------------------------- /testdata/cjk/cur/test4: -------------------------------------------------------------------------------- 1 | From: "Bob" 2 | Subject: CJK 4 3 | To: "Chase" 4 | Date: Thu, 18 Nov 2021 08:35:34 +0200 5 | Message-Id: 4871r2342343e9dfo.fsf@builder.com 6 | User-Agent: mu4e 1.7.5; emacs 29.0.50 7 | 8 | ショルダーバック 9 | 10 | https://github.com/djcb/mu/issues/1428 11 | -------------------------------------------------------------------------------- /testdata/testdir/cur/1220863087.12663_19.mindcrime!2,S: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime 3 | X-Spam-Level: 4 | X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00 autolearn=ham 5 | version=3.2.5 6 | X-Original-To: xxxx@localhost 7 | Delivered-To: xxxx@localhost 8 | Received: from mindcrime (localhost [127.0.0.1]) 9 | by mail.xxxxsoftware.nl (Postfix) with ESMTP id C4D6569CB3 10 | for ; Thu, 7 Aug 2008 08:10:08 +0300 (EEST) 11 | Delivered-To: xxxx.klub@gmail.com 12 | Received: from gmail-imap.l.google.com [66.249.91.109] 13 | by mindcrime with IMAP (fetchmail-6.3.8) 14 | for (single-drop); Thu, 07 Aug 2008 08:10:08 +0300 (EEST) 15 | Received: by 10.142.237.21 with SMTP id k21cs34794wfh; Wed, 6 Aug 2008 16 | 13:40:29 -0700 (PDT) 17 | Received: by 10.100.33.13 with SMTP id g13mr1093301ang.79.1218055228418; Wed, 18 | 06 Aug 2008 13:40:28 -0700 (PDT) 19 | Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by mx.google.com 20 | with ESMTP id d19si15908789and.17.2008.08.06.13.40.27; Wed, 06 Aug 2008 21 | 13:40:28 -0700 (PDT) 22 | Received-SPF: pass (google.com: domain of 23 | help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 24 | as permitted sender) client-ip=199.232.76.165; 25 | Authentication-Results: mx.google.com; spf=pass (google.com: domain of 26 | help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 27 | as permitted sender) 28 | smtp.mail=help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org 29 | Received: from localhost ([127.0.0.1]:56316 helo=lists.gnu.org) by 30 | lists.gnu.org with esmtp (Exim 4.43) id 1KQpo3-0007Pc-Qk for 31 | xxxx.klub@gmail.com; Wed, 06 Aug 2008 16:40:27 -0400 32 | From: anon@example.com 33 | Newsgroups: gnu.emacs.help 34 | Date: Wed, 6 Aug 2008 20:38:35 +0100 35 | Message-ID: 36 | References: <55dbm5-qcl.ln1@news.ducksburg.com> 37 | 38 | Mime-Version: 1.0 39 | Content-Type: text/plain; charset=us-ascii 40 | Content-Transfer-Encoding: 7bit 41 | X-Trace: individual.net bABVU1hcJwWAuRwe/097AAoOXnGGeYR8G1In635iFGIyfDLPUv 42 | X-Orig-Path: news.ducksburg.com!news 43 | Cancel-Lock: sha1:wK7dsPRpNiVxpL/SfvmNzlvUR94= 44 | sha1:oepBoM0tJBLN52DotWmBBvW5wbg= 45 | User-Agent: slrn/pre0.9.9-120/mm/ao (Ubuntu Hardy) 46 | Path: news.stanford.edu!headwall.stanford.edu!newshub.sdsu.edu!feeder.erje.net!proxad.net!feeder1-2.proxad.net!feed.ac-versailles.fr!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail 47 | Xref: news.stanford.edu gnu.emacs.help:160868 48 | To: help-gnu-emacs@gnu.org 49 | Subject: Re: Learning LISP; Scheme vs elisp. 50 | X-BeenThere: help-gnu-emacs@gnu.org 51 | X-Mailman-Version: 2.1.5 52 | Precedence: list 53 | List-Id: Users list for the GNU Emacs text editor 54 | List-Unsubscribe: , 55 | 56 | List-Archive: 57 | List-Post: 58 | List-Help: 59 | List-Subscribe: , 60 | 61 | Sender: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org 62 | Errors-To: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org 63 | Content-Length: 417 64 | Lines: 11 65 | 66 | On 2008-08-01, Thien-Thi Nguyen wrote: 67 | 68 | > warriors attack, felling foe after foe, 69 | > few growing old til they realize: to know 70 | > what deceit is worth deflection; 71 | > such receipt reversed rejection! 72 | > then their heavy arms, e'er transformed to shields: 73 | > balanced hooked charms, ploughed deep, rich yields. 74 | 75 | Aha: the exercise for the reader is to place the parens correctly. 76 | Might take me a while to solve this puzzle. 77 | 78 | -------------------------------------------------------------------------------- /testdata/testdir/cur/1220863087.12663_5.mindcrime!2,S: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime 3 | X-Spam-Level: 4 | X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00 autolearn=ham 5 | version=3.2.5 6 | X-Original-To: xxxx@localhost 7 | Delivered-To: xxxx@localhost 8 | Received: from mindcrime (localhost [127.0.0.1]) 9 | by mail.xxxxsoftware.nl (Postfix) with ESMTP id 32F276963F 10 | for ; Mon, 4 Aug 2008 21:49:34 +0300 (EEST) 11 | Delivered-To: xxxx.klub@gmail.com 12 | Received: from gmail-imap.l.google.com [72.14.221.111] 13 | by mindcrime with IMAP (fetchmail-6.3.8) 14 | for (single-drop); Mon, 04 Aug 2008 21:49:34 +0300 (EEST) 15 | Received: by 10.142.51.12 with SMTP id y12cs89397wfy; Mon, 4 Aug 2008 02:41:16 16 | -0700 (PDT) 17 | Received: by 10.150.156.20 with SMTP id d20mr963580ybe.104.1217842875596; Mon, 18 | 04 Aug 2008 02:41:15 -0700 (PDT) 19 | Received: from sqlite.org (sqlite.org [67.18.92.124]) by mx.google.com with 20 | ESMTP id 6si3605185ywi.1.2008.08.04.02.40.57; Mon, 04 Aug 2008 02:41:15 -0700 21 | (PDT) 22 | Received-SPF: pass (google.com: best guess record for domain of 23 | sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as permitted sender) 24 | client-ip=67.18.92.124; 25 | Authentication-Results: mx.google.com; spf=pass (google.com: best guess record 26 | for domain of sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as 27 | permitted sender) smtp.mail=sqlite-dev-bounces@sqlite.org 28 | Received: from sqlite.org (localhost [127.0.0.1]) by sqlite.org (Postfix) with 29 | ESMTP id 7147F11C45; Mon, 4 Aug 2008 05:40:55 -0400 (EDT) 30 | X-Original-To: sqlite-dev@sqlite.org 31 | Delivered-To: sqlite-dev@sqlite.org 32 | Received: from relay00.pair.com (relay00.pair.com [209.68.5.9]) by sqlite.org 33 | (Postfix) with SMTP id B5F901192C for ; Mon, 4 Aug 34 | 2008 05:40:52 -0400 (EDT) 35 | Received: (qmail 59961 invoked from network); 4 Aug 2008 09:40:50 -0000 36 | Received: from unknown (HELO ?192.168.0.17?) (unknown) by unknown with SMTP; 4 37 | Aug 2008 09:40:50 -0000 38 | X-pair-Authenticated: 87.13.75.164 39 | Message-Id: <83B5AF40-DBFA-4578-A043-04C80276E195@sqlabs.net> 40 | From: anon@example.com 41 | To: sqlite-dev@sqlite.org 42 | Mime-Version: 1.0 (Apple Message framework v926) 43 | Date: Mon, 4 Aug 2008 11:40:49 +0200 44 | X-Mailer: Apple Mail (2.926) 45 | Subject: [sqlite-dev] VM optimization inside sqlite3VdbeExec 46 | X-BeenThere: sqlite-dev@sqlite.org 47 | X-Mailman-Version: 2.1.9 48 | Precedence: list 49 | Reply-To: sqlite-dev@sqlite.org 50 | List-Id: 51 | List-Unsubscribe: , 52 | 53 | List-Archive: 54 | List-Post: 55 | List-Help: 56 | List-Subscribe: , 57 | 58 | Content-Type: text/plain; charset="us-ascii" 59 | Content-Transfer-Encoding: 7bit 60 | Sender: sqlite-dev-bounces@sqlite.org 61 | Errors-To: sqlite-dev-bounces@sqlite.org 62 | Content-Length: 639 63 | 64 | Inside sqlite3VdbeExec there is a very big switch statement. 65 | In order to increase performance with few modifications to the 66 | original code, why not use this technique ? 67 | http://docs.freebsd.org/info/gcc/gcc.info.Labels_as_Values.html 68 | 69 | With a properly defined "instructions" array, instead of the switch 70 | statement you can use something like: 71 | goto * instructions[pOp->opcode]; 72 | --- 73 | Marco Bambini 74 | http://www.sqlabs.net 75 | http://www.sqlabs.net/blog/ 76 | http://www.sqlabs.net/realsqlserver/ 77 | 78 | 79 | 80 | _______________________________________________ 81 | sqlite-dev mailing list 82 | sqlite-dev@sqlite.org 83 | http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev 84 | 85 | -------------------------------------------------------------------------------- /testdata/testdir/cur/1252168370_3.14675.cthulhu!2,S: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on mindcrime 3 | X-Spam-Level: 4 | Delivered-To: dfgh@floppydisk.nl 5 | Message-ID: <43A09C49.9040902@euler.org> 6 | Date: Wed, 14 Dec 2005 23:27:21 +0100 7 | From: Fred Flintstone 8 | User-Agent: Mozilla Thunderbird 1.0.7 (X11/20051010) 9 | X-Accept-Language: nl-NL, nl, en 10 | MIME-Version: 1.0 11 | To: dfgh@floppydisk.nl 12 | Subject: Re: xyz 13 | References: <439C1136.90504@euler.org> <4399DD94.5070309@euler.org> <20051209233303.GA13812@gauss.org> <439B41ED.2080402@euler.org> <4399DD94.5070309@euler.org> <20051209233303.GA13812@gauss.org> <439A1E03.3090604@euler.org> <20051211184308.GB13513@gauss.org> 14 | In-Reply-To: <20051211184308.GB13513@gauss.org> 15 | X-Enigmail-Version: 0.92.0.0 16 | Content-Type: text/plain; charset=UTF-8 17 | Content-Transfer-Encoding: 7bit 18 | X-UIDL: T 2 | To: Bilbo Baggins 3 | Subject: Greetings from =?UTF-8?B?TG90aGzDs3JpZW4=?= 4 | User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) 5 | Fcc: .sent 6 | Organization: The Fellowship of the Ring 7 | MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") 8 | Content-Type: text/plain; charset=UTF-8 9 | Content-Transfer-Encoding: 8bit 10 | Message-Id: 11 | 12 | 13 | Let's write some fünkÿ text 14 | using umlauts. 15 | 16 | Foo. 17 | -------------------------------------------------------------------------------- /testdata/testdir/cur/1305664394.2171_402.cthulhu!2,: -------------------------------------------------------------------------------- 1 | From: =?UTF-8?B?TcO8?= 2 | To: Helmut =?UTF-8?B?S3LDtmdlcg==?= 3 | Subject: =?UTF-8?B?TW90w7ZyaGVhZA==?= 4 | User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) 5 | References: 6 | 1n-Reply-To: 7 | MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") 8 | Content-Type: text/plain; charset=UTF-8 9 | Content-Transfer-Encoding: 8bit 10 | 11 | 12 | Test for issue #38, where apparently searching for accented words in subject, 13 | to etc. fails. 14 | 15 | What about here? Queensrÿche. Mötley Crüe. 16 | 17 | 18 | -------------------------------------------------------------------------------- /testdata/testdir/cur/encrypted!2,S: -------------------------------------------------------------------------------- 1 | Return-path: <> 2 | Envelope-to: peter@example.com 3 | Delivery-date: Fri, 11 May 2012 16:22:03 +0300 4 | Received: from localhost.example.com ([127.0.0.1] helo=borealis) 5 | by borealis with esmtp (Exim 4.77) 6 | id 1SSpnB-00038a-Ux 7 | for djcb@localhost; Fri, 11 May 2012 16:21:58 +0300 8 | Delivered-To: peter@example.com 9 | From: Brian 10 | To: Peter 11 | Subject: encrypted 12 | User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 13 | Date: Fri, 11 May 2012 16:21:42 +0300 14 | Message-ID: 15 | MIME-Version: 1.0 16 | Content-Type: multipart/encrypted; boundary="=-=-="; 17 | protocol="application/pgp-encrypted" 18 | 19 | --=-=-= 20 | Content-Type: application/pgp-encrypted 21 | 22 | Version: 1 23 | 24 | --=-=-= 25 | Content-Type: application/octet-stream 26 | 27 | -----BEGIN PGP MESSAGE----- 28 | Version: GnuPG v1.4.12 (GNU/Linux) 29 | 30 | hQQOA1T38TPQrHD6EA//YXkUB4Dy09ngCRyHWbXmV3XBjuKTr8xrak5ML1kwurav 31 | gyagOHKLMU+5CKvObChiKtXhtgU0od7IC8o+ALlHevQ0XXcqNYA2KUfX8R7akq7d 32 | Xx9mA6D8P7Y/P8juUCLBpfrCi2GC42DtvPZSUu3bL/ctUJ3InPHIfHibKF2HMm7/ 33 | gUHAKY8VPJF39dLP8GLcfki6qFdeWbxgtzmuyzHfCBCLnDL0J9vpEQBpGDFMcc4v 34 | cCbmMJaiPOmRb6U4WOuRVnuXuTztLiIn0jMslzOSFDcLTVBAsrC01r71O+XZKfN4 35 | mIfcpcWJYKM2NQW8Jwf+8Hr84uznBqs8uTTlrmppjkAHZGqGMjiQDxLhDVaCQzMy 36 | O8PSV4xT6HPlKXOwV1OLc+vm0A0RAdSBctgZg40oFn4XdB1ur8edwAkLvc0hJKaz 37 | gyTQiPaXm2Uh2cDeEx4xNgXmwCKasqc9jAlnDC2QwA33+pw3OqgZT5h1obn0fAeR 38 | mgB+iW1503DIi/96p8HLZcr2EswLEH9ViHIEaFj/vlR5BaOncsLB0SsNV/MHRvym 39 | Xg5GUjzPIiyBZ3KaR9OIBiZ5eXw+bSrPAo/CAs0Zwxag7W3CH//oK39Qo1GnkYpc 40 | 4IQxhx4IwkzqtCnripltV/kfpGu0yA/OdK8lOjkUqCwvL97o73utXIxm21Zd3mEP 41 | /iLNrduZjMCq+goz1pDAQa9Dez6VjwRuRPTqeAac8Fx/nzrVzIoIEAt36hpuaH1l 42 | KpbmHpKgsUWcrE5iYT0RRlRRtRF4PfJg8PUmP1hvw8TaEmNfT+0HgzcJB/gRsVdy 43 | gTzkzUDzGZLhRcpmM5eW4BkuUmIO7625pM6Jd3HOGyfCGSXyEZGYYeVKzv8xbzYf 44 | QM6YYKooRN9Ya2jdcWguW0sCSJO/RZ9eaORpTeOba2+Fp6w5L7lga+XM9GLfgref 45 | Cf39XX1RsmRBsrJTw0z5COf4bT8G3/IfQP0QyKWIFITiFjGmpZhLsKQ3KT4vSe/d 46 | gTY1xViVhkjvMFn3cgSOSrvktQpAhsXx0IRazN0T7pTU33a5K0SrZajY9ynFDIw9 47 | we7XYyVwZzYEXjGih5mTH1PhWYK5fZZEKKqaz5TyYv9SeWJ+8FrHeXUKD38SQEHM 48 | qkpl9Iv17RF4Qy9uASWwRoobhKO+GykTaBSTyw8R8ctG/hfAlnaZxQ3TwNyHWyvU 49 | 9SVJsp27ulv/W9MLZtGpEMK0ckAR164Vyou1KOn200BqxbC2tJpegNeD2TP5ZtdY 50 | HIcxkgKr0haYcDnVEf1ulSxv23pZWIexbgvVCG7dRL0eB+6O28f9CWehle10MDyM 51 | 0AYyw8Da2cu7PONMovqt4nayScyGTacFBp7c2KXR9DGZ0mcBwOjL/mGRKcVWN3MG 52 | 2auCrwn2KVWmKZI3Jp0T8KhfGBnFs9lUElpDTOiED1/2bKz6Yoc385QtWx99DFMZ 53 | IWiH5wMxkWFpzjE+GHiJ09vSbTTL4JY9eu2n5nxQmtjYMBVxQm7S7qwH 54 | =0Paa 55 | -----END PGP MESSAGE----- 56 | --=-=-=-- 57 | -------------------------------------------------------------------------------- /testdata/testdir/cur/multimime!2,FS: -------------------------------------------------------------------------------- 1 | Return-path: <> 2 | Envelope-to: djcb@localhost 3 | Delivery-date: Sun, 20 May 2012 09:59:51 +0300 4 | From: Steve Jobs 5 | To: Bill Gates 6 | Subject: multimime 7 | User-agent: mu4e 0.9.8.4; emacs 23.3.1 8 | Date: Sat, 19 May 2012 20:57:56 +0100 9 | Message-ID: 10 | MIME-Version: 1.0 11 | Content-Type: multipart/mixed; boundary="=-=-=" 12 | 13 | --=-=-= 14 | Content-Type: text/plain 15 | 16 | abc 17 | --=-=-= 18 | Content-Type: application/octet-stream 19 | Content-Disposition: attachment; filename="test1.C" 20 | Content-Transfer-Encoding: base64 21 | 22 | aGVyZSBpcyBhIHNpbXBsZSB0ZXN0IGZpbGUuCg== 23 | --=-=-= 24 | Content-Type: text/plain 25 | 26 | def 27 | --=-=-=-- 28 | -------------------------------------------------------------------------------- /testdata/testdir/cur/multirecip!2,S: -------------------------------------------------------------------------------- 1 | Date: Thu, 15 May 2016 14:57:25 -0200 2 | From: 3 | To: a@example.com,b@example.com,c@example.com 4 | Cc: d@example.com,e@example.com 5 | Subject: test with multi to and cc 6 | Message-id: <3BE9E652343245@emss35m06.us.lmco.com> 7 | 8 | Message with multi cc and to. 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /testdata/testdir/cur/signed!2,S: -------------------------------------------------------------------------------- 1 | Return-path: <> 2 | Envelope-to: skipio@localhost 3 | Delivery-date: Fri, 11 May 2012 16:21:57 +0300 4 | Received: from localhost.roma.net([127.0.0.1] helo=borealis) 5 | by borealis with esmtp (Exim 4.77) 6 | id 1SSpnB-00038a-55 7 | for djcb@localhost; Fri, 11 May 2012 16:21:57 +0300 8 | Delivered-To: diggler@gmail.com 9 | From: Skipio 10 | To: Hannibal 11 | Subject: signed 12 | User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 13 | Date: Fri, 11 May 2012 16:20:45 +0300 14 | Message-ID: <878vgy97ma.fsf@roma.net> 15 | MIME-Version: 1.0 16 | Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha1; 17 | protocol="application/pgp-signature" 18 | 19 | --=-=-= 20 | Content-Type: text/plain 21 | 22 | 23 | I am signed! 24 | 25 | --=-=-= 26 | Content-Type: application/pgp-signature 27 | 28 | -----BEGIN PGP SIGNATURE----- 29 | Version: GnuPG v1.4.12 (GNU/Linux) 30 | 31 | iEYEARECAAYFAk+tEi0ACgkQ6WrHoQF92jxTzACeKd/XxY+P7bpymWL3JBRHaW9p 32 | DpwAoKw7PDW4z/lNTkWjndVTjoO9jGhs 33 | =blXz 34 | -----END PGP SIGNATURE----- 35 | --=-=-=-- 36 | 37 | -------------------------------------------------------------------------------- /testdata/testdir/cur/signed-encrypted!2,S: -------------------------------------------------------------------------------- 1 | Return-path: <> 2 | Envelope-to: karjala@localhost 3 | Delivery-date: Fri, 11 May 2012 16:37:57 +0300 4 | From: karjala@example.com 5 | To: lapinkulta@example.com 6 | Subject: signed + encrypted 7 | User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 8 | Date: Fri, 11 May 2012 16:36:08 +0300 9 | Message-ID: <874nrm96wn.fsf@example.com> 10 | MIME-Version: 1.0 11 | Content-Type: multipart/encrypted; boundary="=-=-="; 12 | protocol="application/pgp-encrypted" 13 | 14 | --=-=-= 15 | Content-Type: application/pgp-encrypted 16 | 17 | Version: 1 18 | 19 | --=-=-= 20 | Content-Type: application/octet-stream 21 | 22 | -----BEGIN PGP MESSAGE----- 23 | Version: GnuPG v1.4.12 (GNU/Linux) 24 | 25 | hQQOA1T38TPQrHD6EA/+K4kSpMa7zk+qihUkQnHSq28xYxisNQx6X5DVNjA/Qx16 26 | uZj/40ae+PoSMTVfklP+B2S/IomuTW6dwVqS7aQ3u4MTzi+YOi11k1lEMD7hR0Wb 27 | L0i48o3/iCPuCTpnOsaLZvRL06g+oTi0BF2pgz/YdsgsBTGrTb3pkDGSlLIhvh/J 28 | P8eE3OuzkXS6d8ymJKx2S2wQJrc1AFf1BgJfgc5T0iAvcV+zIMG+PIYcVd04zVpj 29 | cORFEfvGgfxWkeX+Ks3tu/l5PA1EesnoqFdNFZm+RKBg3RFsOm8tBlJ46xJjfeHg 30 | zLgifeSLy3tOX7CvWYs9torrx7s7UOI2gV8kzBqz+a7diyCMezceeQ9l0nIRybwW 31 | C9Egp8Bpfb02iXTOGdE/vRiNItQH14GKmXf4nCSwdtQUm3yzaqY9yL3xBxAlW53e 32 | YOFfPMESt+E7IlPn0c7llWGrcdrhJbUEoGOIPezES7kdeNPzi8G1lLtvT04/SSZJ 33 | QxPH5FNzSFaYFAQSdI7TR69P7L7vtLL8ndkjY49HfLFXochQQzsqrzVxzRCruHxA 34 | zbZSRptNf9SuXEaX9buO1vlFHheGvrCKzEWa6O7JD/DiyrE/zqy4jdlh9abMCouQ 35 | GWGSbn8jk6SMTQQ2Yv/VOyFqifHZp0UJD59tyIdenpxoYu5M0lwHLNVDlRjLEwUQ 36 | AIDz1tbLoM7lxs2FOKGr8QqbKIeMfL+NUmbvVIDc4mJrOlRnHh+cZYm4Z49iTl1v 37 | bYNMYgR5nY7W6rqh0ae7ZOW0h2NzpkAwTzuf1YrSjNavd9KBwOCFtAoZhRwfwFVx 38 | ju+ByHFNnf7g/R6DekHS0pSiatM0cPDJT05atEZb+13CRHHznonmLHi+VahXjrpg 39 | cIUA8Lhjdfm6Fsabo7gNZnTTRxNBqUXKK2vJF/XLbNrH5K2BH2dCCmUNtm3yFWiM 40 | DOzaw3665Y3S6MvZdyKpatbNrVoJdBpRgPxJ1YCSEituFUqHJBStay+aRb5fVkQR 41 | w3+9hWw+Ob0+2EumKbgfQ7iMwTZBCZP4VOxkoqdHvs9aWm4N7wHtXsyCew3icbJx 42 | lyUWsDx/FI+HlQRfOqeAMxmp8kKybmHNw8oGiw+uPPUHSD1NFYVm2DtwhYll3Fvs 43 | YY7r5s3yP1ZnwxMqWI3OsExVUXs8MS4UTAgO+cggO7YidPcANbBDihBFP8mTXtni 44 | Oo5n5v+/eRoLfHmnsGcaK8EkKsfFHpbqn4gxXGcBuHaTTJ/ZhbW6bi1WWZA9ExaJ 45 | IeTDtp5Bks1pJvTjCDacvgwl3rEBM6yaeIvB7575Y/GPMTOZhawhfOxV1smMmTKI 46 | JOWYb3+PuN2cvWetkjFgH8re4sRXq22DKBZHJEWYU8sH0sACAePnIr+pkrOtGeJB 47 | t1zBqZUnrupH6ptk9n/AjbQ+XSMTEKu55gSjYLAYx1EHApx52QLkdh+ej5xCIVeY 48 | 6wS1Iipkoc6/r6F7CKctupXurNY2AlD4uQIOfD6kQgkqK4PY3hsRHQA+Zqj6oRfr 49 | kxysFJZvhgt26IeBVapFs10WuYt9iHfpbPUBQUIZCLyPAh08UdVW64Uc2DvUPy+I 50 | C+3RrmTHQPP/YNKgDQaZ3ySVEDkqjaDPmXr5K0Ibaib2dtPCLcA= 51 | =pv03 52 | -----END PGP MESSAGE----- 53 | --=-=-=-- 54 | 55 | -------------------------------------------------------------------------------- /testdata/testdir/cur/special!2,Sabc: -------------------------------------------------------------------------------- 1 | Date: Thu, 1 Jun 2012 14:57:25 -0200 2 | From: "Rocky Balboa" 3 | To: "Ivan Drago" 4 | Subject: currying and tail optimization 5 | Message-id: <3BE9E653ef345@emss35m06.us.lmco.com> 6 | MIME-version: 1.0 7 | Content-type: text/plain; charset=us-ascii 8 | Content-transfer-encoding: 7BIT 9 | 10 | Test 123. I'm a special message with special flags. 11 | -------------------------------------------------------------------------------- /testdata/testdir2/Foo/cur/fraiche.eml: -------------------------------------------------------------------------------- 1 | From: Sender 2 | To: Recip 3 | Subject: search accents 4 | Date: 2012-12-08 00:48 5 | MIME-Version: 1.0 6 | Content-Type: text/plain; charset=utf-8 7 | Content-Transfer-Encoding: 8bit 8 | 9 | line 1: Глокая куздра штеко будланула бокра и курдячит бокрёнка 10 | line 2: crème fraîche 11 | -------------------------------------------------------------------------------- /testdata/testdir2/Foo/new/.noindex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djcb/mu/154a68d948c9b3e5cdd1568844b40c8343ffeebf/testdata/testdir2/Foo/new/.noindex -------------------------------------------------------------------------------- /testdata/testdir2/Foo/tmp/.noindex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djcb/mu/154a68d948c9b3e5cdd1568844b40c8343ffeebf/testdata/testdir2/Foo/tmp/.noindex -------------------------------------------------------------------------------- /testdata/testdir2/bar/.noupdate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djcb/mu/154a68d948c9b3e5cdd1568844b40c8343ffeebf/testdata/testdir2/bar/.noupdate -------------------------------------------------------------------------------- /testdata/testdir2/bar/cur/181736.eml: -------------------------------------------------------------------------------- 1 | Path: uutiset.elisa.fi!feeder2.news.elisa.fi!feeder.erje.net!newsfeed.kamp.net!newsfeed0.kamp.net!nx02.iad01.newshosting.com!newshosting.com!post01.iad!not-for-mail 2 | X-newsreader: xrn 9.03-beta-14-64bit 3 | Sender: jimbo@lews (Jimbo Foobarcuux) 4 | From: jimbo@slp53.sl.home (Jimbo Foobarcuux) 5 | Reply-To: slp53@pacbell.net 6 | Subject: Re: Are writes "atomic" to readers of the file? 7 | Newsgroups: comp.unix.programmer 8 | References: <87hbblwelr.fsf@sapphire.mobileactivedefense.com> <8762s0jreh.fsf@sapphire.mobileactivedefense.com> <87hbbjc5jt.fsf@sapphire.mobileactivedefense.com> <8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk> 9 | Organization: UseNetServer - www.usenetserver.com 10 | X-Complaints-To: abuse@usenetserver.com 11 | Message-ID: 12 | Date: 08 Mar 2011 17:04:20 GMT 13 | Lines: 27 14 | Xref: uutiset.elisa.fi comp.unix.programmer:181736 15 | 16 | John Denver writes: 17 | >Eric the Red wrote: 18 | > 19 | >>> There _IS_ a requirement that all reads and writes to regular files 20 | >>> be atomic. There is also an ordering guarantee. Any implementation 21 | >>> that doesn't provide both atomicity and ordering guarantees is broken. 22 | >> 23 | >> But where is it specified? 24 | > 25 | >The place where it is stated most explicitly is in XSH7 2.9.7 26 | >Thread Interactions with Regular File Operations: 27 | > 28 | > All of the following functions shall be atomic with respect to each 29 | > other in the effects specified in POSIX.1-2008 when they operate on 30 | > regular files or symbolic links: 31 | > 32 | > [List of functions that includes read() and write()] 33 | > 34 | > If two threads each call one of these functions, each call shall 35 | > either see all of the specified effects of the other call, or none 36 | > of them. 37 | > 38 | 39 | And, for the purposes of this paragraph, the two threads need not be 40 | part of the same process. 41 | 42 | jimbo 43 | -------------------------------------------------------------------------------- /testdata/testdir2/bar/cur/mail1: -------------------------------------------------------------------------------- 1 | Date: Thu, 31 Jul 2008 14:57:25 -0400 2 | From: "John Milton" 3 | Subject: Fere libenter homines id quod volunt credunt 4 | To: "Julius Caesar" 5 | Message-id: <3BE9E6535E3029448670913581E7A1A20D852173@emss35m06.us.lmco.com> 6 | MIME-version: 1.0 7 | x-label: Paradise losT 8 | X-Keywords: milton,john 9 | Content-type: text/plain; charset=us-ascii 10 | Content-transfer-encoding: 7BIT 11 | Precedence: high 12 | 13 | OF Mans First Disobedience, and the Fruit 14 | Of that Forbidden Tree, whose mortal tast 15 | Brought Death into the World, and all our woe, 16 | With loss of Eden, till one greater Man 17 | Restore us, and regain the blissful Seat, [ 5 ] 18 | Sing Heav'nly Muse,that on the secret top 19 | Of Oreb, or of Sinai, didst inspire 20 | That Shepherd, who first taught the chosen Seed, 21 | In the Beginning how the Heav'ns and Earth 22 | Rose out of Chaos: Or if Sion Hill [ 10 ] 23 | Delight thee more, and Siloa's Brook that flow'd 24 | Fast by the Oracle of God; I thence 25 | Invoke thy aid to my adventrous Song, 26 | That with no middle flight intends to soar 27 | Above th' Aonian Mount, while it pursues [ 15 ] 28 | Things unattempted yet in Prose or Rhime. 29 | And chiefly Thou O Spirit, that dost prefer 30 | Before all Temples th' upright heart and pure, 31 | Instruct me, for Thou know'st; Thou from the first 32 | Wast present, and with mighty wings outspread [ 20 ] 33 | Dove-like satst brooding on the vast Abyss 34 | And mad'st it pregnant: What in me is dark 35 | Illumin, what is low raise and support; 36 | That to the highth of this great Argument 37 | I may assert Eternal Providence, [ 25 ] 38 | And justifie the wayes of God to men. 39 | -------------------------------------------------------------------------------- /testdata/testdir2/bar/cur/mail2: -------------------------------------------------------------------------------- 1 | Date: Thu, 31 Jul 2008 14:57:25 -0400 2 | From: "Socrates" 3 | Subject: cool stuff 4 | To: "Alcibiades" 5 | Message-id: <3BE9E6535E0D852173@emss35m06.us.lmco.com> 6 | MIME-version: 1.0 7 | Content-type: text/plain; charset=us-ascii 8 | Content-transfer-encoding: 7BIT 9 | Precedence: high 10 | 11 | The hour of departure has arrived, and we go our ways—I to die, and you to 12 | live. Which is better God only knows. 13 | 14 | http-emacs 15 | -------------------------------------------------------------------------------- /testdata/testdir2/bar/cur/mail3: -------------------------------------------------------------------------------- 1 | From: Napoleon Bonaparte 2 | To: Edmond =?UTF-8?B?RGFudMOocw==?= 3 | Subject: rock on dude 4 | User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) 5 | Fcc: .sent 6 | MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") 7 | Content-Type: text/plain; charset=UTF-8 8 | Content-Transfer-Encoding: 8bit 9 | 10 | Le 24 février 1815, la vigie de Notre-Dame de la Garde signala le trois-mâts 11 | le Pharaon, venant de Smyrne, Trieste et Naples. 12 | 13 | Comme d'habitude, un pilote côtier partit aussitôt du port, rasa le château 14 | d'If, et alla aborder le navire entre le cap de Morgion et l'île de Rion. 15 | 16 | Aussitôt, comme d'habitude encore, la plate-forme du fort Saint-Jean s'était 17 | couverte de curieux; car c'est toujours une grande affaire à Marseille que 18 | l'arrivée d'un bâtiment, surtout quand ce bâtiment, comme le Pharaon, a été 19 | construit, gréé, arrimé sur les chantiers de la vieille Phocée, et appartient 20 | à un armateur de la ville. 21 | 22 | Cependant ce bâtiment s'avançait; il avait heureusement franchi le détroit que 23 | quelque secousse volcanique a creusé entre l'île de Calasareigne et l'île de 24 | Jaros; il avait doublé Pomègue, et il s'avançait sous ses trois huniers, son 25 | grand foc et sa brigantine, mais si lentement et d'une allure si triste, que 26 | les curieux, avec cet instinct qui pressent un malheur, se demandaient quel 27 | accident pouvait être arrivé à bord. Néanmoins les experts en navigation 28 | reconnaissaient que si un accident était arrivé, ce ne pouvait être au 29 | bâtiment lui-même; car il s'avançait dans toutes les conditions d'un navire 30 | parfaitement gouverné: son ancre était en mouillage, ses haubans de beaupré 31 | décrochés; et près du pilote, qui s'apprêtait à diriger le Pharaon par 32 | l'étroite entrée du port de Marseille, était un jeune homme au geste rapide et 33 | à l'œil actif, qui surveillait chaque mouvement du navire et répétait chaque 34 | ordre du pilote. 35 | -------------------------------------------------------------------------------- /testdata/testdir2/bar/cur/mail4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djcb/mu/154a68d948c9b3e5cdd1568844b40c8343ffeebf/testdata/testdir2/bar/cur/mail4 -------------------------------------------------------------------------------- /testdata/testdir2/bar/cur/mail5: -------------------------------------------------------------------------------- 1 | Date: Mon, 13 Jun 2011 14:57:25 -0400 2 | From: xyz@123.xx 3 | Subject: abc 4 | To: foo@bar.cx 5 | Message-id: 6 | 7 | 123 8 | -------------------------------------------------------------------------------- /testdata/testdir2/bar/cur/mail6: -------------------------------------------------------------------------------- 1 | Date: Thu, 31 Jul 2008 14:57:25 -0400 2 | From: "Geoff Tate" 3 | Subject: eyes of a stranger 4 | To: "Enrico Fermi" 5 | Message-id: <3BE9E6535E302944823E7A1A20D852173@msg.id> 6 | MIME-version: 1.0 7 | X-label: @NextActions operation:mindcrime Queensrÿche 8 | Content-type: text/plain; charset=us-ascii 9 | Content-transfer-encoding: 7BIT 10 | Precedence: high 11 | 12 | And I raise my head and stare 13 | Into the eyes of a stranger 14 | I've always known that the mirror never lies 15 | People always turn away 16 | From the eyes of a stranger 17 | Afraid to know what 18 | Lies behind the stare 19 | -------------------------------------------------------------------------------- /testdata/testdir2/bar/cur/mail7: -------------------------------------------------------------------------------- 1 | Date: Mon, 11 Sep 2023 19:57:25 -0400 2 | From: "Tommy" 3 | Subject: Hide and seek 4 | To: "Andreas" 5 | Message-id: <3BE9E65sdfklsajdfl3E7A1A20D852173@msg.id> 6 | MIME-version: 1.0 7 | 8 | Behind the polished barrier 9 | The pending storm draws near 10 | Although it's an inferno 11 | You can not step back for your fears 12 | Hurry son I need to rest 13 | finish the puzzle you do it best 14 | I'll do what I can 15 | But I am telling you 16 | It can't be done without you! 17 | -------------------------------------------------------------------------------- /testdata/testdir2/bar/new/.noindex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djcb/mu/154a68d948c9b3e5cdd1568844b40c8343ffeebf/testdata/testdir2/bar/new/.noindex -------------------------------------------------------------------------------- /testdata/testdir2/bar/tmp/.noindex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djcb/mu/154a68d948c9b3e5cdd1568844b40c8343ffeebf/testdata/testdir2/bar/tmp/.noindex -------------------------------------------------------------------------------- /testdata/testdir2/wom_bat/cur/atomic: -------------------------------------------------------------------------------- 1 | Date: Sat, 12 Nov 2011 12:06:23 -0400 2 | From: "Richard P. Feynman" 3 | Subject: atoms 4 | To: "Democritus" 5 | Message-id: <3BE9E6535E302944823E7A1A20D852173@msg.id> 6 | MIME-version: 1.0 7 | Content-Type: text/plain; charset=UTF-8 8 | Content-Transfer-Encoding: 8bit 9 | Precedence: high 10 | 11 | If, in some cataclysm, all scientific knowledge were to be destroyed, 12 | and only one sentence passed on to the next generation of creatures, 13 | what statement would contain the most information in the fewest words? 14 | I believe it is the atomic hypothesis (or atomic fact, or whatever you 15 | wish to call it) that all things are made of atoms — little particles 16 | that move around in perpetual motion, attracting each other when they 17 | are a little distance apart, but repelling upon being squeezed into 18 | one another. In that one sentence you will see an enormous amount of 19 | information about the world, if just a little imagination and thinking 20 | are applied. 21 | -------------------------------------------------------------------------------- /testdata/testdir2/wom_bat/cur/rfc822.1: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Subject: Fwd: rfc822 3 | From: foobar 4 | To: martin 5 | Content-Type: multipart/mixed; boundary="=-XHhVx/BCC6tJB87HLPqF" 6 | Message-Id: <1077300332.871.27.camel@example.com> 7 | Mime-Version: 1.0 8 | X-Mailer: Ximian Evolution 1.4.5 9 | Date: Fri, 20 Feb 2004 19:05:33 +0100 10 | 11 | --=-XHhVx/BCC6tJB87HLPqF 12 | Content-Type: text/plain 13 | Content-Transfer-Encoding: 7bit 14 | 15 | Hello world, forwarding some RFC822 message 16 | 17 | --=-XHhVx/BCC6tJB87HLPqF 18 | Content-Disposition: inline 19 | Content-Type: message/rfc822 20 | 21 | Return-Path: 22 | Message-ID: <9A01B19D0D605D478E8B72E1367C66340141B9C5@example.com> 23 | From: frob@example.com 24 | To: foo@example.com 25 | Subject: hopjesvla 26 | Date: Sat, 13 Dec 2003 19:35:56 +0100 27 | MIME-Version: 1.0 28 | Content-Type: text/plain; charset=iso-8859-1 29 | Content-Transfer-Encoding: 7bit 30 | 31 | The ship drew on and had safely passed the strait, which some volcanic shock 32 | has made between the Calasareigne and Jaros islands; had doubled Pomegue, and 33 | approached the harbor under topsails, jib, and spanker, but so slowly and 34 | sedately that the idlers, with that instinct which is the forerunner of evil, 35 | asked one another what misfortune could have happened on board. However, those 36 | experienced in navigation saw plainly that if any accident had occurred, it was 37 | not to the vessel herself, for she bore down with all the evidence of being 38 | skilfully handled, the anchor a-cockbill, the jib-boom guys already eased off, 39 | and standing by the side of the pilot, who was steering the Pharaon towards the 40 | narrow entrance of the inner port, was a young man, who, with activity and 41 | vigilant eye, watched every motion of the ship, and repeated each direction of 42 | the pilot. 43 | 44 | --=-XHhVx/BCC6tJB87HLPqF-- 45 | -------------------------------------------------------------------------------- /testdata/testdir2/wom_bat/cur/rfc822.2: -------------------------------------------------------------------------------- 1 | From: dwarf@siblings.net 2 | To: root@eruditorum.org 3 | Subject: Fwd: test abc 4 | References: <8639ddr9wu.fsf@cthulhu.djcbsoftware> 5 | User-agent: mu 0.98pre; emacs 24.0.91.9 6 | Date: Thu, 24 Nov 2011 14:24:00 +0200 7 | Message-ID: <861usxr9nj.fsf@cthulhu.djcbsoftware> 8 | Content-Type: multipart/mixed; boundary="=-=-=" 9 | MIME-Version: 1.0 10 | 11 | --=-=-= 12 | Content-Type: text/plain 13 | 14 | Saw the website. Am willing to stipulate that you are not RIST 9E03. Suspect 15 | that you are the Dentist, who yearns for honest exchange of views. Anonymous, 16 | digitally signed e-mail is the only safe vehicle for same. 17 | 18 | If you want me to believe you are not the Dentist, provide plausible 19 | explanation for your question regarding why we are building the Crypt. 20 | 21 | Yours truly, 22 | 23 | --=-=-= 24 | Content-Type: message/rfc822 25 | Content-Disposition: inline; filename= 26 | "1322137188_3.11919.foo:2,S" 27 | Content-Description: rfc822 28 | 29 | From: dwarf@siblings.net 30 | To: root@eruditorum.org 31 | Subject: test abc 32 | User-agent: mu 0.98pre; emacs 24.0.91.9 33 | Date: Thu, 24 Nov 2011 14:18:25 +0200 34 | Message-ID: <8639ddr9wu.fsf@cthulhu.djcbsoftware> 35 | Content-Type: text/plain 36 | MIME-Version: 1.0 37 | 38 | As I stepped on this unknown middle-aged Filipina's feet during an ill-advised 39 | ballroom dancing foray, she leaned close to me and uttered some latitude and 40 | longitude figures with a conspicuously large number of significant digits of 41 | precision, implying a maximum positional error on the order of the size of a 42 | dinner plate. Gosh, was I ever curious! 43 | 44 | --=-=-=-- 45 | -------------------------------------------------------------------------------- /testdata/testdir4/1220863087.12663_19.mindcrime!2,S: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime 3 | X-Spam-Level: 4 | X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00 autolearn=ham 5 | version=3.2.5 6 | X-Original-To: xxxx@localhost 7 | Delivered-To: xxxx@localhost 8 | Received: from mindcrime (localhost [127.0.0.1]) 9 | by mail.xxxxsoftware.nl (Postfix) with ESMTP id C4D6569CB3 10 | for ; Thu, 7 Aug 2008 08:10:08 +0300 (EEST) 11 | Delivered-To: xxxx.klub@gmail.com 12 | Received: from gmail-imap.l.google.com [66.249.91.109] 13 | by mindcrime with IMAP (fetchmail-6.3.8) 14 | for (single-drop); Thu, 07 Aug 2008 08:10:08 +0300 (EEST) 15 | Received: by 10.142.237.21 with SMTP id k21cs34794wfh; Wed, 6 Aug 2008 16 | 13:40:29 -0700 (PDT) 17 | Received: by 10.100.33.13 with SMTP id g13mr1093301ang.79.1218055228418; Wed, 18 | 06 Aug 2008 13:40:28 -0700 (PDT) 19 | Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by mx.google.com 20 | with ESMTP id d19si15908789and.17.2008.08.06.13.40.27; Wed, 06 Aug 2008 21 | 13:40:28 -0700 (PDT) 22 | Received-SPF: pass (google.com: domain of 23 | help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 24 | as permitted sender) client-ip=199.232.76.165; 25 | Authentication-Results: mx.google.com; spf=pass (google.com: domain of 26 | help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 27 | as permitted sender) 28 | smtp.mail=help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org 29 | Received: from localhost ([127.0.0.1]:56316 helo=lists.gnu.org) by 30 | lists.gnu.org with esmtp (Exim 4.43) id 1KQpo3-0007Pc-Qk for 31 | xxxx.klub@gmail.com; Wed, 06 Aug 2008 16:40:27 -0400 32 | From: anon@example.com 33 | Newsgroups: gnu.emacs.help 34 | Date: Wed, 6 Aug 2008 20:38:35 +0100 35 | Message-ID: 36 | References: <55dbm5-qcl.ln1@news.ducksburg.com> 37 | 38 | Mime-Version: 1.0 39 | Content-Type: text/plain; charset=us-ascii 40 | Content-Transfer-Encoding: 7bit 41 | X-Trace: individual.net bABVU1hcJwWAuRwe/097AAoOXnGGeYR8G1In635iFGIyfDLPUv 42 | X-Orig-Path: news.ducksburg.com!news 43 | Cancel-Lock: sha1:wK7dsPRpNiVxpL/SfvmNzlvUR94= 44 | sha1:oepBoM0tJBLN52DotWmBBvW5wbg= 45 | User-Agent: slrn/pre0.9.9-120/mm/ao (Ubuntu Hardy) 46 | Path: news.stanford.edu!headwall.stanford.edu!newshub.sdsu.edu!feeder.erje.net!proxad.net!feeder1-2.proxad.net!feed.ac-versailles.fr!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail 47 | Xref: news.stanford.edu gnu.emacs.help:160868 48 | To: help-gnu-emacs@gnu.org 49 | Subject: Re: Learning LISP; Scheme vs elisp. 50 | X-BeenThere: help-gnu-emacs@gnu.org 51 | X-Mailman-Version: 2.1.5 52 | Precedence: list 53 | List-Id: Users list for the GNU Emacs text editor 54 | List-Unsubscribe: , 55 | 56 | List-Archive: 57 | List-Post: 58 | List-Help: 59 | List-Subscribe: , 60 | 61 | Sender: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org 62 | Errors-To: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org 63 | Content-Length: 417 64 | Lines: 11 65 | 66 | On 2008-08-01, Thien-Thi Nguyen wrote: 67 | 68 | > warriors attack, felling foe after foe, 69 | > few growing old til they realize: to know 70 | > what deceit is worth deflection; 71 | > such receipt reversed rejection! 72 | > then their heavy arms, e'er transformed to shields: 73 | > balanced hooked charms, ploughed deep, rich yields. 74 | 75 | Aha: the exercise for the reader is to place the parens correctly. 76 | Might take me a while to solve this puzzle. 77 | 78 | -------------------------------------------------------------------------------- /testdata/testdir4/1252168370_3.14675.cthulhu!2,S: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on mindcrime 3 | X-Spam-Level: 4 | Delivered-To: dfgh@floppydisk.nl 5 | Message-ID: <43A09C49.9040902@euler.org> 6 | Date: Wed, 14 Dec 2005 23:27:21 +0100 7 | From: Fred Flintstone 8 | User-Agent: Mozilla Thunderbird 1.0.7 (X11/20051010) 9 | X-Accept-Language: nl-NL, nl, en 10 | MIME-Version: 1.0 11 | To: dfgh@floppydisk.nl 12 | List-Id: =?utf-8?q?Example_of_List_Id?= 13 | Subject: Re: xyz 14 | References: <439C1136.90504@euler.org> <4399DD94.5070309@euler.org> <20051209233303.GA13812@gauss.org> <439B41ED.2080402@euler.org> <4399DD94.5070309@euler.org> <20051209233303.GA13812@gauss.org> <439A1E03.3090604@euler.org> <20051211184308.GB13513@gauss.org> 15 | In-Reply-To: <20051211184308.GB13513@gauss.org> 16 | X-Enigmail-Version: 0.92.0.0 17 | Content-Type: text/plain; charset=UTF-8 18 | Content-Transfer-Encoding: 7bit 19 | X-UIDL: T 2 | To: Bilbo Baggins 3 | Subject: Greetings from =?UTF-8?B?TG90aGzDs3JpZW4=?= 4 | User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) 5 | Fcc: .sent 6 | Organization: The Fellowship of the Ring 7 | MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") 8 | Content-Type: text/plain; charset=UTF-8 9 | Content-Transfer-Encoding: 8bit 10 | 11 | 12 | Let's write some fünkÿ text 13 | using umlauts. 14 | 15 | Foo. 16 | -------------------------------------------------------------------------------- /testdata/testdir4/1305664394.2171_402.cthulhu!2,: -------------------------------------------------------------------------------- 1 | From: =?UTF-8?B?TcO8?= 2 | To: Helmut =?UTF-8?B?S3LDtmdlcg==?= 3 | Subject: =?UTF-8?B?TW90w7ZyaGVhZA==?= 4 | User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) 5 | References: 6 | 1n-Reply-To: 7 | MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") 8 | Content-Type: text/plain; charset=UTF-8 9 | Content-Transfer-Encoding: 8bit 10 | 11 | 12 | Test for issue #38, where apparently searching for accented words in subject, 13 | to etc. fails. 14 | 15 | What about here? Queensrÿche. Mötley Crüe. 16 | 17 | 18 | -------------------------------------------------------------------------------- /testdata/testdir4/181736.eml: -------------------------------------------------------------------------------- 1 | Path: uutiset.elisa.fi!feeder2.news.elisa.fi!feeder.erje.net!newsfeed.kamp.net!newsfeed0.kamp.net!nx02.iad01.newshosting.com!newshosting.com!post01.iad!not-for-mail 2 | X-newsreader: xrn 9.03-beta-14-64bit 3 | Sender: jimbo@lews (Jimbo Foobarcuux) 4 | From: jimbo@slp53.sl.home (Jimbo Foobarcuux) 5 | Reply-To: slp53@pacbell.net 6 | Subject: Re: Are writes "atomic" to readers of the file? 7 | Newsgroups: comp.unix.programmer 8 | References: <87hbblwelr.fsf@sapphire.mobileactivedefense.com> <8762s0jreh.fsf@sapphire.mobileactivedefense.com> <87hbbjc5jt.fsf@sapphire.mobileactivedefense.com> <8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk> 9 | Organization: UseNetServer - www.usenetserver.com 10 | X-Complaints-To: abuse@usenetserver.com 11 | Message-ID: 12 | Date: 08 Mar 2011 17:04:20 GMT 13 | Lines: 27 14 | Xref: uutiset.elisa.fi comp.unix.programmer:181736 15 | 16 | John Denver writes: 17 | >Eric the Red wrote: 18 | > 19 | >>> There _IS_ a requirement that all reads and writes to regular files 20 | >>> be atomic. There is also an ordering guarantee. Any implementation 21 | >>> that doesn't provide both atomicity and ordering guarantees is broken. 22 | >> 23 | >> But where is it specified? 24 | > 25 | >The place where it is stated most explicitly is in XSH7 2.9.7 26 | >Thread Interactions with Regular File Operations: 27 | > 28 | > All of the following functions shall be atomic with respect to each 29 | > other in the effects specified in POSIX.1-2008 when they operate on 30 | > regular files or symbolic links: 31 | > 32 | > [List of functions that includes read() and write()] 33 | > 34 | > If two threads each call one of these functions, each call shall 35 | > either see all of the specified effects of the other call, or none 36 | > of them. 37 | > 38 | 39 | And, for the purposes of this paragraph, the two threads need not be 40 | part of the same process. 41 | 42 | jimbo 43 | -------------------------------------------------------------------------------- /testdata/testdir4/encrypted!2,S: -------------------------------------------------------------------------------- 1 | Return-path: <> 2 | Envelope-to: peter@example.com 3 | Delivery-date: Fri, 11 May 2012 16:22:03 +0300 4 | Received: from localhost.example.com ([127.0.0.1] helo=borealis) 5 | by borealis with esmtp (Exim 4.77) 6 | id 1SSpnB-00038a-Ux 7 | for djcb@localhost; Fri, 11 May 2012 16:21:58 +0300 8 | Delivered-To: peter@example.com 9 | From: Brian 10 | To: Peter 11 | Subject: encrypted 12 | User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 13 | Date: Fri, 11 May 2012 16:21:42 +0300 14 | Message-ID: <877gwi97kp.fsf@example.com> 15 | MIME-Version: 1.0 16 | Content-Type: multipart/encrypted; boundary="=-=-="; 17 | protocol="application/pgp-encrypted" 18 | 19 | --=-=-= 20 | Content-Type: application/pgp-encrypted 21 | 22 | Version: 1 23 | 24 | --=-=-= 25 | Content-Type: application/octet-stream 26 | 27 | -----BEGIN PGP MESSAGE----- 28 | Version: GnuPG v1.4.12 (GNU/Linux) 29 | 30 | hQQOA1T38TPQrHD6EA//YXkUB4Dy09ngCRyHWbXmV3XBjuKTr8xrak5ML1kwurav 31 | gyagOHKLMU+5CKvObChiKtXhtgU0od7IC8o+ALlHevQ0XXcqNYA2KUfX8R7akq7d 32 | Xx9mA6D8P7Y/P8juUCLBpfrCi2GC42DtvPZSUu3bL/ctUJ3InPHIfHibKF2HMm7/ 33 | gUHAKY8VPJF39dLP8GLcfki6qFdeWbxgtzmuyzHfCBCLnDL0J9vpEQBpGDFMcc4v 34 | cCbmMJaiPOmRb6U4WOuRVnuXuTztLiIn0jMslzOSFDcLTVBAsrC01r71O+XZKfN4 35 | mIfcpcWJYKM2NQW8Jwf+8Hr84uznBqs8uTTlrmppjkAHZGqGMjiQDxLhDVaCQzMy 36 | O8PSV4xT6HPlKXOwV1OLc+vm0A0RAdSBctgZg40oFn4XdB1ur8edwAkLvc0hJKaz 37 | gyTQiPaXm2Uh2cDeEx4xNgXmwCKasqc9jAlnDC2QwA33+pw3OqgZT5h1obn0fAeR 38 | mgB+iW1503DIi/96p8HLZcr2EswLEH9ViHIEaFj/vlR5BaOncsLB0SsNV/MHRvym 39 | Xg5GUjzPIiyBZ3KaR9OIBiZ5eXw+bSrPAo/CAs0Zwxag7W3CH//oK39Qo1GnkYpc 40 | 4IQxhx4IwkzqtCnripltV/kfpGu0yA/OdK8lOjkUqCwvL97o73utXIxm21Zd3mEP 41 | /iLNrduZjMCq+goz1pDAQa9Dez6VjwRuRPTqeAac8Fx/nzrVzIoIEAt36hpuaH1l 42 | KpbmHpKgsUWcrE5iYT0RRlRRtRF4PfJg8PUmP1hvw8TaEmNfT+0HgzcJB/gRsVdy 43 | gTzkzUDzGZLhRcpmM5eW4BkuUmIO7625pM6Jd3HOGyfCGSXyEZGYYeVKzv8xbzYf 44 | QM6YYKooRN9Ya2jdcWguW0sCSJO/RZ9eaORpTeOba2+Fp6w5L7lga+XM9GLfgref 45 | Cf39XX1RsmRBsrJTw0z5COf4bT8G3/IfQP0QyKWIFITiFjGmpZhLsKQ3KT4vSe/d 46 | gTY1xViVhkjvMFn3cgSOSrvktQpAhsXx0IRazN0T7pTU33a5K0SrZajY9ynFDIw9 47 | we7XYyVwZzYEXjGih5mTH1PhWYK5fZZEKKqaz5TyYv9SeWJ+8FrHeXUKD38SQEHM 48 | qkpl9Iv17RF4Qy9uASWwRoobhKO+GykTaBSTyw8R8ctG/hfAlnaZxQ3TwNyHWyvU 49 | 9SVJsp27ulv/W9MLZtGpEMK0ckAR164Vyou1KOn200BqxbC2tJpegNeD2TP5ZtdY 50 | HIcxkgKr0haYcDnVEf1ulSxv23pZWIexbgvVCG7dRL0eB+6O28f9CWehle10MDyM 51 | 0AYyw8Da2cu7PONMovqt4nayScyGTacFBp7c2KXR9DGZ0mcBwOjL/mGRKcVWN3MG 52 | 2auCrwn2KVWmKZI3Jp0T8KhfGBnFs9lUElpDTOiED1/2bKz6Yoc385QtWx99DFMZ 53 | IWiH5wMxkWFpzjE+GHiJ09vSbTTL4JY9eu2n5nxQmtjYMBVxQm7S7qwH 54 | =0Paa 55 | -----END PGP MESSAGE----- 56 | --=-=-=-- 57 | 58 | -------------------------------------------------------------------------------- /testdata/testdir4/mail1: -------------------------------------------------------------------------------- 1 | Date: Thu, 31 Jul 2008 14:57:25 -0400 2 | From: "John Milton" 3 | Subject: Fere libenter homines id quod volunt credunt 4 | To: "Julius Caesar" 5 | Message-id: <3BE9E6535E3029448670913581E7A1A20D852173@emss35m06.us.lmco.com> 6 | MIME-version: 1.0 7 | x-label: Paradise losT 8 | X-keywords: john, milton 9 | Content-type: text/plain; charset=us-ascii 10 | Content-transfer-encoding: 7BIT 11 | Precedence: high 12 | 13 | OF Mans First Disobedience, and the Fruit 14 | Of that Forbidden Tree, whose mortal tast 15 | Brought Death into the World, and all our woe, 16 | With loss of Eden, till one greater Man 17 | Restore us, and regain the blissful Seat, [ 5 ] 18 | Sing Heav'nly Muse,that on the secret top 19 | Of Oreb, or of Sinai, didst inspire 20 | That Shepherd, who first taught the chosen Seed, 21 | In the Beginning how the Heav'ns and Earth 22 | Rose out of Chaos: Or if Sion Hill [ 10 ] 23 | Delight thee more, and Siloa's Brook that flow'd 24 | Fast by the Oracle of God; I thence 25 | Invoke thy aid to my adventrous Song, 26 | That with no middle flight intends to soar 27 | Above th' Aonian Mount, while it pursues [ 15 ] 28 | Things unattempted yet in Prose or Rhime. 29 | And chiefly Thou O Spirit, that dost prefer 30 | Before all Temples th' upright heart and pure, 31 | Instruct me, for Thou know'st; Thou from the first 32 | Wast present, and with mighty wings outspread [ 20 ] 33 | Dove-like satst brooding on the vast Abyss 34 | And mad'st it pregnant: What in me is dark 35 | Illumin, what is low raise and support; 36 | That to the highth of this great Argument 37 | I may assert Eternal Providence, [ 25 ] 38 | And justifie the wayes of God to men. 39 | -------------------------------------------------------------------------------- /testdata/testdir4/multimime!2,FS: -------------------------------------------------------------------------------- 1 | Return-path: <> 2 | Envelope-to: djcb@localhost 3 | Delivery-date: Sun, 20 May 2012 09:59:51 +0300 4 | From: Steve Jobs 5 | To: Bill Gates 6 | Subject: multimime 7 | User-agent: mu4e 0.9.8.4; emacs 23.3.1 8 | Date: Sat, 19 May 2012 20:57:56 +0100 9 | Message-ID: 10 | MIME-Version: 1.0 11 | Content-Type: multipart/mixed; boundary="=-=-=" 12 | 13 | --=-=-= 14 | Content-Type: text/plain 15 | 16 | abc 17 | --=-=-= 18 | Content-Type: application/octet-stream 19 | Content-Disposition: attachment; filename="test1.C" 20 | Content-Transfer-Encoding: base64 21 | 22 | aGVyZSBpcyBhIHNpbXBsZSB0ZXN0IGZpbGUuCg== 23 | --=-=-= 24 | Content-Type: text/plain 25 | 26 | def 27 | --=-=-=-- 28 | -------------------------------------------------------------------------------- /testdata/testdir4/signed!2,S: -------------------------------------------------------------------------------- 1 | User-agent: mu4e 1.1.0; emacs 27.0.50 2 | From: Skipio 3 | To: Hannibal 4 | Subject: test 123 5 | Date: Sun, 24 Mar 2019 11:50:42 +0200 6 | Message-ID: <87zhpky51p.fsf@djcbsoftware.nl> 7 | MIME-Version: 1.0 8 | Content-Type: multipart/signed; boundary="=-=-="; 9 | micalg=pgp-sha256; protocol="application/pgp-signature" 10 | 11 | --=-=-= 12 | Content-Type: text/plain 13 | 14 | 15 | I am signed! 16 | 17 | --=-=-= 18 | Content-Type: application/pgp-signature; name="signature.asc" 19 | 20 | -----BEGIN PGP SIGNATURE----- 21 | 22 | iQIzBAEBCAAdFiEEaYec7RdFk3UPFNqYEd3+qdzEoDYFAlyXUwAACgkQEd3+qdzE 23 | oDbjdw//dAosaEyqSfyUMXjS++iJEeDIwKwO6AjEI0xCbJjHmxq93PA61ApE/BS3 24 | d/sKa1dsfN+plRS+Fh3NNGSA7evar9dXtMBUr6hwL0VTmm5NDwedaPeuW6mgyVcB 25 | VNUn5x1e/QdnSClapnGd156sryfcM1pg/667fTHT6WC01Xe0sezpkV9l0j4pslYt 26 | y6ud/Hejszax+NcwQY7vkCcVWfB9K4zbiapdoCjHi78S4YAcsbd//KmePOqn04Sa 27 | Tg1XsmMzIh7L/3njkJdIOd9XctTwYEcN5geY1QKrHQ/3+gBeaEYvwsvrnqnVKqMY 28 | WCg/aYibuXl+xNkPMcKHIj1dXA3m5MkL77RrxODiAYz0YkiQx1/DLZs8PV3IVoB4 29 | f0GGDqyiOwSmSDa4iuCottwO4yG1WM1i7r6pir22qAekIt43wSdwakOrT1IkS8q2 30 | o0VGiQtEPy27D+ufiw06t02Ryf20Q7i2YcueZxYeRBq41m11M41DJ4wH7LQcJsww 31 | qG5iBOdwQFCTWpi1UrbbFjlxXXWvKMuIU+4k7nsamrEL4SDXmq1v13vtlcgJ6vnn 32 | v7c9+MF7laqdfI+BYnlD1v/9LosPbFTm0hPdvK4yIOORp8Iwj/1PGzTOz6SCUxzA 33 | kDu+Y+NN9/SM1ppStg1OikYPcfEXF8igWhuORwqcmpgHxVkIQ9I= 34 | =wnkU 35 | -----END PGP SIGNATURE----- 36 | --=-=-=-- 37 | -------------------------------------------------------------------------------- /testdata/testdir4/signed-bad!2,S: -------------------------------------------------------------------------------- 1 | Return-path: <> 2 | Envelope-to: skipio@localhost 3 | Delivery-date: Fri, 11 May 2012 16:21:57 +0300 4 | Received: from localhost.roma.net([127.0.0.1] helo=borealis) 5 | by borealis with esmtp (Exim 4.77) 6 | id 1SSpnB-00038a-55 7 | for djcb@localhost; Fri, 11 May 2012 16:21:57 +0300 8 | From: Skipio 9 | To: Hannibal 10 | Subject: signed 11 | User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 12 | Date: Fri, 11 May 2012 16:20:45 +0300 13 | Message-ID: <878vgy97ma.fsf@roma.net> 14 | MIME-Version: 1.0 15 | Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha1; 16 | protocol="application/pgp-signature" 17 | 18 | --=-=-= 19 | Content-Type: text/plain 20 | 21 | 22 | I am signed! But it's not good because I added this later 23 | 24 | --=-=-= 25 | Content-Type: application/pgp-signature 26 | 27 | -----BEGIN PGP SIGNATURE----- 28 | Version: GnuPG v1.4.12 (GNU/Linux) 29 | 30 | iEYEARECAAYFAk+tEi0ACgkQ6WrHoQF92jxTzACeKd/XxY+P7bpymWL3JBRHaW9p 31 | DpwAoKw7PDW4z/lNTkWjndVTjoO9jGhs 32 | =blXz 33 | -----END PGP SIGNATURE----- 34 | --=-=-=-- 35 | 36 | -------------------------------------------------------------------------------- /testdata/testdir4/signed-encrypted!2,S: -------------------------------------------------------------------------------- 1 | Return-path: <> 2 | Envelope-to: karjala@localhost 3 | Delivery-date: Fri, 11 May 2012 16:37:57 +0300 4 | From: karjala@example.com 5 | To: lapinkulta@example.com 6 | Subject: signed + encrypted 7 | User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 8 | Date: Fri, 11 May 2012 16:36:08 +0300 9 | Message-ID: <874nrm96wn.fsf@example.com> 10 | MIME-Version: 1.0 11 | Content-Type: multipart/encrypted; boundary="=-=-="; 12 | protocol="application/pgp-encrypted" 13 | 14 | --=-=-= 15 | Content-Type: application/pgp-encrypted 16 | 17 | Version: 1 18 | 19 | --=-=-= 20 | Content-Type: application/octet-stream 21 | 22 | -----BEGIN PGP MESSAGE----- 23 | Version: GnuPG v1.4.12 (GNU/Linux) 24 | 25 | hQQOA1T38TPQrHD6EA/+K4kSpMa7zk+qihUkQnHSq28xYxisNQx6X5DVNjA/Qx16 26 | uZj/40ae+PoSMTVfklP+B2S/IomuTW6dwVqS7aQ3u4MTzi+YOi11k1lEMD7hR0Wb 27 | L0i48o3/iCPuCTpnOsaLZvRL06g+oTi0BF2pgz/YdsgsBTGrTb3pkDGSlLIhvh/J 28 | P8eE3OuzkXS6d8ymJKx2S2wQJrc1AFf1BgJfgc5T0iAvcV+zIMG+PIYcVd04zVpj 29 | cORFEfvGgfxWkeX+Ks3tu/l5PA1EesnoqFdNFZm+RKBg3RFsOm8tBlJ46xJjfeHg 30 | zLgifeSLy3tOX7CvWYs9torrx7s7UOI2gV8kzBqz+a7diyCMezceeQ9l0nIRybwW 31 | C9Egp8Bpfb02iXTOGdE/vRiNItQH14GKmXf4nCSwdtQUm3yzaqY9yL3xBxAlW53e 32 | YOFfPMESt+E7IlPn0c7llWGrcdrhJbUEoGOIPezES7kdeNPzi8G1lLtvT04/SSZJ 33 | QxPH5FNzSFaYFAQSdI7TR69P7L7vtLL8ndkjY49HfLFXochQQzsqrzVxzRCruHxA 34 | zbZSRptNf9SuXEaX9buO1vlFHheGvrCKzEWa6O7JD/DiyrE/zqy4jdlh9abMCouQ 35 | GWGSbn8jk6SMTQQ2Yv/VOyFqifHZp0UJD59tyIdenpxoYu5M0lwHLNVDlRjLEwUQ 36 | AIDz1tbLoM7lxs2FOKGr8QqbKIeMfL+NUmbvVIDc4mJrOlRnHh+cZYm4Z49iTl1v 37 | bYNMYgR5nY7W6rqh0ae7ZOW0h2NzpkAwTzuf1YrSjNavd9KBwOCFtAoZhRwfwFVx 38 | ju+ByHFNnf7g/R6DekHS0pSiatM0cPDJT05atEZb+13CRHHznonmLHi+VahXjrpg 39 | cIUA8Lhjdfm6Fsabo7gNZnTTRxNBqUXKK2vJF/XLbNrH5K2BH2dCCmUNtm3yFWiM 40 | DOzaw3665Y3S6MvZdyKpatbNrVoJdBpRgPxJ1YCSEituFUqHJBStay+aRb5fVkQR 41 | w3+9hWw+Ob0+2EumKbgfQ7iMwTZBCZP4VOxkoqdHvs9aWm4N7wHtXsyCew3icbJx 42 | lyUWsDx/FI+HlQRfOqeAMxmp8kKybmHNw8oGiw+uPPUHSD1NFYVm2DtwhYll3Fvs 43 | YY7r5s3yP1ZnwxMqWI3OsExVUXs8MS4UTAgO+cggO7YidPcANbBDihBFP8mTXtni 44 | Oo5n5v+/eRoLfHmnsGcaK8EkKsfFHpbqn4gxXGcBuHaTTJ/ZhbW6bi1WWZA9ExaJ 45 | IeTDtp5Bks1pJvTjCDacvgwl3rEBM6yaeIvB7575Y/GPMTOZhawhfOxV1smMmTKI 46 | JOWYb3+PuN2cvWetkjFgH8re4sRXq22DKBZHJEWYU8sH0sACAePnIr+pkrOtGeJB 47 | t1zBqZUnrupH6ptk9n/AjbQ+XSMTEKu55gSjYLAYx1EHApx52QLkdh+ej5xCIVeY 48 | 6wS1Iipkoc6/r6F7CKctupXurNY2AlD4uQIOfD6kQgkqK4PY3hsRHQA+Zqj6oRfr 49 | kxysFJZvhgt26IeBVapFs10WuYt9iHfpbPUBQUIZCLyPAh08UdVW64Uc2DvUPy+I 50 | C+3RrmTHQPP/YNKgDQaZ3ySVEDkqjaDPmXr5K0Ibaib2dtPCLcA= 51 | =pv03 52 | -----END PGP MESSAGE----- 53 | --=-=-=-- 54 | 55 | -------------------------------------------------------------------------------- /testdata/testdir4/special!2,Sabc: -------------------------------------------------------------------------------- 1 | Date: Thu, 1 Jun 2012 14:57:25 -0200 2 | From: "Rocky Balboa" 3 | To: "Ivan Drago" 4 | Subject: currying and tail optimization 5 | Message-id: <3BE9E653ef345@emss35m06.us.lmco.com> 6 | MIME-version: 1.0 7 | Content-type: text/plain; charset=us-ascii 8 | Content-transfer-encoding: 7BIT 9 | 10 | Test 123. I'm a special message with special flags. 11 | -------------------------------------------------------------------------------- /thirdparty/fmt/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | --- Optional exception to the license --- 23 | 24 | As an exception, if, as a result of your compiling your source code, portions 25 | of this Software are embedded into a machine-executable object form of such 26 | source code, you may redistribute such embedded portions in such object form 27 | without including the above copyright and permission notices. 28 | -------------------------------------------------------------------------------- /thirdparty/fmt/core.h: -------------------------------------------------------------------------------- 1 | // This file is only provided for compatibility and may be removed in future 2 | // versions. Use fmt/base.h if you don't need fmt::format and fmt/format.h 3 | // otherwise. 4 | 5 | #include "format.h" 6 | --------------------------------------------------------------------------------