Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package emacs-jinx for openSUSE:Factory checked in at 2026-02-04 21:08:37 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/emacs-jinx (Old) and /work/SRC/openSUSE:Factory/.emacs-jinx.new.1670 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "emacs-jinx" Wed Feb 4 21:08:37 2026 rev:11 rq:1330832 version:2.6 Changes: -------- --- /work/SRC/openSUSE:Factory/emacs-jinx/emacs-jinx.changes 2025-04-20 19:51:36.203962089 +0200 +++ /work/SRC/openSUSE:Factory/.emacs-jinx.new.1670/emacs-jinx.changes 2026-02-04 21:08:52.871595189 +0100 @@ -1,0 +2,32 @@ +Tue Feb 03 20:15:06 UTC 2026 - BjΓΆrn Kettunen <[email protected]> + +- Rebase 0001-Only-export-necessary-symbols.-Fixes-105.patch + against version 2.1 + +- Update to version 2.6: + * jinx-next/jinx-previous: Make argument optional + * Add link to proposed file-local language variable bug svg#80071 + +- Changes from version 2.5 + * Drop annotation-function, + We provide an affixation-function supported since Emacs 28. + * Actions can now be triggered via digit keys + * Remove C-u C-u C-u M-$ keybind + +- Changes from version 2.4 + * Use eager-display for the default completion UI, on Emacs 31. + * Update bundled emacs-module.h + * Use globalized minor mode predicate, require Emacs 29 + * jinx-exclude-properties: Exclude propertized text + * jinx-exclude-regexps: Expand docstring + +- Changes from version 2.3 + * jinx-correct-all: Show message when ONLY-CHECK is non-nil + +- Changes from ersion 2.2 + * Stop using enchant_dict_get_extra_word_characters. + Instead rely on the jinx--syntax-table for tokenization. + See also ghub#rrthomas/enchant#244. + * jinx--save-dir: Do not switch to .dir-locals.el (Fix gh#minad/jinx#236) + +------------------------------------------------------------------- Old: ---- jinx-2.1.obscpio New: ---- jinx-2.6.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ emacs-jinx.spec ++++++ --- /var/tmp/diff_new_pack.bA7GUJ/_old 2026-02-04 21:08:53.955640589 +0100 +++ /var/tmp/diff_new_pack.bA7GUJ/_new 2026-02-04 21:08:53.959640757 +0100 @@ -1,7 +1,7 @@ # # spec file for package emacs-jinx # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # Copyright (c) 2023 BjΓΆrn Bidar # # All modifications and additions to the file contributed by third parties @@ -20,7 +20,7 @@ %global _name jinx Name: emacs-%{_name} -Version: 2.1 +Version: 2.6 Release: 0 Summary: Enchanted Spell Checker for Emacs License: GPL-3.0-or-later ++++++ 0001-Only-export-necessary-symbols.-Fixes-105.patch ++++++ --- /var/tmp/diff_new_pack.bA7GUJ/_old 2026-02-04 21:08:53.987641929 +0100 +++ /var/tmp/diff_new_pack.bA7GUJ/_new 2026-02-04 21:08:53.995642264 +0100 @@ -16,7 +16,7 @@ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/jinx-mod.c b/jinx-mod.c -index 33e080d34bc0f53a2e7bc5ff0c3d9ee5bb70eb39..476b8c105985514d2f2870fb50b9bcfe3923abba 100644 +index b28ddf67001b4f78d024352473f6e312b1b731bc..d71b3f1ba7a2cefc0b8970e2d0061258f960eb29 100644 --- a/jinx-mod.c +++ b/jinx-mod.c @@ -20,10 +20,25 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ @@ -46,7 +46,7 @@ static EnchantBroker* broker = 0; static emacs_value Qt, Qnil, Qcons; -@@ -173,7 +188,7 @@ static emacs_value jinx_suggest(emacs_env* env, ptrdiff_t jinx_unused(nargs), +@@ -160,7 +175,7 @@ static emacs_value jinx_suggest(emacs_env* env, ptrdiff_t jinx_unused(nargs), return list; } @@ -56,10 +56,10 @@ if ((size_t)runtime->size < sizeof (*runtime)) return 1; diff --git a/jinx.el b/jinx.el -index 5561f3996a1a2fe5eeb85532ac1c89621f7ea1da..3beec38a32ea830d33d28d03b342ee2e944b399b 100644 +index 9da85d2bf236570ea2e656637353b1b37dc57446..a53d0096485dd08532c6694c4b25d2f6982f9a3f 100644 --- a/jinx.el +++ b/jinx.el -@@ -269,7 +269,7 @@ (easy-menu-define jinx-mode-menu jinx-mode-map +@@ -282,7 +282,7 @@ (easy-menu-define jinx-mode-menu jinx-mode-map ;;;; Internal variables (defvar jinx--compile-flags ++++++ jinx-2.1.obscpio -> jinx-2.6.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jinx-2.1/.elpaignore new/jinx-2.6/.elpaignore --- old/jinx-2.1/.elpaignore 1970-01-01 01:00:00.000000000 +0100 +++ new/jinx-2.6/.elpaignore 2026-01-17 17:50:00.000000000 +0100 @@ -0,0 +1,3 @@ +LICENSE +.elpaignore +.github \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jinx-2.1/.github/ISSUE_TEMPLATE/bug_report.md new/jinx-2.6/.github/ISSUE_TEMPLATE/bug_report.md --- old/jinx-2.1/.github/ISSUE_TEMPLATE/bug_report.md 1970-01-01 01:00:00.000000000 +0100 +++ new/jinx-2.6/.github/ISSUE_TEMPLATE/bug_report.md 2026-01-17 17:50:00.000000000 +0100 @@ -0,0 +1,22 @@ +--- +title: +name: π Bug report +about: Report a bug. Do not use this for questions, support or feature requests. +--- +Thank you for reporting a bug. + +Please use the latest stable release of Emacs 30.1 and start with `emacs -Q` or +`package-isolate` in order to only load a minimal set of packages. This way your +Emacs configuration is not loaded. + +Make sure that you install the newest versions of the involved packages. Please +also reinstall and recompile the involved packages, ideally remove all and +reinstall all packages, to exclude compilation issues due to outdated +dependencies. + +Please provide precise information, stack traces and the exact steps to +reproduce the issue. This is important to ensure that your problem can be +reproduced on a different machine. + +If you are not really sure if your issue is a bug, please open a discussion +instead. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jinx-2.1/.github/ISSUE_TEMPLATE/config.yml new/jinx-2.6/.github/ISSUE_TEMPLATE/config.yml --- old/jinx-2.1/.github/ISSUE_TEMPLATE/config.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/jinx-2.6/.github/ISSUE_TEMPLATE/config.yml 2026-01-17 17:50:00.000000000 +0100 @@ -0,0 +1,23 @@ +blank_issues_enabled: false +contact_links: + - name: "π Please support my work on Jinx and my other Emacs packages" + url: https://github.com/sponsors/minad + about: Thanks! Your support helps dedicating time to project maintenance and development. + - name: "π‘ Suggest a feature β Please create a discussion" + url: https://github.com/minad/jinx/discussions/categories/ideas + about: Start a new discussion suggesting an improvement or a feature. + - name: "π§βπ€βπ§ Ask the community for support" + url: https://www.reddit.com/r/emacs + about: Please be kind and support others. + - name: "π€ Ask the maintainer for support β Please create a discussion" + url: https://github.com/minad/jinx/discussions/categories/q-a + about: Please keep in mind that my bandwidth is limited. + - name: "π Search through old issues or discussions" + url: https://github.com/search?q=repo%3Aminad%2Fjinx&type=issues + about: The same question may have been asked before. + - name: "π Jinx wiki" + url: https://github.com/minad/jinx/wiki + about: Additional configuration tips are covered there. Feel free to edit! + - name: "π Jinx manual" + url: https://github.com/minad/jinx/blob/main/README.org + about: The manual covers the basic setup and workflow. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jinx-2.1/CHANGELOG.org new/jinx-2.6/CHANGELOG.org --- old/jinx-2.1/CHANGELOG.org 2025-04-04 13:23:21.000000000 +0200 +++ new/jinx-2.6/CHANGELOG.org 2026-01-17 17:50:00.000000000 +0100 @@ -2,6 +2,32 @@ #+author: Daniel Mendler #+language: en +* Version 2.6 (2026-01-17) + +- Use =when-let*= instead of =when-let=. +- =jinx-next/previous=: Make argument optional. + +* Version 2.5 (2025-11-29) + +- Actions can be triggered via digit keys now. +- Drop legacy =annotation-function=. + +* Version 2.4 (2025-10-13) + +- =jinx-exclude-properties=: New variable to exclude propertized text from + checking. Exclude =read-only= text by default. +- Use =eager-display= for the default completion UI. +- Require Emacs 29. + +* Version 2.3 (2025-07-28) + +- ~jinx-correct-all~: Show message if ~ONLY-CHECK~ is non-nil. + +* Version 2.2 (2025-05-26) + +- Stop using =enchant_dict_get_extra_word_characters=. Instead rely on the + =jinx--syntax-table= for tokenization. + * Version 2.1 (2025-04-04) - ~jinx-correct~: For capitalized words, offer lower case variants to save in diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jinx-2.1/README.org new/jinx-2.6/README.org --- old/jinx-2.1/README.org 2025-04-04 13:23:21.000000000 +0200 +++ new/jinx-2.6/README.org 2026-01-17 17:50:00.000000000 +0100 @@ -20,14 +20,15 @@ corrected from a list of dictionary words presented as a completion menu. Installing Jinx is straight-forward and configuring should not need much -intervention. Jinx can be used completely on its own, but can also safely -co-exist with Emacs's built-in spell-checker Ispell. +intervention. Jinx can be used completely on its own, and is designed as a full +replacement for Emacs's built-in spell-checker Ispell, but it can also safely +co-exist with it. Jinx's high performance and low resource usage comes from directly calling the API of the [[https://rrthomas.github.io/enchant/][Enchant library]]. Jinx automatically compiles =jinx-mod.c= and loads the dynamic module at startup. By binding directly to the native Enchant API, Jinx avoids slower inter-process communication. Enchant is used by other text editors -and supports multiple backends like [[https://nuspell.github.io/][Nuspell]], [[http://hunspell.github.io/][Hunspell]] and [[http://aspell.net/][Aspell]]. +and supports multiple backends like [[https://nuspell.github.io/][Nuspell]], [[https://hunspell.github.io/][Hunspell]] and [[http://aspell.net/][Aspell]]. Jinx supports spell-checking multiple languages in the same buffer. See the =jinx-languages= variable to customize for multiple languages. Jinx can flexibly @@ -43,18 +44,20 @@ Jinx can be installed from GNU ELPA or MELPA directly with =package-install=. -Most importantly your Emacs must be compiled with dynamic module support. Jinx -requires =libenchant=, which is needed to compile the native module at install -time. If =pkgconf= or =pkg-config= is available, Jinx will use it to locate -=libenchant= during installation. Depending on your BSD or Linux distribution you -have to install different packages: +Your Emacs must be compiled with dynamic module support. Furthermore a C +compiler must be available on your system (=gcc= or =clang=). Jinx requires +=libenchant=, which is needed to compile the native module at install time. If +=pkgconf= or =pkg-config= is available, Jinx will use it to locate =libenchant= during +installation. Depending on your BSD or Linux distribution you have to install +different packages: - Debian, Ubuntu: =libenchant-2-dev=, =pkgconf= - Arch, Gentoo: =enchant=, =pkgconf= - Guix: =emacs-jinx= defined in =emacs-xyz.scm= - Nix: =jinx= defined in =elpa-packages.nix= -- Void, Fedora: =enchant2-devel=, =pkgconf= -- OpenSUSE: =emacs-jinx= or =enchant=, =pkgconf= +- Void: =enchant2-devel=, =pkgconf= +- Fedora: =emacs-jinx= or =enchant2-devel=, =pkgconf-pkg-config= +- OpenSUSE: =emacs-jinx= or =enchant-devel=, =pkgconf-pkg-config= - FreeBSD, OpenBSD, Mac: =enchant2=, =pkgconf= On Windows the installation of the native module may require manual @@ -85,9 +88,9 @@ #+end_src - =M-$= triggers correction for the misspelled word before point. -- =C-u M-$= triggers correction for the entire buffer. -- =C-u C-u M-$= forces correction of the word at point, even if it is not - misspelled. +- =C-u M-$= or =M-x jinx-correct-all= spell-checks the entire buffer. +- =C-u C-u M-$= or =M-x jinx-correct-word= forces correction of the word at point, + even if it is not misspelled. A sample configuration with the popular =use-package= macro is shown here: @@ -109,11 +112,13 @@ from suggestions. If you prefer to use the keyboard, invoke the command =jinx-correct=. The -recommended binding is =M-$=, see the configuration section. Suggested corrections -will be displayed as a completion menu. You can press the displayed digit keys -to quickly select a suggestion. Furthermore the menu offers options to save the -word temporarily for the current session, in the personal dictionary or in the -file-local or directory-local variables. +recommended binding is =M-$=, see the configuration section. In order to check the +entire buffer press the keys =C-u M-$= or use =M-x jinx-correct-all=. + +Suggested corrections will be displayed as a completion menu. You can press the +displayed digit keys to quickly select a suggestion. Furthermore the menu offers +options to save the word temporarily for the current session, in the personal +dictionary or in the file-local or directory-local variables. You can enter arbitrary input at the correction prompt in order to make the correction or to store a modified word in the personal dictionary. For example @@ -134,7 +139,7 @@ #+begin_src emacs-lisp (add-to-list 'vertico-multiform-categories '(jinx grid (vertico-grid-annotate . 20) (vertico-count . 4))) -(vertico-multiform-mode 1) +(vertico-multiform-mode) #+end_src * Navigating between misspellings diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jinx-2.1/emacs-module.h new/jinx-2.6/emacs-module.h --- old/jinx-2.1/emacs-module.h 2025-04-04 13:23:21.000000000 +0200 +++ new/jinx-2.6/emacs-module.h 2026-01-17 17:50:00.000000000 +0100 @@ -1,6 +1,6 @@ /* emacs-module.h - GNU Emacs module API. -Copyright (C) 2015-2021 Free Software Foundation, Inc. +Copyright (C) 2015-2023 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -30,11 +30,12 @@ #include <stdint.h> #include <time.h> -#ifndef __cplusplus +#if ((defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 202311 \ + && !defined __bool_true_false_are_defined && !defined __cplusplus) #include <stdbool.h> #endif -#define EMACS_MAJOR_VERSION 28 +#define EMACS_MAJOR_VERSION 29 #if defined __cplusplus && __cplusplus >= 201103L # define EMACS_NOEXCEPT noexcept @@ -53,7 +54,7 @@ __attribute__ ((__nonnull__ (__VA_ARGS__))) #elif (defined __has_attribute \ && (!defined __clang_minor__ \ - || 3 < __clang_major__ + (5 <= __clang_minor__))) + || 3 < __clang_major__ + (5 <= __clang_minor__))) # if __has_attribute (__nonnull__) # define EMACS_ATTRIBUTE_NONNULL(...) \ __attribute__ ((__nonnull__ (__VA_ARGS__))) @@ -68,7 +69,7 @@ #endif /* Current environment. */ -typedef struct emacs_env_28 emacs_env; +typedef struct emacs_env_29 emacs_env; /* Opaque pointer representing an Emacs Lisp value. BEWARE: Do not assume NULL is a valid value! */ @@ -115,7 +116,7 @@ /* Function has signaled an error using `signal'. */ emacs_funcall_exit_signal = 1, - /* Function has exit using `throw'. */ + /* Function has exited using `throw'. */ emacs_funcall_exit_throw = 2 }; @@ -166,26 +167,26 @@ EMACS_ATTRIBUTE_NONNULL(1, 2, 3); void (*non_local_exit_signal) (emacs_env *env, - emacs_value symbol, emacs_value data) + emacs_value symbol, emacs_value data) EMACS_ATTRIBUTE_NONNULL(1); void (*non_local_exit_throw) (emacs_env *env, - emacs_value tag, emacs_value value) + emacs_value tag, emacs_value value) EMACS_ATTRIBUTE_NONNULL(1); /* Function registration. */ emacs_value (*make_function) (emacs_env *env, - ptrdiff_t min_arity, - ptrdiff_t max_arity, - emacs_value (*func) (emacs_env *env, + ptrdiff_t min_arity, + ptrdiff_t max_arity, + emacs_value (*func) (emacs_env *env, ptrdiff_t nargs, emacs_value* args, void *data) - EMACS_NOEXCEPT + EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1), - const char *docstring, - void *data) + const char *docstring, + void *data) EMACS_ATTRIBUTE_NONNULL(1, 4); emacs_value (*funcall) (emacs_env *env, @@ -240,13 +241,13 @@ /* Create a Lisp string from a utf8 encoded string. */ emacs_value (*make_string) (emacs_env *env, - const char *str, ptrdiff_t len) + const char *str, ptrdiff_t len) EMACS_ATTRIBUTE_NONNULL(1, 2); /* Embedded pointer type. */ emacs_value (*make_user_ptr) (emacs_env *env, - void (*fin) (void *) EMACS_NOEXCEPT, - void *ptr) + void (*fin) (void *) EMACS_NOEXCEPT, + void *ptr) EMACS_ATTRIBUTE_NONNULL(1); void *(*get_user_ptr) (emacs_env *env, emacs_value arg) @@ -257,7 +258,7 @@ void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr)) (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1); void (*set_user_finalizer) (emacs_env *env, emacs_value arg, - void (*fin) (void *) EMACS_NOEXCEPT) + void (*fin) (void *) EMACS_NOEXCEPT) EMACS_ATTRIBUTE_NONNULL(1); /* Vector functions. */ @@ -265,7 +266,7 @@ EMACS_ATTRIBUTE_NONNULL(1); void (*vec_set) (emacs_env *env, emacs_value vector, ptrdiff_t index, - emacs_value value) + emacs_value value) EMACS_ATTRIBUTE_NONNULL(1); ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vector) @@ -301,26 +302,26 @@ EMACS_ATTRIBUTE_NONNULL(1, 2, 3); void (*non_local_exit_signal) (emacs_env *env, - emacs_value symbol, emacs_value data) + emacs_value symbol, emacs_value data) EMACS_ATTRIBUTE_NONNULL(1); void (*non_local_exit_throw) (emacs_env *env, - emacs_value tag, emacs_value value) + emacs_value tag, emacs_value value) EMACS_ATTRIBUTE_NONNULL(1); /* Function registration. */ emacs_value (*make_function) (emacs_env *env, - ptrdiff_t min_arity, - ptrdiff_t max_arity, - emacs_value (*func) (emacs_env *env, + ptrdiff_t min_arity, + ptrdiff_t max_arity, + emacs_value (*func) (emacs_env *env, ptrdiff_t nargs, emacs_value* args, void *data) - EMACS_NOEXCEPT + EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1), - const char *docstring, - void *data) + const char *docstring, + void *data) EMACS_ATTRIBUTE_NONNULL(1, 4); emacs_value (*funcall) (emacs_env *env, @@ -375,13 +376,13 @@ /* Create a Lisp string from a utf8 encoded string. */ emacs_value (*make_string) (emacs_env *env, - const char *str, ptrdiff_t len) + const char *str, ptrdiff_t len) EMACS_ATTRIBUTE_NONNULL(1, 2); /* Embedded pointer type. */ emacs_value (*make_user_ptr) (emacs_env *env, - void (*fin) (void *) EMACS_NOEXCEPT, - void *ptr) + void (*fin) (void *) EMACS_NOEXCEPT, + void *ptr) EMACS_ATTRIBUTE_NONNULL(1); void *(*get_user_ptr) (emacs_env *env, emacs_value arg) @@ -392,7 +393,7 @@ void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr)) (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1); void (*set_user_finalizer) (emacs_env *env, emacs_value arg, - void (*fin) (void *) EMACS_NOEXCEPT) + void (*fin) (void *) EMACS_NOEXCEPT) EMACS_ATTRIBUTE_NONNULL(1); /* Vector functions. */ @@ -400,7 +401,7 @@ EMACS_ATTRIBUTE_NONNULL(1); void (*vec_set) (emacs_env *env, emacs_value vector, ptrdiff_t index, - emacs_value value) + emacs_value value) EMACS_ATTRIBUTE_NONNULL(1); ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vector) @@ -440,26 +441,26 @@ EMACS_ATTRIBUTE_NONNULL(1, 2, 3); void (*non_local_exit_signal) (emacs_env *env, - emacs_value symbol, emacs_value data) + emacs_value symbol, emacs_value data) EMACS_ATTRIBUTE_NONNULL(1); void (*non_local_exit_throw) (emacs_env *env, - emacs_value tag, emacs_value value) + emacs_value tag, emacs_value value) EMACS_ATTRIBUTE_NONNULL(1); /* Function registration. */ emacs_value (*make_function) (emacs_env *env, - ptrdiff_t min_arity, - ptrdiff_t max_arity, - emacs_value (*func) (emacs_env *env, + ptrdiff_t min_arity, + ptrdiff_t max_arity, + emacs_value (*func) (emacs_env *env, ptrdiff_t nargs, emacs_value* args, void *data) - EMACS_NOEXCEPT + EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1), - const char *docstring, - void *data) + const char *docstring, + void *data) EMACS_ATTRIBUTE_NONNULL(1, 4); emacs_value (*funcall) (emacs_env *env, @@ -514,13 +515,13 @@ /* Create a Lisp string from a utf8 encoded string. */ emacs_value (*make_string) (emacs_env *env, - const char *str, ptrdiff_t len) + const char *str, ptrdiff_t len) EMACS_ATTRIBUTE_NONNULL(1, 2); /* Embedded pointer type. */ emacs_value (*make_user_ptr) (emacs_env *env, - void (*fin) (void *) EMACS_NOEXCEPT, - void *ptr) + void (*fin) (void *) EMACS_NOEXCEPT, + void *ptr) EMACS_ATTRIBUTE_NONNULL(1); void *(*get_user_ptr) (emacs_env *env, emacs_value arg) @@ -531,7 +532,7 @@ void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr)) (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1); void (*set_user_finalizer) (emacs_env *env, emacs_value arg, - void (*fin) (void *) EMACS_NOEXCEPT) + void (*fin) (void *) EMACS_NOEXCEPT) EMACS_ATTRIBUTE_NONNULL(1); /* Vector functions. */ @@ -539,7 +540,7 @@ EMACS_ATTRIBUTE_NONNULL(1); void (*vec_set) (emacs_env *env, emacs_value vector, ptrdiff_t index, - emacs_value value) + emacs_value value) EMACS_ATTRIBUTE_NONNULL(1); ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vector) @@ -598,26 +599,26 @@ EMACS_ATTRIBUTE_NONNULL(1, 2, 3); void (*non_local_exit_signal) (emacs_env *env, - emacs_value symbol, emacs_value data) + emacs_value symbol, emacs_value data) EMACS_ATTRIBUTE_NONNULL(1); void (*non_local_exit_throw) (emacs_env *env, - emacs_value tag, emacs_value value) + emacs_value tag, emacs_value value) EMACS_ATTRIBUTE_NONNULL(1); /* Function registration. */ emacs_value (*make_function) (emacs_env *env, - ptrdiff_t min_arity, - ptrdiff_t max_arity, - emacs_value (*func) (emacs_env *env, + ptrdiff_t min_arity, + ptrdiff_t max_arity, + emacs_value (*func) (emacs_env *env, ptrdiff_t nargs, emacs_value* args, void *data) - EMACS_NOEXCEPT + EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1), - const char *docstring, - void *data) + const char *docstring, + void *data) EMACS_ATTRIBUTE_NONNULL(1, 4); emacs_value (*funcall) (emacs_env *env, @@ -672,13 +673,13 @@ /* Create a Lisp string from a utf8 encoded string. */ emacs_value (*make_string) (emacs_env *env, - const char *str, ptrdiff_t len) + const char *str, ptrdiff_t len) EMACS_ATTRIBUTE_NONNULL(1, 2); /* Embedded pointer type. */ emacs_value (*make_user_ptr) (emacs_env *env, - void (*fin) (void *) EMACS_NOEXCEPT, - void *ptr) + void (*fin) (void *) EMACS_NOEXCEPT, + void *ptr) EMACS_ATTRIBUTE_NONNULL(1); void *(*get_user_ptr) (emacs_env *env, emacs_value arg) @@ -689,7 +690,7 @@ void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr)) (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1); void (*set_user_finalizer) (emacs_env *env, emacs_value arg, - void (*fin) (void *) EMACS_NOEXCEPT) + void (*fin) (void *) EMACS_NOEXCEPT) EMACS_ATTRIBUTE_NONNULL(1); /* Vector functions. */ @@ -697,7 +698,7 @@ EMACS_ATTRIBUTE_NONNULL(1); void (*vec_set) (emacs_env *env, emacs_value vector, ptrdiff_t index, - emacs_value value) + emacs_value value) EMACS_ATTRIBUTE_NONNULL(1); ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vector) @@ -726,9 +727,183 @@ const emacs_limb_t *magnitude) EMACS_ATTRIBUTE_NONNULL (1); - /* Add module environment functions newly added in Emacs 28 here. - Before Emacs 28 is released, remove this comment and start - module-env-29.h on the master branch. */ + void (*(*EMACS_ATTRIBUTE_NONNULL (1) + get_function_finalizer) (emacs_env *env, + emacs_value arg)) (void *) EMACS_NOEXCEPT; + + void (*set_function_finalizer) (emacs_env *env, emacs_value arg, + void (*fin) (void *) EMACS_NOEXCEPT) + EMACS_ATTRIBUTE_NONNULL (1); + + int (*open_channel) (emacs_env *env, emacs_value pipe_process) + EMACS_ATTRIBUTE_NONNULL (1); + + void (*make_interactive) (emacs_env *env, emacs_value function, + emacs_value spec) + EMACS_ATTRIBUTE_NONNULL (1); + + /* Create a unibyte Lisp string from a string. */ + emacs_value (*make_unibyte_string) (emacs_env *env, + const char *str, ptrdiff_t len) + EMACS_ATTRIBUTE_NONNULL(1, 2); +}; + +struct emacs_env_29 +{ + /* Structure size (for version checking). */ + ptrdiff_t size; + + /* Private data; users should not touch this. */ + struct emacs_env_private *private_members; + + /* Memory management. */ + + emacs_value (*make_global_ref) (emacs_env *env, emacs_value value) + EMACS_ATTRIBUTE_NONNULL(1); + + void (*free_global_ref) (emacs_env *env, emacs_value global_value) + EMACS_ATTRIBUTE_NONNULL(1); + + /* Non-local exit handling. */ + + enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env) + EMACS_ATTRIBUTE_NONNULL(1); + + void (*non_local_exit_clear) (emacs_env *env) + EMACS_ATTRIBUTE_NONNULL(1); + + enum emacs_funcall_exit (*non_local_exit_get) + (emacs_env *env, emacs_value *symbol, emacs_value *data) + EMACS_ATTRIBUTE_NONNULL(1, 2, 3); + + void (*non_local_exit_signal) (emacs_env *env, + emacs_value symbol, emacs_value data) + EMACS_ATTRIBUTE_NONNULL(1); + + void (*non_local_exit_throw) (emacs_env *env, + emacs_value tag, emacs_value value) + EMACS_ATTRIBUTE_NONNULL(1); + + /* Function registration. */ + + emacs_value (*make_function) (emacs_env *env, + ptrdiff_t min_arity, + ptrdiff_t max_arity, + emacs_value (*func) (emacs_env *env, + ptrdiff_t nargs, + emacs_value* args, + void *data) + EMACS_NOEXCEPT + EMACS_ATTRIBUTE_NONNULL(1), + const char *docstring, + void *data) + EMACS_ATTRIBUTE_NONNULL(1, 4); + + emacs_value (*funcall) (emacs_env *env, + emacs_value func, + ptrdiff_t nargs, + emacs_value* args) + EMACS_ATTRIBUTE_NONNULL(1); + + emacs_value (*intern) (emacs_env *env, const char *name) + EMACS_ATTRIBUTE_NONNULL(1, 2); + + /* Type conversion. */ + + emacs_value (*type_of) (emacs_env *env, emacs_value arg) + EMACS_ATTRIBUTE_NONNULL(1); + + bool (*is_not_nil) (emacs_env *env, emacs_value arg) + EMACS_ATTRIBUTE_NONNULL(1); + + bool (*eq) (emacs_env *env, emacs_value a, emacs_value b) + EMACS_ATTRIBUTE_NONNULL(1); + + intmax_t (*extract_integer) (emacs_env *env, emacs_value arg) + EMACS_ATTRIBUTE_NONNULL(1); + + emacs_value (*make_integer) (emacs_env *env, intmax_t n) + EMACS_ATTRIBUTE_NONNULL(1); + + double (*extract_float) (emacs_env *env, emacs_value arg) + EMACS_ATTRIBUTE_NONNULL(1); + + emacs_value (*make_float) (emacs_env *env, double d) + EMACS_ATTRIBUTE_NONNULL(1); + + /* Copy the content of the Lisp string VALUE to BUFFER as an utf8 + null-terminated string. + + SIZE must point to the total size of the buffer. If BUFFER is + NULL or if SIZE is not big enough, write the required buffer size + to SIZE and return true. + + Note that SIZE must include the last null byte (e.g. "abc" needs + a buffer of size 4). + + Return true if the string was successfully copied. */ + + bool (*copy_string_contents) (emacs_env *env, + emacs_value value, + char *buf, + ptrdiff_t *len) + EMACS_ATTRIBUTE_NONNULL(1, 4); + + /* Create a Lisp string from a utf8 encoded string. */ + emacs_value (*make_string) (emacs_env *env, + const char *str, ptrdiff_t len) + EMACS_ATTRIBUTE_NONNULL(1, 2); + + /* Embedded pointer type. */ + emacs_value (*make_user_ptr) (emacs_env *env, + void (*fin) (void *) EMACS_NOEXCEPT, + void *ptr) + EMACS_ATTRIBUTE_NONNULL(1); + + void *(*get_user_ptr) (emacs_env *env, emacs_value arg) + EMACS_ATTRIBUTE_NONNULL(1); + void (*set_user_ptr) (emacs_env *env, emacs_value arg, void *ptr) + EMACS_ATTRIBUTE_NONNULL(1); + + void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr)) + (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1); + void (*set_user_finalizer) (emacs_env *env, emacs_value arg, + void (*fin) (void *) EMACS_NOEXCEPT) + EMACS_ATTRIBUTE_NONNULL(1); + + /* Vector functions. */ + emacs_value (*vec_get) (emacs_env *env, emacs_value vector, ptrdiff_t index) + EMACS_ATTRIBUTE_NONNULL(1); + + void (*vec_set) (emacs_env *env, emacs_value vector, ptrdiff_t index, + emacs_value value) + EMACS_ATTRIBUTE_NONNULL(1); + + ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vector) + EMACS_ATTRIBUTE_NONNULL(1); + + /* Returns whether a quit is pending. */ + bool (*should_quit) (emacs_env *env) + EMACS_ATTRIBUTE_NONNULL(1); + + /* Processes pending input events and returns whether the module + function should quit. */ + enum emacs_process_input_result (*process_input) (emacs_env *env) + EMACS_ATTRIBUTE_NONNULL (1); + + struct timespec (*extract_time) (emacs_env *env, emacs_value arg) + EMACS_ATTRIBUTE_NONNULL (1); + + emacs_value (*make_time) (emacs_env *env, struct timespec time) + EMACS_ATTRIBUTE_NONNULL (1); + + bool (*extract_big_integer) (emacs_env *env, emacs_value arg, int *sign, + ptrdiff_t *count, emacs_limb_t *magnitude) + EMACS_ATTRIBUTE_NONNULL (1); + + emacs_value (*make_big_integer) (emacs_env *env, int sign, ptrdiff_t count, + const emacs_limb_t *magnitude) + EMACS_ATTRIBUTE_NONNULL (1); void (*(*EMACS_ATTRIBUTE_NONNULL (1) get_function_finalizer) (emacs_env *env, @@ -747,8 +922,12 @@ /* Create a unibyte Lisp string from a string. */ emacs_value (*make_unibyte_string) (emacs_env *env, - const char *str, ptrdiff_t len) + const char *str, ptrdiff_t len) EMACS_ATTRIBUTE_NONNULL(1, 2); + + /* Add module environment functions newly added in Emacs 29 here. + Before Emacs 29 is released, remove this comment and start + module-env-30.h on the master branch. */ }; /* Every module should define a function as follows. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jinx-2.1/jinx-mod.c new/jinx-2.6/jinx-mod.c --- old/jinx-2.1/jinx-mod.c 2025-04-04 13:23:21.000000000 +0200 +++ new/jinx-2.6/jinx-mod.c 2026-01-17 17:50:00.000000000 +0100 @@ -1,6 +1,6 @@ /* Jinx bindings to libenchant -Copyright (C) 2023-2025 Free Software Foundation, Inc. +Copyright (C) 2023-2026 Free Software Foundation, Inc. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -145,19 +145,6 @@ return Qnil; } -static emacs_value jinx_wordchars(emacs_env* env, ptrdiff_t jinx_unused(nargs), - emacs_value args[], void* jinx_unused(data)) { - EnchantDict* dict = env->get_user_ptr(env, args[0]); - if (dict) { - // Enchant older than 2.3.1 does not enforce UTF-8 <gh:rrthomas/enchant#278> - emacs_value str = jinx_str(env, enchant_dict_get_extra_word_characters(dict)); - if (env->non_local_exit_check(env) == emacs_funcall_exit_return) - return str; - env->non_local_exit_clear(env); - } - return Qnil; -} - static emacs_value jinx_suggest(emacs_env* env, ptrdiff_t jinx_unused(nargs), emacs_value args[], void* jinx_unused(data)) { EnchantDict* dict = env->get_user_ptr(env, args[0]); @@ -189,6 +176,5 @@ jinx_defun(env, "jinx--mod-dict", 1, 1, jinx_dict); jinx_defun(env, "jinx--mod-langs", 0, 0, jinx_langs); jinx_defun(env, "jinx--mod-describe", 1, 1, jinx_describe); - jinx_defun(env, "jinx--mod-wordchars", 1, 1, jinx_wordchars); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jinx-2.1/jinx.el new/jinx-2.6/jinx.el --- old/jinx-2.1/jinx.el 2025-04-04 13:23:21.000000000 +0200 +++ new/jinx-2.6/jinx.el 2026-01-17 17:50:00.000000000 +0100 @@ -1,12 +1,12 @@ ;;; jinx.el --- Enchanted Spell Checker -*- lexical-binding: t -*- -;; Copyright (C) 2023-2025 Free Software Foundation, Inc. +;; Copyright (C) 2023-2026 Free Software Foundation, Inc. ;; Author: Daniel Mendler <[email protected]> ;; Maintainer: Daniel Mendler <[email protected]> ;; Created: 2023 -;; Version: 2.1 -;; Package-Requires: ((emacs "28.1") (compat "30")) +;; Version: 2.6 +;; Package-Requires: ((emacs "29.1") (compat "30")) ;; URL: https://github.com/minad/jinx ;; Keywords: convenience, text @@ -71,6 +71,7 @@ "Idle timer delay." :type 'float) +;; TODO Replace with a universal variable in Emacs bug#80071 (defcustom jinx-languages (replace-regexp-in-string "\\..*\\'" "" @@ -154,6 +155,13 @@ checking." :type '(alist :key-type symbol :value-type (choice symbol (repeat face)))) +(defcustom jinx-exclude-properties + '((t read-only)) + "Alist of properties per major mode. +These properties mark regions which should be excluded in spell +checking." + :type '(alist :key-type symbol :value-type (choice symbol (repeat symbol)))) + (defcustom jinx-exclude-regexps '((emacs-lisp-mode "Package-Requires:.*$") (t "[A-Z]+\\>" ;; Uppercase words @@ -163,7 +171,10 @@ "<?[-+_.~a-zA-Z][-+_.~:a-zA-Z0-9]*@[-.a-zA-Z0-9]+>?" ;; Email "\\(?:Local Variables\\|End\\):\\s-*$" ;; Local variable indicator "jinx-\\(?:languages\\|local-words\\):\\s-+.*$")) ;; Local variables - "List of excluded regexps per major mode." + "List of excluded regexps per major mode. +The regexp must match at the beginning of the spell-checked word. +Therefore `jinx-exclude-regexps' cannot be used to exclude larger parts +of a buffer. Write a custom predicate instead, see `jinx--predicates'." :type '(alist :key-type symbol :value-type (choice symbol (repeat regexp)))) (defcustom jinx-suggestion-distance 3 @@ -174,9 +185,11 @@ "Maximal number of suggestions shown in the context menu." :type 'natnum) +;; TODO Replace with a universal variable in Emacs bug#80071 (defvar-local jinx-local-words "" "File-local words, as a string separated by whitespace.") +;; TODO Replace with a universal variable in Emacs bug#80071 (defvar-local jinx-dir-local-words "" "Directory-local words, as a string separated by whitespace.") @@ -278,8 +291,9 @@ "Hooks which reschedule the spell checking timer, see `jinx--reschedule'.") (defvar jinx--predicates - (list #'jinx--face-ignored-p - #'jinx--regexp-ignored-p + (list #'jinx--face-excluded-p + #'jinx--regexp-excluded-p + #'jinx--property-excluded-p #'jinx--word-valid-p) "Predicate functions called at point with argument START. Predicate should return t if the word before point is valid. @@ -288,8 +302,10 @@ (defvar jinx--timer (timer-create) "Global timer to check pending regions.") -(defvar jinx--base-syntax-table +(defvar jinx--syntax-table (let ((st (make-syntax-table))) + (modify-syntax-entry ?' "w" st) + (modify-syntax-entry ?β "w" st) (modify-syntax-entry ?$ "_" st) (modify-syntax-entry ?% "_" st) (modify-syntax-entry '(#xe000 . #xf8ff) "_" st) ;; Priv. use area @@ -301,13 +317,7 @@ (modify-syntax-entry '(#x1cf00 . #x1d7ff) "_" st) ;; Znamenny Musical - Math. Alpha. (modify-syntax-entry '(#x1ee00 . #x1fbff) "_" st) ;; Arabic Math. - Legacy Computing st) - "Parent syntax table of `jinx--syntax-table'.") - -(defvar jinx--syntax-overrides - '((?' . "w") - (?β . "w") - (?. . ".")) - "Syntax table overrides used for `jinx--syntax-table'.") + "Syntax table used during checking.") (defvar jinx--select-keys "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -323,6 +333,9 @@ (defvar-local jinx--exclude-faces nil "List of excluded faces.") +(defvar-local jinx--exclude-properties nil + "List of excluded properties.") + (defvar-local jinx--include-faces nil "List of included faces.") @@ -338,12 +351,6 @@ (defvar jinx--dicts-hash (make-hash-table :test #'equal :weakness 'value) "Weak hash table of all loaded dictionaries.") -(defvar-local jinx--syntax-table nil - "Syntax table used during checking. -The table inherits from `jinx--base-syntax-table'. The table is -configured according to the word characters defined by the local -dictionaries. Afterwards `jinx--syntax-overrides' are applied.") - (defvar-local jinx--session-words nil "List of words accepted in this session.") @@ -351,13 +358,12 @@ (defvar repeat-mode) (defvar jinx-mode) -(declare-function jinx--mod-check nil) -(declare-function jinx--mod-add nil) -(declare-function jinx--mod-suggest nil) -(declare-function jinx--mod-dict nil) -(declare-function jinx--mod-describe nil) -(declare-function jinx--mod-langs nil) -(declare-function jinx--mod-wordchars nil) +(declare-function jinx--mod-check "ext:jinx-mod.c") +(declare-function jinx--mod-add "ext:jinx-mod.c") +(declare-function jinx--mod-suggest "ext:jinx-mod.c") +(declare-function jinx--mod-dict "ext:jinx-mod.c") +(declare-function jinx--mod-describe "ext:jinx-mod.c") +(declare-function jinx--mod-langs "ext:jinx-mod.c") ;;;; Overlay properties @@ -372,18 +378,18 @@ ;;;; Predicates -(defun jinx--regexp-ignored-p (start) - "Return non-nil if word at START matches ignore regexps." +(defun jinx--regexp-excluded-p (pos) + "Return non-nil if word at POS matches a regexp from `jinx-exclude-regexps'." (save-excursion - (goto-char start) + (goto-char pos) (when (and jinx--exclude-regexp (looking-at-p jinx--exclude-regexp)) (save-match-data (looking-at jinx--exclude-regexp) (match-end 0))))) -(defun jinx--face-ignored-p (start) - "Return non-nil if face at START of word is ignored." - (let ((face (get-text-property start 'face))) +(defun jinx--face-excluded-p (pos) + "Return non-nil if face at POS is excluded via `jinx-exclude-faces'." + (let ((face (get-text-property pos 'face))) (or (and jinx--include-faces (if (listp face) @@ -394,9 +400,18 @@ (cl-loop for f in face thereis (memq f jinx--exclude-faces)) (memq face jinx--exclude-faces)))))) +(defun jinx--property-excluded-p (pos) + "Return non-nil if property at POS is excluded via `jinx-exclude-properties'." + (cl-loop for prop in jinx--exclude-properties + thereis (get-char-property pos prop))) + +(defun jinx--read-only-p (pos) + "Return non-nil if POS is read-only." + (get-text-property pos 'read-only)) + (defun jinx--word-valid-p (word) "Return non-nil if WORD is valid. -WORD can also be a start position." +WORD can also be a position." (unless (stringp word) (setq word (buffer-substring-no-properties word (point)))) (or (member word jinx--session-words) @@ -532,8 +547,8 @@ (with-delayed-message (1 "Checking...") (jinx--check-region start end)) (jinx--get-overlays start end visible)) - (user-error (if visible "No misspelled word in visible text" - "No misspelled word in whole buffer")))) + (user-error "No misspelled word in %s" + (if visible "visible text" (format "buffer `%s'" (buffer-name)))))) (defun jinx--delete-overlays (start end) "Delete overlays between START and END." @@ -577,8 +592,8 @@ (timer-set-function jinx--timer nil) (dolist (frame (frame-list)) (dolist (win (window-list frame 'no-miniwindow)) - (when-let ((buffer (window-buffer win)) - ((buffer-local-value 'jinx-mode buffer))) + (when-let* ((buffer (window-buffer win)) + ((buffer-local-value 'jinx-mode buffer))) (with-current-buffer buffer (jinx--check-pending (window-start win) (window-end win))))))) @@ -613,23 +628,27 @@ (default-directory (file-name-directory (or (locate-library c-name t) (error "Jinx: %s not found" c-name)))) - (command - `(,cc ,@jinx--compile-flags "-o" ,mod-name ,c-name - ,@(split-string-and-unquote - (condition-case nil - (car (process-lines "pkg-config" "--cflags" "--libs" "enchant-2")) - (error "-I/usr/include/enchant-2 -I/usr/local/include/enchant-2 -L/usr/local/lib -lenchant-2")))))) + (command nil) + (inhibit-read-only t)) (with-current-buffer (get-buffer-create "*jinx module compilation*") - (let ((inhibit-read-only t)) - (erase-buffer) - (compilation-mode) - (insert (string-join command " ") "\n") - (if (equal 0 (apply #'call-process (car command) nil (current-buffer) t (cdr command))) - (insert (message "Jinx: %s compiled successfully" mod-name)) - (let ((msg (format "Jinx: Compilation of %s failed" mod-name))) - (insert msg) - (pop-to-buffer (current-buffer)) - (error msg))))) + (erase-buffer) + (compilation-mode) + (insert (format "Jinx: Compiling %s\n" mod-name)) + (setq command + `(,cc ,@jinx--compile-flags "-o" ,mod-name ,c-name + ,@(split-string-and-unquote + (condition-case nil + (car (process-lines "pkg-config" "--cflags" "--libs" "enchant-2")) + (error + (insert "Jinx: pkgconf or pkg-config not found\n") + "-I/usr/include/enchant-2 -I/usr/local/include/enchant-2 -L/usr/local/lib -lenchant-2"))))) + (insert (string-join command " ") "\n") + (if (equal 0 (apply #'call-process (car command) nil (current-buffer) t (cdr command))) + (insert (message "Jinx: %s compiled successfully" mod-name)) + (let ((msg (format "Jinx: Compilation of %s failed" mod-name))) + (insert msg) + (pop-to-buffer (current-buffer)) + (error msg)))) (setq mod-file (expand-file-name mod-name)))) ;; Initialize Mac spell checker to avoid dead lock (gh:minad/jinx#91). (when (and (eq window-system 'mac) (fboundp 'mac-do-applescript)) @@ -642,7 +661,7 @@ "Guard BODY during correction loop." `(cl-letf (((symbol-function #'jinx--timer-handler) #'ignore) ;; Inhibit (repeat-mode nil)) ;; No repeating of jinx-next and jinx-previous - (unless jinx-mode (jinx-mode 1)) + (unless jinx-mode (jinx-mode)) ,@body)) (defun jinx--invisible-open-temporarily () @@ -652,7 +671,7 @@ (dolist (ov (overlays-in (pos-bol) (pos-eol)) restore) (let ((inv (overlay-get ov 'invisible))) (when (and (invisible-p inv) (overlay-get ov 'isearch-open-invisible)) - (push (if-let ((fun (overlay-get ov 'isearch-open-invisible-temporary))) + (push (if-let* ((fun (overlay-get ov 'isearch-open-invisible-temporary))) (progn (funcall fun ov nil) (lambda () (funcall fun ov t))) @@ -664,9 +683,9 @@ "Open overlays which hide the current line. See `isearch-open-necessary-overlays' and `isearch-open-overlay-temporary'." (dolist (ov (overlays-in (pos-bol) (pos-eol))) - (when-let (fun (overlay-get ov 'isearch-open-invisible)) - (when (invisible-p (overlay-get ov 'invisible)) - (funcall fun ov))))) + (when-let* ((fun (overlay-get ov 'isearch-open-invisible)) + ((invisible-p (overlay-get ov 'invisible)))) + (funcall fun ov)))) (defun jinx--correct-highlight (overlay fun) "Highlight and show OVERLAY during FUN." @@ -694,35 +713,29 @@ (defun jinx--correct-setup () "Setup minibuffer for correction." - (use-local-map (make-composed-keymap (list jinx-correct-map) (current-local-map))) - ;; TODO Use `eager-display' on Emacs 31 - (when (and (eq completing-read-function #'completing-read-default) - (not (bound-and-true-p vertico-mode)) - (not (bound-and-true-p icomplete-mode))) - (let ((message-log-max nil) - (inhibit-message t)) - (minibuffer-completion-help)))) + (use-local-map + (make-composed-keymap (list jinx-correct-map) (current-local-map)))) -(defun jinx--add-suggestion (list ht word group) +(defun jinx--add-suggestion (list ht word group &optional suffix) "Add suggestion WORD to LIST and HT. -The word will be associated with GROUP and get a prefix key." +The suggestion will get a prefix key. A GROUP and a SUFFIX property are +optionally added." (unless (gethash word ht) (add-text-properties 0 (length word) - (list 'jinx--group group - 'jinx--prefix - (let ((idx (1+ (hash-table-count ht)))) - (cond - ((< idx 10) - (format #("%d " 0 3 (face jinx-key)) - idx)) - ((< (- idx 10) (length jinx--select-keys)) - (format #("0%c " 0 4 (face jinx-key)) - (aref jinx--select-keys (- idx 10))))))) + `( jinx--group ,group + jinx--prefix ,(let ((idx (1+ (hash-table-count ht)))) + (cond + ((< idx 10) + (format #("%d " 0 3 (face jinx-key)) + idx)) + ((< (- idx 10) (length jinx--select-keys)) + (format #("0%c " 0 4 (face jinx-key)) + (aref jinx--select-keys (- idx 10)))))) + jinx--suffix ,suffix) word) - (push word list) - (puthash word t ht)) - list) + (push word (car list)) + (puthash word t ht))) (defun jinx--session-suggestions (word) "Retrieve suggestions for WORD from session." @@ -736,15 +749,15 @@ (defun jinx--correct-suggestions (word) "Retrieve suggestions for WORD from all dictionaries." (let ((ht (make-hash-table :test #'equal)) - (list nil)) + (list (cons nil nil))) (dolist (dict jinx--dicts) (let* ((desc (jinx--mod-describe dict)) (group (format "Suggestions from dictionary β%sβ - %s" (car desc) (cdr desc)))) (dolist (w (jinx--mod-suggest dict word)) - (setq list (jinx--add-suggestion list ht w group))))) + (jinx--add-suggestion list ht w group)))) (dolist (w (jinx--session-suggestions word)) - (setq list (jinx--add-suggestion list ht w "Suggestions from session"))) + (jinx--add-suggestion list ht w "Suggestions from session")) (cl-loop for (key . fun) in jinx--save-keys for actions = (funcall fun nil key word) do @@ -756,12 +769,9 @@ 'face 'jinx-save 'rear-nonsticky t) for a2 = (format #(" [%s]" 0 5 (face jinx-annotation)) a) do (cl-loop - for w2 in (delete-consecutive-dups (list w (downcase w))) do - (push (propertize (concat k2 w2) - 'jinx--group "Accept and save" - 'jinx--suffix a2) - list)))) - (nreverse list))) + for w2 in (list w (downcase w)) do + (jinx--add-suggestion list ht (concat k2 w2) "Accept and save" a2)))) + (nreverse (car list)))) (defun jinx--correct-affixation (cands) "Affixate CANDS during completion." @@ -770,12 +780,6 @@ (or (get-text-property 0 'jinx--prefix cand) "") (or (get-text-property 0 'jinx--suffix cand) "")))) -(defun jinx--correct-annotation (cand) - "Annotate CAND during completion." - (if-let ((prefix (get-text-property 0 'jinx--prefix cand))) - (format #(" (%s)" 0 5 (face jinx-key)) (string-trim prefix)) - (get-text-property 0 'jinx--suffix cand))) - (defun jinx--group (word transform) "Group WORD during completion, TRANSFORM candidate if non-nil." (if transform @@ -808,11 +812,11 @@ (jinx--table-with-metadata (jinx--correct-suggestions word) `((category . jinx) + (eager-display . t) (display-sort-function . ,#'identity) (cycle-sort-function . ,#'identity) (group-function . ,#'jinx--group) - (affixation-function . ,#'jinx--correct-affixation) - (annotation-function . ,#'jinx--correct-annotation))) + (affixation-function . ,#'jinx--correct-affixation))) nil nil initial t word) word))))) (len (length choice))) @@ -827,8 +831,8 @@ (defun jinx--correct-replace (overlay word) "Replace OVERLAY with WORD." - (when-let ((start (overlay-start overlay)) - (end (overlay-end overlay))) + (when-let* ((start (overlay-start overlay)) + (end (overlay-end overlay))) (undo-boundary) (delete-overlay overlay) (goto-char end) @@ -837,19 +841,19 @@ (defun jinx--correct-menu (&rest _) "Return popup mouse menu to correct misspelling." - (when-let ((posn (event-start last-input-event)) - (pt (posn-point posn)) - (ov (car (jinx--get-overlays pt pt t)))) + (when-let* ((posn (event-start last-input-event)) + (pt (posn-point posn)) + (ov (car (jinx--get-overlays pt pt t)))) (let ((menu nil) (word (buffer-substring-no-properties (overlay-start ov) (overlay-end ov)))) (dolist (dict jinx--dicts) - (when-let ((desc (jinx--mod-describe dict)) - (suggestions (jinx--mod-suggest dict word))) + (when-let* ((desc (jinx--mod-describe dict)) + (suggestions (jinx--mod-suggest dict word))) (push `[,(concat "ββ " (car desc) " β " (cdr desc) " ββ") :active nil] menu) (cl-loop for w in suggestions repeat jinx-menu-suggestions do (push `[,w (jinx--correct-replace ,ov ,w)] menu)))) - (when-let ((suggestions (jinx--session-suggestions word))) + (when-let* ((suggestions (jinx--session-suggestions word))) (push ["ββ Session ββ" :active nil] menu) (cl-loop for w in suggestions repeat jinx-menu-suggestions do (push `[,w (jinx--correct-replace ,ov ,w)] menu))) @@ -867,20 +871,14 @@ (defun jinx--load-dicts () "Load dictionaries and setup syntax table." - (setq jinx--dicts (cl-loop for lang in (split-string jinx-languages) - ;; Keep a weak reference to loaded dictionaries. - ;; See <gh:rrthomas/enchant#402>. - for dict = (with-memoization (gethash lang jinx--dicts-hash) - (jinx--mod-dict lang)) - if dict collect dict) - jinx--syntax-table (make-syntax-table jinx--base-syntax-table)) - (unless jinx--dicts - (message "Jinx: No dictionaries available for %S" jinx-languages)) - (dolist (dict jinx--dicts) - (cl-loop for c across (jinx--mod-wordchars dict) do - (modify-syntax-entry c "w" jinx--syntax-table))) - (cl-loop for (k . v) in jinx--syntax-overrides do - (modify-syntax-entry k v jinx--syntax-table))) + (unless (setq jinx--dicts + (cl-loop for lang in (split-string jinx-languages) + ;; Keep a weak reference to loaded dictionaries. + ;; See <gh:rrthomas/enchant#402>. + for dict = (with-memoization (gethash lang jinx--dicts-hash) + (jinx--mod-dict lang)) + if dict collect dict)) + (message "Jinx: No dictionaries available for %S" jinx-languages))) (defun jinx--bounds-of-word () "Return bounds of word at point using `jinx--syntax-table'." @@ -953,11 +951,12 @@ (jinx--add-local-word 'jinx-dir-local-words word) (let ((default-directory (or (locate-dominating-file default-directory ".dir-locals.el") - (when-let (proj (project-current)) + (when-let* ((proj (project-current))) (declare-function project-root "project") (project-root proj)) default-directory))) - (add-dir-local-variable nil 'jinx-dir-local-words jinx-dir-local-words))) + (save-window-excursion + (add-dir-local-variable nil 'jinx-dir-local-words jinx-dir-local-words)))) (list key word "Directory"))) (defun jinx--save-session (save key word) @@ -978,7 +977,7 @@ GLOBAL is non-nil, the languages are changed globally for all buffers. See also the variable `jinx-languages'." (interactive (list (jinx--read-languages) current-prefix-arg)) - (unless jinx-mode (jinx-mode 1)) + (unless jinx-mode (jinx-mode)) (cond (global (kill-local-variable 'jinx-languages) @@ -999,7 +998,7 @@ (defun jinx-correct-all (&optional only-check) "Correct all misspelled words in the buffer. With prefix argument ONLY-CHECK, only check the buffer and highlight all -misspellings, but do not open the correction UI." +misspelled words, but do not open the correction UI." (interactive "*P") (jinx--correct-guard (let* ((overlays (jinx--force-overlays (or (use-region-beginning) (point-min)) @@ -1007,12 +1006,14 @@ :check t)) (count (length overlays)) (idx 0)) - (unless only-check + (if only-check + (message "%d misspelled word%s in buffer `%s'" + count (if (= count 1) "" "s") (buffer-name)) (deactivate-mark) (push-mark) (while-let ((ov (nth idx overlays))) - (if-let (((overlay-buffer ov)) - (skip (jinx--correct-overlay ov :info (format " (%d of %d)" (1+ idx) count)))) + (if-let* (((overlay-buffer ov)) + (skip (jinx--correct-overlay ov :info (format " (%d of %d)" (1+ idx) count)))) (setq idx (mod (+ idx skip) count)) (cl-incf idx))))))) @@ -1026,9 +1027,9 @@ (count (length overlays)) (idx 0)) ;; Not using `while-let' is intentional here. - (while (when-let ((ov (nth idx overlays))) + (while (when-let* ((ov (nth idx overlays))) (if (overlay-buffer ov) - (when-let ((skip (jinx--correct-overlay ov))) + (when-let* ((skip (jinx--correct-overlay ov))) (setq idx (mod (+ idx skip) count))) (cl-incf idx)))))))) ;; Skip deleted overlay @@ -1048,7 +1049,7 @@ (jinx--correct-overlay ov :initial initial) (delete-overlay ov))))) (forward-to-word skip) - (when-let ((bounds (jinx--bounds-of-word))) + (when-let* ((bounds (jinx--bounds-of-word))) (setf (cons start end) bounds initial nil)))))) @@ -1062,15 +1063,11 @@ is 4, corresponding to \\[universal-argument] pressed once, correct all misspelled words. - `jinx-correct-word': If prefix ARG is 16, corresponding to - \\[universal-argument] pressed twice, correct word before point. - - If prefix ARG is 64, corresponding to \\[universal-argument] pressed - three times, check the whole buffer, but do not open the correction - UI." + \\[universal-argument] pressed twice, correct word before point." (interactive "*P") (pcase arg ('nil (if (use-region-p) (jinx-correct-all) (jinx-correct-nearest))) ('(16) (jinx-correct-word)) - ('(64) (jinx-correct-all t)) (_ (jinx-correct-all)))) (defun jinx-correct-select () @@ -1088,9 +1085,10 @@ (insert word) (exit-minibuffer))) -(defun jinx-next (n) +(defun jinx-next (&optional n) "Go to to Nth next misspelled word." (interactive "p" jinx-mode) + (unless n (setq n 1)) (unless (= n 0) (if (minibufferp) (throw 'jinx--goto n) @@ -1100,10 +1098,10 @@ (goto-char (overlay-end (nth (mod n (length ov)) ov))) (jinx--invisible-open-permanently))))) -(defun jinx-previous (n) +(defun jinx-previous (&optional n) "Go to to Nth previous misspelled word." (interactive "p" jinx-mode) - (jinx-next (- n))) + (jinx-next (- (or n 1)))) ;;;###autoload (define-minor-mode jinx-mode @@ -1124,11 +1122,12 @@ (hack-local-variables 'ignore-mode)) (jinx--get-org-language) (setq jinx--exclude-regexp - (when-let ((regexps (jinx--mode-list jinx-exclude-regexps))) + (when-let* ((regexps (jinx--mode-list jinx-exclude-regexps))) (mapconcat (lambda (r) (format "\\(?:%s\\)" r)) regexps "\\|")) jinx--include-faces (jinx--mode-list jinx-include-faces) jinx--exclude-faces (jinx--mode-list jinx-exclude-faces) + jinx--exclude-properties (jinx--mode-list jinx-exclude-properties) jinx--camel (or (eq jinx-camel-modes t) (seq-some #'derived-mode-p jinx-camel-modes)) jinx--session-words (nconc (split-string jinx-dir-local-words) @@ -1147,33 +1146,19 @@ (jit-lock-unregister #'jinx--mark-pending) (jinx--cleanup)))) -;; TODO use `:predicate' on Emacs 29 -(defcustom global-jinx-modes '(text-mode prog-mode conf-mode) - "List of modes where Jinx should be enabled. -The variable can either be t, nil or a list of t, nil, mode -symbols or elements of the form (not modes)." - :type '(repeat sexp)) - ;;;###autoload (define-globalized-minor-mode global-jinx-mode jinx-mode jinx--on - :group 'jinx) + :group 'jinx + :predicate '(text-mode prog-mode conf-mode)) (defun jinx--on () "Turn `jinx-mode' on." - (when (and (not (or noninteractive - buffer-read-only - (buffer-base-buffer) ;; Do not enable in indirect buffers - (eq (aref (buffer-name) 0) ?\s))) - ;; TODO use `:predicate' on Emacs 29 - (or (eq t global-jinx-modes) - (eq t (cl-loop for p in global-jinx-modes thereis - (pcase-exhaustive p - ('t t) - ('nil 0) - ((pred symbolp) (and (derived-mode-p p) t)) - (`(not . ,m) (and (seq-some #'derived-mode-p m) 0))))))) - (jinx-mode 1))) + (unless (or noninteractive + buffer-read-only + (buffer-base-buffer) ;; Do not enable in indirect buffers + (eq (aref (buffer-name) 0) ?\s)) + (jinx-mode))) (provide 'jinx) ;;; jinx.el ends here ++++++ jinx.obsinfo ++++++ --- /var/tmp/diff_new_pack.bA7GUJ/_old 2026-02-04 21:08:54.239652483 +0100 +++ /var/tmp/diff_new_pack.bA7GUJ/_new 2026-02-04 21:08:54.255653153 +0100 @@ -1,5 +1,5 @@ name: jinx -version: 2.1 -mtime: 1743765801 -commit: 84fc35aedddfbf24de144245fe9d1c8a61852f7a +version: 2.6 +mtime: 1768668600 +commit: b412673dec759131fe0abb346998b55225fbe771
