GNU bug report logs - #79477
Emacs Emacs 31.0.50: ispell-tests.el: "Can't find Hunspell dictionary with a \.aff affix file"

Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.

Package: emacs; Reported by: Alan Mackenzie <acm@HIDDEN>; dated Sat, 20 Sep 2025 13:54:01 UTC; Maintainer for emacs is bug-gnu-emacs@HIDDEN.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 18 Oct 2025 08:13:11 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Oct 18 04:13:11 2025
Received: from localhost ([127.0.0.1]:37724 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1vA23p-000445-2a
	for submit <at> debbugs.gnu.org; Sat, 18 Oct 2025 04:13:11 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10]:44466)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <eliz@HIDDEN>) id 1vA23j-000424-TZ
 for 79477 <at> debbugs.gnu.org; Sat, 18 Oct 2025 04:13:06 -0400
Received: from fencepost.gnu.org ([2001:470:142:3::e])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <eliz@HIDDEN>)
 id 1vA23c-0006dN-Os; Sat, 18 Oct 2025 04:12:57 -0400
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org;
 s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date:
 mime-version; bh=7h14espPRmn/UAFCozNXQa35e/vdOZOG53QxOQeWgpU=; b=nRlef46UosEO
 dRpg+Ef6ADgGUHbxXqJrq3tjD/2Y5lX4Omc6dMBgYgZffFBe+hGVQF7DhiFKuLOlcB/6++dpDVryZ
 DimnpEN1Wv/VG8/7UKnhxJnPmHfkmi88L0chKeodielx0NGOPXypQ6tW09xZ94ZTdRX0RjBXuREED
 9vnbURQHX8gs7/uOt1BMh0i6YC+D9/g4PC5XNioVhzC4YCBcv4DMXDPEoDb1mhAZcmkjU0SPAJ10c
 XiAnCVJ5zdEZeb9sOeojrU5AhKuwm0oos4gkRLyWLM5PECfv+BpC+tDiuAVNWc/9Xv4oZwHOaxKYJ
 OzuTF0+aUV4vxtSuVBTc/w==;
Date: Sat, 18 Oct 2025 11:12:53 +0300
Message-Id: <861pn0fx16.fsf@HIDDEN>
From: Eli Zaretskii <eliz@HIDDEN>
To: Lockywolf <for_emacs_1@HIDDEN>
In-Reply-To: <87zfa92b5f.fsf@HIDDEN> (message from Lockywolf on
 Fri, 03 Oct 2025 06:26:20 +0800)
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
References: <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN> <aNUJpg5pNil14MlG@HIDDEN>
 <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN> <aNaACoQQJI98OrU9@HIDDEN>
 <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
 <878qi09mu5.fsf@HIDDEN> <aNfbJiBYAS5nyWWx@HIDDEN>
 <87ikgx5zdh.fsf@HIDDEN>
 <2fcc6634-b3c9-4ede-a79b-6dcb2801ee0a@HIDDEN>
 <87zfa92b5f.fsf@HIDDEN>
X-Spam-Score: -2.3 (--)
X-Debbugs-Envelope-To: 79477
Cc: acm@HIDDEN, jschmidt4gnu@HIDDEN, for_emacs_1@HIDDEN,
 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -3.3 (---)

> From: Lockywolf <for_emacs_1@HIDDEN>
> Cc: Lockywolf <for_emacs_1@HIDDEN>,  Alan Mackenzie <acm@HIDDEN>,
>   Eli Zaretskii <eliz@HIDDEN>,  79477 <at> debbugs.gnu.org
> Date: Fri, 03 Oct 2025 06:26:20 +0800
> 
> Jens Schmidt <jschmidt4gnu@HIDDEN> writes:
> > On 2025-10-02  13:14, Lockywolf wrote:
> > Yep.  "1>2" should be "1>&2" or otherwise you might see funny files
> > called "2" hanging around after running test tests.  If that code path
> > ever is taken ...
> 
> Oh, gees, thank you for spotting that.
> 
> New version of the patch attached.

Should I install this version, or would you like to update it
according to Alan's comments in
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=79477#56 ?




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 4 Oct 2025 10:57:02 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Oct 04 06:57:02 2025
Received: from localhost ([127.0.0.1]:48048 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v4zwj-0006jR-Ov
	for submit <at> debbugs.gnu.org; Sat, 04 Oct 2025 06:57:02 -0400
Received: from mail.muc.de ([193.149.48.3]:24601)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <acm@HIDDEN>) id 1v4zwg-0006j4-Tr
 for 79477 <at> debbugs.gnu.org; Sat, 04 Oct 2025 06:56:59 -0400
Received: (qmail 18930 invoked by uid 3782); 4 Oct 2025 12:56:52 +0200
Received: from muc.de (p4fe15e6d.dip0.t-ipconnect.de [79.225.94.109]) (using
 STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP;
 Sat, 04 Oct 2025 12:56:52 +0200
Received: (qmail 30498 invoked by uid 1000); 4 Oct 2025 10:56:51 -0000
Date: Sat, 4 Oct 2025 10:56:51 +0000
To: Lockywolf <for_emacs_1@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
Message-ID: <aOD9c_-8jjDdZd6O@HIDDEN>
References: <aNUJpg5pNil14MlG@HIDDEN>
 <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN>
 <aNaACoQQJI98OrU9@HIDDEN>
 <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
 <878qi09mu5.fsf@HIDDEN>
 <aNfbJiBYAS5nyWWx@HIDDEN>
 <87ikgx5zdh.fsf@HIDDEN>
 <2fcc6634-b3c9-4ede-a79b-6dcb2801ee0a@HIDDEN>
 <87zfa92b5f.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <87zfa92b5f.fsf@HIDDEN>
X-Submission-Agent: TMDA/1.3.x (Ph3nix)
From: Alan Mackenzie <acm@HIDDEN>
X-Primary-Address: acm@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: acm@HIDDEN, Eli Zaretskii <eliz@HIDDEN>,
 Jens Schmidt <jschmidt4gnu@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Hello, Vladimir.

On Fri, Oct 03, 2025 at 06:26:20 +0800, Lockywolf wrote:
> Jens Schmidt <jschmidt4gnu@HIDDEN> writes:
> > On 2025-10-02  13:14, Lockywolf wrote:
> > Yep.  "1>2" should be "1>&2" or otherwise you might see funny files
> > called "2" hanging around after running test tests.  If that code path
> > ever is taken ...

> Oh, gees, thank you for spotting that.

> New version of the patch attached.

Thanks!

Thanks especially for adding the doc strings and the debug specs.

I've tried out the new patch, and make check now runs cleanly.  :-)

There are one or two things in the patch which drew attention, and might
be worth fixing before committing it.  Or, maybe not.  We could really
do with the patch being committed soon.

However, here are the things which I noticed:

> From 5cc9d3c5bbf2da9c0cadaee22e2e7b8a86de15d1 Mon Sep 17 00:00:00 2001
> From: Lockywolf <for_emacs_1@HIDDEN>
> Date: Mon, 22 Sep 2025 12:46:03 +0800
> Subject: [PATCH] Fix detecting a working hunspell on systems without a
>  dictionary.

[ .... ]

> diff --git a/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash b/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash
> index dec4f2d1667..0cc7ede8e38 100755
> --- a/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash
> +++ b/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash
> @@ -1,5 +1,9 @@
>  #!/bin/bash

> +# Presumably it is okay to use GNU Bash, because it is one of the most
> +# popular shells, and even if it is not available, the calling side
> +# inside Emacs knows how to handle errors gracefully.
> +
>  #exec aspell "$@"

I think there are a few people in the Emacs world who would object to
Bash, given the wide range of systems, many of them obsolete, which are
still supported.  It might be worth while reading up on plain Bourne
shell, so as to be ready for those objections when they arrive.  ;-)

[ .... ]

> diff --git a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
> index 0692e11e567..7b546332fdf 100644
> --- a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
> +++ b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el

[ .... ]

