commit a2dd9d683a02525183b5e692e42622c65639dda8 (HEAD, refs/remotes/origin/master) Merge: 9d47364634 32ef7550ed Author: Stefan Kangas Date: Sun Oct 9 06:31:06 2022 +0200 Merge from origin/emacs-28 32ef7550ed ; Improve documentation of 'file-in-directory-p' commit 9d47364634f96b2f2651a7f3942f8f87b920f02d Author: Stefan Monnier Date: Sat Oct 8 23:06:03 2022 -0400 * lisp/url/url-file.el (url-file): Don't bind `coding-system-for-read` Binding it causes errors when some of the enclosed code ends up loading a `.el` file, and it is unnecessary since the rest of the code (in `url-file-asynch-callback`) is already careful to use `insert-file-contents-literally`. diff --git a/lisp/url/url-file.el b/lisp/url/url-file.el index a72b2e67a6..6258e999c1 100644 --- a/lisp/url/url-file.el +++ b/lisp/url/url-file.el @@ -150,7 +150,6 @@ it up to them." (uncompressed-filename nil) (content-type nil) (content-encoding nil) - (coding-system-for-read 'binary) (filename (url-file-build-filename url))) (or filename (error "File does not exist: %s" (url-recreate-url url))) ;; Need to figure out the content-type from the real extension, commit 81eb7c1809423966975b67a62c8945267d05b1ae Author: Mattias Engdegård Date: Sat Oct 8 18:39:48 2022 +0200 ; * test/src/fns-tests.el (fns-tests--string-lessp-cases): Extend. diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index 9a2bd5cef3..5d5d497c99 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -152,6 +152,8 @@ (,(string-to-multibyte "abc") < "abd") (,(string-to-multibyte "abc") < ,(string-to-multibyte "abd")) (,(string-to-multibyte "\x80") = ,(string-to-multibyte "\x80")) + ("Liberté, Égalité, Fraternité" = "Liberté, Égalité, Fraternité") + ("Liberté, Égalité, Fraternité" < "Liberté, Égalité, Sororité") ;; Cases concerning the ordering of raw bytes: these are ;; troublesome because the current `string<' order is not very useful as commit e4769b20f166aeb78d66d1ac1db4628f72683372 Author: Mattias Engdegård Date: Sat Oct 8 15:25:50 2022 +0200 Restrict string-lessp vectorisation to safe architectures * src/fns.c (HAVE_FAST_UNALIGNED_ACCESS): New. (Fstring_lessp): Only use word operations where safe, because string data from purespace may be unaligned. diff --git a/src/fns.c b/src/fns.c index bc4915eb25..5eab35a564 100644 --- a/src/fns.c +++ b/src/fns.c @@ -433,6 +433,21 @@ If string STR1 is greater, the value is a positive number N; return Qt; } +/* Check whether the platform allows access to unaligned addresses for + size_t integers without trapping or undue penalty (a few cycles is OK). + + This whitelist is incomplete but since it is only used to improve + performance, omitting cases is safe. */ +#if defined __x86_64__|| defined __amd64__ \ + || defined __i386__ || defined __i386 \ + || defined __arm64__ || defined __aarch64__ \ + || defined __powerpc__ || defined __powerpc \ + || defined __ppc__ || defined __ppc +#define HAVE_FAST_UNALIGNED_ACCESS 1 +#else +#define HAVE_FAST_UNALIGNED_ACCESS 0 +#endif + DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, doc: /* Return non-nil if STRING1 is less than STRING2 in lexicographic order. Case is significant. @@ -468,18 +483,23 @@ Symbols are also allowed; their print names are used instead. */) ptrdiff_t nb1 = SBYTES (string1); ptrdiff_t nb2 = SBYTES (string2); ptrdiff_t nb = min (nb1, nb2); - - /* First compare entire machine words. (String data is allocated - with word alignment.) */ - typedef size_t word_t; - int ws = sizeof (word_t); - const word_t *w1 = (const word_t *) SDATA (string1); - const word_t *w2 = (const word_t *) SDATA (string2); ptrdiff_t b = 0; - while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws]) - b += ws; - /* Scan forward to the differing byte (at most ws-1 bytes). */ + /* String data is normally allocated with word alignment, but + there are exceptions (notably pure strings) so we restrict the + wordwise skipping to safe architectures. */ + if (HAVE_FAST_UNALIGNED_ACCESS) + { + /* First compare entire machine words. */ + typedef size_t word_t; + int ws = sizeof (word_t); + const word_t *w1 = (const word_t *) SDATA (string1); + const word_t *w2 = (const word_t *) SDATA (string2); + while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws]) + b += ws; + } + + /* Scan forward to the differing byte. */ while (b < nb && SREF (string1, b) == SREF (string2, b)) b++; commit 9af63d2e8be06dec7a2f90bfe112cbc1397f7942 Author: Mattias Engdegård Date: Sat Oct 8 16:24:40 2022 +0200 Better Lisp_String comments * src/lisp.h (struct Lisp_String): Comments improved. * src/pdumper.c (dump_string): Update hash (comment change only). diff --git a/src/lisp.h b/src/lisp.h index 9710dbef8d..56f24d8281 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1575,10 +1575,15 @@ struct Lisp_String { struct { - ptrdiff_t size; /* MSB is used as the markbit. */ - ptrdiff_t size_byte; /* Set to -1 for unibyte strings, - -2 for data in rodata, - -3 for immovable unibyte strings. */ + /* Number of characters in string; MSB is used as the mark bit. */ + ptrdiff_t size; + /* If nonnegative, number of bytes in the string (which is multibyte). + If negative, the string is unibyte: + -1 for data normally allocated + -2 for data in rodata (C string constants) + -3 for data that must be immovable (used for bytecode) */ + ptrdiff_t size_byte; + INTERVAL intervals; /* Text properties in this string. */ unsigned char *data; } s; diff --git a/src/pdumper.c b/src/pdumper.c index 903298f17d..5e6ccd9bd8 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -2067,7 +2067,7 @@ dump_interval_tree (struct dump_context *ctx, static dump_off dump_string (struct dump_context *ctx, const struct Lisp_String *string) { -#if CHECK_STRUCTS && !defined (HASH_Lisp_String_C2CAF90352) +#if CHECK_STRUCTS && !defined (HASH_Lisp_String_03B2DF1C8E) # error "Lisp_String changed. See CHECK_STRUCTS comment in config.h." #endif /* If we have text properties, write them _after_ the string so that commit 71b3a37569ffa58f3640a742e31eade42cc26f98 Author: Mattias Engdegård Date: Fri Oct 7 18:17:40 2022 +0200 Improved format string error message (bug#58168) * src/editfns.c (styled_format): Better message when the conversion char is non-ASCII from a unibyte format string. diff --git a/src/editfns.c b/src/editfns.c index c1414071c7..3f9618edb0 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -3551,10 +3551,15 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) || float_conversion || conversion == 'i' || conversion == 'o' || conversion == 'x' || conversion == 'X')) - error ("Invalid format operation %%%c", - multibyte_format - ? STRING_CHAR ((unsigned char *) format - 1) - : *((unsigned char *) format - 1)); + { + unsigned char *p = (unsigned char *) format - 1; + if (multibyte_format) + error ("Invalid format operation %%%c", STRING_CHAR (p)); + else + error (*p <= 127 ? "Invalid format operation %%%c" + : "Invalid format operation char #o%03o", + *p); + } else if (! (FIXNUMP (arg) || ((BIGNUMP (arg) || FLOATP (arg)) && conversion != 'c'))) error ("Format specifier doesn't match argument type"); commit 8de7995ae6388e5ae5418cb6af579281121f14a4 Author: Stefan Monnier Date: Sat Oct 8 12:19:40 2022 -0400 package.el: Understand a few more variations in tarball formats * lisp/emacs-lisp/package.el (package-untar-buffer): Fix thinko. (package-tar-file-info): Handle the case where the first file is in a subdirectory. * test/lisp/emacs-lisp/package-tests.el (package-test-bug58367): New test. * test/lisp/emacs-lisp/package-resources/ustar-withsub-0.1.tar: * test/lisp/emacs-lisp/package-resources/v7-withsub-0.1.tar: New files. diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 4268f7d27a..d619142d64 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -930,7 +930,7 @@ untar into a directory named DIR; otherwise, signal an error." (or (string-match regexp name) ;; Tarballs created by some utilities don't list ;; directories with a trailing slash (Bug#13136). - (and (string-equal dir name) + (and (string-equal (expand-file-name dir) name) (eq (tar-header-link-type tar-data) 5)) (error "Package does not untar cleanly into directory %s/" dir))))) (tar-untar-buffer)) @@ -1192,8 +1192,12 @@ Return the pkg-desc, with desc-kind set to KIND." "Find package information for a tar file. The return result is a `package-desc'." (cl-assert (derived-mode-p 'tar-mode)) - (let* ((dir-name (file-name-directory - (tar-header-name (car tar-parse-info)))) + (let* ((dir-name (named-let loop + ((filename (tar-header-name (car tar-parse-info)))) + (let ((dirname (file-name-directory filename))) + ;; The first file can be in a subdir: look for the top. + (if dirname (loop (directory-file-name dirname)) + (file-name-as-directory filename))))) (desc-file (package--description-file dir-name)) (tar-desc (tar-get-file-descriptor (concat dir-name desc-file)))) (unless tar-desc diff --git a/test/lisp/emacs-lisp/package-resources/ustar-withsub-0.1.tar b/test/lisp/emacs-lisp/package-resources/ustar-withsub-0.1.tar new file mode 100644 index 0000000000..009c4fc420 Binary files /dev/null and b/test/lisp/emacs-lisp/package-resources/ustar-withsub-0.1.tar differ diff --git a/test/lisp/emacs-lisp/package-resources/v7-withsub-0.1.tar b/test/lisp/emacs-lisp/package-resources/v7-withsub-0.1.tar new file mode 100644 index 0000000000..16c79e529f Binary files /dev/null and b/test/lisp/emacs-lisp/package-resources/v7-withsub-0.1.tar differ diff --git a/test/lisp/emacs-lisp/package-tests.el b/test/lisp/emacs-lisp/package-tests.el index b903cd781b..ffe4d7cd5f 100644 --- a/test/lisp/emacs-lisp/package-tests.el +++ b/test/lisp/emacs-lisp/package-tests.el @@ -275,11 +275,31 @@ Must called from within a `tar-mode' buffer." (let* ((pkg-el "multi-file-0.2.3.tar") (source-file (expand-file-name pkg-el (ert-resource-directory)))) - (package-initialize) (should-not (package-installed-p 'multie-file)) (package-install-file source-file) (should (package-installed-p 'multi-file)) - (package-delete (cadr (assq 'multi-file package-alist)))) + (package-delete (cadr (assq 'multi-file package-alist)))))) + +(ert-deftest package-test-bug58367 () + "Check variations in tarball formats." + (with-package-test (:basedir (ert-resource-directory)) + (package-initialize) + + ;; A package whose first entry is the main dir but without trailing /. + (let* ((pkg-el "ustar-withsub-0.1.tar") + (source-file (expand-file-name pkg-el (ert-resource-directory)))) + (should-not (package-installed-p 'ustar-withsub)) + (package-install-file source-file) + (should (package-installed-p 'ustar-withsub)) + (package-delete (cadr (assq 'ustar-withsub package-alist)))) + + ;; A package whose first entry is a file in a subdir. + (let* ((pkg-el "v7-withsub-0.1.tar") + (source-file (expand-file-name pkg-el (ert-resource-directory)))) + (should-not (package-installed-p 'v7-withsub)) + (package-install-file source-file) + (should (package-installed-p 'v7-withsub)) + (package-delete (cadr (assq 'v7-withsub package-alist)))) )) (ert-deftest package-test-install-file-EOLs () commit b8ab4f018bd541caf8d7b71e0b1bd6f81f2d3bbb Author: Eli Zaretskii Date: Sat Oct 8 17:40:25 2022 +0300 ; * lisp/vc/vc.el (vc-prepare-patches-separately): Doc fix. diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 13cc4fbaa6..ba3a4c58cf 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3293,11 +3293,11 @@ immediately after this one." (apply #'vc-user-edit-command (apply old args)))))) (defcustom vc-prepare-patches-separately t - "Configure the default behaviour of `vc-prepare-patch'. -If nil, a single message is created by attaching all patches to -the body of a single message. If non-nil, each patch will be -sent out in a separate message, which will be prepared -sequentially." + "Whether `vc-prepare-patch' should generate a separate message for each patch. +If nil, `vc-prepare-patch' creates a single email message by attaching +all the patches to the body of that message. If non-nil, each patch +will be sent out in a separate message, and the messages will be +prepared sequentially." :type 'boolean :safe #'booleanp :version "29.1") commit 84945e86be6b8dc8237983de901eb677bee3ae8b Author: Philip Kaludercic Date: Sat Oct 8 15:06:26 2022 +0200 ; * lisp/vc/vc.el (vc-prepare-patches-separately): Fix docstring Noticed by German Pacenza. diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 1c64551d06..13cc4fbaa6 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3293,10 +3293,11 @@ immediately after this one." (apply #'vc-user-edit-command (apply old args)))))) (defcustom vc-prepare-patches-separately t - "Non-nil means that `vc-prepare-patch' creates a single message. -A single message is created by attaching all patches to the body -of a single message. If nil, each patch will be sent out in a -separate message, which will be prepared sequentially." + "Configure the default behaviour of `vc-prepare-patch'. +If nil, a single message is created by attaching all patches to +the body of a single message. If non-nil, each patch will be +sent out in a separate message, which will be prepared +sequentially." :type 'boolean :safe #'booleanp :version "29.1") commit aa350ba27599c7496f6edc37ef2470051bd9431b Author: Philip Kaludercic Date: Sat Oct 8 14:41:53 2022 +0200 ; Add missing documentation strings * lisp/vc/vc.el (vc-read-revision): Add a docstring. (vc-read-multiple-revisions): Add a docstring. diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 72189cfcb8..1c64551d06 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -1921,6 +1921,13 @@ Return t if the buffer had changes, nil otherwise." "History for `vc-read-revision'.") (defun vc-read-revision (prompt &optional files backend default initial-input multiple) + "Query the user for a revision using PROMPT. +All subsequent arguments are optional. FILES may specify a file +set to restrict the revisions to. BACKEND is a VC backend as +listed in `vc-handled-backends'. DEFAULT and INITIAL-INPUT are +handled as defined by `completing-read'. If MULTIPLE is non-nil, +the user may be prompted for multiple revisions. If possible +this means that `completing-read-multiple' will be used." (cond ((null files) (let ((vc-fileset (vc-deduce-fileset t))) ;FIXME: why t? --Stef @@ -1942,6 +1949,10 @@ Return t if the buffer had changes, nil otherwise." answer))))) (defun vc-read-multiple-revisions (prompt &optional files backend default initial-input) + "Query the user for multiple revisions. +This is equivalent to invoking `vc-read-revision' with t for +MULTIPLE. The arguments PROMPT, FILES, BACKEND, DEFAULT and +INITIAL-INPUT are passed on to `vc-read-revision' directly." (vc-read-revision prompt files backend default initial-input t)) (defun vc-diff-build-argument-list-internal (&optional fileset) commit 49160969ced3482398b9ae616fa482bc92ce9e34 Author: Lars Ingebrigtsen Date: Sat Oct 8 15:41:14 2022 +0200 Make sqlite-select signal errors when there's an error * src/sqlite.c (load_dll_functions): Update. (Fsqlite_select): Signal an error when there's an error preparing the statement. diff --git a/src/sqlite.c b/src/sqlite.c index 54bfb7b6c6..9375b44da2 100644 --- a/src/sqlite.c +++ b/src/sqlite.c @@ -51,6 +51,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_bind_double, (sqlite3_stmt*, int, double)); DEF_DLL_FN (SQLITE_API int, sqlite3_bind_null, (sqlite3_stmt*, int)); DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int)); DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*)); +DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int)); DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*)); @@ -88,6 +89,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension, # undef sqlite3_bind_null # undef sqlite3_bind_int # undef sqlite3_errmsg +# undef sqlite3_errstr # undef sqlite3_step # undef sqlite3_changes # undef sqlite3_column_count @@ -112,6 +114,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension, # define sqlite3_bind_null fn_sqlite3_bind_null # define sqlite3_bind_int fn_sqlite3_bind_int # define sqlite3_errmsg fn_sqlite3_errmsg +# define sqlite3_errstr fn_sqlite3_errstr # define sqlite3_step fn_sqlite3_step # define sqlite3_changes fn_sqlite3_changes # define sqlite3_column_count fn_sqlite3_column_count @@ -139,6 +142,7 @@ load_dll_functions (HMODULE library) LOAD_DLL_FN (library, sqlite3_bind_null); LOAD_DLL_FN (library, sqlite3_bind_int); LOAD_DLL_FN (library, sqlite3_errmsg); + LOAD_DLL_FN (library, sqlite3_errstr); LOAD_DLL_FN (library, sqlite3_step); LOAD_DLL_FN (library, sqlite3_changes); LOAD_DLL_FN (library, sqlite3_column_count); @@ -528,7 +532,7 @@ which means that we return a set object that can be queried with { if (stmt) sqlite3_finalize (stmt); - + errmsg = sqlite3_errstr (ret); goto exit; } commit 5017f2573f7f878a05f82f69d96e50a6f4d78ec0 Author: Lars Ingebrigtsen Date: Sat Oct 8 15:26:01 2022 +0200 Fix vtable-insert-object line insertion * lisp/emacs-lisp/vtable.el (vtable-insert-object): Pass in the correct ellipsis values (bug#58370). (vtable--insert-line): Don't bug out on missing optional arguments. diff --git a/lisp/emacs-lisp/vtable.el b/lisp/emacs-lisp/vtable.el index 9bdf90bf1d..de8503a1cb 100644 --- a/lisp/emacs-lisp/vtable.el +++ b/lisp/emacs-lisp/vtable.el @@ -353,6 +353,11 @@ This also updates the displayed table." (let* ((cache (vtable--cache table)) (inhibit-read-only t) (keymap (get-text-property (point) 'keymap)) + (ellipsis (if (vtable-ellipsis table) + (propertize (truncate-string-ellipsis) + 'face (vtable-face table)) + "")) + (ellipsis-width (string-pixel-width ellipsis)) (elem (and after-object (assq after-object (car cache)))) (line (cons object (vtable--compute-cached-line table object)))) @@ -370,7 +375,8 @@ This also updates the displayed table." ;; FIXME: We have to adjust colors in lines below this if we ;; have :row-colors. (vtable--insert-line table line 0 - (nth 1 cache) (vtable--spacer table)) + (nth 1 cache) (vtable--spacer table) + ellipsis ellipsis-width) (add-text-properties start (point) (list 'keymap keymap 'vtable table))) ;; We may have inserted a non-numerical value into a previously @@ -516,7 +522,8 @@ This also updates the displayed table." (if (> (nth 1 elem) (elt widths index)) (concat (vtable--limit-string - pre-computed (- (elt widths index) ellipsis-width)) + pre-computed (- (elt widths index) + (or ellipsis-width 0))) ellipsis) pre-computed)) ;; Recompute widths. @@ -524,7 +531,8 @@ This also updates the displayed table." (if (> (string-pixel-width value) (elt widths index)) (concat (vtable--limit-string - value (- (elt widths index) ellipsis-width)) + value (- (elt widths index) + (or ellipsis-width 0))) ellipsis) value)))) (start (point)) commit e3fac2be0423d8ea7b8418286b791586be8b58fa Author: Visuwesh Date: Sat Oct 8 15:13:48 2022 +0200 Fix misleading prompt in vc-git-create-tag * lisp/vc/vc-git.el (vc-git-create-tag): Actually pass the DEFAULT argument to vc-read-revision (bug#58378). diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index f9dae8b9ea..ea06ccaf87 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -1635,7 +1635,7 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"." (start-point (when branchp (vc-read-revision (format-prompt "Start point" (car (vc-git-branches))) - (list dir) 'Git)))) + (list dir) 'Git (car (vc-git-branches)))))) (and (or (zerop (vc-git-command nil t nil "update-index" "--refresh")) (y-or-n-p "Modified files exist. Proceed? ") (user-error (format "Can't create %s with modified files" commit dc9f07d39f83b86db4e207b670ec15f85bce0add Author: Lars Ingebrigtsen Date: Sat Oct 8 14:57:47 2022 +0200 Fix typo in etc/TODO diff --git a/etc/TODO b/etc/TODO index 9314a397b5..6253a0a93a 100644 --- a/etc/TODO +++ b/etc/TODO @@ -1745,7 +1745,7 @@ defined. See bug#57607. ** Replace tramp-archive.el by a native libarchive(3) implementation. The former is based on the GVFS archive backend, which makes it -available on GNU/Linix only. That implementation has further +available on GNU/Linux only. That implementation has further drawbacks like it doesn't support to write into archives. * Other known bugs commit 594b3b2cfa56cfd9b03a3e473a7f3bcbd3e72802 Author: Michael Albinus Date: Sat Oct 8 14:54:38 2022 +0200 * etc/TODO (Wishlist items): Add libarchive(3) integration. diff --git a/etc/TODO b/etc/TODO index d884539037..9314a397b5 100644 --- a/etc/TODO +++ b/etc/TODO @@ -886,7 +886,6 @@ window associated with that modeline. https://lists.gnu.org/r/emacs-devel/2007-09/msg02416.html ** Random things that were planned for Emacs-24 - Stefan Monnier writes: "Random things that cross my mind right now that I'd like to see. Some of them from my local hacks, but it's not obvious at all whether they'll make it." @@ -1737,11 +1736,18 @@ https://lists.gnu.org/r/emacs-devel/2012-06/msg00354.html ** Maybe replace lib-src/rcs2log with a Lisp implementation It wouldn't have to be a complete replacement, just enough for vc-rcs-update-changelog. + ** Allow Emacs to use the bottom-right corner of a TTY Emacs doesn't use the bottom-right corner of a TTY when terminfo capability "am" (auto_right_margin) is defined. It could use the bottom-right corner nonetheless when certain other capabilities are defined. See bug#57607. + +** Replace tramp-archive.el by a native libarchive(3) implementation. +The former is based on the GVFS archive backend, which makes it +available on GNU/Linix only. That implementation has further +drawbacks like it doesn't support to write into archives. + * Other known bugs ** 'make-frame' forgets unhandled parameters, at least for X11 frames commit 6b560992681a1588ed4ed0c6b103021f8b13e056 Author: Lars Ingebrigtsen Date: Sat Oct 8 13:20:17 2022 +0200 Mention seq-keep in shortdoc * lisp/emacs-lisp/shortdoc.el (sequence): Mention seq-keep. diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index 4cfd658e10..dbac03432c 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -897,6 +897,8 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), :eval (seq-drop-while #'numberp '(1 2 c d 5))) (seq-filter :eval (seq-filter #'numberp '(a b 3 4 f 6))) + (seq-keep + :eval (seq-keep #'cl-digit-char-p '(?6 ?a ?7))) (seq-remove :eval (seq-remove #'numberp '(1 2 c d 5))) (seq-remove-at-position commit 32ef7550edc887f1f8e052cb57a61c4e82b6eecd (refs/remotes/origin/emacs-28) Author: Eli Zaretskii Date: Sat Oct 8 14:13:50 2022 +0300 ; Improve documentation of 'file-in-directory-p' * lisp/files.el (file-in-directory-p): Clarify doc string. * doc/lispref/files.texi (Truenames): Move the documentation of 'file-in-directory-p' from here... (Contents of Directories): ...to here. Add index entries. (Bug#58364) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 08677f789a..32a862b582 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -1250,14 +1250,6 @@ the @samp{smb} method. For all other connection methods, runtime tests are performed. @end defun -@defun file-in-directory-p file dir -This function returns @code{t} if @var{file} is a file in directory -@var{dir}, or in a subdirectory of @var{dir}. It also returns -@code{t} if @var{file} and @var{dir} are the same directory. It -compares the truenames of the two directories. If @var{dir} does not -name an existing directory, the return value is @code{nil}. -@end defun - @defun vc-responsible-backend file This function determines the responsible VC backend of the given @var{file}. For example, if @file{emacs.c} is a file tracked by Git, @@ -3052,6 +3044,17 @@ is called with one argument (the file or directory) and should return non-@code{nil} if that directory is the one it is looking for. @end defun +@cindex parent directory of file +@cindex ancestor directory of file +@cindex file, ancestor directory of +@defun file-in-directory-p file dir +This function returns @code{t} if @var{file} is a file in directory +@var{dir}, or in a subdirectory of @var{dir}. It also returns +@code{t} if @var{file} and @var{dir} are the same directory. It +compares the truenames of the two directories. If @var{dir} does not +name an existing directory, the return value is @code{nil}. +@end defun + @defun directory-files-and-attributes directory &optional full-name match-regexp nosort id-format count This is similar to @code{directory-files} in deciding which files to report on and how to report their names. However, instead diff --git a/lisp/files.el b/lisp/files.el index 860b9ca724..e07f479625 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -6166,9 +6166,10 @@ If FILE1 or FILE2 does not exist, the return value is unspecified." (equal f1-attr f2-attr)))))) (defun file-in-directory-p (file dir) - "Return non-nil if FILE is in DIR or a subdirectory of DIR. -A directory is considered to be \"in\" itself. -Return nil if DIR is not an existing directory." + "Return non-nil if DIR is a parent directory of FILE. +Value is non-nil if FILE is inside DIR or inside a subdirectory of DIR. +A directory is considered to be a \"parent\" of itself. +DIR must be an existing directory, otherwise the function returns nil." (let ((handler (or (find-file-name-handler file 'file-in-directory-p) (find-file-name-handler dir 'file-in-directory-p)))) (if handler commit 59df0a7bd9e54003108c938519d64f6607cf48d8 Author: Philip Kaludercic Date: Mon Oct 3 20:54:38 2022 +0200 Add a VC command to prepare patches * doc/emacs/vc1-xtra.texi (Miscellaneous VC): Add new node. (Editing VC Commands): Document new feature. * etc/NEWS: Mention 'vc-prepare-patch'. * lisp/vc/log-view.el: Autoload 'log-view-get-marked'. * lisp/vc/vc-git.el (vc-git-prepare-patch): Add Git implementation. * lisp/vc/vc-hg.el (vc-git-prepare-patch): Add Mercurial implementation. * lisp/vc/vc-bzr.el (vc-git-prepare-patch): Add Bazaar implementation. * lisp/vc/vc.el (vc-read-revision): Add a MULTIPLE argument. (vc-read-multiple-revisions): Add an auxiliary function that always calls 'vc-read-revision' with a non-nil value for MULTIPLE. (vc-prepare-patches-separately): Add user option. (message-goto-body): Declare function. (message--name-table): Declare function. (vc-default-prepare-patch): Add a default implementation. (vc-prepare-patch): Add command. (Bug#57400) diff --git a/doc/emacs/vc1-xtra.texi b/doc/emacs/vc1-xtra.texi index 05d2144380..66d3f51c30 100644 --- a/doc/emacs/vc1-xtra.texi +++ b/doc/emacs/vc1-xtra.texi @@ -16,6 +16,7 @@ * Revision Tags:: Symbolic names for revisions. * Version Headers:: Inserting version control headers into working files. * Editing VC Commands:: Editing the VC shell commands that Emacs will run. +* Preparing Patches:: Preparing and Composing patches from within VC @end menu @node Change Logs and VC @@ -282,6 +283,32 @@ type @w{@kbd{C-x v ! C-x v b l}} and then append the names of additional branches to the end of the @samp{git log} command that VC is about to run. +@node Preparing Patches +@subsubsection Preparing Patches + +@findex vc-prepare-patch +When collaborating on projects it is common to send patches via email, +to share changes. If you wish to do this using VC, you can use the +@code{vc-prepare-patch} command. This will prompt you for the +revisions you wish to share, and which destination email address(es) +to use. The command will then prepare those revisions using your +@abbr{MUA, Mail User Agent} for you to review and send. + +@vindex vc-prepare-patches-separately +Depending on the value of the user option +@code{vc-prepare-patches-separately}, @code{vc-prepare-patch} will +generate one or more messages. The default value @code{t} means +prepare and display a message for each revision, one after another. A +value of @code{nil} means to generate a single message with all +patches attached in the body. + +@vindex vc-default-patch-addressee +If you expect to contribute patches on a regular basis, you can set +the user option @code{vc-default-patch-addressee} to the address(es) +you wish to use. This will be used as the default value when invoking +@code{vc-prepare-patch}. Project maintainers may consider setting +this as a directory local variable (@pxref{Directory Variables}). + @node Customizing VC @subsection Customizing VC diff --git a/etc/NEWS b/etc/NEWS index f6744236f0..ca857056fd 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1866,6 +1866,24 @@ Git commands display summary lines. See the two new user options It is used to style the line that separates the 'log-edit' headers from the 'log-edit' summary. +--- +*** The function 'vc-read-revision' accepts a new MULTIPLE argument. +If non-nil, multiple revisions can be queried. This is done using +'completing-read-multiple'. + +--- +*** New function 'vc-read-multiple-revisions' +This function invokes 'vc-read-revision' with a non-nil value for +MULTIPLE. + ++++ +*** New command 'vc-prepare-patch'. +Patches for any version control system can be prepared using VC. The +command will query what commits to send and will compose messages for +your mail user agent. The behaviour of 'vc-prepare-patch' can be +modified by the user options 'vc-prepare-patches-separately' and +'vc-default-patch-addressee'. + ** Message --- diff --git a/lisp/vc/log-view.el b/lisp/vc/log-view.el index 415b1564ed..7a710386fe 100644 --- a/lisp/vc/log-view.el +++ b/lisp/vc/log-view.el @@ -359,6 +359,7 @@ log entries." (overlay-put ov 'log-view-self ov) (overlay-put ov 'log-view-marked (nth 1 entry)))))))) +;;;###autoload (defun log-view-get-marked () "Return the list of tags for the marked log entries." (save-excursion diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el index bce7996712..6f77f99555 100644 --- a/lisp/vc/vc-bzr.el +++ b/lisp/vc/vc-bzr.el @@ -1324,6 +1324,20 @@ stream. Standard error output is discarded." (match-string 1) (error "Cannot determine Bzr repository URL"))))) +(defun vc-bzr-prepare-patch (rev) + (with-current-buffer (generate-new-buffer " *vc-bzr-prepare-patch*") + (vc-bzr-command + "send" t 0 '() + "--revision" (concat (vc-bzr-previous-revision nil rev) ".." rev) + "--output" "-") + (let (subject) + ;; Extract the subject line + (goto-char (point-min)) + (search-forward-regexp "^[^#].*") + (setq subject (match-string 0)) + ;; Return the extracted data + (list :subject subject :buffer (current-buffer))))) + (provide 'vc-bzr) ;;; vc-bzr.el ends here diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index 4a2a42ad2a..f9dae8b9ea 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -95,6 +95,7 @@ ;; - find-file-hook () OK ;; - conflicted-files OK ;; - repository-url (file-or-dir) OK +;; - prepare-patch (rev) OK ;;; Code: @@ -1742,6 +1743,29 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"." (defun vc-git-root (file) (vc-find-root file ".git")) +(defun vc-git-prepare-patch (rev) + (with-current-buffer (generate-new-buffer " *vc-git-prepare-patch*") + (vc-git-command + t 0 '() "format-patch" + "--no-numbered" "--stdout" + ;; From gitrevisions(7): ^ means the th parent + ;; (i.e. ^ is equivalent to ^1). As a + ;; special rule, ^0 means the commit itself and + ;; is used when is the object name of a tag + ;; object that refers to a commit object. + (concat rev "^.." rev)) + (let (subject) + ;; Extract the subject line + (goto-char (point-min)) + (search-forward-regexp "^Subject: \\(.+\\)") + (setq subject (match-string 1)) + ;; Jump to the beginning for the patch + (search-forward-regexp "\n\n") + ;; Return the extracted data + (list :subject subject + :buffer (current-buffer) + :body-start (point))))) + ;; grep-compute-defaults autoloads grep. (declare-function grep-read-regexp "grep" ()) (declare-function grep-read-files "grep" (regexp)) diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index eed9592378..2eebe2d543 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -80,6 +80,7 @@ ;; - delete-file (file) TEST IT ;; - rename-file (old new) OK ;; - find-file-hook () added for bug#10709 +;; - prepare-patch (rev) OK ;; 2) Implement Stefan Monnier's advice: ;; vc-hg-registered and vc-hg-state @@ -1507,6 +1508,17 @@ This runs the command \"hg merge\"." (with-current-buffer buffer (vc-run-delayed (vc-compilation-mode 'hg))) (vc-set-async-update buffer))) +(defun vc-hg-prepare-patch (rev) + (with-current-buffer (generate-new-buffer " *vc-hg-prepare-patch*") + (vc-hg-command t 0 '() "export" "--rev" rev) + (let (subject) + ;; Extract the subject line + (goto-char (point-min)) + (search-forward-regexp "^[^#].*") + (setq subject (match-string 0)) + ;; Return the extracted data + (list :subject subject :buffer (current-buffer))))) + ;;; Internal functions (defun vc-hg-command (buffer okstatus file-or-list &rest flags) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 787dd51d07..72189cfcb8 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -574,6 +574,16 @@ ;; containing FILE-OR-DIR. The optional REMOTE-NAME specifies the ;; remote (in Git parlance) whose URL is to be returned. It has ;; only a meaning for distributed VCS and is ignored otherwise. +;; +;; - prepare-patch (rev) +;; +;; Prepare a patch and return a property list with the keys +;; `:subject' indicating the patch message as a string, `:buffer' +;; with a buffer object that contains the entire patch message and +;; `:body-start' and `:body-end' demarcating what part of said +;; buffer should be inserted into an inline patch. If the two last +;; properties are omitted, `point-min' and `point-max' will +;; respectively be used instead. ;;; Changes from the pre-25.1 API: ;; @@ -1910,7 +1920,7 @@ Return t if the buffer had changes, nil otherwise." (defvar vc-revision-history nil "History for `vc-read-revision'.") -(defun vc-read-revision (prompt &optional files backend default initial-input) +(defun vc-read-revision (prompt &optional files backend default initial-input multiple) (cond ((null files) (let ((vc-fileset (vc-deduce-fileset t))) ;FIXME: why t? --Stef @@ -1923,9 +1933,16 @@ Return t if the buffer had changes, nil otherwise." (completion-table (vc-call-backend backend 'revision-completion-table files))) (if completion-table - (completing-read prompt completion-table - nil nil initial-input 'vc-revision-history default) - (read-string prompt initial-input nil default)))) + (funcall + (if multiple #'completing-read-multiple #'completing-read) + prompt completion-table nil nil initial-input 'vc-revision-history default) + (let ((answer (read-string prompt initial-input nil default))) + (if multiple + (split-string answer "[ \t]*,[ \t]*") + answer))))) + +(defun vc-read-multiple-revisions (prompt &optional files backend default initial-input) + (vc-read-revision prompt files backend default initial-input t)) (defun vc-diff-build-argument-list-internal (&optional fileset) "Build argument list for calling internal diff functions." @@ -3264,6 +3281,105 @@ immediately after this one." (lambda (&rest args) (apply #'vc-user-edit-command (apply old args)))))) +(defcustom vc-prepare-patches-separately t + "Non-nil means that `vc-prepare-patch' creates a single message. +A single message is created by attaching all patches to the body +of a single message. If nil, each patch will be sent out in a +separate message, which will be prepared sequentially." + :type 'boolean + :safe #'booleanp + :version "29.1") + +(defcustom vc-default-patch-addressee nil + "Default addressee for `vc-prepare-patch'. +If nil, no default will be used. This option may be set locally." + :type '(choice (const :tag "No default" nil) + (string :tag "Addressee")) + :safe #'stringp + :version "29.1") + +(declare-function message--name-table "message" (orig-string)) +(declare-function mml-attach-buffer "mml" + (buffer &optional type description disposition)) +(declare-function log-view-get-marked "log-view" ()) + +(defun vc-default-prepare-patch (rev) + (let ((backend (vc-backend buffer-file-name))) + (with-current-buffer (generate-new-buffer " *vc-default-prepare-patch*") + (vc-diff-internal + nil (list backend) rev + (vc-call-backend backend 'previous-revision + buffer-file-name rev) + nil t) + (list :subject (concat "Patch for " + (file-name-nondirectory + (directory-file-name + (vc-root-dir)))) + :buffer (current-buffer))))) + +;;;###autoload +(defun vc-prepare-patch (addressee subject revisions) + "Compose an Email sending patches for REVISIONS to ADDRESSEE. +If `vc-prepare-patches-separately' is non-nil, SUBJECT will be used +as the default subject for the message. Otherwise a separate +message will be composed for each revision. + +When invoked interactively in a Log View buffer with marked +revisions, these revisions will be used." + (interactive + (let ((revs (or (log-view-get-marked) + (vc-read-multiple-revisions "Revisions: "))) + to) + (require 'message) + (while (null (setq to (completing-read-multiple + (format-prompt + "Addressee" + vc-default-patch-addressee) + (message--name-table "") + nil nil nil nil + vc-default-patch-addressee))) + (message "At least one addressee required.") + (sit-for blink-matching-delay)) + (list (string-join to ", ") + (and (not vc-prepare-patches-separately) + (read-string "Subject: " "[PATCH] " nil nil t)) + revs))) + (save-current-buffer + (vc-ensure-vc-buffer) + (let ((patches (mapcar (lambda (rev) + (vc-call-backend + (vc-responsible-backend default-directory) + 'prepare-patch rev)) + revisions))) + (if vc-prepare-patches-separately + (dolist (patch patches) + (compose-mail addressee + (plist-get patch :subject) + nil nil nil nil + `((kill-buffer ,(plist-get patch :buffer)) + (exit-recursive-edit))) + (rfc822-goto-eoh) (forward-line) + (save-excursion ;don't jump to the end + (insert-buffer-substring + (plist-get patch :buffer) + (plist-get patch :body-start) + (plist-get patch :body-end))) + (recursive-edit)) + (compose-mail addressee subject nil nil nil nil + (mapcar + (lambda (p) + (list #'kill-buffer (plist-get p :buffer))) + patches)) + (rfc822-goto-eoh) + (forward-line) + (save-excursion + (dolist (patch patches) + (mml-attach-buffer (buffer-name (plist-get patch :buffer)) + "text/x-patch" + (plist-get patch :subject) + "attachment"))) + (open-line 2))))) + (defun vc-default-responsible-p (_backend _file) "Indicate whether BACKEND is responsible for FILE. The default is to return nil always." commit 5e7e85af02c18571837c8e2669b5bf2b7b9198a3 Author: Po Lu Date: Sat Oct 8 16:38:30 2022 +0800 Stop passing CurrentTime to SetInputFocus * src/xterm.c (xi_focus_handle_for_device, handle_one_xevent): Set the last user time where required for focus to be handled correctly. (x_focus_frame): Do not perform actions prohibited by the ICCCM. diff --git a/src/xterm.c b/src/xterm.c index cdf99f278a..aaf2e7988b 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -12758,11 +12758,21 @@ xi_focus_handle_for_device (struct x_display_info *dpyinfo, switch (event->evtype) { case XI_FocusIn: + /* The last-focus-change time of the device changed, so update the + frame's user time. */ + x_display_set_last_user_time (dpyinfo, event->time, + event->send_event); + device->focus_frame = mentioned_frame; device->focus_frame_time = event->time; break; case XI_FocusOut: + /* The last-focus-change time of the device changed, so update the + frame's user time. */ + x_display_set_last_user_time (dpyinfo, event->time, + event->send_event); + device->focus_frame = NULL; /* So, unfortunately, the X Input Extension is implemented such @@ -18077,6 +18087,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, } /* Not certain about handling scroll bars here */ #endif + /* Set the provided time as the user time, which is + required for SetInputFocus to work correctly after + taking the input focus. */ + x_display_set_last_user_time (dpyinfo, event->xclient.data.l[1], + true); goto done; } @@ -27021,8 +27036,22 @@ x_focus_frame (struct frame *f, bool noactivate) /* Ignore any BadMatch error this request might result in. */ x_ignore_errors_for_next_request (dpyinfo); - XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - RevertToParent, CurrentTime); + if (NILP (Vx_no_window_manager)) + XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), + /* It is invalid to use CurrentTime according to + the ICCCM: + + Clients that use a SetInputFocus request must + set the time field to the timestamp of the + event that caused them to make the + attempt. [...] Note that clients must not use + CurrentTime in the time field. */ + RevertToParent, dpyinfo->last_user_time); + else + XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), + /* But when no window manager is in use, we + don't care. */ + RevertToParent, CurrentTime); x_stop_ignoring_errors (dpyinfo); } } commit 75b7aacbf608ab49991aa945c5a4e54774084294 Author: समीर सिंह Sameer Singh Date: Thu Oct 6 17:34:28 2022 +0530 Add support for the Coptic script (bug#58330) * lisp/language/misc-lang.el ("Coptic"): New language environment. Add sample text and input method. * lisp/international/fontset.el (script-representative-chars) (setup-default-fontset): Support coptic. * lisp/leim/quail/misc-lang.el ("coptic"): New input method. * etc/HELLO: Add a Coptic greeting. * etc/NEWS: Announce the new language environment. diff --git a/etc/HELLO b/etc/HELLO index b05c09da3c..7bc12063f8 100644 --- a/etc/HELLO +++ b/etc/HELLO @@ -41,6 +41,7 @@ C printf (orange red"Hello, world!\n"); Cham (ꨌꩌ) ꨦꨤꩌ ꨦꨁꨰ Cherokee (ᏣᎳᎩ ᎦᏬᏂᎯᏍᏗ) ᎣᏏᏲ / ᏏᏲ Comanche /kəˈmæntʃiː/ Haa marʉ́awe +Coptic (ⲘⲉⲧⲢⲉⲙ̀ⲛⲭⲏⲙⲓ) Ⲛⲟⲩϥⲣⲓ Cree (ᓀᐦᐃᔭᐍᐏᐣ) ᑕᓂᓯ / ᐙᒋᔮ Czech (čeština) Dobrý den Danish (dansk) Hej / Goddag / Halløj diff --git a/etc/NEWS b/etc/NEWS index 88b1431d6a..f6744236f0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1338,6 +1338,7 @@ Mende Kikakui script and language environment Wancho script and language environment Toto script and language environment Gothic script and language environment +Coptic script and language environment --- *** The "Oriya" language environment was renamed to "Odia". diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index 6e44b85e6c..93fedb8c1a 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -152,7 +152,7 @@ '((latin ?A ?Z ?a ?z #x00C0 #x0100 #x0180 #x1e00) (phonetic #x250 #x283) (greek #x3A9) - (coptic #x3E2) + (coptic #x3E2 #x2C80 #x2CAE) (cyrillic #x42F) (armenian #x531) (hebrew #x5D0) @@ -779,6 +779,7 @@ lepcha symbol braille + coptic yi syloti-nagri rejang diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el index 4a2e7838fc..370be4b4a3 100644 --- a/lisp/language/misc-lang.el +++ b/lisp/language/misc-lang.el @@ -319,6 +319,20 @@ in this language environment."))) Ancient Gothic language using the Gothic script is supported in this language environment."))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Coptic +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(set-language-info-alist + "Coptic" '((charset unicode) + (coding-system utf-8) + (coding-priority utf-8) + (input-method . "coptic") + (sample-text . "Coptic (ⲘⲉⲧⲢⲉⲙ̀ⲛⲭⲏⲙⲓ) Ⲛⲟⲩϥⲣⲓ") + (documentation . "\ +Coptic language using the Coptic script is supported in this +language environment."))) + (provide 'misc-lang) ;;; misc-lang.el ends here diff --git a/lisp/leim/quail/misc-lang.el b/lisp/leim/quail/misc-lang.el index dad5cfc3e3..73287ee784 100644 --- a/lisp/leim/quail/misc-lang.el +++ b/lisp/leim/quail/misc-lang.el @@ -1558,5 +1558,122 @@ ("n" ?𐌽) ("m" ?𐌼)) +(quail-define-package + "coptic" "Coptic" "Ⲁ" nil "Coptic input method. + + `\\=`' is used to switch levels instead of Alt-Gr." + nil t t t t nil nil nil nil nil t) + +(quail-define-rules + ("1" ?𐋡) + ("`1" ?1) + ("`!" ?𐋠) + ("2" ?𐋢) + ("`2" ?2) + ("3" ?𐋣) + ("`3" ?3) + ("4" ?𐋤) + ("`4" ?4) + ("5" ?𐋥) + ("`5" ?5) + ("6" ?𐋦) + ("`6" ?6) + ("7" ?𐋧) + ("`7" ?7) + ("8" ?𐋨) + ("`8" ?8) + ("9" ?𐋩) + ("`9" ?9) + ("10" ?𐋪) + ("20" ?𐋫) + ("30" ?𐋬) + ("40" ?𐋭) + ("50" ?𐋮) + ("60" ?𐋯) + ("70" ?𐋰) + ("80" ?𐋱) + ("90" ?𐋲) + ("100" ?𐋳) + ("200" ?𐋴) + ("300" ?𐋵) + ("400" ?𐋶) + ("500" ?𐋷) + ("600" ?𐋸) + ("700" ?𐋹) + ("800" ?𐋺) + ("900" ?𐋻) + ("1/2" ?⳽) + + ("q" ?ⲑ) + ("Q" ?Ⲑ) + ("w" ?ⲱ) + ("W" ?Ⲱ) + ("e" ?ⲉ) + ("E" ?Ⲉ) + ("r" ?ⲣ) + ("R" ?Ⲣ) + ("t" ?ⲧ) + ("T" ?Ⲧ) + ("ti" ?ϯ) + ("Ti" ?Ϯ) + ("y" ?ⲏ) + ("Y" ?Ⲏ) + ("u" ?ⲩ) + ("U" ?Ⲩ) + ("i" ?ⲓ) + ("I" ?Ⲓ) + ("o" ?ⲟ) + ("O" ?Ⲟ) + ("p" ?ⲡ) + ("P" ?Ⲡ) + ("ps" ?ⲯ) + ("Ps" ?Ⲯ) + ("a" ?ⲁ) + ("A" ?Ⲁ) + ("s" ?ⲥ) + ("S" ?Ⲥ) + ("`s" ?ⲋ) + ("`S" ?Ⲋ) + ("sh" ?ϣ) + ("Sh" ?Ϣ) + ("d" ?ⲇ) + ("D" ?Ⲇ) + ("f" ?ⲫ) + ("F" ?Ⲫ) + ("g" ?ⲅ) + ("G" ?Ⲅ) + ("h" ?ϩ) + ("H" ?Ϩ) + ("j" ?ϫ) + ("J" ?Ϫ) + ("k" ?ⲕ) + ("K" ?Ⲕ) + ("kh" ?ⲭ) + ("Kh" ?Ⲭ) + ("l" ?ⲗ) + ("L" ?Ⲗ) + ("z" ?ⲍ) + ("Z" ?Ⲍ) + ("x" ?ⲝ) + ("X" ?Ⲝ) + ("`x" ?ϧ) + ("`X" ?Ϧ) + ("c" ?ϭ) + ("C" ?Ϭ) + ("v" ?ϥ) + ("V" ?Ϥ) + ("b" ?ⲃ) + ("B" ?Ⲃ) + ("n" ?ⲛ) + ("N" ?Ⲛ) + ("`n" ?⳯) + ("m" ?ⲙ) + ("M" ?Ⲙ) + + ("`," ?⳰) + ("`<" ?⳱) + ("`." ?⳾) + ("`/" ?⳿)) + (provide 'misc-lang) ;;; misc-lang.el ends here