> @@ -38,35 +37,51 @@ fake-aspell-path
>
>  (eval-when-compile
>    (require 'cl-macs))
> -(cl-defmacro letopt (bindings &body body)
> -  (declare (indent 1))
> +(cl-defmacro ispell-tests--letopt (bindings &body body)
> +  "Bind BINDINGS with `setopt', then eval BODY.
> +The value of the last form in BODY is returned.
> +Each element of VARLIST is a list (SYMBOL VALUEFORM)
> +(which binds SYMBOL to the value of VALUEFORM with `setopt').
> +This macro is not expected to be used outside of
> +ispell-tests. As `setopt' is naturally mutative,
> +the environment after the end of the form is not
> +guaranteed to be identical to the one before. But the form
> +tries its best.
> +"

This doc string has a superfluous newline at the end.  It would be better
to remove this.

> +  (declare (indent 1) (debug cl-letf))
>    (let* ((binding-var (lambda (binding) (car binding)))
>  	 (binding-val (lambda (binding) (cadr binding)))
> -	 (make-setopt (lambda (a b)
> -			(list 'setopt a b)))
> +	 (make-setopt
> +          (lambda (a b)
> +	    (list 'setopt a b)))
> +         (add-ignore-errors
> +          (lambda (a)
> +            (list 'ignore-errors a)))
>  	 (vars (seq-map binding-var bindings))
>  	 (values (seq-map binding-val bindings))
>  	 (temp-vars (seq-map #'gensym vars))
>  	 (savebindings (seq-mapn #'list temp-vars vars))
>  	 (tempbindings (seq-mapn make-setopt vars values))
> -	 (restorebindings (seq-mapn make-setopt vars temp-vars)))
> +	 (restorebindings (seq-mapn add-ignore-errors (seq-mapn make-setopt vars temp-vars))))
>      `(let ,savebindings
>         (unwind-protect (progn ,@tempbindings
>  			      ,@body)
>  	 ,@(reverse restorebindings)))))

> -(cl-defmacro with-ispell-global-dictionary (bindings &body body)
> -  "This macro should not really be needed, but `ispell.el'.
> -Sets up dictionaries in a stupid way."

This doc string doesn't say what the code the macro generates does.  It
just apologizes for its own existence.  ;-)  Also, the full stop
("period" in American English) at the end of the first line is in the
middle of a sentence.  The "This macro should not ..." really belongs at
the bottom of the doc string, after a description of the macro.

> -  (declare (indent 1))
> -  (let* ((dictionary-val (car bindings))
> +(cl-defmacro ispell-tests--with-ispell-global-dictionary (ldict &body body)
> +  "Temporarily bind `ispell-global-dictionary' to value of LDICT,
> +then eval BODY. Then attempt to restore the original value of
> +`ispell-global-dictionary', which may fail, but this form tries
> +its best. "

There's a space at the end of this doc string.

[ .... ]

Other than that, everything looks OK.

> -- 
> Your sincerely,
> Vladimir Nikishkin (MiEr, lockywolf)
> (Laptop)

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 2 Oct 2025 22:26:49 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Oct 02 18:26:49 2025
Received: from localhost ([127.0.0.1]:42098 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v4Rl7-0000hG-Uz
	for submit <at> debbugs.gnu.org; Thu, 02 Oct 2025 18:26:49 -0400
Received: from coconut.lockywolf.net ([213.165.252.157]:58156)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <for_emacs_1@HIDDEN>)
 id 1v4Rku-0000f7-F4
 for 79477 <at> debbugs.gnu.org; Thu, 02 Oct 2025 18:26:36 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=lockywolf.net;
 s=2024-10-06; t=1759443988;
 bh=V61xuJKtUm1aew4kXI7200M6+kawNfF6sWDJ4IuGG+c=;
 h=From:To:Cc:Subject:In-Reply-To:References:Date;
 b=N6hYJJu8Tw0cLfBtH838aBHzbiddTC4M6bPjkUPZgAe4ruqI/gdu1B/THqFUpF4E/
 J38RvHDZIgyQsQdun5E66wYq22dMlzYwJ6IgeoC3UVOH0PnhhTDipSBAV4KnCocXTw
 HZcTfnt4GVoaMLoThHTDxCeCAK4iuTstVMT3XAubD7CcyyfTqHC8i2AExQgdYIGATp
 8E3BFxd0+eKIHjTWEP1/9OID4n7t1SvFsX6+AQVn5jkmrzDcmKQANK++AF8bxIfL9I
 uX2nO4Me5j+7dXPPSHdaNr0C0uZSqXYn3GC5uUwpPRCxTfg4e8eSAZQlyBlD78PEWE
 HIksd5+WPHPmw==
Received: from laptop.lockywolf.net (unknown [183.94.132.38])
 by coconut.lockywolf.net (postfix-encrypted) with ESMTPSA id D9C183905A;
 Fri,  3 Oct 2025 06:26:25 +0800 (CST)
From: Lockywolf <for_emacs_1@HIDDEN>
To: Jens Schmidt <jschmidt4gnu@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
In-Reply-To: <2fcc6634-b3c9-4ede-a79b-6dcb2801ee0a@HIDDEN>
References: <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN> <aNUJpg5pNil14MlG@HIDDEN>
 <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN> <aNaACoQQJI98OrU9@HIDDEN>
 <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
 <878qi09mu5.fsf@HIDDEN> <aNfbJiBYAS5nyWWx@HIDDEN>
 <87ikgx5zdh.fsf@HIDDEN>
 <2fcc6634-b3c9-4ede-a79b-6dcb2801ee0a@HIDDEN>
User-Agent: mu4e 1.12.12; emacs 31.0.50
Date: Fri, 03 Oct 2025 06:26:20 +0800
Message-ID: <87zfa92b5f.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==-=-="
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: Alan Mackenzie <acm@HIDDEN>, Eli Zaretskii <eliz@HIDDEN>,
 Lockywolf <for_emacs_1@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--==-=-=
Content-Type: multipart/signed; boundary="===-=-=";
	micalg=pgp-sha256; protocol="application/pgp-signature"

--===-=-=
Content-Type: text/plain

Jens Schmidt <jschmidt4gnu@HIDDEN> writes:
> On 2025-10-02  13:14, Lockywolf wrote:
> Yep.  "1>2" should be "1>&2" or otherwise you might see funny files
> called "2" hanging around after running test tests.  If that code path
> ever is taken ...

Oh, gees, thank you for spotting that.

New version of the patch attached.


--===-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iHQEARYIAB0WIQSWBebxCAoqaJP8N/j71sGyD+xtqgUCaN78DgAKCRD71sGyD+xt
ql/RAPjhQgmu0LHRsEkd4/8U2dwgDdi7/+b7eH/hTAkPIynWAQCA/LWpfWI7+Bn0
76OpZPjWNQcMxgTTbV99wB4m/BiYDQ==
=Dt10
-----END PGP SIGNATURE-----
--===-=-=--

--==-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-Fix-detecting-a-working-hunspell-on-systems-without-.patch
Content-Transfer-Encoding: quoted-printable

From=205cc9d3c5bbf2da9c0cadaee22e2e7b8a86de15d1 Mon Sep 17 00:00:00 2001
From: Lockywolf <for_emacs_1@HIDDEN>
Date: Mon, 22 Sep 2025 12:46:03 +0800
Subject: [PATCH] Fix detecting a working hunspell on systems without a
 dictionary.

* test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
  (ispell-tests-hunspell--hunspell-working): Implement checker.
  (ispell/hunspell/ispell-word/russian/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/english/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/language-switch/check-only): Add
  skip-check.
  (ispell/hunspell/ispell-word/russian/check-only/wrong-language): Add
  skip-check.
  (ispell/hunspell/ispell-word/multilang): Add skip-check.

* test/lisp/textmodes/ispell-tests/ispell-tests-common.el
  (fake-aspell-path): Improve checking that an engine works.
  (ispell-tests--letopt): Make restoring variables more robust,
  rename to a local name. Add debug spec.
  (ispell-tests--with-ispell-global-dictionary): Rename to a local name
  Add debug spec.

* test/lisp/textmodes/ispell-tests/ispell-tests.el
  (ispell/ispell-buffer-local-words/ispell-buffer-session-localwords):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-buffer-local-words/ispell-words-keyword):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-complete-word-interior-frag/simple):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-complete-word/ispell-completion-at-point):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-init-process/works-with-home):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-kill-ispell):
  reverse letopt and with-ispell-dictionary.

* test/lisp/textmodes/ispell-resources/fake-aspell-new.bash:
  Add comments on unused function. Replace echo with printf.
=2D--
 .../ispell-resources/fake-aspell-new.bash     |  13 +-
 .../ispell-tests/ispell-aspell-tests.el       |   6 +-
 .../ispell-tests/ispell-hunspell-tests.el     |  26 +-
 .../ispell-international-ispell-tests.el      |   6 +-
 .../ispell-tests/ispell-tests-common.el       |  45 ++--
 .../textmodes/ispell-tests/ispell-tests.el    | 230 +++++++++---------
 6 files changed, 181 insertions(+), 145 deletions(-)

diff --git a/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash b/te=
st/lisp/textmodes/ispell-resources/fake-aspell-new.bash
index dec4f2d1667..0cc7ede8e38 100755
=2D-- a/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash
+++ b/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash
@@ -1,5 +1,9 @@
 #!/bin/bash
=20
+# Presumably it is okay to use GNU Bash, because it is one of the most
+# popular shells, and even if it is not available, the calling side
+# inside Emacs knows how to handle errors gracefully.
+
 #exec aspell "$@"
=20
 #rm -rf ~/lwf_mock-aspell.log
@@ -8,15 +12,11 @@
=20
 #printf 'args=3D"%s"\n' "$*" >> /tmp/lwf_mock-aspell.log || { printf "lwf:=
ERROR\n" ; exit 3 ; }
=20
=2D# coproc aspell { aspell "$@" ; }
=2D
 if [[ "$HOME" =3D=3D '' ]] ; then
=2D    echo "HOME is unset. Aspell usually fails in such a case\n" 1>2
+    printf "HOME is unset. Aspell usually fails in such a case\n" 1>&2
     exit 3
 fi
=20
=2Dvv=3D
=2D
 show_vv()
 {
     printf  '%s\n' "@(#) International Ispell Version 3.1.20 (but really A=
spell 0.60.0)"
@@ -69,6 +69,9 @@ imitate_pipe()
=20
 imitate_interactive()
 {
+    : "This function is not used at the moment, but it might become
+     useful eventually, if Emacs starts supporting calling the backend
+     using the human interface, not just the pipe interface."
     exit 6
     while true ; do
 	read a
diff --git a/test/lisp/textmodes/ispell-tests/ispell-aspell-tests.el b/test=
/lisp/textmodes/ispell-tests/ispell-aspell-tests.el
index f3c9fc7a8a0..c9d6fbb552b 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-aspell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-aspell-tests.el
@@ -90,7 +90,7 @@ ispell/aspell/ispell-word/english/correct
                    "aspell" nil t nil "-a" "-denglish"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "aspell")
+      (ispell-tests--letopt ((ispell-program-name "aspell")
                (ispell-dictionary "english"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -126,7 +126,7 @@ ispell/aspell/ispell-word/english/incorrect
                    "aspell" nil t nil "-a" "-denglish"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "aspell")
+      (ispell-tests--letopt ((ispell-program-name "aspell")
                (ispell-dictionary "english"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -158,7 +158,7 @@ ispell/aspell/ispell-word/english/wrong-language
                   (call-process-region nil nil "aspell" nil '("*scratch*" =
t) nil "-a" "-denglish"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "aspell"))
+      (ispell-tests--letopt ((ispell-program-name "aspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
diff --git a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el b/te=
st/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
index 18206b08608..c057f071d79 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
@@ -34,12 +34,22 @@
                          load-path)))
     (require 'ispell-tests-common)))
=20
+(defun ispell-tests-hunspell--hunspell-working ()
+  (if (not (equal
+            0
+            (call-process "hunspell" nil nil nil "-a")))
+      (progn
+        (message "Hunspell installation is broken and does not support a d=
efault dictionary!")
+        nil)
+    t))
+
 (ert-deftest ispell/hunspell/ispell-word/english/check-only ()
 "This test checks that Russian spellchecking works for Hunspell."
   (skip-unless (executable-find "hunspell"))
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -47,7 +57,7 @@ ispell/hunspell/ispell-word/english/check-only
                   (call-process-region nil nil "hunspell" nil '("*scratch*=
" t) nil "-d en_US"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
@@ -108,6 +118,7 @@ ispell/hunspell/ispell-word/russian/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (let ((retval (with-temp-buffer
@@ -117,7 +128,7 @@ ispell/hunspell/ispell-word/russian/check-only
                   retval )))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
@@ -160,6 +171,7 @@ ispell/hunspell/ispell-word/language-switch/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -167,7 +179,7 @@ ispell/hunspell/ispell-word/language-switch/check-only
                   (call-process-region nil nil "hunspell" nil '("*scratch*=
" t) nil "-d" "ru_RU"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
@@ -227,6 +239,7 @@ ispell/hunspell/ispell-word/russian/check-only/wrong-la=
nguage
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -234,7 +247,7 @@ ispell/hunspell/ispell-word/russian/check-only/wrong-la=
nguage
                   (call-process-region nil nil "hunspell" nil '("*scratch*=
" t) nil "-d" "ru_RU"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
@@ -264,6 +277,7 @@ ispell/hunspell/ispell-word/multilang
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -277,7 +291,7 @@ ispell/hunspell/ispell-word/multilang
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory)
           (multidict "en_US,ru_RU"))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (ispell-hunspell-add-multi-dic multidict)
         (with-temp-buffer
@@ -336,7 +350,5 @@ ispell/hunspell/ispell-word/multilang
           ))))
 )
=20
=2D
=2D
 (provide 'ispell-hunspell-tests)
 ;;; ispell-hunspell-tests.el ends here
diff --git a/test/lisp/textmodes/ispell-tests/ispell-international-ispell-t=
ests.el b/test/lisp/textmodes/ispell-tests/ispell-international-ispell-test=
s.el
index b0e887ae1a9..ff4696f5fe7 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-international-ispell-tests.=
el
+++ b/test/lisp/textmodes/ispell-tests/ispell-international-ispell-tests.el
@@ -56,7 +56,7 @@ ispell/international-ispell/ispell-word/russian/check-only
                   (buffer-string))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "ispell")
+      (ispell-tests--letopt ((ispell-program-name "ispell")
                (ispell-local-dictionary-alist
                 '((
                    "russian"
@@ -141,7 +141,7 @@ ispell/international-ispell/ispell-word/language-switch=
/check-only
                   (buffer-string))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "ispell")
+      (ispell-tests--letopt ((ispell-program-name "ispell")
                (ispell-local-dictionary-alist
                 '((
                    "russian"
@@ -227,7 +227,7 @@ ispell/international-ispell/ispell-word/russian/check-o=
nly/wrong-language
                   (buffer-string))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "ispell")
+      (ispell-tests--letopt ((ispell-program-name "ispell")
                (ispell-local-dictionary-alist
                 '((
                    "russian"
diff --git a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el b/test=
/lisp/textmodes/ispell-tests/ispell-tests-common.el
index 0692e11e567..7b546332fdf 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
@@ -21,10 +21,9 @@ fake-aspell-path
                            (lambda (b)
                              (and
                               (executable-find b)
=2D                              ;; (equal 0
=2D                              ;;        (with-temp-buffer
=2D                              ;;          (call-process b nil t "-v")))
=2D                              ))
+                              (equal 0
+                                     (with-temp-buffer
+                                       (call-process b nil t "-a")))))
                            backend-binaries)))
=20
   (defun ispell-tests--some-backend-available-p ()
@@ -38,35 +37,51 @@ fake-aspell-path
=20
 (eval-when-compile
   (require 'cl-macs))
=2D(cl-defmacro letopt (bindings &body body)
=2D  (declare (indent 1))
+(cl-defmacro ispell-tests--letopt (bindings &body body)
+  "Bind BINDINGS with `setopt', then eval BODY.
+The value of the last form in BODY is returned.
+Each element of VARLIST is a list (SYMBOL VALUEFORM)
+(which binds SYMBOL to the value of VALUEFORM with `setopt').
+This macro is not expected to be used outside of
+ispell-tests. As `setopt' is naturally mutative,
+the environment after the end of the form is not
+guaranteed to be identical to the one before. But the form
+tries its best.
+"
+  (declare (indent 1) (debug cl-letf))
   (let* ((binding-var (lambda (binding) (car binding)))
 	 (binding-val (lambda (binding) (cadr binding)))
=2D	 (make-setopt (lambda (a b)
=2D			(list 'setopt a b)))
+	 (make-setopt
+          (lambda (a b)
+	    (list 'setopt a b)))
+         (add-ignore-errors
+          (lambda (a)
+            (list 'ignore-errors a)))
 	 (vars (seq-map binding-var bindings))
 	 (values (seq-map binding-val bindings))
 	 (temp-vars (seq-map #'gensym vars))
 	 (savebindings (seq-mapn #'list temp-vars vars))
 	 (tempbindings (seq-mapn make-setopt vars values))
=2D	 (restorebindings (seq-mapn make-setopt vars temp-vars)))
+	 (restorebindings (seq-mapn add-ignore-errors (seq-mapn make-setopt vars =
temp-vars))))
     `(let ,savebindings
        (unwind-protect (progn ,@tempbindings
 			      ,@body)
 	 ,@(reverse restorebindings)))))
=20
=2D(cl-defmacro with-ispell-global-dictionary (bindings &body body)
=2D  "This macro should not really be needed, but `ispell.el'.
=2DSets up dictionaries in a stupid way."
=2D  (declare (indent 1))
=2D  (let* ((dictionary-val (car bindings))
+(cl-defmacro ispell-tests--with-ispell-global-dictionary (ldict &body body)
+  "Temporarily bind `ispell-global-dictionary' to value of LDICT,
+then eval BODY. Then attempt to restore the original value of
+`ispell-global-dictionary', which may fail, but this form tries
+its best. "
+  (declare (indent 1) (debug t))
+  (let* ((dictionary-val (car ldict))
 	 (temp-var (gensym 'old-dictionary)))
     `(let ((,temp-var (symbol-value 'ispell-dictionary)))
        (unwind-protect (progn (ispell-change-dictionary ,dictionary-val t)
 			      ,@body)
 	 (progn
            (unwind-protect
=2D               (ispell-change-dictionary ,temp-var t)
+               (ignore-errors (ispell-change-dictionary ,temp-var t))
              (message "restoring original dictionary failed")))))))
=20
 (provide 'ispell-tests-common)
diff --git a/test/lisp/textmodes/ispell-tests/ispell-tests.el b/test/lisp/t=
extmodes/ispell-tests/ispell-tests.el
index d4f3c281e95..cc4a949a0a6 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-tests.el
@@ -432,7 +432,7 @@ ispell/ispell-add-per-file-word-list/longline
 This test fails, because ispell.el does not work well with
 nXML comments."
   :expected-result :failed
=2D  (letopt ((ispell-program-name "ispell"))
+  (ispell-tests--letopt ((ispell-program-name "ispell"))
           (with-temp-buffer
             (let* ((testword (format "%s" (random)))
                    (fill-column 50))
@@ -462,18 +462,19 @@ ispell/ispell-buffer-local-words/ispell-words-keyword
 presumably nobody will have `hellooooooo' in their dictionary."
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
=2D    (with-ispell-global-dictionary nil
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
=2D        (with-temp-buffer
=2D          (nxml-mode)
=2D          (ignore-errors (ispell-kill-ispell))
=2D          (ispell-init-process)
=2D          (let ((test-output (ispell--run-on-word "hellooooooo")))
=2D            (should (listp test-output))
=2D            (should-not (equal t test-output)))
=2D          (ispell-add-per-file-word-list "hellooooooo")
=2D          (ispell-buffer-local-words)
=2D          (should (equal t (ispell--run-on-word "hellooooooo")))))))
+    (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backen=
d)))
+            (ispell-tests--with-ispell-global-dictionary
+             nil
+             (with-temp-buffer
+               (nxml-mode)
+               (ignore-errors (ispell-kill-ispell))
+               (ispell-init-process)
+               (let ((test-output (ispell--run-on-word "hellooooooo")))
+                 (should (listp test-output))
+                 (should-not (equal t test-output)))
+               (ispell-add-per-file-word-list "hellooooooo")
+               (ispell-buffer-local-words)
+               (should (equal t (ispell--run-on-word "hellooooooo")))))))
   )
=20
=20
@@ -484,28 +485,29 @@ ispell/ispell-buffer-local-words/ispell-words-keyword
 presumably nobody will have `hellooooooo' in their dictionary."
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
=2D    (with-ispell-global-dictionary nil
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
=2D               (ispell-dictionary nil))
=2D        (cd temporary-file-directory)
=2D        (with-temp-buffer
=2D          (nxml-mode)
=2D          (ignore-errors (ispell-kill-ispell))
=2D          (ispell-init-process)
=2D          (let ((test-output (ispell--run-on-word "hellooooooo")))
=2D            (should (listp test-output))
=2D            (should-not (equal t test-output)))
=2D          (let ((ispell-buffer-session-localwords (list "hellooooooo")))
=2D            (ispell-buffer-local-words)
=2D            (should (equal t (ispell--run-on-word "hellooooooo"))))))))
+    (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backen=
d))
+             (ispell-dictionary nil))
+            (ispell-tests--with-ispell-global-dictionary
+             nil
+             (cd temporary-file-directory)
+             (with-temp-buffer
+               (nxml-mode)
+               (ignore-errors (ispell-kill-ispell))
+               (ispell-init-process)
+               (let ((test-output (ispell--run-on-word "hellooooooo")))
+                 (should (listp test-output))
+                 (should-not (equal t test-output)))
+               (let ((ispell-buffer-session-localwords (list "hellooooooo"=
)))
+                 (ispell-buffer-local-words)
+                 (should (equal t (ispell--run-on-word "hellooooooo"))))))=
))
   )
=20
 (ert-deftest ispell/ispell-init-process/works-no-home ()
   "Simple test to check that ispell-init-process works."
   :expected-result :failed
   (skip-unless (ispell-tests--some-backend-available-p))
=2D  (with-ispell-global-dictionary nil
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+  (ispell-tests--with-ispell-global-dictionary nil
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (with-environment-variables
               (("HOME" (make-temp-name temporary-file-directory)))
@@ -516,11 +518,12 @@ ispell/ispell-init-process/works-no-home
 (ert-deftest ispell/ispell-init-process/works-with-home ()
   "Simple test to check that ispell-init-process works."
   (skip-unless (ispell-tests--some-backend-available-p))
=2D  (with-ispell-global-dictionary nil
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
=2D        (with-temp-buffer
=2D          (with-environment-variables (("HOME" temporary-file-directory))
=2D            (ispell-init-process))))))
+  (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backend)=
))
+          (ispell-tests--with-ispell-global-dictionary
+           nil
+           (with-temp-buffer
+             (with-environment-variables (("HOME" temporary-file-directory=
))
+               (ispell-init-process))))))
=20
 ;; Some more tests for buffer-local stuff.
 ;; `ispell-buffer-local-dict'
@@ -560,7 +563,7 @@ ispell/ispell-init-process/works-with-home
                     "hello\n\n\n"
                     "<!-- " ispell-dictionary-keyword test-dict " -->"
                     "<!-- " ispell-pdict-keyword test-pdict " -->")
=2D                   (letopt ((ispell-current-dictionary "ispellnonexisten=
t2"))
+                   (ispell-tests--letopt ((ispell-current-dictionary "ispe=
llnonexistent2"))
                      (ispell-buffer-local-dict)
                      (should (equal ispell-current-dictionary test-dict))
                      (should (equal ispell-current-personal-dictionary tes=
t-pdict))))
@@ -577,7 +580,7 @@ ispell/ispell-init-process/works-with-home
                     "hello\n\n\n"
                     "<!-- " ispell-dictionary-keyword test-dict " -->"
                     "<!-- " ispell-pdict-keyword test-pdict " -->")
=2D                   (letopt ((ispell-current-dictionary "ispellnonexisten=
t2"))
+                   (ispell-tests--letopt ((ispell-current-dictionary "ispe=
llnonexistent2"))
                      (let ((ispell-local-dictionary-overridden t))
                        (ispell-buffer-local-dict t))
                      (should-not (equal ispell-local-dictionary test-dict))
@@ -596,7 +599,7 @@ ispell/ispell-init-process/works-with-home
                     "hello\n\n\n"
                     "<!-- " ispell-dictionary-keyword test-dict " -->"
                     "<!-- " ispell-pdict-keyword test-pdict " -->")
=2D                   (letopt ((ispell-current-dictionary "ispellnonexisten=
t2"))
+                   (ispell-tests--letopt ((ispell-current-dictionary "ispe=
llnonexistent2"))
                      (let ((ispell-local-dictionary-overridden t))
                        (ispell-buffer-local-dict t))
                      (should-not (equal ispell-current-dictionary test-dic=
t))
@@ -615,7 +618,7 @@ ispell/ispell-buffer-local-parsing/local-keyword
     (let ((test-parser  "~tex")
           (test-dictname "testdict")
           (test-extcharmode "~latin3"))
=2D      (letopt ((ispell-parser 'ispellnonexistent)
+      (ispell-tests--letopt ((ispell-parser 'ispellnonexistent)
                (ispell-local-dictionary-alist
                 `((,test-dictname "[A-Za-z]" "[^A-Za-z]" "[']"
                                   nil ("-B") ,test-extcharmode utf-8)))
@@ -653,7 +656,7 @@ ispell/ispell-buffer-local-parsing/local-keyword/hunspe=
ll-bug
     (let ((test-parser  "~tex")
           (test-dictname "testdict")
           (test-extcharmode "~latin3"))
=2D      (letopt ((ispell-parser 'ispellnonexistent)
+      (ispell-tests--letopt ((ispell-parser 'ispellnonexistent)
                (ispell-local-dictionary-alist
                 `((,test-dictname "[A-Za-z]" "[^A-Za-z]" "[']"
                                   nil ("-B") ,test-extcharmode utf-8)))
@@ -689,7 +692,7 @@ ispell/ispell-buffer-local-parsing/mode-tex
   (with-temp-buffer
     (let ((test-dictname "testdict")
           (test-extcharmode nil))
=2D      (letopt ((ispell-check-comments t)
+      (ispell-tests--letopt ((ispell-check-comments t)
                (ispell-parser 'use-mode-name)
                (ispell-local-dictionary-alist
                 `((,test-dictname "[A-Za-z]" "[^A-Za-z]" "[']"
@@ -722,7 +725,7 @@ ispell/ispell-buffer-local-parsing/extended-character-m=
ode
     (insert
      "hello\n\n\n")
     (let ((test-extcharmode "~latin3"))
=2D      (letopt ((ispell-check-comments t)
+      (ispell-tests--letopt ((ispell-check-comments t)
                (ispell-parser 'use-mode-name)
                ;; FIXME: what if default dictionary sets
                ;; (ispell-get-extended-character-mode)?
@@ -774,7 +777,7 @@ ispell/ispell-accept-buffer-local-defs/simple
                                "enchant-2"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (with-temp-buffer
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (let ((test-dictname "english")
               (test-extcharmode "~latin3")
               (test-parser "~testparser")
@@ -787,7 +790,7 @@ ispell/ispell-accept-buffer-local-defs/simple
            ispell-pdict-keyword (expand-file-name test-pdict temporary-fil=
e-directory) "\n"
            ispell-parsing-keyword test-parser "\n"
            ispell-words-keyword " " test-localword1 " " test-localword2 "\=
n")
=2D          (letopt ((ispell-check-comments t)
+          (ispell-tests--letopt ((ispell-check-comments t)
                    (ispell-parser 'tex)
                    ;; FIXME: what if default dictionary sets
                    ;; (ispell-get-extended-character-mode)?
@@ -827,7 +830,7 @@ ispell/ispell--run-on-word/default
   "`ispell--run-on-word' should be the simplest interface
 for checking a word."
   (skip-unless (ispell-tests--some-backend-available-p))
=2D  (letopt ((ispell-program-name (ispell-tests--some-backend))
+  (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backend))
            (ispell-dictionary "default"))
     (let ((default-directory temporary-file-directory))
       (with-temp-buffer
@@ -876,7 +879,7 @@ ispell/ispell--run-on-word/default/fails
   (skip-unless (equal
                 0
                 (call-process (ispell-tests--some-backend) nil nil nil "-v=
v")))
=2D  (letopt ((ispell-program-name (ispell-tests--some-backend))
+  (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backend))
            (ispell-dictionary "default"))
     (let ((default-directory temporary-file-directory))
       (with-temp-buffer
@@ -908,7 +911,7 @@ ispell/ispell-word/default/check-only/correct
                 (call-process (ispell-tests--some-backend) nil nil nil "-v=
v")))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -935,7 +938,7 @@ ispell/ispell-word/default/check-only/correct/add-init
                 (call-process (ispell-tests--some-backend) nil nil nil "-v=
v")))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil)
                (ispell-check-only t))
         (ignore-errors (ispell-kill-ispell t t))
@@ -960,7 +963,7 @@ ispell/ispell-word/default/check-only/incorrect
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil)
                (ispell-check-only t))
         (ignore-errors (ispell-kill-ispell t t))
@@ -981,7 +984,7 @@ ispell/ispell-region/correct
     (let* ((default-directory temporary-file-directory)
            (words '("hello" "test" "test" "more" "obvious" "word"))
            (text (string-join words " ")))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -1002,7 +1005,7 @@ ispell/ispell-region/incorrect
     (let* ((default-directory temporary-file-directory)
            (words '("hello" "tarampampamtararam" "world"))
            (text (string-join words " ")))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil)
                (ispell-check-only t))
         (ignore-errors (ispell-kill-ispell t t))
@@ -1028,7 +1031,7 @@ ispell/ispell-buffer/correct
     (let* ((default-directory temporary-file-directory)
            (words '("hello" "test" "test" "more" "obvious" "word"))
            (text (string-join words " ")))
=2D      (letopt ((ispell-dictionary nil)
+      (ispell-tests--letopt ((ispell-dictionary nil)
                (ispell-program-name (ispell-tests--some-backend)))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -1054,7 +1057,7 @@ ispell/ispell-buffer/incorrect
     (let* ((default-directory temporary-file-directory)
            (words '("tarampampamtararam" "test" "test" "more" "obvious" "w=
ord" "badworddd"))
            (text (string-join words " ")))
=2D      (letopt ((ispell-dictionary nil)
+      (ispell-tests--letopt ((ispell-dictionary nil)
                (ispell-program-name (ispell-tests--some-backend)))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -1084,13 +1087,14 @@ ispell/ispell-kill-ispell
            (words '("tarampampamtararam" "test" "test" "more" "obvious" "w=
ord"))
            (text (string-join words " ")))
       (with-temp-buffer
=2D        (with-ispell-global-dictionary nil
=2D          (letopt ((ispell-program-name  (ispell-tests--some-backend)))
=2D            (insert text)
=2D            (ispell-init-process)
=2D            (should ispell-async-processp)
=2D            (should (eq (ispell-process-status) 'run))
=2D            (ispell-kill-ispell nil t)))
+        (ispell-tests--letopt ((ispell-program-name  (ispell-tests--some-b=
ackend)))
+                (ispell-tests--with-ispell-global-dictionary
+                 nil
+                 (insert text)
+                 (ispell-init-process)
+                 (should ispell-async-processp)
+                 (should (eq (ispell-process-status) 'run))
+                 (ispell-kill-ispell nil t)))
         'passed
         )))
   (message "lwf:debug2:ispell-program-name=3D%s:ispell-dictionary=3D%s"
@@ -1160,7 +1164,7 @@ ispell/ispell-change-dictionary
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (ispell-change-dictionary "english")
           (should (equal ispell-local-dictionary "english"))
@@ -1178,7 +1182,7 @@ ispell/ispell-comments-and-strings/correct
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-dictionary nil)
+      (ispell-tests--letopt ((ispell-dictionary nil)
                (ispell-program-name (ispell-tests--some-backend)))
         (with-temp-buffer
           (ispell-kill-ispell t t)
@@ -1199,7 +1203,7 @@ ispell/ispell-comments-and-strings/incorrect
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert "#!/bin/bash\n"
                   "echo \"string to check\"\n"
@@ -1217,7 +1221,7 @@ ispell/ispell-comment-or-string-at-point
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-dictionary nil)
+      (ispell-tests--letopt ((ispell-dictionary nil)
                (ispell-program-name (ispell-tests--some-backend)))
         (with-temp-buffer
           (insert "#!/bin/bash\n"
@@ -1238,7 +1242,7 @@ ispell/ispell-pdict-save
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert "test")
           (ispell-kill-ispell t t)
@@ -1251,7 +1255,7 @@ ispell/ispell-pdict-save/force
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert "testttttt")
           (goto-char 1)
@@ -1265,7 +1269,7 @@ ispell/ispell-pdict-save/modified
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend-availabl=
e-p)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end-available-p)))
         (with-temp-buffer
           (insert "testttttt")
           (goto-char 1)
@@ -1286,7 +1290,7 @@ ispell/ispell-pdict-save/unmodified
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert "testttttt")
           (goto-char 1)
@@ -1307,7 +1311,7 @@ ispell/ispell-lookup-words/simple
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory)
            (tempfile (make-temp-file "emacs-ispell.el-test" nil nil "waveg=
uides")))
=2D      (letopt ((ispell-complete-word-dict tempfile))
+      (ispell-tests--letopt ((ispell-complete-word-dict tempfile))
         (with-temp-buffer
           (insert "waveguid")
           (unwind-protect
@@ -1329,27 +1333,28 @@ ispell/ispell-complete-word/ispell-completion-at-po=
int
     (let* ((default-directory temporary-file-directory)
            (tempfile (make-temp-file "emacs-ispell.el-test" nil nil "waveg=
uides")))
       (ignore-errors (ispell-kill-ispell t t))
=2D      (with-ispell-global-dictionary nil
=2D        (letopt ((ispell-program-name (ispell-tests--some-backend))
=2D                 (ispell-complete-word-dict tempfile))
=2D          (with-temp-buffer
=2D            (insert "waveguid")
=2D            (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
=2D                          (car (nth 2 (ispell-completion-at-point)))))
=2D              (unwind-protect
=2D                  (progn
=2D                    (advice-add 'ispell-command-loop :override
=2D                                #'my-ispell-command-loop)
=2D                    (should (equal (car (nth 2 (ispell-completion-at-poi=
nt)))
=2D                                   "waveguides"))
=2D                    (ispell-complete-word)
=2D                    (should (equal "waveguides" (buffer-string))))
=2D                (progn
=2D                  (delete-file tempfile)
=2D                  (advice-remove
=2D                   'ispell-command-loop
=2D                   #'my-ispell-command-loop)))))
=2D          'passed))))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
+               (ispell-complete-word-dict tempfile))
+              (ispell-tests--with-ispell-global-dictionary
+               nil
+               (with-temp-buffer
+                 (insert "waveguid")
+                 (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
+                               (car (nth 2 (ispell-completion-at-point)))))
+                   (unwind-protect
+                       (progn
+                         (advice-add 'ispell-command-loop :override
+                                     #'my-ispell-command-loop)
+                         (should (equal (car (nth 2 (ispell-completion-at-=
point)))
+                                        "waveguides"))
+                         (ispell-complete-word)
+                         (should (equal "waveguides" (buffer-string))))
+                     (progn
+                       (delete-file tempfile)
+                       (advice-remove
+                        'ispell-command-loop
+                        #'my-ispell-command-loop)))))
+               'passed))))
   )
=20
 (ert-deftest ispell/ispell-complete-word-interior-frag/simple ()
@@ -1357,26 +1362,27 @@ ispell/ispell-complete-word-interior-frag/simple
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory)
            (tempfile (make-temp-file "emacs-ispell.el-test" nil nil "waveg=
uides")))
=2D      (with-ispell-global-dictionary nil
=2D        (letopt ((ispell-program-name (ispell-tests--some-backend))
=2D                 (ispell-complete-word-dict tempfile))
=2D          (with-temp-buffer
=2D            (insert "waveguid")
=2D            (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
=2D                          (car (nth 2 (ispell-completion-at-point)))))
=2D              (unwind-protect
=2D                  (progn
=2D                    (advice-add 'ispell-command-loop :override
=2D                                #'my-ispell-command-loop)
=2D                    (goto-char 4)
=2D                    (ispell-complete-word-interior-frag)
=2D                    (should (equal "waveguides" (buffer-string))))
=2D                (progn
=2D                  (delete-file tempfile)
=2D                  (advice-remove
=2D                   'ispell-command-loop
=2D                   #'my-ispell-command-loop)))))
=2D          'passed))))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
+               (ispell-complete-word-dict tempfile))
+              (ispell-tests--with-ispell-global-dictionary
+               nil
+               (with-temp-buffer
+                 (insert "waveguid")
+                 (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
+                               (car (nth 2 (ispell-completion-at-point)))))
+                   (unwind-protect
+                       (progn
+                         (advice-add 'ispell-command-loop :override
+                                     #'my-ispell-command-loop)
+                         (goto-char 4)
+                         (ispell-complete-word-interior-frag)
+                         (should (equal "waveguides" (buffer-string))))
+                     (progn
+                       (delete-file tempfile)
+                       (advice-remove
+                        'ispell-command-loop
+                        #'my-ispell-command-loop)))))
+               'passed))))
   )
=20
 (ert-deftest ispell/ispell-minor-mode/simple ()
@@ -1385,7 +1391,7 @@ ispell/ispell-minor-mode/simple
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil))
         (with-temp-buffer
           (text-mode)
@@ -1406,7 +1412,7 @@ ispell/ispell-message/correct
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil))
         (with-temp-buffer
           (insert
@@ -1438,7 +1444,7 @@ ispell/ispell-message/incorrect
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert
            "To:
=2D-=20
2.46.4


--==-=-=
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable



=2D-=20
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)

--==-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 2 Oct 2025 19:46:05 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Oct 02 15:46:05 2025
Received: from localhost ([127.0.0.1]:41692 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v4PFY-0007RX-WC
	for submit <at> debbugs.gnu.org; Thu, 02 Oct 2025 15:46:04 -0400
Received: from mr5.vodafonemail.de ([145.253.228.165]:46462)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <jschmidt4gnu@HIDDEN>)
 id 1v4PFP-0007R7-II
 for 79477 <at> debbugs.gnu.org; Thu, 02 Oct 2025 15:45:54 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafonemail.de;
 s=vfde-mb-mr2-23sep; t=1759434344;
 bh=1w5go+wl7raI8PWMi/b4YOAdkOg23nPo97Qh3ZY01PI=;
 h=Message-ID:Date:User-Agent:Subject:To:References:From:
 Content-Language:In-Reply-To:Content-Type:From;
 b=NKLhRIb3/yJJEbjUvVo7TCTsl+v3ggTPz9Kz3nFQNjGwLHLUiDsMrcWyaDgFLTSS+
 wlQf1i+E/q7sHNFKZqKtxhpOFCDS4IphGQg7FaUbf/lN6Xc9cTCnqGj30+2qxCY1lk
 Fc/3WAGeOiyf+sdLV5ufk+bxItn8Fb0F4OD0VYpI=
Received: from smtp.vodafone.de (unknown [10.0.0.2])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by mr5.vodafonemail.de (Postfix) with ESMTPS id 4cd2Mr48Zsz1yCG;
 Thu,  2 Oct 2025 19:45:44 +0000 (UTC)
Received: from [192.168.178.42] (port-92-196-205-47.dynamic.as20676.net
 [92.196.205.47])
 (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
 (No client certificate requested)
 by smtp.vodafone.de (Postfix) with ESMTPSA id 4cd2MZ3rjnz8sXT;
 Thu,  2 Oct 2025 19:45:27 +0000 (UTC)
Message-ID: <2fcc6634-b3c9-4ede-a79b-6dcb2801ee0a@HIDDEN>
Date: Thu, 2 Oct 2025 21:45:26 +0200
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
To: Lockywolf <for_emacs_1@HIDDEN>, Alan Mackenzie <acm@HIDDEN>
References: <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN>
 <aNUJpg5pNil14MlG@HIDDEN> <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN> <aNaACoQQJI98OrU9@HIDDEN>
 <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
 <878qi09mu5.fsf@HIDDEN> <aNfbJiBYAS5nyWWx@HIDDEN>
 <87ikgx5zdh.fsf@HIDDEN>
From: Jens Schmidt <jschmidt4gnu@HIDDEN>
Content-Language: de-DE-frami, en-US
In-Reply-To: <87ikgx5zdh.fsf@HIDDEN>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
X-purgate-type: clean
X-purgate: clean
X-purgate-size: 385
X-purgate-ID: 155817::1759434340-43E54982-1B6F9F79/0/0
X-Spam-Score: -0.7 (/)
X-Debbugs-Envelope-To: 79477
Cc: Eli Zaretskii <eliz@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.7 (-)

On 2025-10-02  13:14, Lockywolf wrote:

> Is there anything else, or this issue can be closed?
Yep.  "1>2" should be "1>&2" or otherwise you might see funny files
called "2" hanging around after running test tests.  If that code path
ever is taken ...

Plus I'll leave the testing to Alan, if he wants to, since it's a bit
involved for me to set up the test bed.

Thanks!





Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 2 Oct 2025 11:15:20 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Oct 02 07:15:20 2025
Received: from localhost ([127.0.0.1]:39693 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v4HHJ-0002a5-Sd
	for submit <at> debbugs.gnu.org; Thu, 02 Oct 2025 07:15:19 -0400
Received: from coconut.lockywolf.net ([213.165.252.157]:47128)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <for_emacs_1@HIDDEN>)
 id 1v4HH8-0002Uv-Iq
 for 79477 <at> debbugs.gnu.org; Thu, 02 Oct 2025 07:15:09 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=lockywolf.net;
 s=2024-10-06; t=1759403704;
 bh=z8wQPJau132M+cdrqRGh4SiP7wpoAGc2g+U1PdGWKqY=;
 h=From:To:Cc:Subject:In-Reply-To:References:Date;
 b=UZTTYh7hE2Dyv0mqRAl55qI5+zS3yamYIX2OaBNU/qjj69EhXW7S3FiYPhtbRaTdx
 9PvOuPjgvY7B7JBzzROrXKEaiIfnndCv+1sHYI6XwZlk2cfN/FlFzOY8ZlqS5w+Ui2
 qVhBhmxkoAgmM86CAxxpJeREyLvCpdgtVBIwK+NeVNAGOqnPUH3xyHPkd0Y+chc1G8
 2/Tn7jIO0gvbVR5KfDU+ur+sfDkEDDrjkjjao7c7an6sDy1uDVeU2z/Gk42FZUcbHw
 8RescrGzmzU18M4xulm4+FfSZLV/lOcGpSCLhIjOJuW4FfgOh8PjTVW95hc5gxBBs6
 QUyy/qMBflJ3g==
Received: from laptop.lockywolf.net (unknown
 [IPv6:2408:824e:d2e:8ed0:a941:e1c:c5b7:df52])
 by coconut.lockywolf.net (postfix-encrypted) with ESMTPSA id 7A01039011;
 Thu,  2 Oct 2025 19:14:57 +0800 (CST)
From: Lockywolf <for_emacs_1@HIDDEN>
To: Alan Mackenzie <acm@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
In-Reply-To: <aNfbJiBYAS5nyWWx@HIDDEN>
References: <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN> <aNUJpg5pNil14MlG@HIDDEN>
 <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN> <aNaACoQQJI98OrU9@HIDDEN>
 <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
 <878qi09mu5.fsf@HIDDEN> <aNfbJiBYAS5nyWWx@HIDDEN>
User-Agent: mu4e 1.12.12; emacs 31.0.50
Date: Thu, 02 Oct 2025 19:14:50 +0800
Message-ID: <87ikgx5zdh.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==-=-="
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: Eli Zaretskii <eliz@HIDDEN>, Jens Schmidt <jschmidt4gnu@HIDDEN>,
 Lockywolf <for_emacs_1@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--==-=-=
Content-Type: multipart/signed; boundary="===-=-=";
	micalg=pgp-sha256; protocol="application/pgp-signature"

--===-=-=
Content-Type: text/plain

Alan Mackenzie <acm@HIDDEN> writes:

> However, I'm a little unhappy about some aspects of your original patch
> which implemented these tests.  There are several functions and macros
> which are lacking a properly written doc string, leaving the reader to
> guess what they do.
> For example, the macro letopt has no doc string.  It is hard work indeed
> The doc string for with-ispell-global-dictionary is likewise wholly
> Please write a debug spec for letopt (and any other macros lacking one).
> Debug specs are a bit of a black art, but the debug spec for one of `let'
> or `let*' would be an excellent starting point, and may even work

I have tried to write reasonable debug specs to both macros.
I have also renamed them to test-local names, as the previous names were
too abstract and over-promising.

Thank you for reminding me about the debug specs.

Jens Schmidt <jschmidt4gnu@HIDDEN> writes:

>Also, attached is the result of me reviewing fake-aspell-new.bash (watch
>out for comments starting with "##").  As a general remark, I think it
>is better to use plain Posix-/bin/sh scripts instead of Bash scripts (in
>particular for fake-aspell.bash), but for these two it might not matter
>that much ...

I have incorporated some of your suggestions. In particular I left out
the suggestion to remove (unused) interactive emulation, because I am
still hoping to eventually make ispell.el support "nuspell", which is a
very fast alternative to "hunspell", but which unfortunately does not
support the pipe interface.

Patch attached.

--===-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQSWBebxCAoqaJP8N/j71sGyD+xtqgUCaN5erAAKCRD71sGyD+xt
qopJAQC5iA9/NzhPy32wJnCBmaHYp0UlMUSxvAc4e6vA2ulD+QEAoeJ4guapxclx
G8YgG/kGiQZMuYvcdC1/YHMkdZZf/gE=
=LA1z
-----END PGP SIGNATURE-----
--===-=-=--

--==-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-Fix-detecting-a-working-hunspell-on-systems-without-.patch
Content-Transfer-Encoding: quoted-printable

From=204f7427227a4ccf0fa9e56a26b9e2547340bd4f60 Mon Sep 17 00:00:00 2001
From: Lockywolf <for_emacs_1@HIDDEN>
Date: Mon, 22 Sep 2025 12:46:03 +0800
Subject: [PATCH] Fix detecting a working hunspell on systems without a
 dictionary.

* test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
  (ispell-tests-hunspell--hunspell-working): Implement checker.
  (ispell/hunspell/ispell-word/russian/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/english/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/language-switch/check-only): Add
  skip-check.
  (ispell/hunspell/ispell-word/russian/check-only/wrong-language): Add
  skip-check.
  (ispell/hunspell/ispell-word/multilang): Add skip-check.

* test/lisp/textmodes/ispell-tests/ispell-tests-common.el
  (fake-aspell-path): Improve checking that an engine works.
  (ispell-tests--letopt): Make restoring variables more robust,
  rename to a local name. Add debug spec.
  (ispell-tests--with-ispell-global-dictionary): Rename to a local name
  Add debug spec.

* test/lisp/textmodes/ispell-tests/ispell-tests.el
  (ispell/ispell-buffer-local-words/ispell-buffer-session-localwords):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-buffer-local-words/ispell-words-keyword):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-complete-word-interior-frag/simple):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-complete-word/ispell-completion-at-point):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-init-process/works-with-home):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-kill-ispell):
  reverse letopt and with-ispell-dictionary.

* test/lisp/textmodes/ispell-resources/fake-aspell-new.bash:
  Add comments on unused function. Replace echo with printf.
=2D--
 .../ispell-resources/fake-aspell-new.bash     |  13 +-
 .../ispell-tests/ispell-aspell-tests.el       |   6 +-
 .../ispell-tests/ispell-hunspell-tests.el     |  26 +-
 .../ispell-international-ispell-tests.el      |   6 +-
 .../ispell-tests/ispell-tests-common.el       |  45 ++--
 .../textmodes/ispell-tests/ispell-tests.el    | 230 +++++++++---------
 6 files changed, 181 insertions(+), 145 deletions(-)

diff --git a/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash b/te=
st/lisp/textmodes/ispell-resources/fake-aspell-new.bash
index dec4f2d1667..455447ecbc8 100755
=2D-- a/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash
+++ b/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash
@@ -1,5 +1,9 @@
 #!/bin/bash
=20
+# Presumably it is okay to use GNU Bash, because it is one of the most
+# popular shells, and even if it is not available, the calling side
+# inside Emacs knows how to handle errors gracefully.
+
 #exec aspell "$@"
=20
 #rm -rf ~/lwf_mock-aspell.log
@@ -8,15 +12,11 @@
=20
 #printf 'args=3D"%s"\n' "$*" >> /tmp/lwf_mock-aspell.log || { printf "lwf:=
ERROR\n" ; exit 3 ; }
=20
=2D# coproc aspell { aspell "$@" ; }
=2D
 if [[ "$HOME" =3D=3D '' ]] ; then
=2D    echo "HOME is unset. Aspell usually fails in such a case\n" 1>2
+    printf "HOME is unset. Aspell usually fails in such a case\n" 1>2
     exit 3
 fi
=20
=2Dvv=3D
=2D
 show_vv()
 {
     printf  '%s\n' "@(#) International Ispell Version 3.1.20 (but really A=
spell 0.60.0)"
@@ -69,6 +69,9 @@ imitate_pipe()
=20
 imitate_interactive()
 {
+    : "This function is not used at the moment, but it might become
+     useful eventually, if Emacs starts supporting calling the backend
+     using the human interface, not just the pipe interface."
     exit 6
     while true ; do
 	read a
diff --git a/test/lisp/textmodes/ispell-tests/ispell-aspell-tests.el b/test=
/lisp/textmodes/ispell-tests/ispell-aspell-tests.el
index f3c9fc7a8a0..c9d6fbb552b 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-aspell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-aspell-tests.el
@@ -90,7 +90,7 @@ ispell/aspell/ispell-word/english/correct
                    "aspell" nil t nil "-a" "-denglish"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "aspell")
+      (ispell-tests--letopt ((ispell-program-name "aspell")
                (ispell-dictionary "english"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -126,7 +126,7 @@ ispell/aspell/ispell-word/english/incorrect
                    "aspell" nil t nil "-a" "-denglish"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "aspell")
+      (ispell-tests--letopt ((ispell-program-name "aspell")
                (ispell-dictionary "english"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -158,7 +158,7 @@ ispell/aspell/ispell-word/english/wrong-language
                   (call-process-region nil nil "aspell" nil '("*scratch*" =
t) nil "-a" "-denglish"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "aspell"))
+      (ispell-tests--letopt ((ispell-program-name "aspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
diff --git a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el b/te=
st/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
index 18206b08608..c057f071d79 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
@@ -34,12 +34,22 @@
                          load-path)))
     (require 'ispell-tests-common)))
=20
+(defun ispell-tests-hunspell--hunspell-working ()
+  (if (not (equal
+            0
+            (call-process "hunspell" nil nil nil "-a")))
+      (progn
+        (message "Hunspell installation is broken and does not support a d=
efault dictionary!")
+        nil)
+    t))
+
 (ert-deftest ispell/hunspell/ispell-word/english/check-only ()
 "This test checks that Russian spellchecking works for Hunspell."
   (skip-unless (executable-find "hunspell"))
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -47,7 +57,7 @@ ispell/hunspell/ispell-word/english/check-only
                   (call-process-region nil nil "hunspell" nil '("*scratch*=
" t) nil "-d en_US"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
@@ -108,6 +118,7 @@ ispell/hunspell/ispell-word/russian/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (let ((retval (with-temp-buffer
@@ -117,7 +128,7 @@ ispell/hunspell/ispell-word/russian/check-only
                   retval )))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
@@ -160,6 +171,7 @@ ispell/hunspell/ispell-word/language-switch/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -167,7 +179,7 @@ ispell/hunspell/ispell-word/language-switch/check-only
                   (call-process-region nil nil "hunspell" nil '("*scratch*=
" t) nil "-d" "ru_RU"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
@@ -227,6 +239,7 @@ ispell/hunspell/ispell-word/russian/check-only/wrong-la=
nguage
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -234,7 +247,7 @@ ispell/hunspell/ispell-word/russian/check-only/wrong-la=
nguage
                   (call-process-region nil nil "hunspell" nil '("*scratch*=
" t) nil "-d" "ru_RU"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
           (insert
@@ -264,6 +277,7 @@ ispell/hunspell/ispell-word/multilang
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -277,7 +291,7 @@ ispell/hunspell/ispell-word/multilang
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory)
           (multidict "en_US,ru_RU"))
=2D      (letopt ((ispell-program-name "hunspell"))
+      (ispell-tests--letopt ((ispell-program-name "hunspell"))
         (ignore-errors (ispell-kill-ispell t t))
         (ispell-hunspell-add-multi-dic multidict)
         (with-temp-buffer
@@ -336,7 +350,5 @@ ispell/hunspell/ispell-word/multilang
           ))))
 )
=20
=2D
=2D
 (provide 'ispell-hunspell-tests)
 ;;; ispell-hunspell-tests.el ends here
diff --git a/test/lisp/textmodes/ispell-tests/ispell-international-ispell-t=
ests.el b/test/lisp/textmodes/ispell-tests/ispell-international-ispell-test=
s.el
index b0e887ae1a9..ff4696f5fe7 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-international-ispell-tests.=
el
+++ b/test/lisp/textmodes/ispell-tests/ispell-international-ispell-tests.el
@@ -56,7 +56,7 @@ ispell/international-ispell/ispell-word/russian/check-only
                   (buffer-string))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "ispell")
+      (ispell-tests--letopt ((ispell-program-name "ispell")
                (ispell-local-dictionary-alist
                 '((
                    "russian"
@@ -141,7 +141,7 @@ ispell/international-ispell/ispell-word/language-switch=
/check-only
                   (buffer-string))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "ispell")
+      (ispell-tests--letopt ((ispell-program-name "ispell")
                (ispell-local-dictionary-alist
                 '((
                    "russian"
@@ -227,7 +227,7 @@ ispell/international-ispell/ispell-word/russian/check-o=
nly/wrong-language
                   (buffer-string))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name "ispell")
+      (ispell-tests--letopt ((ispell-program-name "ispell")
                (ispell-local-dictionary-alist
                 '((
                    "russian"
diff --git a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el b/test=
/lisp/textmodes/ispell-tests/ispell-tests-common.el
index 0692e11e567..7b546332fdf 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
@@ -21,10 +21,9 @@ fake-aspell-path
                            (lambda (b)
                              (and
                               (executable-find b)
=2D                              ;; (equal 0
=2D                              ;;        (with-temp-buffer
=2D                              ;;          (call-process b nil t "-v")))
=2D                              ))
+                              (equal 0
+                                     (with-temp-buffer
+                                       (call-process b nil t "-a")))))
                            backend-binaries)))
=20
   (defun ispell-tests--some-backend-available-p ()
@@ -38,35 +37,51 @@ fake-aspell-path
=20
 (eval-when-compile
   (require 'cl-macs))
=2D(cl-defmacro letopt (bindings &body body)
=2D  (declare (indent 1))
+(cl-defmacro ispell-tests--letopt (bindings &body body)
+  "Bind BINDINGS with `setopt', then eval BODY.
+The value of the last form in BODY is returned.
+Each element of VARLIST is a list (SYMBOL VALUEFORM)
+(which binds SYMBOL to the value of VALUEFORM with `setopt').
+This macro is not expected to be used outside of
+ispell-tests. As `setopt' is naturally mutative,
+the environment after the end of the form is not
+guaranteed to be identical to the one before. But the form
+tries its best.
+"
+  (declare (indent 1) (debug cl-letf))
   (let* ((binding-var (lambda (binding) (car binding)))
 	 (binding-val (lambda (binding) (cadr binding)))
=2D	 (make-setopt (lambda (a b)
=2D			(list 'setopt a b)))
+	 (make-setopt
+          (lambda (a b)
+	    (list 'setopt a b)))
+         (add-ignore-errors
+          (lambda (a)
+            (list 'ignore-errors a)))
 	 (vars (seq-map binding-var bindings))
 	 (values (seq-map binding-val bindings))
 	 (temp-vars (seq-map #'gensym vars))
 	 (savebindings (seq-mapn #'list temp-vars vars))
 	 (tempbindings (seq-mapn make-setopt vars values))
=2D	 (restorebindings (seq-mapn make-setopt vars temp-vars)))
+	 (restorebindings (seq-mapn add-ignore-errors (seq-mapn make-setopt vars =
temp-vars))))
     `(let ,savebindings
        (unwind-protect (progn ,@tempbindings
 			      ,@body)
 	 ,@(reverse restorebindings)))))
=20
=2D(cl-defmacro with-ispell-global-dictionary (bindings &body body)
=2D  "This macro should not really be needed, but `ispell.el'.
=2DSets up dictionaries in a stupid way."
=2D  (declare (indent 1))
=2D  (let* ((dictionary-val (car bindings))
+(cl-defmacro ispell-tests--with-ispell-global-dictionary (ldict &body body)
+  "Temporarily bind `ispell-global-dictionary' to value of LDICT,
+then eval BODY. Then attempt to restore the original value of
+`ispell-global-dictionary', which may fail, but this form tries
+its best. "
+  (declare (indent 1) (debug t))
+  (let* ((dictionary-val (car ldict))
 	 (temp-var (gensym 'old-dictionary)))
     `(let ((,temp-var (symbol-value 'ispell-dictionary)))
        (unwind-protect (progn (ispell-change-dictionary ,dictionary-val t)
 			      ,@body)
 	 (progn
            (unwind-protect
=2D               (ispell-change-dictionary ,temp-var t)
+               (ignore-errors (ispell-change-dictionary ,temp-var t))
              (message "restoring original dictionary failed")))))))
=20
 (provide 'ispell-tests-common)
diff --git a/test/lisp/textmodes/ispell-tests/ispell-tests.el b/test/lisp/t=
extmodes/ispell-tests/ispell-tests.el
index d4f3c281e95..cc4a949a0a6 100644
=2D-- a/test/lisp/textmodes/ispell-tests/ispell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-tests.el
@@ -432,7 +432,7 @@ ispell/ispell-add-per-file-word-list/longline
 This test fails, because ispell.el does not work well with
 nXML comments."
   :expected-result :failed
=2D  (letopt ((ispell-program-name "ispell"))
+  (ispell-tests--letopt ((ispell-program-name "ispell"))
           (with-temp-buffer
             (let* ((testword (format "%s" (random)))
                    (fill-column 50))
@@ -462,18 +462,19 @@ ispell/ispell-buffer-local-words/ispell-words-keyword
 presumably nobody will have `hellooooooo' in their dictionary."
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
=2D    (with-ispell-global-dictionary nil
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
=2D        (with-temp-buffer
=2D          (nxml-mode)
=2D          (ignore-errors (ispell-kill-ispell))
=2D          (ispell-init-process)
=2D          (let ((test-output (ispell--run-on-word "hellooooooo")))
=2D            (should (listp test-output))
=2D            (should-not (equal t test-output)))
=2D          (ispell-add-per-file-word-list "hellooooooo")
=2D          (ispell-buffer-local-words)
=2D          (should (equal t (ispell--run-on-word "hellooooooo")))))))
+    (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backen=
d)))
+            (ispell-tests--with-ispell-global-dictionary
+             nil
+             (with-temp-buffer
+               (nxml-mode)
+               (ignore-errors (ispell-kill-ispell))
+               (ispell-init-process)
+               (let ((test-output (ispell--run-on-word "hellooooooo")))
+                 (should (listp test-output))
+                 (should-not (equal t test-output)))
+               (ispell-add-per-file-word-list "hellooooooo")
+               (ispell-buffer-local-words)
+               (should (equal t (ispell--run-on-word "hellooooooo")))))))
   )
=20
=20
@@ -484,28 +485,29 @@ ispell/ispell-buffer-local-words/ispell-words-keyword
 presumably nobody will have `hellooooooo' in their dictionary."
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
=2D    (with-ispell-global-dictionary nil
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
=2D               (ispell-dictionary nil))
=2D        (cd temporary-file-directory)
=2D        (with-temp-buffer
=2D          (nxml-mode)
=2D          (ignore-errors (ispell-kill-ispell))
=2D          (ispell-init-process)
=2D          (let ((test-output (ispell--run-on-word "hellooooooo")))
=2D            (should (listp test-output))
=2D            (should-not (equal t test-output)))
=2D          (let ((ispell-buffer-session-localwords (list "hellooooooo")))
=2D            (ispell-buffer-local-words)
=2D            (should (equal t (ispell--run-on-word "hellooooooo"))))))))
+    (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backen=
d))
+             (ispell-dictionary nil))
+            (ispell-tests--with-ispell-global-dictionary
+             nil
+             (cd temporary-file-directory)
+             (with-temp-buffer
+               (nxml-mode)
+               (ignore-errors (ispell-kill-ispell))
+               (ispell-init-process)
+               (let ((test-output (ispell--run-on-word "hellooooooo")))
+                 (should (listp test-output))
+                 (should-not (equal t test-output)))
+               (let ((ispell-buffer-session-localwords (list "hellooooooo"=
)))
+                 (ispell-buffer-local-words)
+                 (should (equal t (ispell--run-on-word "hellooooooo"))))))=
))
   )
=20
 (ert-deftest ispell/ispell-init-process/works-no-home ()
   "Simple test to check that ispell-init-process works."
   :expected-result :failed
   (skip-unless (ispell-tests--some-backend-available-p))
=2D  (with-ispell-global-dictionary nil
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+  (ispell-tests--with-ispell-global-dictionary nil
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (with-environment-variables
               (("HOME" (make-temp-name temporary-file-directory)))
@@ -516,11 +518,12 @@ ispell/ispell-init-process/works-no-home
 (ert-deftest ispell/ispell-init-process/works-with-home ()
   "Simple test to check that ispell-init-process works."
   (skip-unless (ispell-tests--some-backend-available-p))
=2D  (with-ispell-global-dictionary nil
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
=2D        (with-temp-buffer
=2D          (with-environment-variables (("HOME" temporary-file-directory))
=2D            (ispell-init-process))))))
+  (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backend)=
))
+          (ispell-tests--with-ispell-global-dictionary
+           nil
+           (with-temp-buffer
+             (with-environment-variables (("HOME" temporary-file-directory=
))
+               (ispell-init-process))))))
=20
 ;; Some more tests for buffer-local stuff.
 ;; `ispell-buffer-local-dict'
@@ -560,7 +563,7 @@ ispell/ispell-init-process/works-with-home
                     "hello\n\n\n"
                     "<!-- " ispell-dictionary-keyword test-dict " -->"
                     "<!-- " ispell-pdict-keyword test-pdict " -->")
=2D                   (letopt ((ispell-current-dictionary "ispellnonexisten=
t2"))
+                   (ispell-tests--letopt ((ispell-current-dictionary "ispe=
llnonexistent2"))
                      (ispell-buffer-local-dict)
                      (should (equal ispell-current-dictionary test-dict))
                      (should (equal ispell-current-personal-dictionary tes=
t-pdict))))
@@ -577,7 +580,7 @@ ispell/ispell-init-process/works-with-home
                     "hello\n\n\n"
                     "<!-- " ispell-dictionary-keyword test-dict " -->"
                     "<!-- " ispell-pdict-keyword test-pdict " -->")
=2D                   (letopt ((ispell-current-dictionary "ispellnonexisten=
t2"))
+                   (ispell-tests--letopt ((ispell-current-dictionary "ispe=
llnonexistent2"))
                      (let ((ispell-local-dictionary-overridden t))
                        (ispell-buffer-local-dict t))
                      (should-not (equal ispell-local-dictionary test-dict))
@@ -596,7 +599,7 @@ ispell/ispell-init-process/works-with-home
                     "hello\n\n\n"
                     "<!-- " ispell-dictionary-keyword test-dict " -->"
                     "<!-- " ispell-pdict-keyword test-pdict " -->")
=2D                   (letopt ((ispell-current-dictionary "ispellnonexisten=
t2"))
+                   (ispell-tests--letopt ((ispell-current-dictionary "ispe=
llnonexistent2"))
                      (let ((ispell-local-dictionary-overridden t))
                        (ispell-buffer-local-dict t))
                      (should-not (equal ispell-current-dictionary test-dic=
t))
@@ -615,7 +618,7 @@ ispell/ispell-buffer-local-parsing/local-keyword
     (let ((test-parser  "~tex")
           (test-dictname "testdict")
           (test-extcharmode "~latin3"))
=2D      (letopt ((ispell-parser 'ispellnonexistent)
+      (ispell-tests--letopt ((ispell-parser 'ispellnonexistent)
                (ispell-local-dictionary-alist
                 `((,test-dictname "[A-Za-z]" "[^A-Za-z]" "[']"
                                   nil ("-B") ,test-extcharmode utf-8)))
@@ -653,7 +656,7 @@ ispell/ispell-buffer-local-parsing/local-keyword/hunspe=
ll-bug
     (let ((test-parser  "~tex")
           (test-dictname "testdict")
           (test-extcharmode "~latin3"))
=2D      (letopt ((ispell-parser 'ispellnonexistent)
+      (ispell-tests--letopt ((ispell-parser 'ispellnonexistent)
                (ispell-local-dictionary-alist
                 `((,test-dictname "[A-Za-z]" "[^A-Za-z]" "[']"
                                   nil ("-B") ,test-extcharmode utf-8)))
@@ -689,7 +692,7 @@ ispell/ispell-buffer-local-parsing/mode-tex
   (with-temp-buffer
     (let ((test-dictname "testdict")
           (test-extcharmode nil))
=2D      (letopt ((ispell-check-comments t)
+      (ispell-tests--letopt ((ispell-check-comments t)
                (ispell-parser 'use-mode-name)
                (ispell-local-dictionary-alist
                 `((,test-dictname "[A-Za-z]" "[^A-Za-z]" "[']"
@@ -722,7 +725,7 @@ ispell/ispell-buffer-local-parsing/extended-character-m=
ode
     (insert
      "hello\n\n\n")
     (let ((test-extcharmode "~latin3"))
=2D      (letopt ((ispell-check-comments t)
+      (ispell-tests--letopt ((ispell-check-comments t)
                (ispell-parser 'use-mode-name)
                ;; FIXME: what if default dictionary sets
                ;; (ispell-get-extended-character-mode)?
@@ -774,7 +777,7 @@ ispell/ispell-accept-buffer-local-defs/simple
                                "enchant-2"))))
   (with-environment-variables (("HOME" temporary-file-directory))
     (with-temp-buffer
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (let ((test-dictname "english")
               (test-extcharmode "~latin3")
               (test-parser "~testparser")
@@ -787,7 +790,7 @@ ispell/ispell-accept-buffer-local-defs/simple
            ispell-pdict-keyword (expand-file-name test-pdict temporary-fil=
e-directory) "\n"
            ispell-parsing-keyword test-parser "\n"
            ispell-words-keyword " " test-localword1 " " test-localword2 "\=
n")
=2D          (letopt ((ispell-check-comments t)
+          (ispell-tests--letopt ((ispell-check-comments t)
                    (ispell-parser 'tex)
                    ;; FIXME: what if default dictionary sets
                    ;; (ispell-get-extended-character-mode)?
@@ -827,7 +830,7 @@ ispell/ispell--run-on-word/default
   "`ispell--run-on-word' should be the simplest interface
 for checking a word."
   (skip-unless (ispell-tests--some-backend-available-p))
=2D  (letopt ((ispell-program-name (ispell-tests--some-backend))
+  (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backend))
            (ispell-dictionary "default"))
     (let ((default-directory temporary-file-directory))
       (with-temp-buffer
@@ -876,7 +879,7 @@ ispell/ispell--run-on-word/default/fails
   (skip-unless (equal
                 0
                 (call-process (ispell-tests--some-backend) nil nil nil "-v=
v")))
=2D  (letopt ((ispell-program-name (ispell-tests--some-backend))
+  (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-backend))
            (ispell-dictionary "default"))
     (let ((default-directory temporary-file-directory))
       (with-temp-buffer
@@ -908,7 +911,7 @@ ispell/ispell-word/default/check-only/correct
                 (call-process (ispell-tests--some-backend) nil nil nil "-v=
v")))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -935,7 +938,7 @@ ispell/ispell-word/default/check-only/correct/add-init
                 (call-process (ispell-tests--some-backend) nil nil nil "-v=
v")))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil)
                (ispell-check-only t))
         (ignore-errors (ispell-kill-ispell t t))
@@ -960,7 +963,7 @@ ispell/ispell-word/default/check-only/incorrect
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil)
                (ispell-check-only t))
         (ignore-errors (ispell-kill-ispell t t))
@@ -981,7 +984,7 @@ ispell/ispell-region/correct
     (let* ((default-directory temporary-file-directory)
            (words '("hello" "test" "test" "more" "obvious" "word"))
            (text (string-join words " ")))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -1002,7 +1005,7 @@ ispell/ispell-region/incorrect
     (let* ((default-directory temporary-file-directory)
            (words '("hello" "tarampampamtararam" "world"))
            (text (string-join words " ")))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil)
                (ispell-check-only t))
         (ignore-errors (ispell-kill-ispell t t))
@@ -1028,7 +1031,7 @@ ispell/ispell-buffer/correct
     (let* ((default-directory temporary-file-directory)
            (words '("hello" "test" "test" "more" "obvious" "word"))
            (text (string-join words " ")))
=2D      (letopt ((ispell-dictionary nil)
+      (ispell-tests--letopt ((ispell-dictionary nil)
                (ispell-program-name (ispell-tests--some-backend)))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -1054,7 +1057,7 @@ ispell/ispell-buffer/incorrect
     (let* ((default-directory temporary-file-directory)
            (words '("tarampampamtararam" "test" "test" "more" "obvious" "w=
ord" "badworddd"))
            (text (string-join words " ")))
=2D      (letopt ((ispell-dictionary nil)
+      (ispell-tests--letopt ((ispell-dictionary nil)
                (ispell-program-name (ispell-tests--some-backend)))
         (ignore-errors (ispell-kill-ispell t t))
         (with-temp-buffer
@@ -1084,13 +1087,14 @@ ispell/ispell-kill-ispell
            (words '("tarampampamtararam" "test" "test" "more" "obvious" "w=
ord"))
            (text (string-join words " ")))
       (with-temp-buffer
=2D        (with-ispell-global-dictionary nil
=2D          (letopt ((ispell-program-name  (ispell-tests--some-backend)))
=2D            (insert text)
=2D            (ispell-init-process)
=2D            (should ispell-async-processp)
=2D            (should (eq (ispell-process-status) 'run))
=2D            (ispell-kill-ispell nil t)))
+        (ispell-tests--letopt ((ispell-program-name  (ispell-tests--some-b=
ackend)))
+                (ispell-tests--with-ispell-global-dictionary
+                 nil
+                 (insert text)
+                 (ispell-init-process)
+                 (should ispell-async-processp)
+                 (should (eq (ispell-process-status) 'run))
+                 (ispell-kill-ispell nil t)))
         'passed
         )))
   (message "lwf:debug2:ispell-program-name=3D%s:ispell-dictionary=3D%s"
@@ -1160,7 +1164,7 @@ ispell/ispell-change-dictionary
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (ispell-change-dictionary "english")
           (should (equal ispell-local-dictionary "english"))
@@ -1178,7 +1182,7 @@ ispell/ispell-comments-and-strings/correct
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-dictionary nil)
+      (ispell-tests--letopt ((ispell-dictionary nil)
                (ispell-program-name (ispell-tests--some-backend)))
         (with-temp-buffer
           (ispell-kill-ispell t t)
@@ -1199,7 +1203,7 @@ ispell/ispell-comments-and-strings/incorrect
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert "#!/bin/bash\n"
                   "echo \"string to check\"\n"
@@ -1217,7 +1221,7 @@ ispell/ispell-comment-or-string-at-point
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-dictionary nil)
+      (ispell-tests--letopt ((ispell-dictionary nil)
                (ispell-program-name (ispell-tests--some-backend)))
         (with-temp-buffer
           (insert "#!/bin/bash\n"
@@ -1238,7 +1242,7 @@ ispell/ispell-pdict-save
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert "test")
           (ispell-kill-ispell t t)
@@ -1251,7 +1255,7 @@ ispell/ispell-pdict-save/force
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert "testttttt")
           (goto-char 1)
@@ -1265,7 +1269,7 @@ ispell/ispell-pdict-save/modified
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend-availabl=
e-p)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end-available-p)))
         (with-temp-buffer
           (insert "testttttt")
           (goto-char 1)
@@ -1286,7 +1290,7 @@ ispell/ispell-pdict-save/unmodified
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert "testttttt")
           (goto-char 1)
@@ -1307,7 +1311,7 @@ ispell/ispell-lookup-words/simple
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory)
            (tempfile (make-temp-file "emacs-ispell.el-test" nil nil "waveg=
uides")))
=2D      (letopt ((ispell-complete-word-dict tempfile))
+      (ispell-tests--letopt ((ispell-complete-word-dict tempfile))
         (with-temp-buffer
           (insert "waveguid")
           (unwind-protect
@@ -1329,27 +1333,28 @@ ispell/ispell-complete-word/ispell-completion-at-po=
int
     (let* ((default-directory temporary-file-directory)
            (tempfile (make-temp-file "emacs-ispell.el-test" nil nil "waveg=
uides")))
       (ignore-errors (ispell-kill-ispell t t))
=2D      (with-ispell-global-dictionary nil
=2D        (letopt ((ispell-program-name (ispell-tests--some-backend))
=2D                 (ispell-complete-word-dict tempfile))
=2D          (with-temp-buffer
=2D            (insert "waveguid")
=2D            (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
=2D                          (car (nth 2 (ispell-completion-at-point)))))
=2D              (unwind-protect
=2D                  (progn
=2D                    (advice-add 'ispell-command-loop :override
=2D                                #'my-ispell-command-loop)
=2D                    (should (equal (car (nth 2 (ispell-completion-at-poi=
nt)))
=2D                                   "waveguides"))
=2D                    (ispell-complete-word)
=2D                    (should (equal "waveguides" (buffer-string))))
=2D                (progn
=2D                  (delete-file tempfile)
=2D                  (advice-remove
=2D                   'ispell-command-loop
=2D                   #'my-ispell-command-loop)))))
=2D          'passed))))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
+               (ispell-complete-word-dict tempfile))
+              (ispell-tests--with-ispell-global-dictionary
+               nil
+               (with-temp-buffer
+                 (insert "waveguid")
+                 (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
+                               (car (nth 2 (ispell-completion-at-point)))))
+                   (unwind-protect
+                       (progn
+                         (advice-add 'ispell-command-loop :override
+                                     #'my-ispell-command-loop)
+                         (should (equal (car (nth 2 (ispell-completion-at-=
point)))
+                                        "waveguides"))
+                         (ispell-complete-word)
+                         (should (equal "waveguides" (buffer-string))))
+                     (progn
+                       (delete-file tempfile)
+                       (advice-remove
+                        'ispell-command-loop
+                        #'my-ispell-command-loop)))))
+               'passed))))
   )
=20
 (ert-deftest ispell/ispell-complete-word-interior-frag/simple ()
@@ -1357,26 +1362,27 @@ ispell/ispell-complete-word-interior-frag/simple
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory)
            (tempfile (make-temp-file "emacs-ispell.el-test" nil nil "waveg=
uides")))
=2D      (with-ispell-global-dictionary nil
=2D        (letopt ((ispell-program-name (ispell-tests--some-backend))
=2D                 (ispell-complete-word-dict tempfile))
=2D          (with-temp-buffer
=2D            (insert "waveguid")
=2D            (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
=2D                          (car (nth 2 (ispell-completion-at-point)))))
=2D              (unwind-protect
=2D                  (progn
=2D                    (advice-add 'ispell-command-loop :override
=2D                                #'my-ispell-command-loop)
=2D                    (goto-char 4)
=2D                    (ispell-complete-word-interior-frag)
=2D                    (should (equal "waveguides" (buffer-string))))
=2D                (progn
=2D                  (delete-file tempfile)
=2D                  (advice-remove
=2D                   'ispell-command-loop
=2D                   #'my-ispell-command-loop)))))
=2D          'passed))))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
+               (ispell-complete-word-dict tempfile))
+              (ispell-tests--with-ispell-global-dictionary
+               nil
+               (with-temp-buffer
+                 (insert "waveguid")
+                 (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
+                               (car (nth 2 (ispell-completion-at-point)))))
+                   (unwind-protect
+                       (progn
+                         (advice-add 'ispell-command-loop :override
+                                     #'my-ispell-command-loop)
+                         (goto-char 4)
+                         (ispell-complete-word-interior-frag)
+                         (should (equal "waveguides" (buffer-string))))
+                     (progn
+                       (delete-file tempfile)
+                       (advice-remove
+                        'ispell-command-loop
+                        #'my-ispell-command-loop)))))
+               'passed))))
   )
=20
 (ert-deftest ispell/ispell-minor-mode/simple ()
@@ -1385,7 +1391,7 @@ ispell/ispell-minor-mode/simple
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil))
         (with-temp-buffer
           (text-mode)
@@ -1406,7 +1412,7 @@ ispell/ispell-message/correct
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end))
                (ispell-dictionary nil))
         (with-temp-buffer
           (insert
@@ -1438,7 +1444,7 @@ ispell/ispell-message/incorrect
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory))
=2D      (letopt ((ispell-program-name (ispell-tests--some-backend)))
+      (ispell-tests--letopt ((ispell-program-name (ispell-tests--some-back=
end)))
         (with-temp-buffer
           (insert
            "To:
=2D-=20
2.46.4


--==-=-=
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable


Is there anything else, or this issue can be closed?

=2D-=20
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)

--==-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 27 Sep 2025 13:19:50 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Sep 27 09:19:50 2025
Received: from localhost ([127.0.0.1]:39913 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v2Uq5-0004gX-L1
	for submit <at> debbugs.gnu.org; Sat, 27 Sep 2025 09:19:50 -0400
Received: from mr3.vodafonemail.de ([145.253.228.163]:46146)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <jschmidt4gnu@HIDDEN>)
 id 1v2Ups-0004en-Eu
 for 79477 <at> debbugs.gnu.org; Sat, 27 Sep 2025 09:19:41 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafonemail.de;
 s=vfde-mb-mr2-23sep; t=1758979170;
 bh=YkMoZnOEkLVhfaEmXWL+ee5DjmqfZTkohz7wDfda1JU=;
 h=Content-Type:Message-ID:Date:User-Agent:Subject:To:References:
 From:Content-Language:In-Reply-To:From;
 b=aZXsmNK2f99zNsy6oY2Af0T/DXmVW3t80J4M8qt5UlEzt+CPIzBy20WzJR1GOzlwc
 cu6QeKYfmm9m9cfLYt45OQCL8lFmhBRIAJJVd1P5u67xA7TmuxPO6imRGmuLnyrmV/
 4h2rLaXoEFEcrofZ2APdZepXaVrOuQN/kdF7SoqA=
Received: from smtp.vodafone.de (unknown [10.0.0.2])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by mr3.vodafonemail.de (Postfix) with ESMTPS id 4cYp2V1Pc4z2GRR;
 Sat, 27 Sep 2025 13:19:29 +0000 (UTC)
Received: from [192.168.178.42] (port-92-199-130-153.dynamic.as20676.net
 [92.199.130.153])
 (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
 (No client certificate requested)
 by smtp.vodafone.de (Postfix) with ESMTPSA id 4cYp2D0vq7z8sXJ;
 Sat, 27 Sep 2025 13:19:13 +0000 (UTC)
Content-Type: multipart/mixed; boundary="------------R9pEUurKjbUOk1VIrKzB3MbI"
Message-ID: <e108ae88-85a9-4673-85b5-234ca16d70cf@HIDDEN>
Date: Sat, 27 Sep 2025 15:19:08 +0200
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
To: Alan Mackenzie <acm@HIDDEN>, Lockywolf <for_emacs_1@HIDDEN>
References: <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN>
 <aNUJpg5pNil14MlG@HIDDEN> <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN> <aNaACoQQJI98OrU9@HIDDEN>
 <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
 <878qi09mu5.fsf@HIDDEN> <aNfbJiBYAS5nyWWx@HIDDEN>
From: Jens Schmidt <jschmidt4gnu@HIDDEN>
Content-Language: de-DE-frami, en-US
In-Reply-To: <aNfbJiBYAS5nyWWx@HIDDEN>
X-purgate-type: clean
X-purgate: clean
X-purgate-size: 5407
X-purgate-ID: 155817::1758979165-17E44F98-3E27576D/0/0
X-Spam-Score: -0.7 (/)
X-Debbugs-Envelope-To: 79477
Cc: Eli Zaretskii <eliz@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.7 (-)

This is a multi-part message in MIME format.
--------------R9pEUurKjbUOk1VIrKzB3MbI
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit

On 2025-09-27  14:40, Alan Mackenzie wrote:

> However, I'm a little unhappy about some aspects of your original patch
> which implemented these tests.  There are several functions and macros
> which are lacking a properly written doc string, leaving the reader to
> guess what they do.

+1

Also, attached is the result of me reviewing fake-aspell-new.bash (watch
out for comments starting with "##").  As a general remark, I think it
is better to use plain Posix-/bin/sh scripts instead of Bash scripts (in
particular for fake-aspell.bash), but for these two it might not matter
that much ...

Thanks for providing the tests!  I guess our reports won't be the last
ones, since testing such a feature across a lot of ports and distributions
will always ask for trouble.

(Still working on that other bug, life is currently interfering.)

--------------R9pEUurKjbUOk1VIrKzB3MbI
Content-Type: text/plain; charset=UTF-8; name="fake-aspell-new.bash"
Content-Disposition: attachment; filename="fake-aspell-new.bash"
Content-Transfer-Encoding: base64

IyEvYmluL2Jhc2gKCiMjIHlvdSBwcm9iYWJseSBzaG91bGQgYWRkIGEgY29tbWVudCBoZXJl
IHRoYXQgaXQgaXMgT0sgdG8gdXNlCiMjIEJhc2ggKHdoaWNoIG5vdCBhbGwgcG9ydHMgbWln
aHQgaGF2ZSksIHNpbmNlIHRoZSBjYWxsZXIKIyMgaGFuZGxlcyBmYWlsdXJlcyBleGVjdXRp
bmcgdGhpcyBzY3JpcHQgcHJvcGVybHkuCgojZXhlYyBhc3BlbGwgIiRAIgoKI3JtIC1yZiB+
L2x3Zl9tb2NrLWFzcGVsbC5sb2cKCiNwcmludGYgJ2RhdGU9IiVzIlxuJyAiJChkYXRlIC0t
aXNvPXNlY29uZHMpIiA+IC90bXAvbHdmX21vY2stYXNwZWxsLmxvZwoKI3ByaW50ZiAnYXJn
cz0iJXMiXG4nICIkKiIgPj4gL3RtcC9sd2ZfbW9jay1hc3BlbGwubG9nIHx8IHsgcHJpbnRm
ICJsd2Y6RVJST1JcbiIgOyBleGl0IDMgOyB9CgojIGNvcHJvYyBhc3BlbGwgeyBhc3BlbGwg
IiRAIiA7IH0KCmlmIFtbICIkSE9NRSIgPT0gJycgXV0gOyB0aGVuCiMjICB5b3UgcmVhbGx5
IHdhbnQKIyMgICAgcHJpbnRmICJIT01FIGlzIHVuc2V0LiBBc3BlbGwgdXN1YWxseSBmYWls
cyBpbiBzdWNoIGEgY2FzZVxuIiAxPiYyCiMjICBoZXJlCiAgICBlY2hvICJIT01FIGlzIHVu
c2V0LiBBc3BlbGwgdXN1YWxseSBmYWlscyBpbiBzdWNoIGEgY2FzZVxuIiAxPjIKICAgIGV4
aXQgMwpmaQoKIyMgdGhpcyB2YXJpYWJsZSBpcyBub3QgdXNlZCwgcHJvYmFibHkgcmVtb3Zl
IGl0Pwp2dj0KCnNob3dfdnYoKQp7CiAgICBwcmludGYgICclc1xuJyAiQCgjKSBJbnRlcm5h
dGlvbmFsIElzcGVsbCBWZXJzaW9uIDMuMS4yMCAoYnV0IHJlYWxseSBBc3BlbGwgMC42MC4w
KSIKfQoKaW5fZGljdCgpCnsKICAgIGxvY2FsIHg9JDEKICAgIGZvciB5IGluICR7c2Vzc2lv
bmRpY3RbQF19OyBkbwogICAgICAgIGlmIFsgJHkgPSAkeCBdOyB0aGVuIHJldHVybiAwOyBm
aQogICAgZG9uZQogICAgcmV0dXJuIDEKfQoKaW1pdGF0ZV9waXBlKCkKewogICAgbG9jYWwg
YQogICAgc2hvd192dgogICAgIyMgaWYgeW91IHdhbnQgdG8gZW5zdXJlIHRydWUgMToxIGlu
cHV0IGluIGJlbG93IHJlYWQgc3RhdGVtZW50CiAgICAjIyAod2l0aG91dCB3aGl0ZXNwYWNl
IGJlaW5nIG1hbmdsZWQgYW5kIGJhY2tzbGFzaGVzIGJlaW5nCiAgICAjIyBoYW5kbGVkKSwg
dGhlbiBnbyBmb3IgIndoaWxlIElGUz0nJyByZWFkIC1yIGE7IGRvIgogICAgd2hpbGUgcmVh
ZCBhIDsgZG8KCSNwcmludGYgJ3BpcGU9IiVzIlxuJyAiJGEiID4+IC90bXAvbHdmX21vY2st
YXNwZWxsLmxvZwoJaWYgW1sgIiRhIiA9PSAnJyBdXSA7IHRoZW4KICAgICAgICAgICAgIyMg
cHJvYmFibHkgdXNlIGFuIGV4cGxpY2l0ICJwcmludGYgJ1xuJyIgaGVyZT8KCSAgICBwcmlu
dGYgJycKCWVsaWYgW1sgIiRhIiA9PSAnKycgfHwgIiRhIiA9PSAnfm5yb2ZmJyB8fCAiJGEi
ID09ICd+dGV4JyB8fCAiJGEiID09ICchJyB8fCAiJGEiID09ICctJyB8fCAiJGEiID09ICcl
JyBdXSA7IHRoZW4KCSAgICBwcmludGYgJycKCWVsaWYgW1sgIiR7YTowOjF9IiA9PSAnQCcg
XV0gOyB0aGVuCgkgICAgc2Vzc2lvbmRpY3QrPSgiJHthOjF9IikKCSAgICBwcmludGYgJycK
CWVsc2UKCSAgICBmb3IgYiBpbiAkYSA7IGRvCgkJaWYgW1sgIiRiIiA9PSAnXicgXV0gOyB0
aGVuCgkJICAgIHByaW50ZiAnJwoJCWVsaWYgaW5fZGljdCAiJGIiIHx8IGluX2RpY3QgIiR7
YiNefSIgOyB0aGVuCgkJICAgIHByaW50ZiAnKlxuJwoJCWVsaWYgW1sgIiRiIiA9PSAnXnRh
cmFtcGFtcGFtdGFyYXJhbScgfHwgIiRiIiA9PSAndGFyYW1wYW1wYW10YXJhcmFtJyBdXSA7
IHRoZW4KCQkgICAgcHJpbnRmICcjIHRhcmFtcGFtcGFtdGFyYXJhbSAwXG4nICMgd3Jvbmcg
d29yZAoJCWVsaWYgW1sgIiRiIiA9PSAnXmJhZHdvcmRkZCcgfHwgIiRiIiA9PSAnYmFkd29y
ZGRkJyBdXSA7IHRoZW4KCQkgICAgcHJpbnRmICcjIGJhZHdvcmRkZCAwXG4nICMgd3Jvbmcg
d29yZAoJCWVsaWYgW1sgIiRiIiA9PSAnXmhlbGxvb29vb29vJyB8fCAiJGIiID09ICdoZWxs
b29vb29vbycgXV0gOyB0aGVuCgkJICAgIHByaW50ZiAnIyBoZWxsb29vb29vbyAwXG4nICMg
d3Jvbmcgd29yZAoJCWVsaWYgW1sgIiRiIiA9PSAnXicgXV0gOyB0aGVuCgkJICAgIHByaW50
ZiAnXG4nCgkJZWxzZQoJCSAgICBwcmludGYgIipcbiIKCQlmaQoJICAgIGRvbmUKCSAgICBw
cmludGYgJ1xuJwoJZmkKICAgIGRvbmUKfQoKIyMgdGhpcyBmdW5jdGlvbiBpcyBub3QgdXNl
ZCwgcHJvYmFibHkgcmVtb3ZlIGl0PwppbWl0YXRlX2ludGVyYWN0aXZlKCkKewogICAgZXhp
dCA2CiAgICB3aGlsZSB0cnVlIDsgZG8KCXJlYWQgYQojCXByaW50ZiAnaW50ZXJhY3RpdmU9
IiVzIlxuJyAiJGEiID4+IC90bXAvbHdmX21vY2stYXNwZWxsLmxvZwoJaWYgW1sgIiRhIiA9
PSAnJyBdXSA7IHRoZW4KCSAgICBwcmludGYgJ1xuJwoJZWxpZiBbWyAiJGEiID09ICd0YXJh
bXBhbXBhbXRhcmFyYW0nIF1dIDsgdGhlbgoJICAgIHByaW50ZiAnIyB0YXJhbXBhbXBhbXRh
cmFyYW0gMFxuXG4nICMgd3Jvbmcgd29yZAoJZWxzZQoJICAgIHByaW50ZiAnKlxuXG4nCglm
aQogICAgZG9uZQp9CgoKd2hpbGUgOjsgZG8KICAgIGNhc2UgJDEgaW4KICAgICAgICAtdnZ8
LXYpCiAgICAgICAgICAgIHNob3dfdnYgIyBmb3IgaXNwZWxsLmVsIHZlcnNpb24gZGV0ZWN0
aW9uCiAgICAgICAgICAgIGV4aXQKICAgICAgICAgICAgOzsKICAgICAgICAtYSkgICAgICAg
IyBpbWl0YXRlIFJFUEwKCSAgICBpbWl0YXRlX3BpcGUKCSAgICBleGl0CiAgICAgICAgICAg
IDs7CgktPyopCiAgICAgICAgICAgIHByaW50ZiAnV0FSTjogVW5rbm93biBvcHRpb24gKGln
bm9yZWQpOiAlc1xuJyAiJDEiID4mMgoJICAgIDs7CiAgICAgICAgKikKICAgICAgICAgICAg
YnJlYWsKICAgIGVzYWMKICAgIHNoaWZ0CmRvbmUKCnByaW50ZiAnVXNhZ2U6IGFzcGVsbCBb
b3B0aW9uc10gPGNvbW1hbmQ+XG4nCgojcHJpbnRmICd0aGlzIHBsYWNlIHNob3VsZCBiZSB1
bnJlYWNoYWJsZVxuJyA+PiAvdG1wL2x3Zl9tb2NrLWFzcGVsbC5sb2cK

--------------R9pEUurKjbUOk1VIrKzB3MbI--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 27 Sep 2025 12:40:26 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Sep 27 08:40:26 2025
Received: from localhost ([127.0.0.1]:39675 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v2UDy-0000FH-6r
	for submit <at> debbugs.gnu.org; Sat, 27 Sep 2025 08:40:26 -0400
Received: from mail.muc.de ([193.149.48.3]:30647)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <acm@HIDDEN>) id 1v2UDm-00008V-K1
 for 79477 <at> debbugs.gnu.org; Sat, 27 Sep 2025 08:40:20 -0400
Received: (qmail 51750 invoked by uid 3782); 27 Sep 2025 14:40:07 +0200
Received: from muc.de (p4fe150d6.dip0.t-ipconnect.de [79.225.80.214]) (using
 STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP;
 Sat, 27 Sep 2025 14:40:07 +0200
Received: (qmail 19993 invoked by uid 1000); 27 Sep 2025 12:40:06 -0000
Date: Sat, 27 Sep 2025 12:40:06 +0000
To: Lockywolf <for_emacs_1@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
Message-ID: <aNfbJiBYAS5nyWWx@HIDDEN>
References: <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN>
 <aNUJpg5pNil14MlG@HIDDEN>
 <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN>
 <aNaACoQQJI98OrU9@HIDDEN>
 <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
 <878qi09mu5.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <878qi09mu5.fsf@HIDDEN>
X-Submission-Agent: TMDA/1.3.x (Ph3nix)
From: Alan Mackenzie <acm@HIDDEN>
X-Primary-Address: acm@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: acm@HIDDEN, Eli Zaretskii <eliz@HIDDEN>,
 Jens Schmidt <jschmidt4gnu@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Hello, Vladimir.

On Sat, Sep 27, 2025 at 19:06:10 +0800, Lockywolf wrote:
> Jens Schmidt <jschmidt4gnu@HIDDEN> writes:

[ .... ]

> @Alan Mackenzie: could you test the new patch, please (attached)?

[ .... ]

With the new patch, make check reports no errors found.  So, yes it
works, and thanks!

However, I'm a little unhappy about some aspects of your original patch
which implemented these tests.  There are several functions and macros
which are lacking a properly written doc string, leaving the reader to
guess what they do.

For example, the macro letopt has no doc string.  It is hard work indeed
to guess its function from its source.  This is largely because it is
built upon the obscure macro cl-defmacro, which itself is lacking an
adequate doc string.  May I suggest that you write one?  The special
forms `let' and `let*' will give good examples to start from.

The doc string for with-ispell-global-dictionary is likewise wholly
inadequate.  It is probably not necessary to justify a macro's existence
in its doc string.  This info is probably better in a comment.  But a
proper doc string _must_ say what the function _does_ (or, for a macro,
what the generated code does), and describe each argument, both its
meaning and its form.

Also macros need debug specs, so that edebug works properly with them.
Because of the lack of a debug spec for letopt, when I tried to debug
ispell/ispell--run-on-word/default a week or so ago, edebug didn't work
at all, there being no stop point inside that function.

Please write a debug spec for letopt (and any other macros lacking one).
Debug specs are a bit of a black art, but the debug spec for one of `let'
or `let*' would be an excellent starting point, and may even work
unchanged (depending on how letopt evaluates its arguments).  To see the
debug spec of `let', do M-: (symbol-plist 'let), and look for the
edebug-form-spec property.  Full details can be found in the elisp manual
starting at page "Edebug and Macros".

> -- 
> Your sincerely,
> Vladimir Nikishkin (MiEr, lockywolf)
> (Laptop)

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 27 Sep 2025 11:06:40 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Sep 27 07:06:40 2025
Received: from localhost ([127.0.0.1]:39273 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v2SlD-0003jP-3S
	for submit <at> debbugs.gnu.org; Sat, 27 Sep 2025 07:06:40 -0400
Received: from coconut.lockywolf.net ([213.165.252.157]:37488)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <for_emacs_1@HIDDEN>)
 id 1v2Sky-0003ir-Je
 for 79477 <at> debbugs.gnu.org; Sat, 27 Sep 2025 07:06:31 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=lockywolf.net;
 s=2024-10-06; t=1758971182;
 bh=JkQq2l08udfWykv2OMz6DaNOZSKnePZNwcA9tlUTG00=;
 h=From:To:Cc:Subject:In-Reply-To:References:Date;
 b=Pp8fZUT2FiYN2Y735vIW2woXZcu366JHRFhUEUVtCkEp0L0l+1rabptu+LGuLsKDp
 yFy4jDEGoghzUEcijKc1eDIfRBFWigADZ+EeaEoFFFwMvk4+/3kUCHlHbaydABbXs3
 xlTE5Em3QQopT4HMjig9/KDrbvjvxUTyfrG7OfaMn4ZeUoV+VW/RGLhR9sjCs8H4yr
 eufoZncmUkvr6cieFHoIQJM/5j/EJbBEi1l9Vi3dkNVaDeNQ8Kzw3gcXitglCot/9d
 6/HqtsfP12A0L5SXZ/iF0DricfAuIUpWpGbLnpr12E6Ir5MvRRWjUaRFuc91saAAQw
 edVnRLoVcWZdA==
Received: from laptop.lockywolf.net (unknown [IPv6:2001:470:24:315::102])
 by coconut.lockywolf.net (postfix-encrypted) with ESMTPSA id EE9CF38F7D;
 Sat, 27 Sep 2025 19:06:18 +0800 (CST)
From: Lockywolf <for_emacs_1@HIDDEN>
To: Jens Schmidt <jschmidt4gnu@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
In-Reply-To: <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN> <86o6r5gq8z.fsf@HIDDEN>
 <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN> <aNUJpg5pNil14MlG@HIDDEN>
 <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN> <aNaACoQQJI98OrU9@HIDDEN>
 <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
User-Agent: mu4e 1.12.12; emacs 31.0.50
Date: Sat, 27 Sep 2025 19:06:10 +0800
Message-ID: <878qi09mu5.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: Alan Mackenzie <acm@HIDDEN>, Eli Zaretskii <eliz@HIDDEN>,
 Lockywolf <for_emacs_1@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: multipart/signed; boundary="==-=-=";
	micalg=pgp-sha256; protocol="application/pgp-signature"

--==-=-=
Content-Type: text/plain

Jens Schmidt <jschmidt4gnu@HIDDEN> writes:

> Hi Alan, Vladimir,
>
> sorry for butting in, but while I have been working on "my"
> bug#79514 I also investigated on this one.  I have been able to
> reproduce (I think) Alan's issue by:
>
> - moving my ispell and aspell binaries aside so that there is
>   only hunspell left as spell checker and
>
> - ensuring that "hunspell -a" fails with error
>
>     Can't open affix or dictionary files for dictionary named "en_US".
>
>   (Which was relatively easy because I only have a German hunspell
>   dictionary installed and Debian hunspell uses my current locale
>   "en_US" to determine the default dictionary.)
>
> With that setup I also get 25 failed tests without your patch
> applied, but only 6 after I applied your patch and recompiled
> all test/lisp/textmodes/ispell-tests/*.elc files.
>
> The remaining 6 failed tests all still fail with what Alan has been
> seeing:
>
>   Can't find Hunspell dictionary with a .aff affix file
>
> The failing tests are:
>
>   FAILED  ispell/ispell-buffer-local-words/ispell-buffer-session-localwords
>   FAILED  ispell/ispell-buffer-local-words/ispell-words-keyword
>   FAILED  ispell/ispell-complete-word-interior-frag/simple
>   FAILED  ispell/ispell-complete-word/ispell-completion-at-point
>   FAILED  ispell/ispell-init-process/works-with-home
>   FAILED  ispell/ispell-kill-ispell
>
> The relevant part of the stack trace from the log file should be:
>
>   error("Can't find Hunspell dictionary with a .aff affix file")
>   ispell-find-hunspell-dictionaries()
>   ispell-set-spellchecker-params()
>   ispell-change-dictionary(nil t)
>   (unwind-protect (ispell-change-dictionary old-dictionary203 t) (mess
>   (progn (unwind-protect (ispell-change-dictionary old-dictionary203 t
>   (unwind-protect (progn (ispell-change-dictionary nil t) (let ((ispel
>   (let ((old-dictionary203 (symbol-value 'ispell-dictionary))) (unwind
>   (let ((process-environment (copy-sequence process-environment))) (se
>
> So I think what is happening here is that through your macro
>
>   with-ispell-global-dictionary
>
> function `ispell-find-hunspell-dictionaries' and, hence, "hunspell"
> itself still get called, even if only your mock backend has been
> found during test initialization.
>
> This is stressed by the fact that exactly those tests fail that use
> macro `with-ispell-global-dictionary' (except
> `ispell/ispell-init-process/works-no-home', which is expected to
> fail, anyway).
>
> This is further stressed by the fact that I can make the remaining
> 6 test failures go away by swapping the `letopt' and
> `with-ispell-global-dictionary' calls, that is, by changing
>
>     (with-ispell-global-dictionary nil
>       (letopt ((ispell-program-name (ispell-tests--some-backend)))
>
> to
>
>     (letopt ((ispell-program-name (ispell-tests--some-backend)))
>       (with-ispell-global-dictionary nil
>
> Hope that helps.

Thank you!

@Alan Mackenzie: could you test the new patch, please (attached)?

--==-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQSWBebxCAoqaJP8N/j71sGyD+xtqgUCaNfFJQAKCRD71sGyD+xt
quxQAPwMmxujPcJv8W4zq4dksHgTsroLQMDfV3Cw+cPi7NmZRQEAhKwkYH+v85dh
Ej6ExD1X0Q9Ye4V0MLqe9Ix2wIDgMAs=
=iTBn
-----END PGP SIGNATURE-----
--==-=-=--

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-Fix-detecting-a-working-hunspell-on-systems-without-.patch

From 3feb6deb0e6a0c119d0ea6b2879dbecce7a3815e Mon Sep 17 00:00:00 2001
From: Lockywolf <for_emacs_1@HIDDEN>
Date: Mon, 22 Sep 2025 12:46:03 +0800
Subject: [PATCH] Fix detecting a working hunspell on systems without a
 dictionary.

* test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
  (ispell-tests-hunspell--hunspell-working): Implement checker.
  (ispell/hunspell/ispell-word/russian/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/english/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/language-switch/check-only): Add
  skip-check.
  (ispell/hunspell/ispell-word/russian/check-only/wrong-language): Add
  skip-check.
  (ispell/hunspell/ispell-word/multilang): Add skip-check.

* test/lisp/textmodes/ispell-tests/ispell-tests-common.el
  (fake-aspell-path): Improve checking that an engine works.
  (letopt): Make restoring variables more robust.

* test/lisp/textmodes/ispell-tests/ispell-tests.el
  (ispell/ispell-buffer-local-words/ispell-buffer-session-localwords):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-buffer-local-words/ispell-words-keyword):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-complete-word-interior-frag/simple):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-complete-word/ispell-completion-at-point):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-init-process/works-with-home):
  reverse letopt and with-ispell-dictionary.
  (ispell/ispell-kill-ispell):
  reverse letopt and with-ispell-dictionary.
---
 .../ispell-tests/ispell-hunspell-tests.el     |  16 +-
 .../ispell-tests/ispell-tests-common.el       |  17 +-
 .../textmodes/ispell-tests/ispell-tests.el    | 164 +++++++++---------
 3 files changed, 109 insertions(+), 88 deletions(-)

diff --git a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el b/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
index 18206b08608..530a542ef1d 100644
--- a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
@@ -34,12 +34,22 @@
                          load-path)))
     (require 'ispell-tests-common)))
 
+(defun ispell-tests-hunspell--hunspell-working ()
+  (if (not (equal
+            0
+            (call-process "hunspell" nil nil nil "-a")))
+      (progn
+        (message "Hunspell installation is broken and does not support a default dictionary!")
+        nil)
+    t))
+
 (ert-deftest ispell/hunspell/ispell-word/english/check-only ()
 "This test checks that Russian spellchecking works for Hunspell."
   (skip-unless (executable-find "hunspell"))
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -108,6 +118,7 @@ ispell/hunspell/ispell-word/russian/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (let ((retval (with-temp-buffer
@@ -160,6 +171,7 @@ ispell/hunspell/ispell-word/language-switch/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -227,6 +239,7 @@ ispell/hunspell/ispell-word/russian/check-only/wrong-language
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -264,6 +277,7 @@ ispell/hunspell/ispell-word/multilang
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -336,7 +350,5 @@ ispell/hunspell/ispell-word/multilang
           ))))
 )
 
-
-
 (provide 'ispell-hunspell-tests)
 ;;; ispell-hunspell-tests.el ends here
diff --git a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
index 0692e11e567..801bb6e6b6f 100644
--- a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
@@ -21,10 +21,9 @@ fake-aspell-path
                            (lambda (b)
                              (and
                               (executable-find b)
-                              ;; (equal 0
-                              ;;        (with-temp-buffer
-                              ;;          (call-process b nil t "-v")))
-                              ))
+                              (equal 0
+                                     (with-temp-buffer
+                                       (call-process b nil t "-a")))))
                            backend-binaries)))
 
   (defun ispell-tests--some-backend-available-p ()
@@ -42,14 +41,18 @@ letopt
   (declare (indent 1))
   (let* ((binding-var (lambda (binding) (car binding)))
 	 (binding-val (lambda (binding) (cadr binding)))
-	 (make-setopt (lambda (a b)
-			(list 'setopt a b)))
+	 (make-setopt
+          (lambda (a b)
+	    (list 'setopt a b)))
+         (add-ignore-errors
+          (lambda (a)
+            (list 'ignore-errors a)))
 	 (vars (seq-map binding-var bindings))
 	 (values (seq-map binding-val bindings))
 	 (temp-vars (seq-map #'gensym vars))
 	 (savebindings (seq-mapn #'list temp-vars vars))
 	 (tempbindings (seq-mapn make-setopt vars values))
-	 (restorebindings (seq-mapn make-setopt vars temp-vars)))
+	 (restorebindings (seq-mapn add-ignore-errors (seq-mapn make-setopt vars temp-vars))))
     `(let ,savebindings
        (unwind-protect (progn ,@tempbindings
 			      ,@body)
diff --git a/test/lisp/textmodes/ispell-tests/ispell-tests.el b/test/lisp/textmodes/ispell-tests/ispell-tests.el
index d4f3c281e95..155d4b01188 100644
--- a/test/lisp/textmodes/ispell-tests/ispell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-tests.el
@@ -462,18 +462,19 @@ ispell/ispell-buffer-local-words/ispell-words-keyword
 presumably nobody will have `hellooooooo' in their dictionary."
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
-    (with-ispell-global-dictionary nil
-      (letopt ((ispell-program-name (ispell-tests--some-backend)))
-        (with-temp-buffer
-          (nxml-mode)
-          (ignore-errors (ispell-kill-ispell))
-          (ispell-init-process)
-          (let ((test-output (ispell--run-on-word "hellooooooo")))
-            (should (listp test-output))
-            (should-not (equal t test-output)))
-          (ispell-add-per-file-word-list "hellooooooo")
-          (ispell-buffer-local-words)
-          (should (equal t (ispell--run-on-word "hellooooooo")))))))
+    (letopt ((ispell-program-name (ispell-tests--some-backend)))
+            (with-ispell-global-dictionary
+             nil
+             (with-temp-buffer
+               (nxml-mode)
+               (ignore-errors (ispell-kill-ispell))
+               (ispell-init-process)
+               (let ((test-output (ispell--run-on-word "hellooooooo")))
+                 (should (listp test-output))
+                 (should-not (equal t test-output)))
+               (ispell-add-per-file-word-list "hellooooooo")
+               (ispell-buffer-local-words)
+               (should (equal t (ispell--run-on-word "hellooooooo")))))))
   )
 
 
@@ -484,20 +485,21 @@ ispell/ispell-buffer-local-words/ispell-words-keyword
 presumably nobody will have `hellooooooo' in their dictionary."
   (skip-unless (ispell-tests--some-backend-available-p))
   (with-environment-variables (("HOME" temporary-file-directory))
-    (with-ispell-global-dictionary nil
-      (letopt ((ispell-program-name (ispell-tests--some-backend))
-               (ispell-dictionary nil))
-        (cd temporary-file-directory)
-        (with-temp-buffer
-          (nxml-mode)
-          (ignore-errors (ispell-kill-ispell))
-          (ispell-init-process)
-          (let ((test-output (ispell--run-on-word "hellooooooo")))
-            (should (listp test-output))
-            (should-not (equal t test-output)))
-          (let ((ispell-buffer-session-localwords (list "hellooooooo")))
-            (ispell-buffer-local-words)
-            (should (equal t (ispell--run-on-word "hellooooooo"))))))))
+    (letopt ((ispell-program-name (ispell-tests--some-backend))
+             (ispell-dictionary nil))
+            (with-ispell-global-dictionary
+             nil
+             (cd temporary-file-directory)
+             (with-temp-buffer
+               (nxml-mode)
+               (ignore-errors (ispell-kill-ispell))
+               (ispell-init-process)
+               (let ((test-output (ispell--run-on-word "hellooooooo")))
+                 (should (listp test-output))
+                 (should-not (equal t test-output)))
+               (let ((ispell-buffer-session-localwords (list "hellooooooo")))
+                 (ispell-buffer-local-words)
+                 (should (equal t (ispell--run-on-word "hellooooooo"))))))))
   )
 
 (ert-deftest ispell/ispell-init-process/works-no-home ()
@@ -516,11 +518,12 @@ ispell/ispell-init-process/works-no-home
 (ert-deftest ispell/ispell-init-process/works-with-home ()
   "Simple test to check that ispell-init-process works."
   (skip-unless (ispell-tests--some-backend-available-p))
-  (with-ispell-global-dictionary nil
-      (letopt ((ispell-program-name (ispell-tests--some-backend)))
-        (with-temp-buffer
-          (with-environment-variables (("HOME" temporary-file-directory))
-            (ispell-init-process))))))
+  (letopt ((ispell-program-name (ispell-tests--some-backend)))
+          (with-ispell-global-dictionary
+           nil
+           (with-temp-buffer
+             (with-environment-variables (("HOME" temporary-file-directory))
+               (ispell-init-process))))))
 
 ;; Some more tests for buffer-local stuff.
 ;; `ispell-buffer-local-dict'
@@ -1084,13 +1087,14 @@ ispell/ispell-kill-ispell
            (words '("tarampampamtararam" "test" "test" "more" "obvious" "word"))
            (text (string-join words " ")))
       (with-temp-buffer
-        (with-ispell-global-dictionary nil
-          (letopt ((ispell-program-name  (ispell-tests--some-backend)))
-            (insert text)
-            (ispell-init-process)
-            (should ispell-async-processp)
-            (should (eq (ispell-process-status) 'run))
-            (ispell-kill-ispell nil t)))
+        (letopt ((ispell-program-name  (ispell-tests--some-backend)))
+                (with-ispell-global-dictionary
+                 nil
+                 (insert text)
+                 (ispell-init-process)
+                 (should ispell-async-processp)
+                 (should (eq (ispell-process-status) 'run))
+                 (ispell-kill-ispell nil t)))
         'passed
         )))
   (message "lwf:debug2:ispell-program-name=%s:ispell-dictionary=%s"
@@ -1329,27 +1333,28 @@ ispell/ispell-complete-word/ispell-completion-at-point
     (let* ((default-directory temporary-file-directory)
            (tempfile (make-temp-file "emacs-ispell.el-test" nil nil "waveguides")))
       (ignore-errors (ispell-kill-ispell t t))
-      (with-ispell-global-dictionary nil
-        (letopt ((ispell-program-name (ispell-tests--some-backend))
-                 (ispell-complete-word-dict tempfile))
-          (with-temp-buffer
-            (insert "waveguid")
-            (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
-                          (car (nth 2 (ispell-completion-at-point)))))
-              (unwind-protect
-                  (progn
-                    (advice-add 'ispell-command-loop :override
-                                #'my-ispell-command-loop)
-                    (should (equal (car (nth 2 (ispell-completion-at-point)))
-                                   "waveguides"))
-                    (ispell-complete-word)
-                    (should (equal "waveguides" (buffer-string))))
-                (progn
-                  (delete-file tempfile)
-                  (advice-remove
-                   'ispell-command-loop
-                   #'my-ispell-command-loop)))))
-          'passed))))
+      (letopt ((ispell-program-name (ispell-tests--some-backend))
+               (ispell-complete-word-dict tempfile))
+              (with-ispell-global-dictionary
+               nil
+               (with-temp-buffer
+                 (insert "waveguid")
+                 (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
+                               (car (nth 2 (ispell-completion-at-point)))))
+                   (unwind-protect
+                       (progn
+                         (advice-add 'ispell-command-loop :override
+                                     #'my-ispell-command-loop)
+                         (should (equal (car (nth 2 (ispell-completion-at-point)))
+                                        "waveguides"))
+                         (ispell-complete-word)
+                         (should (equal "waveguides" (buffer-string))))
+                     (progn
+                       (delete-file tempfile)
+                       (advice-remove
+                        'ispell-command-loop
+                        #'my-ispell-command-loop)))))
+               'passed))))
   )
 
 (ert-deftest ispell/ispell-complete-word-interior-frag/simple ()
@@ -1357,26 +1362,27 @@ ispell/ispell-complete-word-interior-frag/simple
   (with-environment-variables (("HOME" temporary-file-directory))
     (let* ((default-directory temporary-file-directory)
            (tempfile (make-temp-file "emacs-ispell.el-test" nil nil "waveguides")))
-      (with-ispell-global-dictionary nil
-        (letopt ((ispell-program-name (ispell-tests--some-backend))
-                 (ispell-complete-word-dict tempfile))
-          (with-temp-buffer
-            (insert "waveguid")
-            (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
-                          (car (nth 2 (ispell-completion-at-point)))))
-              (unwind-protect
-                  (progn
-                    (advice-add 'ispell-command-loop :override
-                                #'my-ispell-command-loop)
-                    (goto-char 4)
-                    (ispell-complete-word-interior-frag)
-                    (should (equal "waveguides" (buffer-string))))
-                (progn
-                  (delete-file tempfile)
-                  (advice-remove
-                   'ispell-command-loop
-                   #'my-ispell-command-loop)))))
-          'passed))))
+      (letopt ((ispell-program-name (ispell-tests--some-backend))
+               (ispell-complete-word-dict tempfile))
+              (with-ispell-global-dictionary
+               nil
+               (with-temp-buffer
+                 (insert "waveguid")
+                 (cl-labels ((my-ispell-command-loop (_p _n _w _s _e)
+                               (car (nth 2 (ispell-completion-at-point)))))
+                   (unwind-protect
+                       (progn
+                         (advice-add 'ispell-command-loop :override
+                                     #'my-ispell-command-loop)
+                         (goto-char 4)
+                         (ispell-complete-word-interior-frag)
+                         (should (equal "waveguides" (buffer-string))))
+                     (progn
+                       (delete-file tempfile)
+                       (advice-remove
+                        'ispell-command-loop
+                        #'my-ispell-command-loop)))))
+               'passed))))
   )
 
 (ert-deftest ispell/ispell-minor-mode/simple ()
-- 
2.46.4


--=-=-=
Content-Type: text/plain


-- 
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)

--=-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 26 Sep 2025 20:14:41 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Sep 26 16:14:41 2025
Received: from localhost ([127.0.0.1]:36912 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v2Eq1-0001Yp-AY
	for submit <at> debbugs.gnu.org; Fri, 26 Sep 2025 16:14:41 -0400
Received: from mr6.vodafonemail.de ([145.253.228.166]:57346)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <jschmidt4gnu@HIDDEN>)
 id 1v2Epu-0001YT-Ej
 for 79477 <at> debbugs.gnu.org; Fri, 26 Sep 2025 16:14:35 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafonemail.de;
 s=vfde-mb-mr2-23sep; t=1758917668;
 bh=K0c2veE64vwsSUntrWYGCMqkZpxqyV9WUl4QVU+ZLng=;
 h=Message-ID:Date:User-Agent:Subject:To:References:From:
 Content-Language:In-Reply-To:Content-Type:From;
 b=YOJ/luEzr/YQcqFZXO16ESTkexW84XnH8KTP9YNXj2fs4/oTSNFOzQ8o+KuFckwER
 ysEEMN3Znf+ZXnLb5anaja9L53ErHpfKNt1hfmOLxErKmJWpbhSNRiTbfekOeJLmVL
 8Hr5V1xM2pywS9d8tCIAAL1qqtaOgJBsMFnruZE8=
Received: from smtp.vodafone.de (unknown [10.0.0.2])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by mr6.vodafonemail.de (Postfix) with ESMTPS id 4cYMHm2llkz1xxW;
 Fri, 26 Sep 2025 20:14:28 +0000 (UTC)
Received: from [192.168.178.42] (port-83-236-12-121.dynamic.as20676.net
 [83.236.12.121])
 (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
 (No client certificate requested)
 by smtp.vodafone.de (Postfix) with ESMTPSA id 4cYMHV29Bcz8sXy;
 Fri, 26 Sep 2025 20:14:11 +0000 (UTC)
Message-ID: <0cd516f1-e445-46b2-8665-b76da7f47402@HIDDEN>
Date: Fri, 26 Sep 2025 22:14:09 +0200
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
To: Alan Mackenzie <acm@HIDDEN>, Lockywolf <for_emacs_1@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN> <86o6r5gq8z.fsf@HIDDEN>
 <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN> <87ikh7fluk.fsf@HIDDEN>
 <aNUJpg5pNil14MlG@HIDDEN> <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN> <aNaACoQQJI98OrU9@HIDDEN>
From: Jens Schmidt <jschmidt4gnu@HIDDEN>
Content-Language: de-DE-frami, en-US
In-Reply-To: <aNaACoQQJI98OrU9@HIDDEN>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
X-purgate-type: clean
X-purgate: clean
X-purgate-size: 2820
X-purgate-ID: 155817::1758917664-78C9A8E0-E0F1FDDC/0/0
X-Spam-Score: -0.7 (/)
X-Debbugs-Envelope-To: 79477
Cc: Eli Zaretskii <eliz@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.7 (-)

Hi Alan, Vladimir,

sorry for butting in, but while I have been working on "my"
bug#79514 I also investigated on this one.  I have been able to
reproduce (I think) Alan's issue by:

- moving my ispell and aspell binaries aside so that there is
  only hunspell left as spell checker and

- ensuring that "hunspell -a" fails with error

    Can't open affix or dictionary files for dictionary named "en_US".

  (Which was relatively easy because I only have a German hunspell
  dictionary installed and Debian hunspell uses my current locale
  "en_US" to determine the default dictionary.)

With that setup I also get 25 failed tests without your patch
applied, but only 6 after I applied your patch and recompiled
all test/lisp/textmodes/ispell-tests/*.elc files.

The remaining 6 failed tests all still fail with what Alan has been
seeing:

  Can't find Hunspell dictionary with a .aff affix file

The failing tests are:

  FAILED  ispell/ispell-buffer-local-words/ispell-buffer-session-localwords
  FAILED  ispell/ispell-buffer-local-words/ispell-words-keyword
  FAILED  ispell/ispell-complete-word-interior-frag/simple
  FAILED  ispell/ispell-complete-word/ispell-completion-at-point
  FAILED  ispell/ispell-init-process/works-with-home
  FAILED  ispell/ispell-kill-ispell

The relevant part of the stack trace from the log file should be:

  error("Can't find Hunspell dictionary with a .aff affix file")
  ispell-find-hunspell-dictionaries()
  ispell-set-spellchecker-params()
  ispell-change-dictionary(nil t)
  (unwind-protect (ispell-change-dictionary old-dictionary203 t) (mess
  (progn (unwind-protect (ispell-change-dictionary old-dictionary203 t
  (unwind-protect (progn (ispell-change-dictionary nil t) (let ((ispel
  (let ((old-dictionary203 (symbol-value 'ispell-dictionary))) (unwind
  (let ((process-environment (copy-sequence process-environment))) (se

So I think what is happening here is that through your macro

  with-ispell-global-dictionary

function `ispell-find-hunspell-dictionaries' and, hence, "hunspell"
itself still get called, even if only your mock backend has been
found during test initialization.

This is stressed by the fact that exactly those tests fail that use
macro `with-ispell-global-dictionary' (except
`ispell/ispell-init-process/works-no-home', which is expected to
fail, anyway).

This is further stressed by the fact that I can make the remaining
6 test failures go away by swapping the `letopt' and
`with-ispell-global-dictionary' calls, that is, by changing

    (with-ispell-global-dictionary nil
      (letopt ((ispell-program-name (ispell-tests--some-backend)))

to

    (letopt ((ispell-program-name (ispell-tests--some-backend)))
      (with-ispell-global-dictionary nil

Hope that helps.





Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 26 Sep 2025 11:59:18 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Fri Sep 26 07:59:18 2025
Received: from localhost ([127.0.0.1]:34910 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v276c-0004Sj-83
	for submit <at> debbugs.gnu.org; Fri, 26 Sep 2025 07:59:18 -0400
Received: from mail.muc.de ([193.149.48.3]:49535)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <acm@HIDDEN>) id 1v276X-0004SJ-MT
 for 79477 <at> debbugs.gnu.org; Fri, 26 Sep 2025 07:59:14 -0400
Received: (qmail 56427 invoked by uid 3782); 26 Sep 2025 13:59:07 +0200
Received: from muc.de (pd953ada4.dip0.t-ipconnect.de [217.83.173.164]) (using
 STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP;
 Fri, 26 Sep 2025 13:59:06 +0200
Received: (qmail 25310 invoked by uid 1000); 26 Sep 2025 11:59:06 -0000
Date: Fri, 26 Sep 2025 11:59:06 +0000
To: Lockywolf <for_emacs_1@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
Message-ID: <aNaACoQQJI98OrU9@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN> <86o6r5gq8z.fsf@HIDDEN>
 <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN>
 <aNUJpg5pNil14MlG@HIDDEN>
 <87o6qyddzu.fsf@HIDDEN>
 <875xd6aq8s.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <875xd6aq8s.fsf@HIDDEN>
X-Submission-Agent: TMDA/1.3.x (Ph3nix)
From: Alan Mackenzie <acm@HIDDEN>
X-Primary-Address: acm@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: acm@HIDDEN, Eli Zaretskii <eliz@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Hello, Vladimir.

On Fri, Sep 26, 2025 at 10:42:43 +0800, Lockywolf wrote:
> Lockywolf <for_emacs_1@HIDDEN> writes:

> > [[PGP Signed Part:Good signature from FBD6C1B20FEC6DAA Lockywolf (Provisional) <*@lockywolf.net> (trust ultimate) created at 2025-09-25T18:26:57+0800 using EDDSA]]
> > Alan Mackenzie <acm@HIDDEN> writes:


> > This sounds ... odd?
> > Why would you be reporting "successes" to this mailing list?
> > Did you mean to write "failures" or, maybe, "unexpected successes"?

I see the purpose of these tests as to find problems.  21 of them have
succeeded in doing that.

> > That is very interesting, since, apparently, it picks up the correct
> > mock engine from the resources directory, and should not be using
> > Hunspell at all.

Could it be that the mock engine is itself calling hunspell?

> > This should not matter if the patch is attached, because it should not
> > be looking at hunspell at all, as long as "hunspell -a" fails. Can you
> > confirm that running "hunspell -a" fails on your machine?

    $ hunspell -a

outputs a message on the terminal about the lack of dictionaries, and has
a result code of 1.  So yes, it fails.

> > Also, would you mind attaching all the log files to your next message?
> > I mean the following files:

> > ./test/lisp/textmodes/ispell-tests/ispell-international-ispell-tests.log
> > ./test/lisp/textmodes/ispell-tests/ispell-tests-common.log
> > ./test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.log
> > ./test/lisp/textmodes/ispell-tests/ispell-aspell-tests.log
> > ./test/lisp/textmodes/ispell-tests/ispell-tests.log

I'd really rather not post log files in bulk unless it's absolutely needed.

> Also, would you mind trying the following patch:


[ .... ]


> It is basically the same as the previous one, there is one improvement
> for better preservation of the environment.
> (Do not forget to apply it to master, not to the previous application of
> the same patch: git clean -xfd ; git am ...)

Thanks for saying that!  Otherwise I would surely have got the two
patches into a tangle.

That patch applied cleanly, but I still got the 21 successes.

It's looking like the tests in ispell-tests.el are calling hunspell, but
without first calling ispell-tests-hunspell--hunspell-working.

> -- 
> Your sincerely,
> Vladimir Nikishkin (MiEr, lockywolf)
> (Laptop)

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 26 Sep 2025 02:43:08 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Sep 25 22:43:08 2025
Received: from localhost ([127.0.0.1]:33034 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v1yQN-0006Vs-Bt
	for submit <at> debbugs.gnu.org; Thu, 25 Sep 2025 22:43:08 -0400
Received: from coconut.lockywolf.net ([213.165.252.157]:57842)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <for_emacs_1@HIDDEN>)
 id 1v1yQG-0006TZ-0d
 for 79477 <at> debbugs.gnu.org; Thu, 25 Sep 2025 22:43:04 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=lockywolf.net;
 s=2024-10-06; t=1758854574;
 bh=QFLoexdG6DQx41DtIo2RZJwRd/5hpYVeCnF/hhsVJUA=;
 h=From:To:Cc:Subject:In-Reply-To:References:Date;
 b=R40mE38Ob3mDdQorbSITT9nMIFPdDu4GbZrn/xWl2xJJaYLmImVSBkEP8wi7afRq6
 iJO5hQk6B+iPjO/USVVBITcpJb6t99FEqqZIu7D8nRvXMamGvMWO8po9XOHSSOSDsx
 TQHNOusgWLxv+poMuBcd/fLmOGqc7glvhk9upACWY1Z7OA98UhhsRE5W11YUj6s0Qv
 Xbg97LxnfAibMb2F/JxnEHH/20hneiXfZGQG644PDaC/OMy31qgBN4cfhEGqFk9eRZ
 doRrTmRUMnf7OG96qy9G6AUE5ivHFQhxtROtcfyeOaSTWjhVXDEwOnqhUPpBDwArt0
 RwRnXs3hU/v2A==
Received: from laptop.lockywolf.net (unknown [IPv6:2001:470:24:315::102])
 by coconut.lockywolf.net (postfix-encrypted) with ESMTPSA id 6613E37E0F;
 Fri, 26 Sep 2025 10:42:50 +0800 (CST)
From: Lockywolf <for_emacs_1@HIDDEN>
To: Lockywolf <for_emacs_1@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
In-Reply-To: <87o6qyddzu.fsf@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN> <86o6r5gq8z.fsf@HIDDEN>
 <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN> <aNUJpg5pNil14MlG@HIDDEN>
 <87o6qyddzu.fsf@HIDDEN>
User-Agent: mu4e 1.12.12; emacs 31.0.50
Date: Fri, 26 Sep 2025 10:42:43 +0800
Message-ID: <875xd6aq8s.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: Alan Mackenzie <acm@HIDDEN>, Eli Zaretskii <eliz@HIDDEN>,
 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: multipart/signed; boundary="==-=-=";
	micalg=pgp-sha256; protocol="application/pgp-signature"

--==-=-=
Content-Type: text/plain

Lockywolf <for_emacs_1@HIDDEN> writes:

> [[PGP Signed Part:Good signature from FBD6C1B20FEC6DAA Lockywolf (Provisional) <*@lockywolf.net> (trust ultimate) created at 2025-09-25T18:26:57+0800 using EDDSA]]
> Alan Mackenzie <acm@HIDDEN> writes:
>
>
> This sounds ... odd?
> Why would you be reporting "successes" to this mailing list?
> Did you mean to write "failures" or, maybe, "unexpected successes"?
>
>
> That is very interesting, since, apparently, it picks up the correct
> mock engine from the resources directory, and should not be using
> Hunspell at all.
>
>
> This should not matter if the patch is attached, because it should not
> be looking at hunspell at all, as long as "hunspell -a" fails. Can you
> confirm that running "hunspell -a" fails on your machine?
>
> Also, would you mind attaching all the log files to your next message?
> I mean the following files:
>
> ./test/lisp/textmodes/ispell-tests/ispell-international-ispell-tests.log
> ./test/lisp/textmodes/ispell-tests/ispell-tests-common.log
> ./test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.log
> ./test/lisp/textmodes/ispell-tests/ispell-aspell-tests.log
> ./test/lisp/textmodes/ispell-tests/ispell-tests.log

Also, would you mind trying the following patch:

--==-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQSWBebxCAoqaJP8N/j71sGyD+xtqgUCaNX9pgAKCRD71sGyD+xt
qh37AP9eDqeYdm6f+MvtmZ7QpB3l1TO8ayWApHEIn5W3a4Jv5AD/UpEEwNb1Ha8N
HPxS81OdWHOk8TpAi5zWvhIfjp78jQU=
=gdVS
-----END PGP SIGNATURE-----
--==-=-=--

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-Fix-detecting-a-working-hunspell-on-systems-without-.patch

From 339003c9db6a4d48734f199e955e2d9caa26a8f8 Mon Sep 17 00:00:00 2001
From: Lockywolf <for_emacs_1@HIDDEN>
Date: Mon, 22 Sep 2025 12:46:03 +0800
Subject: [PATCH] Fix detecting a working hunspell on systems without a
 dictionary.

* test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
  (ispell-tests-hunspell--hunspell-working): Implement checker.
  (ispell/hunspell/ispell-word/russian/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/english/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/language-switch/check-only): Add
  skip-check.
  (ispell/hunspell/ispell-word/russian/check-only/wrong-language): Add
  skip-check.
  (ispell/hunspell/ispell-word/multilang): Add skip-check.

* test/lisp/textmodes/ispell-tests/ispell-tests-common.el
  (fake-aspell-path): Improve checking that an engine works.
  (letopt): Make restoring variables more robust.
---
 .../ispell-tests/ispell-hunspell-tests.el       | 16 ++++++++++++++--
 .../ispell-tests/ispell-tests-common.el         | 17 ++++++++++-------
 2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el b/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
index 18206b08608..530a542ef1d 100644
--- a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
@@ -34,12 +34,22 @@
                          load-path)))
     (require 'ispell-tests-common)))
 
+(defun ispell-tests-hunspell--hunspell-working ()
+  (if (not (equal
+            0
+            (call-process "hunspell" nil nil nil "-a")))
+      (progn
+        (message "Hunspell installation is broken and does not support a default dictionary!")
+        nil)
+    t))
+
 (ert-deftest ispell/hunspell/ispell-word/english/check-only ()
 "This test checks that Russian spellchecking works for Hunspell."
   (skip-unless (executable-find "hunspell"))
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -108,6 +118,7 @@ ispell/hunspell/ispell-word/russian/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (let ((retval (with-temp-buffer
@@ -160,6 +171,7 @@ ispell/hunspell/ispell-word/language-switch/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -227,6 +239,7 @@ ispell/hunspell/ispell-word/russian/check-only/wrong-language
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -264,6 +277,7 @@ ispell/hunspell/ispell-word/multilang
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -336,7 +350,5 @@ ispell/hunspell/ispell-word/multilang
           ))))
 )
 
-
-
 (provide 'ispell-hunspell-tests)
 ;;; ispell-hunspell-tests.el ends here
diff --git a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
index 0692e11e567..801bb6e6b6f 100644
--- a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
@@ -21,10 +21,9 @@ fake-aspell-path
                            (lambda (b)
                              (and
                               (executable-find b)
-                              ;; (equal 0
-                              ;;        (with-temp-buffer
-                              ;;          (call-process b nil t "-v")))
-                              ))
+                              (equal 0
+                                     (with-temp-buffer
+                                       (call-process b nil t "-a")))))
                            backend-binaries)))
 
   (defun ispell-tests--some-backend-available-p ()
@@ -42,14 +41,18 @@ letopt
   (declare (indent 1))
   (let* ((binding-var (lambda (binding) (car binding)))
 	 (binding-val (lambda (binding) (cadr binding)))
-	 (make-setopt (lambda (a b)
-			(list 'setopt a b)))
+	 (make-setopt
+          (lambda (a b)
+	    (list 'setopt a b)))
+         (add-ignore-errors
+          (lambda (a)
+            (list 'ignore-errors a)))
 	 (vars (seq-map binding-var bindings))
 	 (values (seq-map binding-val bindings))
 	 (temp-vars (seq-map #'gensym vars))
 	 (savebindings (seq-mapn #'list temp-vars vars))
 	 (tempbindings (seq-mapn make-setopt vars values))
-	 (restorebindings (seq-mapn make-setopt vars temp-vars)))
+	 (restorebindings (seq-mapn add-ignore-errors (seq-mapn make-setopt vars temp-vars))))
     `(let ,savebindings
        (unwind-protect (progn ,@tempbindings
 			      ,@body)
-- 
2.46.4


--=-=-=
Content-Type: text/plain


It is basically the same as the previous one, there is one improvement
for better preservation of the environment.
(Do not forget to apply it to master, not to the previous application of
the same patch: git clean -xfd ; git am ...)

-- 
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)

--=-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 25 Sep 2025 10:27:17 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Sep 25 06:27:17 2025
Received: from localhost ([127.0.0.1]:55988 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v1jBz-0001xn-IH
	for submit <at> debbugs.gnu.org; Thu, 25 Sep 2025 06:27:17 -0400
Received: from coconut.lockywolf.net
 ([2a04:c5c0:0:d7:f816:3eff:fe6b:287f]:44898)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <for_emacs_1@HIDDEN>)
 id 1v1jBs-0001wE-OJ
 for 79477 <at> debbugs.gnu.org; Thu, 25 Sep 2025 06:27:10 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=lockywolf.net;
 s=2024-10-06; t=1758796025;
 bh=bn5wfm3fsQEbgF8na0edOJLZ22zCo7od/bBIGeZmS+o=;
 h=From:To:Cc:Subject:In-Reply-To:References:Date;
 b=QcvJdcpw+TdLzzfNGLEZgtws54y33aJQiHe9K3zwwdGELgHT9t8J+EZRh4Q1FeNdA
 fVqiMD25Syc+JG+zYRjXh6JP3Q/Gyq1Xgmjq/Y5Cj+WtFKYam1fiCNMTA8cXsNq13x
 wfMs0cpS7Box4tizzD9fyKPUoYdRXR9kpZSo5jqwRJJpPFILIO0KCFEsGNIrYHU+Lv
 RaIBfgLwKV4w7ySwRVygbdxoIvPfk4VF4OMGdnS8vaJviGuy5r4ZuMss2usjtA7w2K
 r6wGRCMLV1Vbbo2j3r66OZ9iTn5+fs6rGJMMyaS4INHIwg2KdOrGGFN90CatkektrM
 0EszWh+EEw/wQ==
Received: from laptop.lockywolf.net (unknown [IPv6:2001:470:24:315::102])
 by coconut.lockywolf.net (postfix-encrypted) with ESMTPSA id CD76D38EB8;
 Thu, 25 Sep 2025 18:27:02 +0800 (CST)
From: Lockywolf <for_emacs_1@HIDDEN>
To: Alan Mackenzie <acm@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
In-Reply-To: <aNUJpg5pNil14MlG@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN> <86o6r5gq8z.fsf@HIDDEN>
 <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN> <aNUJpg5pNil14MlG@HIDDEN>
User-Agent: mu4e 1.12.12; emacs 31.0.50
Date: Thu, 25 Sep 2025 18:26:45 +0800
Message-ID: <87o6qyddzu.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: multipart/signed; boundary="=-=-=";
 micalg=pgp-sha256; protocol="application/pgp-signature"
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: Eli Zaretskii <eliz@HIDDEN>, Lockywolf <for_emacs_1@HIDDEN>,
 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

Alan Mackenzie <acm@HIDDEN> writes:

> It does now, thanks.  It didn't, for some reason, when I tried it on
> Monday.  When I run it, I still get 21 successes in

This sounds ... odd?
Why would you be reporting "successes" to this mailing list?
Did you mean to write "failures" or, maybe, "unexpected successes"?

> test/lisp/textmodes/ispell-tests/ispell-tests.log.  All of them are due
> to the lack of hunspell .aff files.  A typical extract from that .log
> file looks like:
> #########################################################################
> available backend
> is:/home/acm/emacs/emacs.git/master/test/lisp/textmodes/ispell-resources/=
fake-aspell-new.bash

That is very interesting, since, apparently, it picks up the correct
mock engine from the resources directory, and should not be using
Hunspell at all.

> Using vacuous schema
> Starting new Ispell process /home/acm/emacs/emacs.git/master/test/lisp/te=
xtmodes/ispell-resources/fake-aspell-new.bash with default dictionary... \
> Starting new Ispell process /home/acm/emacs/emacs.git/master/test/lisp/te=
xtmodes/ispell-resources/fake-aspell-new.bash with default dictionary...done
> Ispell process killed
> Test ispell/ispell--run-on-word/default backtrace:
>   signal(error ("Can't find Hunspell dictionary with a .aff affix file
>   error("Can't find Hunspell dictionary with a .aff affix file")
>   ispell-find-hunspell-dictionaries()
>   ispell-set-spellchecker-params()
>   #f(compiled-function (symbol value) #<bytecode 0x1ae5f0d358345f20>)(
>   setopt--set(ispell-program-name "/usr/bin/hunspell")
>   #f(compiled-function () #<bytecode 0x9426a5fec421f9f>)()
>   #f(compiled-function () #<bytecode -0x78fdbf874643584>)()
>   #f(compiled-function () #<bytecode -0xdef4c5130b7f4b6>)()
>   handler-bind-1(#f(compiled-function () #<bytecode -0xdef4c5130b7f4b6
>   ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
>   ert-run-test(#s(ert-test :name ispell/ispell--run-on-word/default :d
>   ert-run-or-rerun-test(#s(ert--stats :selector ... :tests ... :test-m
>   ert-run-tests((not (or (tag :expensive-test) (tag :unstable))) #f(co
>   ert-run-tests-batch((not (or (tag :expensive-test) (tag :unstable)))
>   ert-run-tests-batch-and-exit((not (or (tag :expensive-test) (tag :un
>   eval((ert-run-tests-batch-and-exit '(not (or (tag :expensive-test) (
>   command-line-1(("-L" ":." "-l" "ert" "--eval" "(setq treesit-extra-l
>   command-line()
>   normal-top-level()
> Test ispell/ispell--run-on-word/default condition:
>     (error "Can't find Hunspell dictionary with a .aff affix file")
>    FAILED   1/65  ispell/ispell--run-on-word/default (0.043346 sec) at li=
sp/textmodes/ispell-tests/ispell-tests.el:826
> #########################################################################
>
> I've looked at why I've got no .aff files.  I'm running Gentoo Gnu/Linux,
> and I've installed evince, the .pdf reader.  evince has, as a dependency
> gspell, which depends on enchant, which depends on hunspell.

This should not matter if the patch is attached, because it should not
be looking at hunspell at all, as long as "hunspell -a" fails. Can you
confirm that running "hunspell -a" fails on your machine?

Also, would you mind attaching all the log files to your next message?
I mean the following files:

./test/lisp/textmodes/ispell-tests/ispell-international-ispell-tests.log
./test/lisp/textmodes/ispell-tests/ispell-tests-common.log
./test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.log
./test/lisp/textmodes/ispell-tests/ispell-aspell-tests.log
./test/lisp/textmodes/ispell-tests/ispell-tests.log


=2D-=20
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)

--=-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQSWBebxCAoqaJP8N/j71sGyD+xtqgUCaNUY8QAKCRD71sGyD+xt
qqPlAP9iY/f14h/r2RZrXCzysHr503mFgqM2U5EzY+7+9ONJjAEAqdvWZrsstqsQ
ST1Y/KGioI+uG7nkIMXRu1Dd8iukvg4=
=QoB0
-----END PGP SIGNATURE-----
--=-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 25 Sep 2025 09:22:05 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Sep 25 05:22:05 2025
Received: from localhost ([127.0.0.1]:55739 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v1iAr-0004LK-6h
	for submit <at> debbugs.gnu.org; Thu, 25 Sep 2025 05:22:04 -0400
Received: from mail.muc.de ([193.149.48.3]:63342)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <acm@HIDDEN>) id 1v1iAf-0004Ih-S8
 for 79477 <at> debbugs.gnu.org; Thu, 25 Sep 2025 05:21:52 -0400
Received: (qmail 8179 invoked by uid 3782); 25 Sep 2025 11:21:43 +0200
Received: from muc.de (p4fe15bae.dip0.t-ipconnect.de [79.225.91.174]) (using
 STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP;
 Thu, 25 Sep 2025 11:21:42 +0200
Received: (qmail 342 invoked by uid 1000); 25 Sep 2025 09:21:42 -0000
Date: Thu, 25 Sep 2025 09:21:42 +0000
To: Lockywolf <for_emacs_1@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
Message-ID: <aNUJpg5pNil14MlG@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN> <86o6r5gq8z.fsf@HIDDEN>
 <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
 <87ikh7fluk.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <87ikh7fluk.fsf@HIDDEN>
X-Submission-Agent: TMDA/1.3.x (Ph3nix)
From: Alan Mackenzie <acm@HIDDEN>
X-Primary-Address: acm@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: acm@HIDDEN, Eli Zaretskii <eliz@HIDDEN>, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Hello, Vladimir.

Sorry for the delayed reply.

On Thu, Sep 25, 2025 at 07:54:11 +0800, Lockywolf wrote:
> Lockywolf <for_emacs_1@HIDDEN> writes:

> > [[PGP Signed Part:Good signature from FBD6C1B20FEC6DAA Lockywolf (Provisional) <*@lockywolf.net> (trust ultimate) created at 2025-09-22T12:51:52+0800 using EDDSA]]
> > Alan Mackenzie <acm@HIDDEN> writes:


> > I am attaching a patch with a better checker that the hunspell and
> > enchant-2 backends are working.

> > [[End of PGP Signed Part]]
> > [2. text/x-patch; 0001-Fix-detecting-a-working-hunspell-on-systems-without-.patch]...

> Does this patch work for you?

It does now, thanks.  It didn't, for some reason, when I tried it on
Monday.  When I run it, I still get 21 successes in
test/lisp/textmodes/ispell-tests/ispell-tests.log.  All of them are due
to the lack of hunspell .aff files.  A typical extract from that .log
file looks like:

#########################################################################
available backend is:/home/acm/emacs/emacs.git/master/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash
Using vacuous schema
Starting new Ispell process /home/acm/emacs/emacs.git/master/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash with default dictionary... \
Starting new Ispell process /home/acm/emacs/emacs.git/master/test/lisp/textmodes/ispell-resources/fake-aspell-new.bash with default dictionary...done
Ispell process killed
Test ispell/ispell--run-on-word/default backtrace:
  signal(error ("Can't find Hunspell dictionary with a .aff affix file
  error("Can't find Hunspell dictionary with a .aff affix file")
  ispell-find-hunspell-dictionaries()
  ispell-set-spellchecker-params()
  #f(compiled-function (symbol value) #<bytecode 0x1ae5f0d358345f20>)(
  setopt--set(ispell-program-name "/usr/bin/hunspell")
  #f(compiled-function () #<bytecode 0x9426a5fec421f9f>)()
  #f(compiled-function () #<bytecode -0x78fdbf874643584>)()
  #f(compiled-function () #<bytecode -0xdef4c5130b7f4b6>)()
  handler-bind-1(#f(compiled-function () #<bytecode -0xdef4c5130b7f4b6
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name ispell/ispell--run-on-word/default :d
  ert-run-or-rerun-test(#s(ert--stats :selector ... :tests ... :test-m
  ert-run-tests((not (or (tag :expensive-test) (tag :unstable))) #f(co
  ert-run-tests-batch((not (or (tag :expensive-test) (tag :unstable)))
  ert-run-tests-batch-and-exit((not (or (tag :expensive-test) (tag :un
  eval((ert-run-tests-batch-and-exit '(not (or (tag :expensive-test) (
  command-line-1(("-L" ":." "-l" "ert" "--eval" "(setq treesit-extra-l
  command-line()
  normal-top-level()
Test ispell/ispell--run-on-word/default condition:
    (error "Can't find Hunspell dictionary with a .aff affix file")
   FAILED   1/65  ispell/ispell--run-on-word/default (0.043346 sec) at lisp/textmodes/ispell-tests/ispell-tests.el:826
#########################################################################

I've looked at why I've got no .aff files.  I'm running Gentoo Gnu/Linux,
and I've installed evince, the .pdf reader.  evince has, as a dependency
gspell, which depends on enchant, which depends on hunspell.

I have never explicitly installed hunspell, or set up any Gentoo
mechanism for it to be installed.  It happened by default when I set up
my machine.  Actually to install any dictionaries would have required me
to set this up first.  This might be a bug in Gentoo.

So this configuration, hunspell with no dictionaries installed, may be
quite common, at least on Gentoo.  I think it might not be wise to error
out, just because .aff files aren't found.

> -- 
> Your sincerely,
> Vladimir Nikishkin (MiEr, lockywolf)
> (Laptop)

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 24 Sep 2025 23:54:35 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Wed Sep 24 19:54:35 2025
Received: from localhost ([127.0.0.1]:53288 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v1ZJf-0001k2-Mr
	for submit <at> debbugs.gnu.org; Wed, 24 Sep 2025 19:54:35 -0400
Received: from coconut.lockywolf.net
 ([2a04:c5c0:0:d7:f816:3eff:fe6b:287f]:34236)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <for_emacs_1@HIDDEN>)
 id 1v1ZJZ-0001j8-7c
 for 79477 <at> debbugs.gnu.org; Wed, 24 Sep 2025 19:54:29 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=lockywolf.net;
 s=2024-10-06; t=1758758061;
 bh=w/E8ASp4aOkrLgkBQncnXprIUvczBBjEn2qHqvEsgfo=;
 h=From:To:Cc:Subject:In-Reply-To:References:Date;
 b=Rjs6hPVExnWF6wdAV8vOCzO07PqwduZ1FCheOiMixavSulidBCzqMo8eQI21cqsE8
 J0w7x5KjqrLiSRfExzJOhE6KwU5VpZms9XYKJ7NqzmM0uyrfc+Jof60fovcNYaJuGl
 gzJzpKlc99cl4iC3/9H8wbkHP9LgG5kGjM8M8S0lkW4jYSkF3Ow3e1nr/coi3Na4v0
 HsYdgqS5nXSQHbTKBQ1V7+G+hFaGpnAb2ST+wWKG5+3wjumaaUXiUvHgSsJ1UuYnDi
 1IjDJg48zxtxsPb2E72vzU+BqTr9uvAq0jklyvT/upKWwrbukvdHpVZdW/Ae48+IRS
 pfhmlwU0LiAgw==
Received: from laptop.lockywolf.net (unknown [IPv6:2001:470:24:315::102])
 by coconut.lockywolf.net (postfix-encrypted) with ESMTPSA id 0970E38E06;
 Thu, 25 Sep 2025 07:54:18 +0800 (CST)
From: Lockywolf <for_emacs_1@HIDDEN>
To: Lockywolf <for_emacs_1@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
In-Reply-To: <87plbj6qe1.fsf@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN> <86o6r5gq8z.fsf@HIDDEN>
 <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
 <87plbj6qe1.fsf@HIDDEN>
User-Agent: mu4e 1.12.12; emacs 31.0.50
Date: Thu, 25 Sep 2025 07:54:11 +0800
Message-ID: <87ikh7fluk.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: multipart/signed; boundary="=-=-=";
 micalg=pgp-sha256; protocol="application/pgp-signature"
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: Alan Mackenzie <acm@HIDDEN>, Eli Zaretskii <eliz@HIDDEN>,
 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

Lockywolf <for_emacs_1@HIDDEN> writes:

> [[PGP Signed Part:Good signature from FBD6C1B20FEC6DAA Lockywolf (Provisi=
onal) <*@lockywolf.net> (trust ultimate) created at 2025-09-22T12:51:52+080=
0 using EDDSA]]
> Alan Mackenzie <acm@HIDDEN> writes:
>
>
> I am attaching a patch with a better checker that the hunspell and
> enchant-2 backends are working.
>
> [[End of PGP Signed Part]]
> [2. text/x-patch; 0001-Fix-detecting-a-working-hunspell-on-systems-withou=
t-.patch]...

Does this patch work for you?

=2D-=20
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)

--=-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQSWBebxCAoqaJP8N/j71sGyD+xtqgUCaNSEpQAKCRD71sGyD+xt
qml5AQCQGnGTx2Y1FuzQsAqMBsvIQxenWib5wQ1ZHdy9n6Q3uQD+P6B/e5IsdYXa
cTP0EMimt23CtgIx2z7YPLU/rEuGyQw=
=1ZCN
-----END PGP SIGNATURE-----
--=-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 22 Sep 2025 04:52:14 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Mon Sep 22 00:52:14 2025
Received: from localhost ([127.0.0.1]:60150 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v0YX7-0007Xp-N8
	for submit <at> debbugs.gnu.org; Mon, 22 Sep 2025 00:52:14 -0400
Received: from coconut.lockywolf.net ([213.165.252.157]:55250)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <for_emacs_1@HIDDEN>)
 id 1v0YWv-0007XC-Pf
 for 79477 <at> debbugs.gnu.org; Mon, 22 Sep 2025 00:52:09 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=lockywolf.net;
 s=2024-10-06; t=1758516720;
 bh=zUbZZfDSOfgNd60u8f8uUc4gGUXb5Lpb+BohRljL0bo=;
 h=From:To:Cc:Subject:In-Reply-To:References:Date;
 b=smmhk+tI6iuARJGdKj1mATtJyTF5SBxKpokWDeB1lCPZogRj/7bXgBkRsNsMUVDXY
 MhQSK0aV5ksgGwg4pBcA1ciIGrMHeP9TXkAT1a/3IU2YfAvPpebOCyZQjWsTsJcpfC
 NWUbzYbk0oaK9mR3t8LgblJmb1YW45+PXqR1kgmwFPZJ49JZ2qt+C8lfkAUI57hANr
 0WAEqDMc+mL20QOY7WgdBHofcArBMIK0BOtFwPrLQopGG5tYl/VIHfavVP6pGdFbrF
 ihw5ypGk3r/oi9I7rsM5vRWStyQOqFm3zCPyVRkxGRSOtjn37YsVoxzQBGgepOB8xz
 LrUDnsWwHY8eg==
Received: from laptop.lockywolf.net (unknown [IPv6:2001:470:24:315::102])
 by coconut.lockywolf.net (postfix-encrypted) with ESMTPSA id 9C19C38B3C;
 Mon, 22 Sep 2025 12:51:57 +0800 (CST)
From: Lockywolf <for_emacs_1@HIDDEN>
To: Alan Mackenzie <acm@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
In-Reply-To: <aNAtdBfbsl0Jb7Pg@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN> <86o6r5gq8z.fsf@HIDDEN>
 <aM7SZoq00EvBcQhT@HIDDEN> <aNAtdBfbsl0Jb7Pg@HIDDEN>
User-Agent: mu4e 1.12.12; emacs 31.0.50
Date: Mon, 22 Sep 2025 12:51:50 +0800
Message-ID: <87plbj6qe1.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: Eli Zaretskii <eliz@HIDDEN>, Lockywolf <for_emacs_1@HIDDEN>,
 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: multipart/signed; boundary="==-=-=";
	micalg=pgp-sha256; protocol="application/pgp-signature"

--==-=-=
Content-Type: text/plain

Alan Mackenzie <acm@HIDDEN> writes:

> Hello, Eli and Lockywolf.
>
> On Sat, Sep 20, 2025 at 16:12:22 +0000, Alan Mackenzie wrote:
> It didn't.  That error message still appears in ~14 tests in the log
> file.
> It seems the algorithm for detecting working spelling checkers is
> suboptimal.  I looked at the top level binding of filter-binaries in
> ispell-tests-common.el.  There, there is a tentative commented out trial
> call to the various spelling checkers.  Perhaps this code is needed after
> all.

I am attaching a patch with a better checker that the hunspell and
enchant-2 backends are working.


--==-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQSWBebxCAoqaJP8N/j71sGyD+xtqgUCaNDV6AAKCRD71sGyD+xt
qkmuAP0Rzfc03/BSfkfofi/E0CGggGpTDeIVuhQMQOjgasX3RAEAn/Sb3toltEHA
rRoRxL+L5m0/mBYUw7WiwvzF32a1Bwg=
=cJsv
-----END PGP SIGNATURE-----
--==-=-=--

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
 filename=0001-Fix-detecting-a-working-hunspell-on-systems-without-.patch

From e7c53263092946e54d6353eefbd6c782698a20e8 Mon Sep 17 00:00:00 2001
From: Lockywolf <for_emacs_1@HIDDEN>
Date: Mon, 22 Sep 2025 12:46:03 +0800
Subject: [PATCH] Fix detecting a working hunspell on systems without a
 dictionary.

* test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
  (ispell-tests-hunspell--hunspell-working): Implement checker.
  (ispell/hunspell/ispell-word/russian/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/english/check-only): Add skip-check.
  (ispell/hunspell/ispell-word/language-switch/check-only): Add
  skip-check.
  (ispell/hunspell/ispell-word/russian/check-only/wrong-language): Add
  skip-check.
  (ispell/hunspell/ispell-word/multilang): Add skip-check.

* test/lisp/textmodes/ispell-tests/ispell-tests-common.el
  fake-aspell-path: Improve checking that an engine works.
---
 .../ispell-tests/ispell-hunspell-tests.el        | 16 ++++++++++++++--
 .../ispell-tests/ispell-tests-common.el          |  7 +++----
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el b/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
index 8b625276e28..5d094b91838 100644
--- a/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-hunspell-tests.el
@@ -34,12 +34,22 @@
                              (file-name-directory load-file-name))))
   (load "ispell-tests-common.el"))
 
+(defun ispell-tests-hunspell--hunspell-working ()
+  (if (not (equal
+            0
+            (call-process "hunspell" nil nil nil "-a")))
+      (progn
+        (message "Hunspell installation is broken and does not support a default dictionary!")
+        nil)
+    t))
+
 (ert-deftest ispell/hunspell/ispell-word/english/check-only ()
 "This test checks that Russian spellchecking works for Hunspell."
   (skip-unless (executable-find "hunspell"))
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -108,6 +118,7 @@ ispell/hunspell/ispell-word/russian/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (let ((retval (with-temp-buffer
@@ -160,6 +171,7 @@ ispell/hunspell/ispell-word/language-switch/check-only
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -227,6 +239,7 @@ ispell/hunspell/ispell-word/russian/check-only/wrong-language
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -264,6 +277,7 @@ ispell/hunspell/ispell-word/multilang
   (skip-unless (equal
                 0
                 (call-process "hunspell" nil nil nil "-vv")))
+  (skip-unless (ispell-tests-hunspell--hunspell-working))
   (skip-unless (equal
                 0
                 (with-temp-buffer
@@ -336,7 +350,5 @@ ispell/hunspell/ispell-word/multilang
           ))))
 )
 
-
-
 (provide 'ispell-hunspell-tests)
 ;;; ispell-hunspell-tests.el ends here
diff --git a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
index 0692e11e567..7a1cbb512c3 100644
--- a/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
+++ b/test/lisp/textmodes/ispell-tests/ispell-tests-common.el
@@ -21,10 +21,9 @@ fake-aspell-path
                            (lambda (b)
                              (and
                               (executable-find b)
-                              ;; (equal 0
-                              ;;        (with-temp-buffer
-                              ;;          (call-process b nil t "-v")))
-                              ))
+                              (equal 0
+                                     (with-temp-buffer
+                                       (call-process b nil t "-a")))))
                            backend-binaries)))
 
   (defun ispell-tests--some-backend-available-p ()
-- 
2.46.4


--=-=-=
Content-Type: text/plain



-- 
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)

--=-=-=--




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 21 Sep 2025 16:53:28 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sun Sep 21 12:53:27 2025
Received: from localhost ([127.0.0.1]:55686 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v0NJT-0006Ga-8V
	for submit <at> debbugs.gnu.org; Sun, 21 Sep 2025 12:53:27 -0400
Received: from mail.muc.de ([193.149.48.3]:32724)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <acm@HIDDEN>) id 1v0NJM-0006EH-L1
 for 79477 <at> debbugs.gnu.org; Sun, 21 Sep 2025 12:53:20 -0400
Received: (qmail 50247 invoked by uid 3782); 21 Sep 2025 18:53:09 +0200
Received: from muc.de (p4fe15168.dip0.t-ipconnect.de [79.225.81.104]) (using
 STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP;
 Sun, 21 Sep 2025 18:53:08 +0200
Received: (qmail 6769 invoked by uid 1000); 21 Sep 2025 16:53:08 -0000
Date: Sun, 21 Sep 2025 16:53:08 +0000
To: Eli Zaretskii <eliz@HIDDEN>, Lockywolf <for_emacs_1@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
Message-ID: <aNAtdBfbsl0Jb7Pg@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN> <86o6r5gq8z.fsf@HIDDEN>
 <aM7SZoq00EvBcQhT@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <aM7SZoq00EvBcQhT@HIDDEN>
X-Submission-Agent: TMDA/1.3.x (Ph3nix)
From: Alan Mackenzie <acm@HIDDEN>
X-Primary-Address: acm@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: acm@HIDDEN, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Hello, Eli and Lockywolf.

On Sat, Sep 20, 2025 at 16:12:22 +0000, Alan Mackenzie wrote:
> On Sat, Sep 20, 2025 at 17:20:12 +0300, Eli Zaretskii wrote:
> > > Date: Sat, 20 Sep 2025 13:52:58 +0000
> > > From: Alan Mackenzie <acm@HIDDEN>

> > > Hello, Emacs.

> > > When I run the test suite with make check, I get 25 successes in
> > > test/lisp/textmode/ispell-tests/ispell-tests.log.  Each of these has the
> > > same error message, "Can't find Hunspell dictionary with a .aff affix
> > > file".

> > > I don't know what a .aff file is, but it seems like my setup is missing
> > > one.  Despite this, surely ispell-tests.el should cope with this
> > > deficiency, rather than emitting 25 error messages.

> > Are you saying that you have the Hunspell executable, but not its
> > dictionaries?

> Yes, that is indeed the case.  The Hunspell installation script on Gentoo
> installs the dictionaries it is specifically asked to install, and if
> none are requested, none are installed.  No sensible default is used.
> This may be a Gentoo bug.

> > What happens if you invoke Hunspell from the shell prompt -- does it
> > work or does it show some error message?

> I get the error message:

>     Can't open affix or dictionary files for dictionary named "en_GB".

> ..

> > If your Hunspell installation is workable, you should have a
> > /usr/share/hunspell directory with *.aff files.  If they are missing,
> > either install them or remove the Hunspell executable.  The Emacs test
> > suite is not supposed to cope with installations that don't work, so
> > showing error messages is OK in that case.

> I have what is arguably a valid installation, even though not useful.  I
> tried reinstalling it, and got no warning message about the lack of
> languages.

> After deinstalling hunspell ...., I get a different message in
> ispell-tests.log:

>     (error "No Ispell process to read output from!")

> , but I suspect that will go away as soon as I reboot.

It didn't.  That error message still appears in ~14 tests in the log
file.

> > If all of the above doesn't resolve your problem, please show the
> > exact error messages, with everything else that the test displays
> > (which you should have done in the first place, of course).

A typical extract from ispell-tests.log is:

available backend is:enchant-2
Using vacuous schema
Starting new Ispell process enchant-2 with default dictionary... \
Starting new Ispell process enchant-2 with default dictionary...done
Test ispell/ispell--run-on-word/default backtrace:
  error("No Ispell process to read output from!")
  ispell-accept-output()
  ispell--run-on-word("hellooooooo")
  #f(compiled-function () #<bytecode 0xa19031b981b9dcc>)()
  #f(compiled-function () #<bytecode 0x9f1e8a77bce1789>)()
  handler-bind-1(#f(compiled-function () #<bytecode 0x9f1e8a77bce1789>
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name ispell/ispell--run-on-word/default :d
  ert-run-or-rerun-test(#s(ert--stats :selector ... :tests ... :test-m
  ert-run-tests((not (or (tag :expensive-test) (tag :unstable))) #f(co
  ert-run-tests-batch((not (or (tag :expensive-test) (tag :unstable)))
  ert-run-tests-batch-and-exit((not (or (tag :expensive-test) (tag :un
  eval((ert-run-tests-batch-and-exit '(not (or (tag :expensive-test) (
  command-line-1(("-L" ":." "-l" "ert" "--eval" "(setq treesit-extra-l
  command-line()
  normal-top-level()
Test ispell/ispell--run-on-word/default condition:
    (error "No Ispell process to read output from!")
   FAILED   1/65  ispell/ispell--run-on-word/default (0.046193 sec) at lisp/textmodes/ispell-tests/ispell-tests.el:826

..  enchant-2 is indeed installed on my system.  I didn't explicitly
install it, it must be a dependency of something else, possibly firefox.

> Maybe later, after I've rebooted.

I rebooted, it didn't help.

> > FWIW, I've just tried renaming the Hunspell executable, and the test
> > suite correctly skipped the relevant ispell tests.  So if Hunspell is
> > not installed, I don't expect any error messages.

It seems the algorithm for detecting working spelling checkers is
suboptimal.  I looked at the top level binding of filter-binaries in
ispell-tests-common.el.  There, there is a tentative commented out trial
call to the various spelling checkers.  Perhaps this code is needed after
all.

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 20 Sep 2025 16:12:34 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Sep 20 12:12:34 2025
Received: from localhost ([127.0.0.1]:46689 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1v00CP-0001hG-Hh
	for submit <at> debbugs.gnu.org; Sat, 20 Sep 2025 12:12:33 -0400
Received: from mail.muc.de ([193.149.48.3]:62629)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <acm@HIDDEN>) id 1v00CM-0001gq-LZ
 for 79477 <at> debbugs.gnu.org; Sat, 20 Sep 2025 12:12:31 -0400
Received: (qmail 47472 invoked by uid 3782); 20 Sep 2025 18:12:23 +0200
Received: from muc.de (p4fe15935.dip0.t-ipconnect.de [79.225.89.53]) (using
 STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP;
 Sat, 20 Sep 2025 18:12:23 +0200
Received: (qmail 1409 invoked by uid 1000); 20 Sep 2025 16:12:22 -0000
Date: Sat, 20 Sep 2025 16:12:22 +0000
To: Eli Zaretskii <eliz@HIDDEN>
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
Message-ID: <aM7SZoq00EvBcQhT@HIDDEN>
References: <aM6xupDJ-pp-Q8Xk@HIDDEN>
 <86o6r5gq8z.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <86o6r5gq8z.fsf@HIDDEN>
X-Submission-Agent: TMDA/1.3.x (Ph3nix)
From: Alan Mackenzie <acm@HIDDEN>
X-Primary-Address: acm@HIDDEN
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 79477
Cc: acm@HIDDEN, 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Hello, Eli.

Thanks for such a quick reply!

On Sat, Sep 20, 2025 at 17:20:12 +0300, Eli Zaretskii wrote:
> > Date: Sat, 20 Sep 2025 13:52:58 +0000
> > From: Alan Mackenzie <acm@HIDDEN>

> > Hello, Emacs.

> > When I run the test suite with make check, I get 25 successes in
> > test/lisp/textmode/ispell-tests/ispell-tests.log.  Each of these has the
> > same error message, "Can't find Hunspell dictionary with a .aff affix
> > file".

> > I don't know what a .aff file is, but it seems like my setup is missing
> > one.  Despite this, surely ispell-tests.el should cope with this
> > deficiency, rather than emitting 25 error messages.

> Are you saying that you have the Hunspell executable, but not its
> dictionaries?

Yes, that is indeed the case.  The Hunspell installation script on Gentoo
installs the dictionaries it is specifically asked to install, and if
none are requested, none are installed.  No sensible default is used.
This may be a Gentoo bug.

> What happens if you invoke Hunspell from the shell prompt -- does it
> work or does it show some error message?

I get the error message:

    Can't open affix or dictionary files for dictionary named "en_GB".

..

> If your Hunspell installation is workable, you should have a
> /usr/share/hunspell directory with *.aff files.  If they are missing,
> either install them or remove the Hunspell executable.  The Emacs test
> suite is not supposed to cope with installations that don't work, so
> showing error messages is OK in that case.

I have what is arguably a valid installation, even though not useful.  I
tried reinstalling it, and got no warning message about the lack of
languages.

After deinstalling hunspell ...., I get a different message in
ispell-tests.log:

    (error "No Ispell process to read output from!")

, but I suspect that will go away as soon as I reboot.

> If all of the above doesn't resolve your problem, please show the
> exact error messages, with everything else that the test displays
> (which you should have done in the first place, of course).

Maybe later, after I've rebooted.

> FWIW, I've just tried renaming the Hunspell executable, and the test
> suite correctly skipped the relevant ispell tests.  So if Hunspell is
> not installed, I don't expect any error messages.

OK, thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at 79477 <at> debbugs.gnu.org:


Received: (at 79477) by debbugs.gnu.org; 20 Sep 2025 14:20:27 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Sep 20 10:20:26 2025
Received: from localhost ([127.0.0.1]:46206 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1uzyRu-0001dS-H5
	for submit <at> debbugs.gnu.org; Sat, 20 Sep 2025 10:20:26 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10]:51616)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <eliz@HIDDEN>) id 1uzyRq-0001cv-BS
 for 79477 <at> debbugs.gnu.org; Sat, 20 Sep 2025 10:20:24 -0400
Received: from fencepost.gnu.org ([2001:470:142:3::e])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <eliz@HIDDEN>)
 id 1uzyRj-0003Zp-N9; Sat, 20 Sep 2025 10:20:15 -0400
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org;
 s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date:
 mime-version; bh=2OFPpy2PJTqFMXlvPOMtAmNfNSboxLk8kryctWNdcfM=; b=HGBXQYTVRP8q
 FY86fDeHu1wyPZUCRuMOEUAEkcHD2+Ce2EXNe4oWYo1LJFUCSAOZPN3NPc67QkMkWwfFaomamG+vq
 NEtDbR0QY6JjCmPCN7zfjmNeXi7mWswIFs5lLCiFmaCKmA76S5BdfQpgQTG1/9JoSjeuEunOkUmwx
 hL4iZJgpim7Zd6J3Dr5yNQ5b1NhuFpsU8zYkdlSAhbpEsLbskjFU063gL7qKpOFeKXRXjQ+kt3OEK
 3LfkoW6DLo1Nl9WskSB22y/KKcZLdIod1lsBmk+9xhrqsEZoALNwRC5lcVkHadSOcC4IbnonxgwmN
 Tc5ThH3Z0JN2kCX8Zxn6uA==;
Date: Sat, 20 Sep 2025 17:20:12 +0300
Message-Id: <86o6r5gq8z.fsf@HIDDEN>
From: Eli Zaretskii <eliz@HIDDEN>
To: Alan Mackenzie <acm@HIDDEN>
In-Reply-To: <aM6xupDJ-pp-Q8Xk@HIDDEN> (message from Alan Mackenzie on
 Sat, 20 Sep 2025 13:52:58 +0000)
Subject: Re: bug#79477: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find
 Hunspell dictionary with a \.aff affix file"
References: <aM6xupDJ-pp-Q8Xk@HIDDEN>
X-Spam-Score: -2.3 (--)
X-Debbugs-Envelope-To: 79477
Cc: 79477 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -3.3 (---)

> Date: Sat, 20 Sep 2025 13:52:58 +0000
> From: Alan Mackenzie <acm@HIDDEN>
> 
> Hello, Emacs.
> 
> When I run the test suite with make check, I get 25 successes in
> test/lisp/textmode/ispell-tests/ispell-tests.log.  Each of these has the
> same error message, "Can't find Hunspell dictionary with a .aff affix
> file".
> 
> I don't know what a .aff file is, but it seems like my setup is missing
> one.  Despite this, surely ispell-tests.el should cope with this
> deficiency, rather than emitting 25 error messages.

Are you saying that you have the Hunspell executable, but not its
dictionaries?  What happens if you invoke Hunspell from the shell
prompt -- does it work or does it show some error message?

If your Hunspell installation is workable, you should have a
/usr/share/hunspell directory with *.aff files.  If they are missing,
either install them or remove the Hunspell executable.  The Emacs test
suite is not supposed to cope with installations that don't work, so
showing error messages is OK in that case.

If all of the above doesn't resolve your problem, please show the
exact error messages, with everything else that the test displays
(which you should have done in the first place, of course).

FWIW, I've just tried renaming the Hunspell executable, and the test
suite correctly skipped the relevant ispell tests.  So if Hunspell is
not installed, I don't expect any error messages.




Information forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.

Message received at submit <at> debbugs.gnu.org:


Received: (at submit) by debbugs.gnu.org; 20 Sep 2025 13:53:14 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Sep 20 09:53:14 2025
Received: from localhost ([127.0.0.1]:45127 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1uzy1a-00084y-61
	for submit <at> debbugs.gnu.org; Sat, 20 Sep 2025 09:53:14 -0400
Received: from lists.gnu.org ([2001:470:142::17]:59072)
 by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.84_2) (envelope-from <acm@HIDDEN>) id 1uzy1X-00084T-DB
 for submit <at> debbugs.gnu.org; Sat, 20 Sep 2025 09:53:12 -0400
Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <acm@HIDDEN>) id 1uzy1R-0003FI-21
 for bug-gnu-emacs@HIDDEN; Sat, 20 Sep 2025 09:53:05 -0400
Received: from mail.muc.de ([193.149.48.3])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <acm@HIDDEN>) id 1uzy1P-0006DS-3w
 for bug-gnu-emacs@HIDDEN; Sat, 20 Sep 2025 09:53:04 -0400
Received: (qmail 68840 invoked by uid 3782); 20 Sep 2025 15:52:59 +0200
Received: from muc.de (p4fe15935.dip0.t-ipconnect.de [79.225.89.53]) (using
 STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP;
 Sat, 20 Sep 2025 15:52:59 +0200
Received: (qmail 31949 invoked by uid 1000); 20 Sep 2025 13:52:58 -0000
Date: Sat, 20 Sep 2025 13:52:58 +0000
To: bug-gnu-emacs@HIDDEN
Subject: Emacs Emacs 31.0.50: ispell-tests.el: "Can't find Hunspell
 dictionary with a \.aff affix file"
Message-ID: <aM6xupDJ-pp-Q8Xk@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
X-Submission-Agent: TMDA/1.3.x (Ph3nix)
From: Alan Mackenzie <acm@HIDDEN>
X-Primary-Address: acm@HIDDEN
Received-SPF: pass client-ip=193.149.48.3; envelope-from=acm@HIDDEN;
 helo=mail.muc.de
X-Spam_score_int: -18
X-Spam_score: -1.9
X-Spam_bar: -
X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9,
 RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001,
 SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no
X-Spam_action: no action
X-Spam-Score: 0.9 (/)
X-Debbugs-Envelope-To: submit
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -0.1 (/)

Hello, Emacs.

When I run the test suite with make check, I get 25 successes in
test/lisp/textmode/ispell-tests/ispell-tests.log.  Each of these has the
same error message, "Can't find Hunspell dictionary with a .aff affix
file".

I don't know what a .aff file is, but it seems like my setup is missing
one.  Despite this, surely ispell-tests.el should cope with this
deficiency, rather than emitting 25 error messages.

-- 
Alan Mackenzie (Nuremberg, Germany).




Acknowledgement sent to Alan Mackenzie <acm@HIDDEN>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs@HIDDEN. Full text available.
Report forwarded to bug-gnu-emacs@HIDDEN:
bug#79477; Package emacs. Full text available.
Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.
Last modified: Sat, 18 Oct 2025 08:15:02 UTC

GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997 nCipher Corporation Ltd, 1994-97 Ian Jackson.