Received: (at 80323) by debbugs.gnu.org; 8 Feb 2026 16:58:41 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sun Feb 08 11:58:41 2026 Received: from localhost ([127.0.0.1]:53186 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1vp87N-0002zF-7u for submit <at> debbugs.gnu.org; Sun, 08 Feb 2026 11:58:41 -0500 Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:26537) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <monnier@HIDDEN>) id 1vp87K-0002yL-Ko for 80323 <at> debbugs.gnu.org; Sun, 08 Feb 2026 11:58:39 -0500 Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 2F20181BB1; Sun, 8 Feb 2026 11:58:33 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1770569911; bh=JMZc7U41aIK0hwDsoYaGuklSYp/d3IIg0JfrNLfhbuo=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=HsFKtmjz2U41V3Av7cMvQLzM7fefxhfb8lEaxoOH7JbXRGPDQ10fo8UZe8jaPznD3 GHi8hFp0gsxYlmzQN2F8yLgMVAylqibfCrkVninV/NUzMWZhbyVK+DvCKGiSPUhnOV PuJc8pc5I6EYljSkE1QIBZjdy4LbFFbnRaKtWR+0CI7rBoabd14vjWEp1y6D4+EuXb vFDx0Nsbx7z0rRgQcWxiqA8mH/JaQD6CcgI13GURgeW21EHYmXvGfzGYO7bfRAoS5c R5hHQf6VF/j+PK8ryiiUdeNEkaTRG8KDiCzu/UFCJYcrKHeKzO+sPIESBVLUf0PKld A+ZX/yWa2rItA== Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 0D34880872; Sun, 8 Feb 2026 11:58:31 -0500 (EST) Received: from pastel (104-195-243-38.cpe.teksavvy.com [104.195.243.38]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id BDF331208A4; Sun, 8 Feb 2026 11:58:30 -0500 (EST) From: Stefan Monnier <monnier@HIDDEN> To: =?windows-1252?B?Sm/jbyBU4XZvcmE=?= <joaotavora@HIDDEN> Subject: Re: feature/newflex2 a0b5ff9bb79: Rewrite flex completion scoring with Gotoh algorithm In-Reply-To: <20260207212515.0BD1CC06C63@HIDDEN> Message-ID: <jwvqzqv2myy.fsf-monnier+emacs@HIDDEN> References: <177049951444.27865.13520833628888303186@HIDDEN> <20260207212515.0BD1CC06C63@HIDDEN> Date: Sun, 08 Feb 2026 11:58:30 -0500 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable X-SPAM-INFO: Spam detection results: 0 ALL_TRUSTED -1 Passed through trusted hosts only via SMTP AWL -0.142 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain DKIM_VALID_EF -0.1 Message has a valid DKIM or DK signature from envelope-from domain X-SPAM-LEVEL: X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 80323 Cc: Axel Forsman <axel@HIDDEN>, Eli Zaretskii <eliz@HIDDEN>, Sean Whitton <spwhitton@HIDDEN>, 80323 <at> debbugs.gnu.org, =?windows-1252?Q?St=E9phane?= Marks <shipmints@HIDDEN> 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 (---) Jo=E3o T=E1vora [2026-02-07 16:25:14] wrote: > branch: feature/newflex2 > commit a0b5ff9bb79681279a351de47d379f247e14424d > Author: Jo=E3o T=E1vora <joaotavora@HIDDEN> > Commit: Jo=E3o T=E1vora <joaotavora@HIDDEN> > > Rewrite flex completion scoring with Gotoh algorithm LGTM! =3D=3D=3D Stefan
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 7 Feb 2026 14:02:54 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Feb 07 09:02:54 2026 Received: from localhost ([127.0.0.1]:34827 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1voith-0008E5-W5 for submit <at> debbugs.gnu.org; Sat, 07 Feb 2026 09:02:54 -0500 Received: from sendmail.purelymail.com ([34.202.193.197]:44574) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <spwhitton@HIDDEN>) id 1voitf-0008Do-LL for 80323 <at> debbugs.gnu.org; Sat, 07 Feb 2026 09:02:52 -0500 DKIM-Signature: a=rsa-sha256; b=TrUBGvIKu9hJXG6EGydfhDPzX3MRcUwmQPNy/hwzPUbWT79bVzszTln8dD4u64Oax7iaZSOalR8vQCVOilcs0/52wbbsx2V7nOxPbwzNrWr7vC70fWMw3vo+yZxvQvimCUwylqxAolpjz97r2LimlNCfneYmaEqyJN9oOpWgVvUYK306NwC+QiGbUDIFwG/MD38/jME8sZQx+jlrWNSGhNgAaHmAs7x0Z3WHp2Vq58WtQZMRIgiggIAAkH5BjtiC+ghdwzUL1iZWsKEhFF3oqCg9qkSFBSKOcV9W8orusRL776x52kzIx6Bip++mjQ38l5TZ+9s+mm3oD/r7pbQXoA==; s=purelymail3; d=spwhitton.name; v=1; bh=p0lZsLcCskyX18PTPQOEFstBoDNWLCBW0OBlQRI5jOU=; h=Received:Received:From:To:Subject:Date; DKIM-Signature: a=rsa-sha256; b=RM1oKRhmqN12Sr30no77HaMkRbUFztLJ1L0KkIthg3qJ9g/xJQARWOeKdpHyYUeinBSizfD4lLQ5P3pS7ygUj6gMskxo3kksYfex7WTxkh8eOGc7P+/IHn8t0y5Ma/kkn85QikKdpO2OTH3T1UgoxLub3uVfWHQUMckIUARGiQBZfuW0rhRHlrWnil1DIdSlVpiLqUQc/OfiR/rZ0qMK7Dm4ksBZ9EPg+A+IjsSaPor1M/n3NuboxLH8JzRzohHaIU9L5hOlD9XKCrrAIin8ZKVjsyfvG3/5y+2ki+twHRcFFRJxPRHrh4NMOTQuZRwMfdKovKXtjEHikZTIgiznNg==; s=purelymail3; d=purelymail.com; v=1; bh=p0lZsLcCskyX18PTPQOEFstBoDNWLCBW0OBlQRI5jOU=; h=Feedback-ID:Received:Received:From:To:Subject:Date; Feedback-ID: 20115:3760:null:purelymail X-Pm-Original-To: 80323 <at> debbugs.gnu.org Received: by smtp.purelymail.com (Purelymail SMTP) with ESMTPSA id 1583924012; (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384); Sat, 07 Feb 2026 14:02:45 +0000 (UTC) Received: by zephyr.silentflame.com (Postfix, from userid 1000) id E53DE940445; Sat, 07 Feb 2026 14:02:44 +0000 (GMT) From: Sean Whitton <spwhitton@HIDDEN> To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm In-Reply-To: <CALDnm51COBHHWot_5rMBxqwECbW0pzx2XwcKSFZsJBOoHeJ++A@HIDDEN> References: <87y0la2egy.fsf@HIDDEN> <87fr7fjj1d.fsf@HIDDEN> <87v7gadm9s.fsf@HIDDEN> <CALDnm51EU49u5XkmT0tX6WdhQxLEiQ5Og-31M7ynkfh_8FySaQ@HIDDEN> <87h5rttni6.fsf@HIDDEN> <CALDnm50RYodwE6D1keiXvcpU3KBW2q9qCiU6MRZXqzjR-wYjHQ@HIDDEN> <CALDnm51COBHHWot_5rMBxqwECbW0pzx2XwcKSFZsJBOoHeJ++A@HIDDEN> Date: Sat, 07 Feb 2026 14:02:44 +0000 Message-ID: <87fr7cd52z.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 80323 Cc: 80323 <at> debbugs.gnu.org, Stefan Monnier <monnier@HIDDEN> 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, Jo=C3=A3o T=C3=A1vora [07/Feb 1:54am GMT] wrote: > On Sat, Feb 7, 2026 at 12:49=E2=80=AFAM Jo=C3=A3o T=C3=A1vora <joaotavora= @gmail.com> wrote: >> >> On Sat, Feb 7, 2026 at 12:18=E2=80=AFAM Jo=C3=A3o T=C3=A1vora <joaotavor= a@HIDDEN> wrote: >> > >> > Jo=C3=A3o T=C3=A1vora <joaotavora@HIDDEN> writes: >> > >> > > Hmmm I can't reproduce this. Are you sure you're not loading stale f= iles?Try: >> > > >> > > src/emacs -Q -f fido-vertical-mode -f project-find-file >> > > >> > > from the Emacs source tree. >> > > >> > > I do see highlighting mistakes, but the filtering and sorting looks = solid. >> > >> > I've fixed the highlighting mistakes and simplified the code in the >> >> Never mind, I think I do see some errors occasionally. >> They're not in the C-code, rather in the Elisp. Probably its time >> flex stops (ab)using the legacy "pcm" and "substring" styles >> infrastructure. > > Think I fixed them. Have a go at feature/newflex when you find the time. > > I'll still try to decouple flex from the PCM machinery though, should > remove many hacks. Thanks, my issue seems not to be reproducible with the current branch. --=20 Sean Whitton
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 7 Feb 2026 01:55:07 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 06 20:55:07 2026 Received: from localhost ([127.0.0.1]:58810 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1voXXP-0004pU-GP for submit <at> debbugs.gnu.org; Fri, 06 Feb 2026 20:55:07 -0500 Received: from mail-ot1-x336.google.com ([2607:f8b0:4864:20::336]:42214) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>) id 1voXXK-0004nB-MF for 80323 <at> debbugs.gnu.org; Fri, 06 Feb 2026 20:55:05 -0500 Received: by mail-ot1-x336.google.com with SMTP id 46e09a7af769-7d1872504cbso2200422a34.0 for <80323 <at> debbugs.gnu.org>; Fri, 06 Feb 2026 17:55:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770429301; cv=none; d=google.com; s=arc-20240605; b=CWvpSu9jhsNsOWOQk1Yk9Jsgob7UKG+uX7UE0ehcN7tUDzZWK9Fn24kt+OqbsfNsx9 W4VGuaBW+YPN+L9o/OKxSiGjbrE4+RGKFDDwaE91NF1GjkB5YHyVBZxvzS8RMNtNWZTU Lsp/3tbWqDwJxj5arYdyGpQ0nOWlMpv86jmp7AHoyEuDjZGGlyZSdl0P/NcK/43bts6O qpYvzCNEBYHdL25uxJJOAAjqt0yTSFv5Z4+deooFUzU/i/CvmHpjO6Drm3k5c5PRFqhM tPxir35umkJCnoojL3t+HK0BFwsAIOGBKn8PMcWkBRwcc2LT1XJvGO9fdxZwybIjPYmX ElbA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=nP8gJv4wXFoRou49Y/iW/B8jJJ7BcPhdE3t8frCng5E=; fh=KXVSpnQI7fHeNqW1W1EkZX7Vh0/EVBulmzyl15jHwBY=; b=K7Ooyab+rugU98hejPLu1jXDZspBKsCNnfh1HaLR2JFbG8swJ3EhEQ1hIdvf/SgXgF 1G4MZQpikZtD3cB6N477hs6eTWwR1jNequoe5C1IB9pHDDCdKLozELowHW3WrynbVTSx dEbyY2yUnH8PKmyYnosxmswy7BrkYMwUnVAqGNHvIn55il72NN5VoWq5ajg/M/O1lYFU xtu144+e38ZAyykxm9SgBHIJTZIBrac6de46cXjCHHWO78v+H6YfMBqpgyCwdZ0lYBIW 2nFQHEKcljUOmF5La9zjyM8vCgNdAMDds/KLL4U6MgynqN1jbVCYjvuTLfbPYBXqZC2g iO3g==; darn=debbugs.gnu.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770429301; x=1771034101; darn=debbugs.gnu.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=nP8gJv4wXFoRou49Y/iW/B8jJJ7BcPhdE3t8frCng5E=; b=Qm7eGvMmNjo5VAZut+6zyA2uY0yFhS6MedxHkYqavzRPgJ44LBF38sviiZmNWRxZtp MWn2cSoSBfvWytxwjaaLVeeYiooc/l+i/vgt+0vQRIuDmkL6ybmNO1hZTz1LWjaq8zkt QkEztohy4VLYt5Hfb0fRIqZu+5RXL42uT7ZB8kx0tg9cO30/JgpsK14MPKn7ltXdRfNP GmdW/8QiLjwbUIbiOMbEk0bXZRt1JBwLOeTBn8+2KXTY92ilLm27aMi56Ar9odeUj781 eUj5LmXeh4XR1oZCVAS42hxo9WOWauY4E0FvDDYD3kHcq0uasNLfhwfeqjY8lk+341ip jlCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770429301; x=1771034101; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=nP8gJv4wXFoRou49Y/iW/B8jJJ7BcPhdE3t8frCng5E=; b=RRSfz0H+AOKsC+aUljeqYT8cUL7e5XpoIp54/FUPeHmjUj3oihFe/Fn22LZWthb3YL qkI/jslAem3s3NePkX0dyi5lR+2HdJAVrSlB4TJqMLLAiQ8VeF4stCORHfilz0Q3bWUt XIrLbuot3D3DTiLmvV8AlYQejBUqNztphh2ULfckoqB8Utww/sSWT4pY3L7uBYmqzyCv uB5XdYO6+yrgJ7kRRLWLyfDWd6zU395ozu1vKajbjcZOLFYxcWxh624aSNRTQ26WMHol s3jnn1xcF1lvq3r6B/64limtJbDEy/DFydwaqbts40M1Ig8DvtTM64jgR8MVkVyr7o9k TeWQ== X-Gm-Message-State: AOJu0YxcOZYKZi0U18QlE6yo2BnY5wGnWXz5bH+hoBbQnRT6t3pizf3J hF3W+1R9LYYYDwxDRtXGCERYvuYn5U+PIi5mYM/qdNiyaj0XtUfLbJNojmk77xI7GcHlvTlMIGA YPtZWl0xg0Y+cEdeMxwI+tlQKovKuaws= X-Gm-Gg: AZuq6aI2Y6B/S+VlMuPg00PSTI3ijQP9tqcnCcCiCywZMQOy1PA9B2fpDc2CmZQb1pl UHt8DtYyHpHabsTj/5DEw3jOGBNXCGWx/EQjSHpSSjMrYyXhFDHh8oviYurWpHF8eIQr8SRrJDQ CGozo5MkaLeQXOBEiqHcPjEOwRspNBgxPz6Ms14pUreDq9y7ahDOMBLbYw8Sw3kbJjilZabMRBV k8AGBEfKM8ntq9PwyxAh8hhd7pOdIIT33QAtm7TrtK33Aw11FTFNu1Y5y7LTg/dsdWxsA== X-Received: by 2002:a05:6830:661c:b0:7cf:cd54:f4bc with SMTP id 46e09a7af769-7d4634194admr2736895a34.18.1770429301170; Fri, 06 Feb 2026 17:55:01 -0800 (PST) MIME-Version: 1.0 References: <87y0la2egy.fsf@HIDDEN> <87fr7fjj1d.fsf@HIDDEN> <87v7gadm9s.fsf@HIDDEN> <CALDnm51EU49u5XkmT0tX6WdhQxLEiQ5Og-31M7ynkfh_8FySaQ@HIDDEN> <87h5rttni6.fsf@HIDDEN> <CALDnm50RYodwE6D1keiXvcpU3KBW2q9qCiU6MRZXqzjR-wYjHQ@HIDDEN> In-Reply-To: <CALDnm50RYodwE6D1keiXvcpU3KBW2q9qCiU6MRZXqzjR-wYjHQ@HIDDEN> From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> Date: Sat, 7 Feb 2026 01:54:50 +0000 X-Gm-Features: AZwV_QhFhlvhKlJ4dNxUtMJvGRLPicd84iq5qW0zR252Mw7BsR5nAQdvBm5mu_s Message-ID: <CALDnm51COBHHWot_5rMBxqwECbW0pzx2XwcKSFZsJBOoHeJ++A@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm To: Sean Whitton <spwhitton@HIDDEN> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 80323 Cc: 80323 <at> debbugs.gnu.org, Stefan Monnier <monnier@HIDDEN> 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.0 (/) On Sat, Feb 7, 2026 at 12:49=E2=80=AFAM Jo=C3=A3o T=C3=A1vora <joaotavora@g= mail.com> wrote: > > On Sat, Feb 7, 2026 at 12:18=E2=80=AFAM Jo=C3=A3o T=C3=A1vora <joaotavora= @gmail.com> wrote: > > > > Jo=C3=A3o T=C3=A1vora <joaotavora@HIDDEN> writes: > > > > > Hmmm I can't reproduce this. Are you sure you're not loading stale fi= les?Try: > > > > > > src/emacs -Q -f fido-vertical-mode -f project-find-file > > > > > > from the Emacs source tree. > > > > > > I do see highlighting mistakes, but the filtering and sorting looks s= olid. > > > > I've fixed the highlighting mistakes and simplified the code in the > > Never mind, I think I do see some errors occasionally. > They're not in the C-code, rather in the Elisp. Probably its time > flex stops (ab)using the legacy "pcm" and "substring" styles > infrastructure. Think I fixed them. Have a go at feature/newflex when you find the time. I'll still try to decouple flex from the PCM machinery though, should remove many hacks. --=20 Jo=C3=A3o T=C3=A1vora
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 7 Feb 2026 00:49:55 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 06 19:49:54 2026 Received: from localhost ([127.0.0.1]:58306 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1voWWI-00013f-Kn for submit <at> debbugs.gnu.org; Fri, 06 Feb 2026 19:49:54 -0500 Received: from mail-ot1-x331.google.com ([2607:f8b0:4864:20::331]:45203) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>) id 1voWWF-00013U-Vz for 80323 <at> debbugs.gnu.org; Fri, 06 Feb 2026 19:49:52 -0500 Received: by mail-ot1-x331.google.com with SMTP id 46e09a7af769-7d18a9d2b1aso2194072a34.2 for <80323 <at> debbugs.gnu.org>; Fri, 06 Feb 2026 16:49:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770425390; cv=none; d=google.com; s=arc-20240605; b=PNSLaHVHzyJS+vYu/+hkULZ1FMfx9brF9qD3R+iAHKiXa3rNSJsgzUfe4sXePZUEuS O0pAHF+278VycOH8vmSyCCESoWa9GuVVZndObtjiK63di6EnlXcrbR1B0tH0wzo+PpbH m6YzxktRQo3s9u1avSVeH7RE1fhz9apLS1ZAmnL3hbipTO/plyn6RyhyRVBvGQ9dVSfF k644Zs3DJq5j7OldPma/jkDKA99EMeiOz0yFkxPNOqWR4P8fwcUDRW/y1nrczqd6FGPF jMND1AZe8DplfEi69JKdyWui2Sb7FSC8JzVtU6XN53Ww5FLr1T9wW/cC7Rs9Ot/0fuM+ tcrg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=6RQh8WAynncQJLE6oYWmfMAlDqxtVEkV7ohpxF+bS0Q=; fh=9UkE8d2UXp2uy5oCUPNyofwz0gi9iC3+JO7kqnVpHUc=; b=ObpiScBdNpnMZQSyp3nAmpnp45hMwqtgL2yIOvutFBEI7jyxH2j40giqoyP0YwHNb+ 1Ft8D5q0cnQt9dY9OXp3a///tCGxdQekqi453Aaeiv6Vl5qCgMB6hCf5EpIvEN5C2NDC GJSEsILQ8TaWofSt+3ESIGrB5Fbhkp3z54mMbcma4mD6aFWbltGKah3Bss7JLNnwvQ09 /pflwncra/oRi/n2TLF4Ffzpf6Pz4agT3vRSp6ZH7PDqdMi0sX9yMSDCu5na3R98kj4/ zJGUGoQ9tnNKR+LM6hk487F/9MZQ8ijpkCkFt5rx9+eWZ2xWcOLj9f9oc2ykJF7le4RZ ZY8w==; darn=debbugs.gnu.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770425390; x=1771030190; darn=debbugs.gnu.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=6RQh8WAynncQJLE6oYWmfMAlDqxtVEkV7ohpxF+bS0Q=; b=i1Xrx7NA7mAQllm3PnbD8qh8dpIdYou+fEzikkH4anW42ZCUFJkrM06H4sgP7rcdQ8 skk375jULzO5jVtF8qA9FW2DZEMC+PZspi4yShiBDkmMgn6BF8dcIFPPmehghYnVja5K dXbd+odCRFbU6Msc2kWv4xI7h9FDtyUh/GNYW+IzLnvWAf9VRqSdVROuLSo5m+rGa8zt OAAcKq3WW9lHdBLJOxMiJZWazY1FiNcmsIfzKhqsQt4+ogmPU8XQ6BY0nF8ZvfkAf7Ye Wks2FYN67/clZuvB7Jj84nlNJJmDsOXG2M7FD9bZjmiQKtSzLhMCnjB3+kKXcAOp3fgY NwQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770425390; x=1771030190; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=6RQh8WAynncQJLE6oYWmfMAlDqxtVEkV7ohpxF+bS0Q=; b=F+a2Tm+OaE+u+RKLrEzv/B0Nr9IDyqJEN4KHeKJJMf0THDzkUQ8t6rsRjNwQdUYbCr nuuud+CJoK8+Za+UYuJNRz0WV9RAqteDdbg6G9SEQiVKVmU84BZGwNqMb+BP70k3y+CL bUzUQoxBpRkptxTOicgHKWxfuROj8OJUAVt00dGxBe2jLguD2NNtx0Ia9RaaKQNwj6Bv pBAvHTBKLQzGWTav9DggJ+yddfT3foK9nggj88q3d3XRiwb5FY+BQ5kuWkyWkteDIO4z OoLoOKvykep8JzUp9vPQytRIZkN+VtpmcK8nDbSQYsoF5dNc1VIv3/MFiNyfWyXnGop1 X+NQ== X-Gm-Message-State: AOJu0YyxgU675nsAA/i9srP6utuPn7lxtdhrkFJOxs+M3r/JjymXfgqU oKrdBDBmlN2JhJyH7gv2EW5z5yKI45vnF40U7TmPAmliw6AfpP/V6JVZa/CM7Uf51iu3pYxp+7G qWO/ijDEMakUUnBKsoB032AuxkE4nPuY= X-Gm-Gg: AZuq6aLMcNJ5qw7xZigsT/KKNUfVYejoojkamc1CP137SoQg4A5yFYimqEUOOI1Wri5 P1TeEJUK/nKtbcRFAmnKC+TBqRDdx115yBAG5EsBUmW4g3WNf7kylFQCiVEkxio7IOvRG5h+/B9 QfKecNSUc+w8V/4IyqSlfYIjHC5UBZgYNyw1rukOoSj8NoDigOUGQEKilzzF72PjIVZVCSRoKM+ heLUmCPkcvWwZ6/H0XxJWqF32COrIl7aqwr2ZxpfkOBoW/o+Tj8KqUSSo8Iha8qUVQ+oA== X-Received: by 2002:a05:6830:6188:b0:771:5ae2:fce0 with SMTP id 46e09a7af769-7d464488f2bmr2140669a34.20.1770425390601; Fri, 06 Feb 2026 16:49:50 -0800 (PST) MIME-Version: 1.0 References: <87y0la2egy.fsf@HIDDEN> <87fr7fjj1d.fsf@HIDDEN> <87v7gadm9s.fsf@HIDDEN> <CALDnm51EU49u5XkmT0tX6WdhQxLEiQ5Og-31M7ynkfh_8FySaQ@HIDDEN> <87h5rttni6.fsf@HIDDEN> In-Reply-To: <87h5rttni6.fsf@HIDDEN> From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> Date: Sat, 7 Feb 2026 00:49:39 +0000 X-Gm-Features: AZwV_QhLNwXhWDl-m6zLRnOiIETzxTKErkonrPqkczpSOZ-yh84-ykR0hyj0d-M Message-ID: <CALDnm50RYodwE6D1keiXvcpU3KBW2q9qCiU6MRZXqzjR-wYjHQ@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm To: Sean Whitton <spwhitton@HIDDEN> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 80323 Cc: Axel Forsman <axel@HIDDEN>, Eli Zaretskii <eliz@HIDDEN>, 80323 <at> debbugs.gnu.org, Stefan Monnier <monnier@HIDDEN>, =?UTF-8?Q?St=C3=A9phane_Marks?= <shipmints@HIDDEN> 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.0 (/) On Sat, Feb 7, 2026 at 12:18=E2=80=AFAM Jo=C3=A3o T=C3=A1vora <joaotavora@g= mail.com> wrote: > > Jo=C3=A3o T=C3=A1vora <joaotavora@HIDDEN> writes: > > > Hmmm I can't reproduce this. Are you sure you're not loading stale file= s?Try: > > > > src/emacs -Q -f fido-vertical-mode -f project-find-file > > > > from the Emacs source tree. > > > > I do see highlighting mistakes, but the filtering and sorting looks sol= id. > > I've fixed the highlighting mistakes and simplified the code in the Never mind, I think I do see some errors occasionally. They're not in the C-code, rather in the Elisp. Probably its time flex stops (ab)using the legacy "pcm" and "substring" styles infrastructure. Jo=C3=A3o
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 7 Feb 2026 00:18:17 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 06 19:18:17 2026 Received: from localhost ([127.0.0.1]:58126 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1voW1h-0007rU-37 for submit <at> debbugs.gnu.org; Fri, 06 Feb 2026 19:18:17 -0500 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]:46222) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>) id 1voW1e-0007rF-Mb for 80323 <at> debbugs.gnu.org; Fri, 06 Feb 2026 19:18:15 -0500 Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-48069a48629so24251725e9.0 for <80323 <at> debbugs.gnu.org>; Fri, 06 Feb 2026 16:18:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770423493; x=1771028293; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oWAx3tdmxvE4pL2o01uVS2Ul6lirt3B/HPz4jwSzZXM=; b=f3dZJOfZqdnSgBgHNXhiuQiBWvPkerUZQtGgp3/HmyiNDR9QGEn8DTIAHSh6OnbdCd qqL6UMYrsvejQ+xKxVOgB36Nt2SR3iYMZYTw4UUPn6kHmaY9lrN5yR22wkIbLZBR+ZIh MIVFCsxxJxn5nE38PxhyPutEnGedmPvHOG+6LAlMUWsJPkXN1GAwSPDGnO7Q9o8zOFdL /6sR7KYZiP9TBA/UuPuWvO9msT+djDXEaGj4DaYw6DBHyscFCxp08AYt0R4LANfwh3HX HyKAgejFGeLwC2SfUDU1R0+2TsiWOAerWNoaxrVZ46wGhxX/wb9WQK2Lhmp8blQbfvuZ YI1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770423493; x=1771028293; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=oWAx3tdmxvE4pL2o01uVS2Ul6lirt3B/HPz4jwSzZXM=; b=Fs14xH9vysCcSkIr0ulJNqQ2xaem59Rri/5bPu+ElR/9FMePWsnlVA/kqMCcrRRj33 TPz9BO09AqWV+HCiBSBPBIgtbgVslqwK1yGDP9oSlLq1ct/CfRjeGsVXJandu0CJcfb2 THP+LroBFIvhOp4GQgkKgxfR35l2W4XG6unhRFlrCUM5/1ndnP83FIb20iWRQMLr6/Bl oaC36HOtQohzdUuCsOHzixDcJYBXoRa4D7ClJtwrKYMcMAv9Y4ACupK9aPtM1FSQdunD 19LQqAtjV5uWHjC9ZSVNtTnGJB1euJ2yeLp/jS3aAY2YwRN/73A6pTjlTQrpp3rrSc18 Wu1A== X-Gm-Message-State: AOJu0Yyf2o0A9ZXC7hjiLOLJ/k3hPsy5AZf/G0yHffesy9yUdUxMVsz7 WGTuaqoAxDGJqbGweiP1dXuy6hkd4GzwiStokaMOJ8kmLzcJ4gs7o7jB1CNmpQ== X-Gm-Gg: AZuq6aJUNjN5NoKzgJ254siUmKM7GEudk4/rLmHT4sP6lO6KVmEsjlzRqfXiTbbv72M MLiPLLpPFA2G1aKAIXeegCD8CIdcrzcrFnHNSgvmGEPX9lq1jKXlBJ67LOzOcvtSVs/ywM+CaXV 57aB64e8RSb1UkadvxkY0L/JxzyVggOZitqfB6CpadyoVQC9hdWEOA8LNjJBt5z5C9Z0/NWVa62 2fsdU68e8g8hBYY+zyTh/QaSmMeqHzP4xwFomWPfurN8NtfcVVlnagA911aDISz9Pt1sMtfCXXh cxof3fftV58mMDrWiY9dsEV0gsa8S8XMe1LKqYGuki+1xPLcUSGLD/g/91E48Nftf4VpoGv9bOF xfOKYfdzV1ZF9Tdl00DlIhiFnPps8oBU7tbg4hB4E5Nvmh5GWPLGRi3Tbt8ZPmL4BsPtdZdOJWW PbU/tLORfYchjJBG9764D48En7LA== X-Received: by 2002:a05:600c:474c:b0:482:ef72:5778 with SMTP id 5b1f17b1804b1-483201dc4efmr68817435e9.8.1770423492972; Fri, 06 Feb 2026 16:18:12 -0800 (PST) Received: from krug (87-196-74-61.net.novis.pt. [87.196.74.61]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48317d299bfsm146853795e9.2.2026.02.06.16.18.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 06 Feb 2026 16:18:11 -0800 (PST) From: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> To: Sean Whitton <spwhitton@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm In-Reply-To: <CALDnm51EU49u5XkmT0tX6WdhQxLEiQ5Og-31M7ynkfh_8FySaQ@HIDDEN> References: <87y0la2egy.fsf@HIDDEN> <87fr7fjj1d.fsf@HIDDEN> <87v7gadm9s.fsf@HIDDEN> <CALDnm51EU49u5XkmT0tX6WdhQxLEiQ5Og-31M7ynkfh_8FySaQ@HIDDEN> Date: Sat, 07 Feb 2026 00:18:09 +0000 Message-ID: <87h5rttni6.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 80323 Cc: Axel Forsman <axel@HIDDEN>, Eli Zaretskii <eliz@HIDDEN>, 80323 <at> debbugs.gnu.org, Stefan Monnier <monnier@HIDDEN>, =?utf-8?Q?St=C3=A9phane?= Marks <shipmints@HIDDEN> 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.0 (/) Jo=C3=A3o T=C3=A1vora <joaotavora@HIDDEN> writes: > Hmmm I can't reproduce this. Are you sure you're not loading stale files?= Try:=20 > > src/emacs -Q -f fido-vertical-mode -f project-find-file > > from the Emacs source tree. > > I do see highlighting mistakes, but the filtering and sorting looks solid= .=20 I've fixed the highlighting mistakes and simplified the code in the latest version pushed to feature/newflex. I've also that flex occasionally manages to be slightly faster than hotfuzz in short patterns (1-4 chars). =E2=9D=AF src/emacs -Q --batch -l bench-completion-full.el -- flex vc Total time: 0.825 seconds (13.0 GCs taking 0.090 sec) Time per call: 4.125 ms =E2=9D=AF src/emacs -Q --batch -L ~/Source/Emacs/hotfuzz -l bench-completio= n-full.el -- hotfuzz vc Total time: 0.909 seconds (26.0 GCs taking 0.204 sec) Time per call: 4.545 ms Jo=C3=A3o
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 6 Feb 2026 14:18:46 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 06 09:18:46 2026 Received: from localhost ([127.0.0.1]:53086 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1voMfV-0002dp-R9 for submit <at> debbugs.gnu.org; Fri, 06 Feb 2026 09:18:46 -0500 Received: from mail-oo1-xc2a.google.com ([2607:f8b0:4864:20::c2a]:43190) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>) id 1voMfS-0002dd-Nh for 80323 <at> debbugs.gnu.org; Fri, 06 Feb 2026 09:18:44 -0500 Received: by mail-oo1-xc2a.google.com with SMTP id 006d021491bc7-662f91bba0fso1996717eaf.0 for <80323 <at> debbugs.gnu.org>; Fri, 06 Feb 2026 06:18:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770387522; cv=none; d=google.com; s=arc-20240605; b=anh8XUTdGOqAwuFXpMzI6fHZ0A6u6bTO8557zeWsFEukMOJqtHPGXEl3DAchcg0Wk8 +yPO6CK/8Ifktv9M031eXhFJp45zXMgX9KT598OFI0M/gbYzr4GDXXTNgzsKPV80++l3 cT/+KYsaXQPT9JC6WoBc724ni1AYYcrCIOlzj7ourB9uQ343euquZNYrcdw3b2wkyDc6 Gw71XSKhvKA5C5XXVQdVEaCgOwgpMT4XLPcO+xGhG+SP/n8OPN4MetbRIR5LM8voBn72 hl/qJ2mLTm6czXxwFtoVfLYW88/qjw13ZkXuQS2hY80x/dlFNIdHU0RL0f8Id+OBDPQf 3jQA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=XcGgvF6speofxb7JFmsxeV7N/sXUtehBuc6TBMolQ50=; fh=9UkE8d2UXp2uy5oCUPNyofwz0gi9iC3+JO7kqnVpHUc=; b=VQtB9UfjzCM30PrUkV+48EhD6WgI/lEDufscsuB2aho7+2kXyxqkZjZBMn0jwyguvL A3i3Z199+W7fVoTW/88gYRKr1N04rlmwbrLSAehOC6qM09cTgAnQOKygWsVK/EzIL1vQ howDJDqYKNl011PM4gmvUXSZMr0EGDABHBioYh1F5ToukC9G+66FV2aEJB7cB6xzemkD C89axCishOz1HzZMkO3xYglKDQ8/4WvUmrgIzo07tsR6be6zU0c3Ba8/Q6rNfrt2L7VO cQv+8g/1wb1qJqvCZXar5RwAZ18fuWAWuGJe0FW7S8HX2zMMsRWDf8bOjQ9ove0YEhJx JMOQ==; darn=debbugs.gnu.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770387522; x=1770992322; darn=debbugs.gnu.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=XcGgvF6speofxb7JFmsxeV7N/sXUtehBuc6TBMolQ50=; b=BNooQLZImK0voOb2b6lU7JvZLj79ohoaDuASDDVrQZNtU7KA7ozgkbr1h6kEYMsp18 OdkmqvqjmYy0T8PR/Ur61//WAqt7FBcm6u6yzbl8/Fd2++H/Cflv2BjxFCWhZe/Cm5TR 7NIabss3xPia/GVXTc3sBEjZfmqWcCkNLPcbEiWKzb9fOr3UmSAeNH56k0Lhk0kxzLjF +0XAr1doI/G9m7G7Ende+Sun+jIkn0ZCTIby+LjnwfH2Xfd+/aeTkz5pATbukxLOfVmX AumeWEPCRQLcre8RCxdpy733e8eD9ENQIuKmejTufX3BTQq4EQy4jWIPRbWE577oect2 VU+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770387522; x=1770992322; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=XcGgvF6speofxb7JFmsxeV7N/sXUtehBuc6TBMolQ50=; b=WIVOpzz68ZD5n5VcK77nmM3XaoK5E8yaL9MhSdEr2Ty22gfRBTuvxKwIaKaffLS5mk xp8z6dqIjx5NMQ4hQxa8btK2+yux5L7s25/LMXcW9u53D1PFRGyCcLDlg+KU6TJcpeIv mFY3uPlXTY47WatwTorRQ8HU0owUOVamGV/AZILwNJaFb4XndCfY/9au6crzYnSiUT7E 21I6Vu+uDD2axNuX4TGaXKimjLqK5qP7vhvES0dI3bD3DxmJoTB89e63PwaPVQ0xY96w toJ00UPPDQwEvUzA0t/s8vA8/RjsR+ga631ceOI91VUYmx/AhGodTuXnfFIb3RMWXw/W PtZw== X-Gm-Message-State: AOJu0YwFigTmcR8GV/bV/AfpMfJT5OV9YWq1OhR2zc15JjG7zO4/c4Oh kFi0P5Gj3zt89ihGhhRNjXgr3WNlBDCEnlEAFfPZZS5U4PfUdHWItoPTQSY8hdTY9GYX/EsNRmb /Mos/Xtj7k7TXsrs0jTKZ/Lt+IVfimtU= X-Gm-Gg: AZuq6aKkSpZfoMB77N/Ca/YyRFz4lTsX4hS+JRarEQfav2VhXFY8/Q4/gm+7Gsm6Ptn 3u7krl9mKd9fBZdYUJoCyO9c8l3L1+HDJXZXcI0a+g9J0euIuPb2WBoVOh0mPZ29nESlif5BwNG pNulT+YJCOU+pUiylyXN9zlBWSMBNPZELI/9iornpj9klGcMvrM3E0yugrgdSbHUfz+edeThBNt Bt1nWUqS7PHKmcdFJ3Bw/UAL7ZTDg4/eboIMZzuiY1a5ZfPvs/dGjTVXcvDA8zNnPtg5bg= X-Received: by 2002:a05:6820:211:b0:662:ee28:1133 with SMTP id 006d021491bc7-66d0f7f2c42mr1114001eaf.0.1770387521695; Fri, 06 Feb 2026 06:18:41 -0800 (PST) MIME-Version: 1.0 References: <87y0la2egy.fsf@HIDDEN> <87fr7fjj1d.fsf@HIDDEN> <87v7gadm9s.fsf@HIDDEN> In-Reply-To: <87v7gadm9s.fsf@HIDDEN> From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> Date: Fri, 6 Feb 2026 14:18:32 +0000 X-Gm-Features: AZwV_Qg7K-FJMOlPlhsGgjNtUOEnDc-J_DtqecBLV6bndPdSFxa9Z2ggrWJ_h9s Message-ID: <CALDnm51EU49u5XkmT0tX6WdhQxLEiQ5Og-31M7ynkfh_8FySaQ@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm To: Sean Whitton <spwhitton@HIDDEN> Content-Type: multipart/alternative; boundary="0000000000005874c8064a28776c" X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 80323 Cc: Axel Forsman <axel@HIDDEN>, Eli Zaretskii <eliz@HIDDEN>, 80323 <at> debbugs.gnu.org, Stefan Monnier <monnier@HIDDEN>, =?UTF-8?Q?St=C3=A9phane_Marks?= <shipmints@HIDDEN> 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.0 (/) --0000000000005874c8064a28776c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hmmm I can't reproduce this. Are you sure you're not loading stale files?Try: src/emacs -Q -f fido-vertical-mode -f project-find-file from the Emacs source tree. I do see highlighting mistakes, but the filtering and sorting looks solid. Jo=C3=A3o On Fri, Feb 6, 2026, 13:39 Sean Whitton <spwhitton@HIDDEN> wrote: > Hello, > > Jo=C3=A3o T=C3=A1vora [05/Feb 3:40pm GMT] wrote: > > Jo=C3=A3o T=C3=A1vora <joaotavora@HIDDEN> writes: > > > >> Hi, > >> > >> The patch I'm attaching fixes them for good. > >> > > > > I'm attaching a new version of the patch, which now also lives in the > > feature/newflex branch of the Savannah repository. It fixes the > > problems with multibyte characters, adds comments to the code, and has > > other improvements. I've reviewed the flex unit tests and created a ne= w > > test with kanji characters. > > > > Please give it some testing. > > I did 'C-x p f' in emacs.git and typed 'vcvc' seeking to match > 'lisp/vc/vc.el' and it got stuck again. This is what I have in > *Messages*: > > Error in post-command-hook (icomplete-post-command-hook): (error > "Pattern vcvc. does not match > test/lisp/emacs-lisp/package-resources/newer-versions/archive-contents") > > -- > Sean Whitton > --0000000000005874c8064a28776c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"auto"><div>Hmmm I can't reproduce this. Are you sure you= 9;re not loading stale files?Try:=C2=A0</div><div dir=3D"auto"><br></div><d= iv dir=3D"auto">src/emacs -Q -f fido-vertical-mode -f project-find-file</di= v><div dir=3D"auto"><br></div><div dir=3D"auto">from the Emacs source tree.= </div><div dir=3D"auto"><br></div><div dir=3D"auto">I do see highlighting m= istakes, but the filtering and sorting looks solid.=C2=A0</div><div dir=3D"= auto"><br></div><div dir=3D"auto">Jo=C3=A3o</div></div><br><div class=3D"gm= ail_quote gmail_quote_container"><div dir=3D"ltr" class=3D"gmail_attr">On F= ri, Feb 6, 2026, 13:39 Sean Whitton <<a href=3D"mailto:spwhitton@spwhitt= on.name">spwhitton@HIDDEN</a>> wrote:<br></div><blockquote class= =3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rg= b(204,204,204);padding-left:1ex">Hello,<br> <br> Jo=C3=A3o T=C3=A1vora [05/Feb=C2=A0 3:40pm GMT] wrote:<br> > Jo=C3=A3o T=C3=A1vora <<a href=3D"mailto:joaotavora@HIDDEN" targ= et=3D"_blank" rel=3D"noreferrer">joaotavora@HIDDEN</a>> writes:<br> ><br> >> Hi,<br> >><br> >> The patch I'm attaching fixes them for good.<br> >><br> ><br> > I'm attaching a new version of the patch, which now also lives in = the<br> > feature/newflex branch of the Savannah repository.=C2=A0 It fixes the<= br> > problems with multibyte characters, adds comments to the code, and has= <br> > other improvements.=C2=A0 I've reviewed the flex unit tests and cr= eated a new<br> > test with kanji characters.<br> ><br> > Please give it some testing.<br> <br> I did 'C-x p f' in emacs.git and typed 'vcvc' seeking to ma= tch<br> 'lisp/vc/vc.el' and it got stuck again.=C2=A0 This is what I have i= n<br> *Messages*:<br> <br> Error in post-command-hook (icomplete-post-command-hook): (error<br> "Pattern vcvc. does not match<br> test/lisp/emacs-lisp/package-resources/newer-versions/archive-contents"= ;)<br> <br> -- <br> Sean Whitton<br> </blockquote></div> --0000000000005874c8064a28776c--
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 6 Feb 2026 13:39:22 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 06 08:39:22 2026 Received: from localhost ([127.0.0.1]:52831 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1voM3O-0000hP-CR for submit <at> debbugs.gnu.org; Fri, 06 Feb 2026 08:39:22 -0500 Received: from sendmail.purelymail.com ([34.202.193.197]:59106) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <spwhitton@HIDDEN>) id 1voM3M-0000h9-8j for 80323 <at> debbugs.gnu.org; Fri, 06 Feb 2026 08:39:20 -0500 DKIM-Signature: a=rsa-sha256; b=We0PpQtUXN8QQahkIG+IGnbwel2ewHvP5kpK8O0RKda7ReRnu86nl10nbascePEfQqiM4RcNUeV8qhVy5+f94Ai0AWwrbS0DKC7HrnJVxRzJCjQ6OJ7fl6MCEWujBwEBI0xU9jyjrYUyuQpgQrQBcyT3+Z/UEZBOMTYwNt73OOAeqVKIwFkgy2bnTfawCRFO8dlOoYKr+iffNTl4HPD5Et7a1x7I6GYxwd53lsLmDtGA1DoAfSEi8gbBqYkUKLqXrBR/JBLp32IWou2Vc/dtS2aFCfdsG9sA/auBFF/QPMgXjeIrFVHpyp1iAqJg3vsHwSmibjcUBkqgwTxlNKv29Q==; s=purelymail3; d=spwhitton.name; v=1; bh=DOU9F8+fpZv5e9SEbMY/GaL3kur7wmKWvcs9UqYbNaA=; h=Received:Received:From:To:Subject:Date; DKIM-Signature: a=rsa-sha256; b=EGbGScZoSBMPOmuPvEZ3xkoEZ6n/1kEpPvnIFmwSgBK14/QXwsTneTImuOSuM4sU7uPvrIC0YyObgVbnbELnpMBFNKL1pYShPwZ0zjuOl6b+hfljdGhwly8D/vLTvAc4QQmXcs+XVBAJnMEeqs6fnVh+dzqn+QEXQ5I9mwKLNo8Js641/d/+mlfBrdfculHfNNhoik3WDfFIG0bAjwlHVhnG8bDMKmmXf7+L4+K/ymGsmUd9S/c+Cf1um/Qrl228qJKnCIsy0sXBo6DD3NUcfrBFCYn8kWZwtXOAS6HRR0rxrkJ1tb0DPT0dA8FmnCQ+klziDTYRyoqYzKx6gbsXdA==; s=purelymail3; d=purelymail.com; v=1; bh=DOU9F8+fpZv5e9SEbMY/GaL3kur7wmKWvcs9UqYbNaA=; h=Feedback-ID:Received:Received:From:To:Subject:Date; Feedback-ID: 20115:3760:null:purelymail X-Pm-Original-To: 80323 <at> debbugs.gnu.org Received: by smtp.purelymail.com (Purelymail SMTP) with ESMTPSA id 2017938127; (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384); Fri, 06 Feb 2026 13:39:12 +0000 (UTC) Received: by zephyr.silentflame.com (Postfix, from userid 1000) id 5A6DB9406A5; Fri, 06 Feb 2026 13:39:11 +0000 (GMT) From: Sean Whitton <spwhitton@HIDDEN> To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm In-Reply-To: <87fr7fjj1d.fsf@HIDDEN> References: <87y0la2egy.fsf@HIDDEN> <87fr7fjj1d.fsf@HIDDEN> Date: Fri, 06 Feb 2026 13:39:11 +0000 Message-ID: <87v7gadm9s.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 80323 Cc: axel@HIDDEN, Eli Zaretskii <eliz@HIDDEN>, 80323 <at> debbugs.gnu.org, monnier@HIDDEN, =?utf-8?Q?St=C3=A9phane?= Marks <shipmints@HIDDEN> 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, Jo=C3=A3o T=C3=A1vora [05/Feb 3:40pm GMT] wrote: > Jo=C3=A3o T=C3=A1vora <joaotavora@HIDDEN> writes: > >> Hi, >> >> The patch I'm attaching fixes them for good. >> > > I'm attaching a new version of the patch, which now also lives in the > feature/newflex branch of the Savannah repository. It fixes the > problems with multibyte characters, adds comments to the code, and has > other improvements. I've reviewed the flex unit tests and created a new > test with kanji characters. > > Please give it some testing. I did 'C-x p f' in emacs.git and typed 'vcvc' seeking to match 'lisp/vc/vc.el' and it got stuck again. This is what I have in *Messages*: Error in post-command-hook (icomplete-post-command-hook): (error "Pattern vcvc. does not match test/lisp/emacs-lisp/package-resources/newer-versions/archive-contents") --=20 Sean Whitton
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.
Received: (at 80323) by debbugs.gnu.org; 5 Feb 2026 15:40:27 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 05 10:40:27 2026
Received: from localhost ([127.0.0.1]:43898 helo=debbugs.gnu.org)
by debbugs.gnu.org with esmtp (Exim 4.84_2)
(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
id 1vo1Sz-0002fM-BF
for submit <at> debbugs.gnu.org; Thu, 05 Feb 2026 10:40:27 -0500
Received: from mail-wr1-x431.google.com ([2a00:1450:4864:20::431]:43093)
by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)
(Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>)
id 1vo1Sv-0002fA-7e
for 80323 <at> debbugs.gnu.org; Thu, 05 Feb 2026 10:40:23 -0500
Received: by mail-wr1-x431.google.com with SMTP id
ffacd0b85a97d-4359249bbacso1420362f8f.0
for <80323 <at> debbugs.gnu.org>; Thu, 05 Feb 2026 07:40:21 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20230601; t=1770306019; x=1770910819; darn=debbugs.gnu.org;
h=content-transfer-encoding:mime-version:user-agent:message-id:date
:references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date
:message-id:reply-to;
bh=M0P3doNGb63HVkhxN/vZHCuIGpEXonLDVp5CELsh/ac=;
b=jKf9QJSDhgi478Sx7AREktN433+5k0n+f+EkSXoIW+umjzEFgbOICoTJqlyHTx54Ls
BmzluVjIO6umNqFJHj/1g07PdcpdTIYyzl+QsgcCfZiaEPvYPb0/LKRM77LFSu9RLWoy
I8AeV/GLtWufTuy6d45kln+r7IMMGang3+yTXfVDdtXf2vgXTit0r5BHAVA1Ap3ubfeB
nupR7BjLpmqbBhMucwTtTWL2JNF+HgLOgQ5oTXRnIh5liBMuNokW+8mQUIxlBPDEf10Q
GYCthwF6c/9mf90ErLegCGfn9FbmP/txNvsZhADLtrt38i5BMPd1hJlEP1w1vvWEy0eu
OFtg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20230601; t=1770306019; x=1770910819;
h=content-transfer-encoding:mime-version:user-agent:message-id:date
:references:in-reply-to:subject:cc:to:from:x-gm-gg
:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;
bh=M0P3doNGb63HVkhxN/vZHCuIGpEXonLDVp5CELsh/ac=;
b=DrsaM48VCa1olKn5IDKbC5zI+rJZKsBkWL8NiMyUQXu1QVvL3Rlu9HfBXF/6L7BzA1
dL6PducbU2zB+ht2w0YPXWgmRsGSMeghFK+U500yRnXXqEcXmBPLC1OMKhTb7HsvidUj
XKqRYi1SPC6s9/W0G7uPC9/C1B79gGAy85/q3vCIh+U41NAbsKJhqo7ZaIHCb8OHZOED
FPDAKrRHW2nsUr6Rt1FHIP5EcBKPZsL5yxzdSBhNILvBivIvSHqFusE9iuVuiQTPdJY7
7NkzxA/ue/v/r38Upggh/my4LOM6FQLnzf3v56oS1gaSqkMuOaLJQogwQT18tLVQHFMR
YN6Q==
X-Gm-Message-State: AOJu0YxoUqmazDvpV4YDtAmRmIDEiRYoN73TbV4LGs+haKYRxkyGpQ2V
mO6P7NrFoqDyGp/JATpI0OjInc4HB/KqXH9g6epsgQm5L55FDnT6t32F
X-Gm-Gg: AZuq6aKBqfmkM2fgYJD/9ZGVf3j4Xd1GWmEPnzcUqbdoamFxNr8SaTRs1NOI1il4IDJ
Vslu5RHZL/bJNVu/oCtVesXKNiITlQlDeeAU7K8XTOVzTp/GobrLvGAjxaxokwZZcI/D783n/8q
bvRxdP0of53H8qpKFumURgZa5ocKtel97ua5MtmgmyIxYfiq2SVSHkZS1Agfz7vTe+fnYYscu/j
qQXmcRzAZcnZsRZssEqHuFCIwR4dYlCmLA+aJ8LfzZkE+It5Ihn+80EvWQPVycJITMuP1W0PRpP
KAGWTx14+tuvpNBpfkeiTOSrQvTJw+hhmBo/KNAjZcv5Zvzrx3kc5b04rfu/q/Ttf5hsUzxPohS
v7tkgo+B3LBw6fWnYfQTxoX34qRoAf/THAG+wzLcE1+q8FynErvc4rCGFQHA8QQzV7esyJJWK9O
YnUvdX8PC4nHcnLqauYTSxM5xyYQ==
X-Received: by 2002:a05:6000:2502:b0:431:8bf:f08c with SMTP id
ffacd0b85a97d-436213e5dd2mr5671713f8f.21.1770306019035;
Thu, 05 Feb 2026 07:40:19 -0800 (PST)
Received: from krug (87-196-74-61.net.novis.pt. [87.196.74.61])
by smtp.gmail.com with ESMTPSA id
ffacd0b85a97d-43617e25d0dsm15373917f8f.7.2026.02.05.07.40.16
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Thu, 05 Feb 2026 07:40:17 -0800 (PST)
From: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN>
To: 80323 <at> debbugs.gnu.org
Subject: Re: [PATCH] Rewrite flex completion scoring with Gotoh algorithm
In-Reply-To: <87y0la2egy.fsf@HIDDEN>
References: <87y0la2egy.fsf@HIDDEN>
Date: Thu, 05 Feb 2026 15:40:14 +0000
Message-ID: <87fr7fjj1d.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: 4.6 (++++)
X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org",
has NOT identified this incoming email as spam. The original
message has been attached to this so you can view it or label
similar future email. If you have any questions, see
the administrator of that system for details.
Content preview: João Távora writes: > Hi, > > The patch I'm attaching fixes
them for good. > I'm attaching a new version of the patch, which now also
lives in the feature/newflex branch of the Savannah repository. It fixes
the problems with multibyte characters, adds comments to the code, and [...]
Content analysis details: (4.6 points, 10.0 required)
pts rule name description
---- ---------------------- --------------------------------------------------
3.6 RCVD_IN_SBL_CSS RBL: Received via a relay in Spamhaus SBL-CSS
[87.196.74.61 listed in zen.spamhaus.org]
0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
-0.0 SPF_PASS SPF: sender matches SPF record
0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail
provider (joaotavora[at]gmail.com)
1.0 FORGED_GMAIL_RCVD 'From' gmail.com does not match 'Received'
headers
-0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/,
no trust
[2a00:1450:4864:20:0:0:0:431 listed in]
[list.dnswl.org]
X-Debbugs-Envelope-To: 80323
Cc: =?utf-8?Q?St=C3=A9phane?= Marks <shipmints@HIDDEN>,
Sean Whitton <spwhitton@HIDDEN>, Eli Zaretskii <eliz@HIDDEN>,
monnier@HIDDEN, axel@HIDDEN
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.6 (+++)
X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org",
has NOT identified this incoming email as spam. The original
message has been attached to this so you can view it or label
similar future email. If you have any questions, see
the administrator of that system for details.
Content preview: João Távora writes: > Hi, > > The patch I'm attaching fixes
them for good. > I'm attaching a new version of the patch, which now also
lives in the feature/newflex branch of the Savannah repository. It fixes
the problems with multibyte characters, adds comments to the code, and [...]
Content analysis details: (3.6 points, 10.0 required)
pts rule name description
---- ---------------------- --------------------------------------------------
3.6 RCVD_IN_SBL_CSS RBL: Received via a relay in Spamhaus SBL-CSS
[87.196.74.61 listed in zen.spamhaus.org]
-0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/,
no trust
[2a00:1450:4864:20:0:0:0:431 listed in]
[list.dnswl.org]
0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
-0.0 SPF_PASS SPF: sender matches SPF record
0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail
provider (joaotavora[at]gmail.com)
1.0 FORGED_GMAIL_RCVD 'From' gmail.com does not match 'Received'
headers
-1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list
manager
Jo=C3=A3o T=C3=A1vora <joaotavora@HIDDEN> writes:
> Hi,
>
> The patch I'm attaching fixes them for good.
>
I'm attaching a new version of the patch, which now also lives in the
feature/newflex branch of the Savannah repository. It fixes the
problems with multibyte characters, adds comments to the code, and has
other improvements. I've reviewed the flex unit tests and created a new
test with kanji characters.
Please give it some testing.
Regarding performance, I had said before that this was slightly faster
than 'hotfuzz' in certain scenarios. That's mostly not true. When its
multithreading, all-in-one sorting/filtering C module is used, hotfuzz
is faster, though not by much. I don't think we'll ever get that
performance without significantly redoing the completion API and
leveraging multi-threading for such embarrassingly parallelisable
problems.
I also said it's slower than the old flex. That's also not true, it's
now strictly faster (and of course much more correct).
See attached "benchmark-completion-full.el" for a utility to test both
styles. It takes the style name and a pattern to match against every
symbol in obarray. Here are are possible invocations:
$ src/emacs -Q --batch -l bench-completion-full.el -- flex custgroup 2=
>&1
[...]
Total completions: 7
First 10: (customize-group custom-group-of-mode custom-add-to-group cust=
om-declare-group custom-current-group customize-group-othe customize-apropo=
s-gr)
[...]
Total time: 1.699 seconds (2.0 GCs taking 0.015 sec)
Time per call: 8.493 ms
=20=20=20
$ src/emacs -Q --batch -L ~/Source/Emacs/hotfuzz -l bench-completion-ful=
l.el -- hotfuzz custgroup 2>&1
[...]
Total completions: 7
First 10: (customize-group custom-add-to-group custom-group-of-mode cust=
om-declare-group custom-current-group customize-apropos-gr customize-group-=
othe)
[...]
Total time: 1.016 seconds (25.0 GCs taking 0.207 sec)
Time per call: 5.078 ms
The algorithm itself isn't the bottleneck, rather the logic in
minibuffer.el which hotfuzz sidesteps, in part. To make the new flex
competitive I had to do some changes to that file's Elisp too. They are
not too pretty, but then neither is that file.
I don't think I violated any tenets of the "PCM"completion API, but I'd
like Stefan to take a look if possible.
Patch after my sig,
Jo=C3=A3o
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index fc193fe54f0..5b5408a595c 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -4421,9 +4421,12 @@ completion-pcm--segments-point-idx
(setq idx i)))
idx))
=20
-(defun completion-pcm--all-completions (prefix pattern table pred)
+(defun completion-pcm--all-completions (prefix pattern table pred
+ &optional override-re)
"Find all completions for PATTERN in TABLE obeying PRED.
-PATTERN is as returned by `completion-pcm--string->pattern'."
+PATTERN is as returned by `completion-pcm--string->pattern'.
+OVERRIDE-RE means to use this regular expression instead of grabbing one
+from PATTERN."
;; (cl-assert (=3D (car (completion-boundaries prefix table pred ""))
;; (length prefix)))
;; Find an initial list of possible completions.
@@ -4435,7 +4438,7 @@ completion-pcm--all-completions
;; Use all-completions to do an initial cull. This is a big win,
;; since all-completions is written in C!
(let* (;; Convert search pattern to a standard regular expression.
- (regex (completion-pcm--pattern->regex pattern))
+ (regex (or override-re (completion-pcm--pattern->regex pattern)=
))
(case-fold-search completion-ignore-case)
(completion-regexp-list (cons regex completion-regexp-list))
(compl (all-completions
@@ -4450,18 +4453,12 @@ completion-pcm--all-completions
(when (string-match-p regex c) (push c poss)))
(nreverse poss))))))
=20
-(defvar flex-score-match-tightness 3
- "Controls how the `flex' completion style scores its matches.
+(defvar flex-score-match-tightness nil)
=20
-Value is a positive number. A number smaller than 1 makes the
-scoring formula reward matches scattered along the string, while
-a number greater than one make the formula reward matches that
-are clumped together. I.e \"foo\" matches both strings
-\"fbarbazoo\" and \"fabrobazo\", which are of equal length, but
-only a value greater than one will score the former (which has
-one large \"hole\" and a clumped-together \"oo\" match) higher
-than the latter (which has two \"holes\" and three
-one-letter-long matches).")
+(make-obsolete-variable
+ 'flex-score-match-tightness
+ "It never did anything very useful anyway."
+ "31.0")
=20
(defvar completion-lazy-hilit nil
"If non-nil, request lazy highlighting of completion candidates.
@@ -4502,133 +4499,49 @@ completion-lazy-hilit
(funcall completion-lazy-hilit-fn (copy-sequence str))
str))
=20
-(defun completion--hilit-from-re (string regexp &optional point-idx)
- "Fontify STRING using REGEXP POINT-IDX.
-Uses `completions-common-part' and `completions-first-difference'
-faces to fontify STRING.
-POINT-IDX is the position of point in the presumed \"PCM\" pattern
-from which REGEXP was generated."
- (let* ((md (and regexp (string-match regexp string) (cddr (match-data t)=
)))
- (pos (if point-idx (match-beginning point-idx) (match-end 0)))
- (me (and md (match-end 0)))
- (from 0))
- (while md
- (add-face-text-property from (pop md)
- 'completions-common-part nil string)
- (setq from (pop md)))
- (if (and (numberp pos) (> (length string) pos))
- (add-face-text-property
- pos (1+ pos)
- 'completions-first-difference
- nil string))
- (unless (or (not me) (=3D from me))
- (add-face-text-property from me 'completions-common-part nil string))
- string))
-
-(defun completion--flex-score-1 (md-groups match-end len)
- "Compute matching score of completion.
-The score lies in the range between 0 and 1, where 1 corresponds to
-the full match.
-MD-GROUPS is the \"group\" part of the match data.
-MATCH-END is the end of the match.
-LEN is the length of the completion string."
- (let* ((from 0)
- ;; To understand how this works, consider these simple
- ;; ascii diagrams showing how the pattern "foo"
- ;; flex-matches "fabrobazo", "fbarbazoo" and
- ;; "barfoobaz":
-
- ;; f abr o baz o
- ;; + --- + --- +
-
- ;; f barbaz oo
- ;; + ------ ++
-
- ;; bar foo baz
- ;; +++
-
- ;; "+" indicates parts where the pattern matched. A
- ;; "hole" in the middle of the string is indicated by
- ;; "-". Note that there are no "holes" near the edges
- ;; of the string. The completion score is a number
- ;; bound by (0..1] (i.e., larger than (but not equal
- ;; to) zero, and smaller or equal to one): the higher
- ;; the better and only a perfect match (pattern equals
- ;; string) will have score 1. The formula takes the
- ;; form of a quotient. For the numerator, we use the
- ;; number of +, i.e. the length of the pattern. For
- ;; the denominator, it first computes
- ;;
- ;; hole_i_contrib =3D 1 + (Li-1)^(1/tightness)
- ;;
- ;; , for each hole "i" of length "Li", where tightness
- ;; is given by `flex-score-match-tightness'. The
- ;; final value for the denominator is then given by:
- ;;
- ;; (SUM_across_i(hole_i_contrib) + 1) * len
- ;;
- ;; , where "len" is the string's length.
- (score-numerator 0)
- (score-denominator 0)
- (last-b 0))
- (while (and md-groups (car md-groups))
- (let ((a from)
- (b (pop md-groups)))
- (setq
- score-numerator (+ score-numerator (- b a)))
- (unless (or (=3D a last-b)
- (zerop last-b)
- (=3D a len))
- (setq
- score-denominator (+ score-denominator
- 1
- (expt (- a last-b 1)
- (/ 1.0
- flex-score-match-tightness)))))
- (setq
- last-b b))
- (setq from (pop md-groups)))
- ;; If `pattern' doesn't have an explicit trailing any, the
- ;; regex `re' won't produce match data representing the
- ;; region after the match. We need to account to account
- ;; for that extra bit of match (bug#42149).
- (unless (=3D from match-end)
- (let ((a from)
- (b match-end))
- (setq
- score-numerator (+ score-numerator (- b a)))
- (unless (or (=3D a last-b)
- (zerop last-b)
- (=3D a len))
- (setq
- score-denominator (+ score-denominator
- 1
- (expt (- a last-b 1)
- (/ 1.0
- flex-score-match-tightness)))))
- (setq
- last-b b)))
- (/ score-numerator (* len (1+ score-denominator)) 1.0)))
-
-(defvar completion--flex-score-last-md nil
- "Helper variable for `completion--flex-score'.")
-
-(defun completion--flex-score (str re &optional dont-error)
- "Compute flex score of completion STR based on RE.
-If DONT-ERROR, just return nil if RE doesn't match STR."
- (let ((case-fold-search completion-ignore-case))
- (cond ((string-match re str)
- (let* ((match-end (match-end 0))
- (md (cddr
- (setq
- completion--flex-score-last-md
- (match-data t completion--flex-score-last-md)))))
- (completion--flex-score-1 md match-end (length str))))
- ((not dont-error)
- (error "Internal error: %s does not match %s" re str)))))
-
-(defvar completion-pcm--regexp nil
- "Regexp from PCM pattern in `completion-pcm--hilit-commonality'.")
+(cl-defun completion--flex-score (pat str &optional dont-error)
+ "Compute flex score of STR matching PAT using Gotoh algorithm.
+If DONT-ERROR, return nil if PAT cannot match STR.
+Return (NORMALIZED-COST . MATCHES) where NORMALIZED-COST is a
+number (lower =3D better) and MATCHES is a list of match positions in STR."
+ (pcase-let ((`(,cost . ,matches)
+ (completion--flex-score-gotoh pat str)))
+ (unless cost
+ (if dont-error (cl-return-from completion--flex-score nil)
+ (error "Pattern %s does not match %s" pat str)))
+ (cons (* (1+ cost) (- (length str) (length pat))) matches)))
+
+(defun completion--flex-propertize (str matches point-idx segments)
+ "Add completion faces to STR based on MATCHES and POINT-IDX.
+MATCHES is a list of match positions. POINT-IDX is a match group index
+from the PCM pattern. SEGMENTS are extracted from the full PCM pattern.
+Adds `completions-common-part' for matched positions and
+`completions-first-difference' for the position corresponding to point."
+ (when point-idx
+ ;; Compute character position from segments
+ (let* ((pos (cl-loop for seg in segments
+ for i from 1
+ while (<=3D i point-idx)
+ sum (length (car seg)))))
+ ;; Add first-difference after pos-th match, if in range
+ (let ((point-match (and (> pos 0)
+ (<=3D pos (length matches))
+ (nth (1- pos) matches))))
+ (when (and point-match (< (1+ point-match) (length str)))
+ (add-face-text-property
+ (1+ point-match) (+ 2 point-match)
+ 'completions-first-difference nil str)))))
+ ;; Highlight matched positions
+ (dolist (pos matches)
+ (add-face-text-property pos (1+ pos)
+ 'completions-common-part
+ nil str))
+ str)
+
+(defvar completion-flex--pattern-str nil
+ "Pattern string for flex completion scoring.
+This is the concatenated string parts from the PCM pattern,
+used by `completion--flex-score' for Gotoh algorithm matching.")
=20
(defun completion-pcm--hilit-commonality (pattern completions)
"Show where and how well PATTERN matches COMPLETIONS.
@@ -4645,22 +4558,37 @@ completion-pcm--hilit-commonality
Else, if `completion-lazy-hilit' is t, return COMPLETIONS
unchanged, but setup a suitable `completion-lazy-hilit-fn' (which
see) for later lazy highlighting."
- (setq completion-pcm--regexp nil
- completion-lazy-hilit-fn nil)
+ (setq completion-lazy-hilit-fn nil
+ completion-flex--pattern-str nil)
(cond
((and completions (cl-loop for e in pattern thereis (stringp e)))
(let* ((segments (completion-pcm--pattern->segments pattern))
- (re (completion-pcm--segments->regex segments 'group))
- (point-idx (completion-pcm--segments-point-idx segments)))
- (setq completion-pcm--regexp re)
+ (point-idx (completion-pcm--segments-point-idx segments))
+ ;; Extract pattern string (concatenate string elements)
+ (pat (mapconcat #'identity
+ (delq nil (mapcar (lambda (x)
+ (if (stringp x) x nil))
+ pattern))
+ "")))
+ (setq completion-flex--pattern-str pat)
(cond (completion-lazy-hilit
(setq completion-lazy-hilit-fn
- (lambda (str) (completion--hilit-from-re str re point-i=
dx)))
+ (lambda (str)
+ (let ((result (completion--flex-score pat str t)))
+ (when result
+ (completion--flex-propertize
+ str (cdr result) point-idx segments)))
+ str))
completions)
(t
(mapcar
(lambda (str)
- (completion--hilit-from-re (copy-sequence str) re point-id=
x))
+ (setq str (copy-sequence str))
+ (let ((result (completion--flex-score pat str t)))
+ (when result
+ (completion--flex-propertize
+ str (cdr result) point-idx segments)))
+ str)
completions)))))
(t completions)))
=20
@@ -4959,11 +4887,13 @@ completion-pcm-try-completion
;; Mostly derived from the code of `basic' completion.
=20
(defun completion-substring--all-completions
- (string table pred point &optional transform-pattern-fn)
+ (string table pred point &optional
+ transform-pattern-fn simple-re)
"Match the presumed substring STRING to the entries in TABLE.
-Respect PRED and POINT. The pattern used is a PCM-style
-substring pattern, but it be massaged by TRANSFORM-PATTERN-FN, if
-that is non-nil."
+Respect PRED and POINT. The pattern used is a PCM-style substring
+pattern, but it be massaged by TRANSFORM-PATTERN-FN, if that is non-nil.
+SIMPLE-RE is means to pass a simpler faster regular expression to
+`completion-pcm--all-completions'"
(let* ((beforepoint (substring string 0 point))
(afterpoint (substring string point))
(bounds (completion-boundaries beforepoint table pred afterpoint))
@@ -4978,7 +4908,13 @@ completion-substring--all-completions
(if transform-pattern-fn
(funcall transform-pattern-fn pattern)
pattern)))
- (all (completion-pcm--all-completions prefix pattern table pred)))
+ (override-re (and simple-re
+ (mapconcat #'identity
+ (split-string
+ (substring string (car bounds)
+ (+ point (cdr bounds))) =
"" t)
+ ".*")))
+ (all (completion-pcm--all-completions prefix pattern table pred o=
verride-re)))
(list all pattern prefix suffix (car bounds))))
=20
(defun completion-substring-try-completion (string table pred point)
@@ -5009,7 +4945,7 @@ completion-flex-nospace
=20
(defun completion--flex-adjust-metadata (metadata)
"If `flex' is actually doing filtering, adjust sorting."
- (let ((flex-is-filtering-p completion-pcm--regexp)
+ (let ((flex-is-filtering-p completion-flex--pattern-str)
(existing-dsf
(completion-metadata-get metadata 'display-sort-function))
(existing-csf
@@ -5021,11 +4957,11 @@ completion--flex-adjust-metadata
(mapcar
(lambda (str)
(cons
- (- (completion--flex-score
- (or (get-text-property
- 0 'completion--unquoted str)
- str)
- completion-pcm--regexp))
+ (car (completion--flex-score
+ completion-flex--pattern-str
+ (or (get-text-property
+ 0 'completion--unquoted str)
+ str)))
str))
(if existing-sort-fn
(funcall existing-sort-fn completions)
@@ -5067,7 +5003,8 @@ completion-flex-try-completion
(pcase-let ((`(,all ,pattern ,prefix ,suffix ,_carbounds)
(completion-substring--all-completions
string table pred point
- #'completion-flex--make-flex-pattern)))
+ #'completion-flex--make-flex-pattern
+ t)))
(if minibuffer-completing-file-name
(setq all (completion-pcm--filename-try-filter all)))
;; Try some "merging", meaning add as much as possible to the
@@ -5084,7 +5021,8 @@ completion-flex-all-completions
(pcase-let ((`(,all ,pattern ,prefix ,_suffix ,_carbounds)
(completion-substring--all-completions
string table pred point
- #'completion-flex--make-flex-pattern)))
+ #'completion-flex--make-flex-pattern
+ t)))
(when all
(nconc (completion-pcm--hilit-commonality pattern all)
(length prefix))))))
diff --git a/src/minibuf.c b/src/minibuf.c
index 5dc2b230883..f7dffc24b94 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -20,6 +20,7 @@ Copyright (C) 1985-1986, 1993-2026 Free Software Foundati=
on, Inc.
=20
#include <config.h>
#include <errno.h>
+#include <math.h>
=20
#include <binary-io.h>
=20
@@ -2279,6 +2280,201 @@ init_minibuf_once_for_pdumper (void)
last_minibuf_string =3D Qnil;
}
=20
+/* FLEX/GOTOH algorithm for the 'flex' completion-style. Adapted from
+ GOTOH, Osamu. An improved algorithm for matching biological
+ sequences. Journal of molecular biology, 1982, 162.3: 705-708.
+
+ This algorithm matches patterns to candidate strings, or needles to
+ haystacks. It works with cost matrices: imagine rows of these
+ matrices as pattern characters, and columns as the candidate string
+ characters. There is a -1 row, and a -1 column. The values there
+ hold real costs used for situations "before the first ever" match of
+ a pattern character to a string character.
+
+ M and D are cost matrices. At the end of the algorithm, M will have
+ non-infinite values only for the spots where a pattern character
+ matches a string character. So a non-infinite M[i,j] means the i-th
+ character of the pattern matches the j-th character of the string.
+ The value stored is the lowest possible cost the algorithm had to
+ "pay" to be able to make that match there, given everything that may
+ have happened before/to the left. An infinite value simply means no
+ match at this pattern/string position. Note that both row and column
+ of M may have more than one match at multiple indices. But this
+ particular implementation of the algorithm assumes they have at least
+ one match.
+
+ D (originally stands for 'Deletion' in the Gotoh paper) has "running
+ costs". Each value D[i,j] represents what the algorithm has to pay
+ to make or extend a gap when a match is found at i+1, j+1. By that
+ time, that cost may or may not be lower than continuing from a match
+ that had also been found at i,j. We always pick the lowest cost, and
+ by the time we reach the final column, we know we have picked the
+ cheapest possible path choosing when to gap, and when to follow up.
+
+ Along the way, we construct P, a matrix used just for backtracking,
+ to reconstruct that path. Maybe P isn't needed, and all the
+ information can be cleverly derived from the final state of M and D.
+ But I couldn't make it work. */
+DEFUN ("completion--flex-score-gotoh", Fcompletion__flex_score_gotoh,
+ Scompletion__flex_score_gotoh, 2, 2, 0,
+ doc: /* Compute flex score of STR matching PAT using Gotoh
+algorithm. Return nil if no match found, else return (COST . MATCHES)
+where COST is a fixnum (lower is better) and MATCHES is a list of match
+positions in STR. */)
+ (Lisp_Object pat, Lisp_Object str)
+{
+ /* Pre-allocated matrices for flex completion scoring. */
+#define FLEX_MAX_STR_SIZE 512
+#define FLEX_MAX_PAT_SIZE 128
+#define FLEX_MAX_MATRIX_SIZE FLEX_MAX_PAT_SIZE * FLEX_MAX_STR_SIZE
+ /* Macro for 2D indexing into "flat" arrays. */
+#define MAT(matrix, i, j) ((matrix)[((i) + 1) * width + ((j) + 1)])
+
+ CHECK_STRING (pat);
+ CHECK_STRING (str);
+
+ size_t patlen =3D SCHARS (pat);
+ size_t strlen =3D SCHARS (str);
+ size_t width =3D strlen + 1;
+ size_t size =3D (patlen + 1) * width;
+
+ /* Bail if strings are empty or matrix too large. */
+ if (patlen =3D=3D 0 || strlen =3D=3D 0)
+ return Qnil;
+
+ if (size > FLEX_MAX_MATRIX_SIZE)
+ return Qnil;
+
+ /* Cost constants (lower is better). Maybe these could be
+ defcustom's?*/
+ const int gap_open_cost =3D 10;
+ const int gap_extend_cost =3D 1;
+ const int pos_inf =3D INT_MAX / 2;
+
+ static int M[FLEX_MAX_MATRIX_SIZE];
+ static int D[FLEX_MAX_MATRIX_SIZE];
+ static size_t P[FLEX_MAX_MATRIX_SIZE];
+
+ /* Initialize costs. Fill both matrices with positive infinity. */
+ for (int j =3D 0; j < size; j++) M[j] =3D pos_inf;
+ for (int j =3D 0; j < size; j++) D[j] =3D pos_inf;
+ /* Except for D[0,0], which is 0, for prioritizing matches at the
+ beginning. Remaining elements on the first row are gap_open_cost/2
+ to represent cheaper leading gaps. */
+ for (int j =3D 0; j < width; j++) D[j] =3D gap_open_cost/2;
+ D[0] =3D 0;
+
+ /* Index of last match before gap started, as computed in the previous
+ row. Used to build P. */
+ int prev_gap_origin =3D -1;
+
+ /* Poor man's iterator type. */
+ typedef struct iter { int x; ptrdiff_t c; ptrdiff_t b; } iter_t;
+
+ /* Info about first match computed in the previous row. */
+ iter_t prev_match =3D {0,0,0};
+ /* Forward pass. */
+ for (iter_t i =3D {0,0,0}; i.x < patlen; i.x++)
+ {
+ int pat_char =3D fetch_string_char_advance(pat, &i.c, &i.b);
+ int gap_origin =3D -1;
+ bool match_seen =3D false;
+
+ for (iter_t j =3D prev_match; j.x < strlen; j.x++)
+ {
+ iter_t jcopy =3D j; /* else advance function destroys it... */
+ int str_char
+ =3D fetch_string_char_advance (str, &j.c, &j.b);
+
+ /* Check if characters match (case-insensitive if needed). */
+ bool cmatch;
+ if (completion_ignore_case)
+ cmatch =3D (downcase (pat_char) =3D=3D downcase (str_char));
+ else
+ cmatch =3D (pat_char =3D=3D str_char);
+
+ /* Compute match cost M[i][j], i.e. replace its infinite
+ value with something finite. */
+ if (cmatch)
+ {
+ if (!match_seen)
+ {
+ match_seen =3D true;
+ prev_match =3D jcopy;
+ }
+ int pmatch_cost =3D MAT (M, i.x - 1, j.x - 1);
+ int pgap_cost =3D MAT (D, i.x - 1, j.x - 1);
+
+ if (pmatch_cost <=3D pgap_cost)
+ {
+ /* Not only did the previous char also match (else
+ pmatch_cost would have been infinite) but following
+ it up with this match is best overall. */
+ MAT (M, i.x, j.x) =3D pmatch_cost;
+ MAT (P, i.x, j.x) =3D j.x - 1;
+ }
+ else
+ {
+ /* Gapping is best, regardless of whether the previous
+ char also matched. That is, it's better to arrive at
+ this match from a gap. */
+ MAT (M, i.x, j.x) =3D pgap_cost;
+ MAT (P, i.x, j.x) =3D prev_gap_origin;
+ }
+ }
+
+ /* Regardless of a match here, compute D[i,j], the best
+ accumulated gapping cost at this point, considering whether
+ it's more advantageous to open from a previous match on
+ this row (a cost which may well be infinite if no such
+ match ever existed) or extend a gap started sometime
+ before. The next iteration will take this into account,
+ and so will the next row when analyzing a possible match
+ for the j+1-th string character. */
+ int open_cost =3D MAT (M, i.x, j.x - 1) + gap_open_cost;
+ int extend_cost =3D MAT (D, i.x, j.x - 1) + gap_extend_cost;
+
+ if (open_cost < extend_cost)
+ {
+ MAT (D, i.x, j.x) =3D open_cost;
+ gap_origin =3D j.x - 1; /* New gap. */
+ }
+ else
+ MAT (D, i.x, j.x) =3D extend_cost; /* Extend gap. */
+ }
+ prev_gap_origin =3D gap_origin;
+ }
+
+ /* Find best (lowest) cost in last row. */
+ int best_cost =3D pos_inf;
+ int lastcol =3D -1;
+
+ for (int j =3D 0; j < strlen; j++)
+ {
+ int cost =3D MAT (M, patlen - 1, j);
+ if (cost < best_cost)
+ {
+ best_cost =3D cost;
+ lastcol =3D j;
+ }
+ }
+
+ if (lastcol < 0 || best_cost >=3D pos_inf)
+ return Qnil;
+
+ /* Build match positions list by tracing back through P matrix. */
+ Lisp_Object matches =3D Qnil;
+ for (int i =3D patlen - 1, l =3D lastcol; i >=3D 0 && l >=3D 0; i--)
+ {
+ matches =3D Fcons (make_fixnum (l), matches);
+ l =3D MAT (P, i, l);
+ }
+
+ return Fcons (make_fixnum (best_cost), matches);
+#undef MAT
+
+}
+
void
syms_of_minibuf (void)
{
@@ -2541,6 +2737,7 @@ syms_of_minibuf (void)
defsubr (&Stest_completion);
defsubr (&Sassoc_string);
defsubr (&Scompleting_read);
+ defsubr (&Scompletion__flex_score_gotoh);
DEFSYM (Qminibuffer_quit_recursive_edit, "minibuffer-quit-recursive-edit=
");
DEFSYM (Qinternal_complete_buffer, "internal-complete-buffer");
DEFSYM (Qcompleting_read_function, "completing-read-function");
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 79ffb1d3fc7..02df7661c75 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -205,11 +205,6 @@ completion-all-sorted-completions
'("some/alpha" "base/epsilon" "base/delta"))
`("epsilon" "delta" "beta" "alpha" "gamma" . 5))))
=20
-(defun completion--pcm-score (comp)
- "Get `completion-score' from COMP."
- ;; FIXME, uses minibuffer.el implementation details
- (completion--flex-score comp completion-pcm--regexp))
-
(defun completion--pcm-first-difference-pos (comp)
"Get `completions-first-difference' from COMP."
(cl-loop for pos =3D (next-single-property-change 0 'face comp)
@@ -244,20 +239,11 @@ completion-pcm-test-2
"barfoobar")))
=20
(ert-deftest completion-pcm-test-3 ()
- ;; Full match!
- (should (eql
- (completion--pcm-score
- (car (completion-pcm-all-completions
- "R" '("R" "hello") nil 1)))
- 1.0)))
+ (should (car (completion-pcm-all-completions
+ "R" '("R" "hello") nil 1))))
=20
(ert-deftest completion-pcm-test-4 ()
- ;; One fourth of a match and no match due to point being at the end
- (should (eql
- (completion--pcm-score
- (car (completion-pcm-all-completions
- "RO" '("RaOb") nil 1)))
- (/ 1.0 4.0)))
+ ;; No match due to point being at the end
(should (null
(completion-pcm-all-completions
"RO" '("RaOb") nil 2))))
@@ -420,24 +406,14 @@ completion-pcm-bug4219
"a")))
=20
(ert-deftest completion-substring-test-1 ()
- ;; One third of a match!
(should (equal
(car (completion-substring-all-completions
"foo" '("hello" "world" "barfoobar") nil 3))
- "barfoobar"))
- (should (eql
- (completion--pcm-score
- (car (completion-substring-all-completions
- "foo" '("hello" "world" "barfoobar") nil 3)))
- (/ 1.0 3.0))))
+ "barfoobar")))
=20
(ert-deftest completion-substring-test-2 ()
- ;; Full match!
- (should (eql
- (completion--pcm-score
- (car (completion-substring-all-completions
- "R" '("R" "hello") nil 1)))
- 1.0)))
+ (should (car (completion-substring-all-completions
+ "R" '("R" "hello") nil 1))))
=20
(ert-deftest completion-substring-test-3 ()
;; Substring match
@@ -495,39 +471,70 @@ completion-substring-test-5
(completion-substring-try-completion "b" '("ab" "ab") nil 0)
'("ab" . 2))))
=20
+(defun completion--sorted-flex-completions (pat list &optional point)
+ "Flex test helper"
+ (let ((all (completion-flex-all-completions pat list nil point)))
+ (setcdr (last all) nil)
+ (sort all
+ (lambda (a b)
+ (< (car (completion--flex-score pat a))
+ (car (completion--flex-score pat b)))))))
+
(ert-deftest completion-flex-test-1 ()
- ;; Fuzzy match
(should (equal
(car (completion-flex-all-completions
"foo" '("hello" "world" "fabrobazo") nil 3))
"fabrobazo")))
=20
(ert-deftest completion-flex-test-2 ()
- ;; Full match!
- (should (eql
- (completion--pcm-score
- (car (completion-flex-all-completions
- "R" '("R" "hello") nil 1)))
- 1.0)))
+ (should (car (completion--sorted-flex-completions
+ "R" '("R" "hello") 1))))
=20
(ert-deftest completion-flex-test-3 ()
- ;; Another fuzzy match, but more of a "substring" one
(should (equal
- (car (completion-flex-all-completions
- "custgroup" '("customize-group-other-window") nil 4))
+ (car (completion--sorted-flex-completions
+ "custgroup" '("customize-group-other-window") 4))
"customize-group-other-window"))
;; `completions-first-difference' should be at the right place
(should (equal
(completion--pcm-first-difference-pos
- (car (completion-flex-all-completions
- "custgroup" '("customize-group-other-window") nil 4)))
+ (car (completion--sorted-flex-completions
+ "custgroup" '("customize-group-other-window") 4)))
4))
(should (equal
(completion--pcm-first-difference-pos
- (car (completion-flex-all-completions
- "custgroup" '("customize-group-other-window") nil 9)))
+ (car (completion--sorted-flex-completions
+ "custgroup" '("customize-group-other-window") 9)))
15)))
=20
+(ert-deftest completion-flex-test-non-ascii ()
+ "Test flex completion with variable-width UTF-8 characters."
+ ;; Uses Japanese Kanji to test multi-byte character handling.
+
+ ;; =E6=97=A5=E6=9C=AC =3D "nihon" (Japan), =E6=9D=B1=E4=BA=AC =3D "t=C5=
=8Dky=C5=8D" (Tokyo)
+ (should (equal
+ (car (completion--sorted-flex-completions
+ "=E6=97=A5=E6=9C=AC" '("=E6=97=A5=E6=9C=AC=E8=AA=9E" "=E6=
=97=A5=E6=9C=AC" "=E4=B8=AD=E5=9B=BD") 2))
+ "=E6=97=A5=E6=9C=AC"))
+
+ ;; =E5=9B=B3=E6=9B=B8=E9=A4=A8 =3D "toshokan" (library)
+ (should (equal
+ (car (completion--sorted-flex-completions
+ "tsk" '("=E5=9B=B3=E6=9B=B8=E9=A4=A8-toshokan" "task" "de=
sk") 3))
+ "task"))
+
+ ;; Mixed pattern (Kanji + ASCII) matching mixed string
+ ;; =E5=AD=A6=E6=A0=A1 =3D "gakk=C5=8D" (school)
+ (should (equal
+ (car (completion--sorted-flex-completions
+ "=E5=AD=A6s" '("=E5=AD=A6=E6=A0=A1-school" "school" "=E5=
=AD=A6=E7=94=9F") 2))
+ "=E5=AD=A6=E6=A0=A1-school"))
+
+ ;; Pattern "=E6=9D=B1" should match "=E6=9D=B1=E4=BA=AC" better than "=
=E9=96=A2=E6=9D=B1"
+ (let ((results (completion--sorted-flex-completions
+ "=E6=9D=B1" '("=E6=9D=B1=E4=BA=AC" "=E9=96=A2=E6=9D=B1")=
1)))
+ (should (equal (car results) "=E6=9D=B1=E4=BA=AC"))))
+
(defmacro with-minibuffer-setup (completing-read &rest body)
(declare (indent 1) (debug t))
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.
Received: (at 80323) by debbugs.gnu.org; 4 Feb 2026 20:44:29 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Wed Feb 04 15:44:29 2026
Received: from localhost ([127.0.0.1]:35676 helo=debbugs.gnu.org)
by debbugs.gnu.org with esmtp (Exim 4.84_2)
(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
id 1vnjjh-0000ek-5b
for submit <at> debbugs.gnu.org; Wed, 04 Feb 2026 15:44:29 -0500
Received: from mail-wm1-x32a.google.com ([2a00:1450:4864:20::32a]:48253)
by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)
(Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>)
id 1vnjje-0000eb-7m
for 80323 <at> debbugs.gnu.org; Wed, 04 Feb 2026 15:44:27 -0500
Received: by mail-wm1-x32a.google.com with SMTP id
5b1f17b1804b1-4805ef35864so1583025e9.0
for <80323 <at> debbugs.gnu.org>; Wed, 04 Feb 2026 12:44:26 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20230601; t=1770237865; x=1770842665; darn=debbugs.gnu.org;
h=content-transfer-encoding:mime-version:user-agent:message-id:date
:references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date
:message-id:reply-to;
bh=6lAmBtpiatm9ADH51xVbxWiAchWXfdeHfPt320Tc0qM=;
b=gIGJN0qGjEjBuoNZwlMVInu0D545U96Wluqss8GmO1apAdWgJHzEXPTlChcdjXDrPF
z6GQrUboPDjATHtN5MJEAdhqvDR8cLYb/2TisWa4WNtm3Nt1FlOYQ7CKZrAZQzmYtpDA
rBPZRHS3ISHqTMXPv+B4xyej2chHjLoHpHf7SeItHxau6713eBrWB0e/61k07dFhZt/R
8Psq4vMcelygyLX2GMhn7erpisr4dzAZxIwcVyRjyskKWeXT1XonbMdRNeQpi0NDywjf
Z5sTEIZTSK1p1fb9laPztjsOkc+JTrYHJMAtQYp57EFgitXilFDkDhpccewQAQnlQpCO
ydMg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20230601; t=1770237865; x=1770842665;
h=content-transfer-encoding:mime-version:user-agent:message-id:date
:references:in-reply-to:subject:cc:to:from:x-gm-gg
:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;
bh=6lAmBtpiatm9ADH51xVbxWiAchWXfdeHfPt320Tc0qM=;
b=TYzS+UioCGXFDDs8wHC6GiitaAJe22RlQGyne5Yo1o4QavUf84sN87dq63LyU/5/9b
4x742sYazaOC0rOp6Vm2284rE/t+JOMkpw5+cldJFNPxje39HQj5TIWmlJf4x14nWFBe
S1gf4/esH8vjKcHJFkmLJBPgF8142VPXmppsTrtTSwq/zQaJ1wGSkdI9tmBfhRqS1l7G
cmbvMvoJDE56f8ssB/4bL6tE0Mxq/vQAodCRtMbQVR9D/ygeWRjV8ouyxGYWrtLohjxC
jjpab47lCFOVpjN9V3IzeDnLUBX93XHMuEWTdhARGHYRfCznH1WEM+SV9T83GFVW4JJ9
OeiQ==
X-Forwarded-Encrypted: i=1;
AJvYcCUYBxLdbm4G6CvP13JuzE4hAlvFcWk/LGgYZNzZwsLE1w9QuPF+nJSXhv+83R/TP3YLc6K+jQ==@debbugs.gnu.org
X-Gm-Message-State: AOJu0YwcA4liSZoP+7YIAUHJnL280zq3bDbK8DG8KgUxkJSAmT/BZMOQ
wE89WpXsODPY7k2E+dxa9o6LlCmrrEKSlMivAq+1+Zh+VGmeJU+vkRze
X-Gm-Gg: AZuq6aIEoB8m8SGhqoomebfBRnP+3n1Wua+n9JsAZO47eBXyyxHaKoDVWAgP+jbMG4C
pZ3rId9HbOiqS38iluFWEuxlWCzyyI9B+dPGZZl1u49uvu2K9lbyASwq047MHf9ZTfUQcUBPSaJ
EK/zkzsgszKyYtgui6N1j+7MqfbA6wbVXMkMg9l2rp+qomP1AghbPywc7sRnqVhPhTgqL2vcUdV
3uu9gaH5Lm7eKkLk8/gKC1HUwf2yZ+Q0ipIeMsyGWgWiBkcJEH4kNB5SXiVBXzwwx2L3BvOJWTM
Gt/OkRi1dfnzXMnrftHAY6ZtULBDSJCyRTNVmFtE2mx/td0oGNCDsYLBfDlFg3OpOx2sfYU9Ud4
ubV5EJvVMBdJ1UfULXh4agSWdJC2wF9zThk2WQmKLJooWDF7+A7aETz7O/aX7bqCniWEwklRRpo
/sDncxWNebHDLDE5+QGrILXj6onQ==
X-Received: by 2002:a05:6000:288a:b0:430:f7dc:7e8e with SMTP id
ffacd0b85a97d-4361805271fmr5357384f8f.34.1770237864753;
Wed, 04 Feb 2026 12:44:24 -0800 (PST)
Received: from krug (87-196-74-61.net.novis.pt. [87.196.74.61])
by smtp.gmail.com with ESMTPSA id
ffacd0b85a97d-43618064844sm8636234f8f.42.2026.02.04.12.44.23
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Wed, 04 Feb 2026 12:44:24 -0800 (PST)
From: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN>
To: Eli Zaretskii <eliz@HIDDEN>
Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh
algorithm
In-Reply-To: <86y0l8xyor.fsf@HIDDEN>
References: <87y0la2egy.fsf@HIDDEN> <87ms1q9bpq.fsf@HIDDEN>
<CAN+1HbrAG_1YF4UzOyY_ARWzhKHsWCMaxgWb1qp8Rg1sq4SjVg@HIDDEN>
<87zf5p7362.fsf@HIDDEN> <87qzr08yni.fsf@HIDDEN>
<CALDnm50pn2rgD+K=gyr9Cj-iZy_rMFDmBRmHkT5P84hiVxaQnw@HIDDEN>
<jwv4inwcxpt.fsf-monnier+emacs@HIDDEN>
<CALDnm50HQJnS7i89-x0UcZ2GZ8raWE6mL_a-_drQV06u4Gbg7A@HIDDEN>
<86y0l8xyor.fsf@HIDDEN>
Date: Wed, 04 Feb 2026 20:44:22 +0000
Message-ID: <87qzr06xy1.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13)
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: 4.6 (++++)
X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org",
has NOT identified this incoming email as spam. The original
message has been attached to this so you can view it or label
similar future email. If you have any questions, see
the administrator of that system for details.
Content preview: Eli Zaretskii writes: >> Cc: 80323 <at> debbugs.gnu.org, Sean Whitton
>> From: João Távora >> Date: Wed, 4 Feb 2026 15:58:24 +0000 >> >> I don't
know if it does for sure, but the algo needs to compare character s, and
cur [...]
Content analysis details: (4.6 points, 10.0 required)
pts rule name description
---- ---------------------- --------------------------------------------------
3.6 RCVD_IN_SBL_CSS RBL: Received via a relay in Spamhaus SBL-CSS
[87.196.74.61 listed in zen.spamhaus.org]
0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
-0.0 SPF_PASS SPF: sender matches SPF record
0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail
provider (joaotavora[at]gmail.com)
1.0 FORGED_GMAIL_RCVD 'From' gmail.com does not match 'Received'
headers
-0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/,
no trust
[2a00:1450:4864:20:0:0:0:32a listed in]
[list.dnswl.org]
X-Debbugs-Envelope-To: 80323
Cc: spwhitton@HIDDEN, monnier@HIDDEN, 80323 <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.6 (+++)
X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org",
has NOT identified this incoming email as spam. The original
message has been attached to this so you can view it or label
similar future email. If you have any questions, see
the administrator of that system for details.
Content preview: Eli Zaretskii writes: >> Cc: 80323 <at> debbugs.gnu.org, Sean Whitton
>> From: João Távora >> Date: Wed, 4 Feb 2026 15:58:24 +0000 >> >> I don't
know if it does for sure, but the algo needs to compare character s, and
cur [...]
Content analysis details: (3.6 points, 10.0 required)
pts rule name description
---- ---------------------- --------------------------------------------------
3.6 RCVD_IN_SBL_CSS RBL: Received via a relay in Spamhaus SBL-CSS
[87.196.74.61 listed in zen.spamhaus.org]
-0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/,
no trust
[2a00:1450:4864:20:0:0:0:32a listed in]
[list.dnswl.org]
0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
-0.0 SPF_PASS SPF: sender matches SPF record
0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail
provider (joaotavora[at]gmail.com)
1.0 FORGED_GMAIL_RCVD 'From' gmail.com does not match 'Received'
headers
-1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list
manager
Eli Zaretskii <eliz@HIDDEN> writes:
>> Cc: 80323 <at> debbugs.gnu.org, Sean Whitton <spwhitton@HIDDEN>
>> From: Jo=C3=A3o T=C3=A1vora <joaotavora@HIDDEN>
>> Date: Wed, 4 Feb 2026 15:58:24 +0000
>>=20
>> I don't know if it does for sure, but the algo needs to compare characte=
r s, and currently addresses memory
>> like bytes naively with [] as if I were using C++ and that did the right=
thing. It does mostly and the patch
>> passes all the current tests, but then all these tests are for ASCII. Bu=
t in C the [] is very dumb and so some
>> macro salad is probably required.
>
> I think it's a terminology issue. AFAIU, by "wide characters" you
> mean characters whose internal representation in a string takes more
> than 1 byte. For that, string_char_and_length is the function to use:
> it returns to you the Unicode codepoint of a character and the number
> of bytes its multibyte sequence takes (which you can then use to
> advance your 'char *' pointer to the beginning of the next character's
> multibyte sequence). Or you can use fetch_string_char_advance, which
> will do all that for you in one go.
Thanks. That's the info I was looking for.
Jo=C3=A3o
PS: BTW, just to correct myself, using [] probably be a bad idea for
variable charsize strings in C++ too, iterators would be preferable,
which I understand is what I'm going to do here.
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 4 Feb 2026 16:29:13 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Feb 04 11:29:12 2026 Received: from localhost ([127.0.0.1]:33887 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1vnfke-00058Z-HO for submit <at> debbugs.gnu.org; Wed, 04 Feb 2026 11:29:12 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:37084) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <eliz@HIDDEN>) id 1vnfkb-00058D-Ko for 80323 <at> debbugs.gnu.org; Wed, 04 Feb 2026 11:29:10 -0500 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 1vnfkM-0006G9-MB; Wed, 04 Feb 2026 11:29:03 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=BXxntAMdmlm1QHDPR9NoFx5XTnqs/0hujnTc9M24oyU=; b=k7JQDUO5l/utxrq/pfs0 zksj3jbx4AoJ08r6taIyuqlCnPH1qJP+c59ppcv1BpS3no62uc8ypoqDDCSbKUBHA8/TdvOSkMtl2 tLpS8OEo1ZwVtEsb5GMaQnG2K+TALt6Wr0531AAWdVSGVVdfnvdUSEqY6szLEu7saKNjJ7b73ioYM YguR2+kIsMlkdBaxjeH+KOI5S9uGGB+FbKoG5NLeYJ2iuNG7CPO7O83qRE21AhVREJgjfGUzQfptN TQAGfnHh3CrqvM8ELIfoU+jDd49oWGA/UJEReL/8jvtEC3lgWKpoYwQCkgPYFWe1QQ9v+XMJoGGFf deXkRzto1x+feA==; Date: Wed, 04 Feb 2026 18:26:12 +0200 Message-Id: <86y0l8xyor.fsf@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> In-Reply-To: <CALDnm50HQJnS7i89-x0UcZ2GZ8raWE6mL_a-_drQV06u4Gbg7A@HIDDEN> (message from =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= on Wed, 4 Feb 2026 15:58:24 +0000) Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm References: <87y0la2egy.fsf@HIDDEN> <87ms1q9bpq.fsf@HIDDEN> <CAN+1HbrAG_1YF4UzOyY_ARWzhKHsWCMaxgWb1qp8Rg1sq4SjVg@HIDDEN> <87zf5p7362.fsf@HIDDEN> <87qzr08yni.fsf@HIDDEN> <CALDnm50pn2rgD+K=gyr9Cj-iZy_rMFDmBRmHkT5P84hiVxaQnw@HIDDEN> <jwv4inwcxpt.fsf-monnier+emacs@HIDDEN> <CALDnm50HQJnS7i89-x0UcZ2GZ8raWE6mL_a-_drQV06u4Gbg7A@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 80323 Cc: spwhitton@HIDDEN, monnier@HIDDEN, 80323 <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 (---) > Cc: 80323 <at> debbugs.gnu.org, Sean Whitton <spwhitton@HIDDEN> > From: João Távora <joaotavora@HIDDEN> > Date: Wed, 4 Feb 2026 15:58:24 +0000 > > I don't know if it does for sure, but the algo needs to compare character s, and currently addresses memory > like bytes naively with [] as if I were using C++ and that did the right thing. It does mostly and the patch > passes all the current tests, but then all these tests are for ASCII. But in C the [] is very dumb and so some > macro salad is probably required. I think it's a terminology issue. AFAIU, by "wide characters" you mean characters whose internal representation in a string takes more than 1 byte. For that, string_char_and_length is the function to use: it returns to you the Unicode codepoint of a character and the number of bytes its multibyte sequence takes (which you can then use to advance your 'char *' pointer to the beginning of the next character's multibyte sequence). Or you can use fetch_string_char_advance, which will do all that for you in one go. Stefan, AFAIU, means "width" as in "character width on display".
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 4 Feb 2026 16:28:52 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Feb 04 11:28:52 2026 Received: from localhost ([127.0.0.1]:33881 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1vnfkK-00057S-1Q for submit <at> debbugs.gnu.org; Wed, 04 Feb 2026 11:28:52 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:41448) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <eliz@HIDDEN>) id 1vnfkH-00057B-Qh for 80323 <at> debbugs.gnu.org; Wed, 04 Feb 2026 11:28:50 -0500 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 1vnfkB-0006EN-Kj; Wed, 04 Feb 2026 11:28:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=BXxntAMdmlm1QHDPR9NoFx5XTnqs/0hujnTc9M24oyU=; b=oweVJjbTCnLzdEbI+1u5 nimev9UJ5HwvrFu6zmHjEO4h73rAr7c/7bT/qA2qRGyzo+mfVuOorBJpdFj8vBPCWWpJDRUjsZwgH 8bdiQjiroYNqvmZPVtbKz7pE5UxUUh23kcG32/mm2zdZor+YRybwXq+/Zfm1g/AWSoi6ylKJC62Fl bI+QKbFKhhw0CalNln18JDXMiKOkgiZZsDmKfWwQ70MXWUcubocmArLCBHanISYYY8iCln2A3+cfS FTPuIQh7sQbpSEOUri3pY9QbaaU4Odhu9oZqXHFIGeom8Wf/5BYY68nhkdwLhyUGpb0SwAqY5fVZy b1dHWMRaLzsSbQ==; Date: Wed, 04 Feb 2026 18:20:11 +0200 Message-Id: <86zf5oxyys.fsf@HIDDEN> From: Eli Zaretskii <eliz@HIDDEN> To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> In-Reply-To: <CALDnm50HQJnS7i89-x0UcZ2GZ8raWE6mL_a-_drQV06u4Gbg7A@HIDDEN> (message from =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= on Wed, 4 Feb 2026 15:58:24 +0000) Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm References: <87y0la2egy.fsf@HIDDEN> <87ms1q9bpq.fsf@HIDDEN> <CAN+1HbrAG_1YF4UzOyY_ARWzhKHsWCMaxgWb1qp8Rg1sq4SjVg@HIDDEN> <87zf5p7362.fsf@HIDDEN> <87qzr08yni.fsf@HIDDEN> <CALDnm50pn2rgD+K=gyr9Cj-iZy_rMFDmBRmHkT5P84hiVxaQnw@HIDDEN> <jwv4inwcxpt.fsf-monnier+emacs@HIDDEN> <CALDnm50HQJnS7i89-x0UcZ2GZ8raWE6mL_a-_drQV06u4Gbg7A@HIDDEN> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 80323 Cc: spwhitton@HIDDEN, monnier@HIDDEN, 80323 <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 (---) > Cc: 80323 <at> debbugs.gnu.org, Sean Whitton <spwhitton@HIDDEN> > From: João Távora <joaotavora@HIDDEN> > Date: Wed, 4 Feb 2026 15:58:24 +0000 > > I don't know if it does for sure, but the algo needs to compare character s, and currently addresses memory > like bytes naively with [] as if I were using C++ and that did the right thing. It does mostly and the patch > passes all the current tests, but then all these tests are for ASCII. But in C the [] is very dumb and so some > macro salad is probably required. I think it's a terminology issue. AFAIU, by "wide characters" you mean characters whose internal representation in a string takes more than 1 byte. For that, string_char_and_length is the function to use: it returns to you the Unicode codepoint of a character and the number of bytes its multibyte sequence takes (which you can then use to advance your 'char *' pointer to the beginning of the next character's multibyte sequence). Or you can use fetch_string_char_advance, which will do all that for you in one go. Stefan, AFAIU, means "width" as in "character width on display".
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 4 Feb 2026 15:58:39 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Feb 04 10:58:39 2026 Received: from localhost ([127.0.0.1]:33663 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1vnfH4-0003bj-Ny for submit <at> debbugs.gnu.org; Wed, 04 Feb 2026 10:58:39 -0500 Received: from mail-oi1-x231.google.com ([2607:f8b0:4864:20::231]:51291) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>) id 1vnfH1-0003ba-M8 for 80323 <at> debbugs.gnu.org; Wed, 04 Feb 2026 10:58:36 -0500 Received: by mail-oi1-x231.google.com with SMTP id 5614622812f47-45c962424daso2813409b6e.2 for <80323 <at> debbugs.gnu.org>; Wed, 04 Feb 2026 07:58:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770220715; cv=none; d=google.com; s=arc-20240605; b=EadOd6zEbx8bHBGGqGxNpHPuPERgq+1LBOAVmelrZIQ+DkLZJC95qJHxIWQ5APjV0n CChHyOPvc+ryfFqWQPNqp0Ql1cRg97vRj9wo2imTyhshRYsLbaj/CP20HOhAlv9wh/GX SpsTihY7e6EOtxGyoDSmLYJrHCUoMiEywYa+Ea4DDmDXdo3wCWot70NBvfhvpnU23i65 XoSZBWTDPUhK2AWwFJOh4WhTGkqqq3hccqv9UvzcGLKI97xQGGqhmq/cAMH+DWAhoZyn 7MdlVvYXZyRYKeRYUSa1IsolDE0DoxnV4/lBl6V7vzYMACk4Xv5b0/bFZCBGyt9nrTxl MO1A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=v3AkcNX6ddqeXvjwFr8SlMGwU5RbuYGlk6js9/QayKM=; fh=fattA/Lbu7M/Ba5BzE8F9o64SJlL0j/WyN012wjpVuo=; b=bRokyxvSUn6FDaIPQh1Yg/u9/lodarCrbUVZlSv9O1IQ+WL0tghNyVZe3n6m4elXQU n4X6clQtMTD4MrIxNlEi3X071wnSFOrlxBqPFeGVSwgYnGRbeLAg5a5vUurcXCUcLhSA M1cgQHN89TsRrKPKBZVDpdYH4WemZcp0bxF4mMHsPLauSOyG1kTPKILYGGUL8JyC21Ux mFivE85r9ElBTG91X+oWWakqsFMnnkfapoWxFMqQ3a9a6Bw/KZvQeLb8+uyO5XI87bj4 BGdPGdoOC5hfd6Ai/tREql7LRbWMNxmSjmxkK70VpCjezDpYAsi/MmQ8+/kbmEv71qpx k/EA==; darn=debbugs.gnu.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770220715; x=1770825515; darn=debbugs.gnu.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=v3AkcNX6ddqeXvjwFr8SlMGwU5RbuYGlk6js9/QayKM=; b=WWggO9IZJLy1L5v4/BWYhGEGcv0Y6nRU+t6VAC42iUcVL9ptl5MpdYbqMrgq+D0k03 6tXishbOA2M5XEhL19X9XGdGRx4dN82NsWJk5vrUuLi0AARCn5yqlMAw8S8XVe5nazAC x03DmIDMM1m5EOD+grbx39ikGugRlPu767QXq/PSQ+Jage23ATpmFJke4VFObsu7qIdY w3XmKK3Jn8UzpDNjBrbc8L4J0K1SoGtTPHe+UcovZfIaIC7r0d8yi36251Hr8Rljmfdh yT2pRFpoxsC6w5RMvAtbWmArY0bdrUhtZ12sYw0U12M1CMH7m2tsZd4nN1l1pbdRQB56 Dsjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770220715; x=1770825515; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=v3AkcNX6ddqeXvjwFr8SlMGwU5RbuYGlk6js9/QayKM=; b=YjYNz9N5dX8YsKGa1EmdD0VcpPl5lwsp/rrQxnuUD1cxs6+8qmMpw6xetv21Qd/G1t B4MImbyGrnfWYr94eaPdm+DAL0F1VQaVxdIQdq15e/8wz3QKWeRE90g9cvTtCB9hCNgC V8UvjjHzp8GcPFcSZa10hrNrEe3KUVHt4VwvOqGmmloamK+/G+DjClAGu0RVAAcrAetF k4VAt6paDgekkJ4ucAp3FSzCzC00dpCsHw35JS/lGq5g8vyBi9Ln3sRfF8rKa8j9FIom tkFnlJmUoyoztXy3121z7LB40nK9MZLkNeLPoxqT1QE305PRscwESf742cdAclUowJ8c h6Gw== X-Forwarded-Encrypted: i=1; AJvYcCV0Pe7GbMFtW3CxyWJ/PbMf8ibmWyqvvCuFVSMIp0RBFyfgTuSgpFdrrbcL1IoB7tfJymOaVA==@debbugs.gnu.org X-Gm-Message-State: AOJu0YzEw9PH46ixBZWIaTCBFydskV1eB0ac7HdNWtXKHpB50TaKemb/ 46DFIxrb3499yXYp5Dlry53XsWa/vVZJ0HawdS3S8DgEmF+Rd9oMyW6SGhse764QsXMyEhNPvwh VrFviDcCffa1LFhY+GW5GPAJHYg+koHzGyw== X-Gm-Gg: AZuq6aJoWAyEeIlskr+f9Uvtody6MpfjxCpYIlcu8SsDj/KqrkZmuk0XXjXIiGS+edc 4Y1QODtunUyCsLGY/7dKe9k5npqTNA3Pffq+F5J553+rMmihW6hv6UWxHMQC2jlTT7TdeBUx3N1 ZBWpskLmlkf4trGtApVw1PPY8P7xCi+6lb/l2QtlrbCVFB9W2PVEk7UYazyC38IVg/KZHfMVv/M R5qm3D4J+EevZ7Cby9LvH1sYIZSDgNNyDXVmFVqYizPKOr7JRLkE6QO4z61LCVncR3vF/I= X-Received: by 2002:a05:6808:c2a2:b0:450:c602:751d with SMTP id 5614622812f47-462d58e42c7mr1927906b6e.21.1770220714591; Wed, 04 Feb 2026 07:58:34 -0800 (PST) MIME-Version: 1.0 References: <87y0la2egy.fsf@HIDDEN> <87ms1q9bpq.fsf@HIDDEN> <CAN+1HbrAG_1YF4UzOyY_ARWzhKHsWCMaxgWb1qp8Rg1sq4SjVg@HIDDEN> <87zf5p7362.fsf@HIDDEN> <87qzr08yni.fsf@HIDDEN> <CALDnm50pn2rgD+K=gyr9Cj-iZy_rMFDmBRmHkT5P84hiVxaQnw@HIDDEN> <jwv4inwcxpt.fsf-monnier+emacs@HIDDEN> In-Reply-To: <jwv4inwcxpt.fsf-monnier+emacs@HIDDEN> From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> Date: Wed, 4 Feb 2026 15:58:24 +0000 X-Gm-Features: AZwV_Qhb7ZP_EZISe8OmLJXUJJEt14wRmTGnzZB2CPMFjwR3vA0rCaQlNx9SgXs Message-ID: <CALDnm50HQJnS7i89-x0UcZ2GZ8raWE6mL_a-_drQV06u4Gbg7A@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm To: Stefan Monnier <monnier@HIDDEN> Content-Type: multipart/alternative; boundary="000000000000de089f064a01a09b" X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 80323 Cc: 80323 <at> debbugs.gnu.org, Sean Whitton <spwhitton@HIDDEN> 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.0 (/) --000000000000de089f064a01a09b Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable I don't know if it does for sure, but the algo needs to compare character s, and currently addresses memory like bytes naively with [] as if I were using C++ and that did the right thing. It does mostly and the patch passes all the current tests, but then all these tests are for ASCII. But in C the [] is very dumb and so some macro salad is probably required. On Wed, Feb 4, 2026, 15:53 Stefan Monnier <monnier@HIDDEN> wrote: > > Seems like my patch is too naive regarding wide chars. Gotta fix that. > > What's the recommended way to iterate such strings in C code? > > I'm missing something: why does the width of characters matter? > > > =3D=3D=3D Stefan > > Jo=C3=A3o T=C3=A1vora --000000000000de089f064a01a09b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"auto"><div><div>I don't know if it does for sure, but the a= lgo needs to compare character s, and currently addresses memory like bytes= naively with [] as if I were using C++ and that did the right thing. It do= es mostly and the patch passes all the current tests, but then all these te= sts are for ASCII. But in C the [] is very dumb and so some macro salad is = probably required.</div><br><div class=3D"gmail_quote"><div dir=3D"ltr" cla= ss=3D"gmail_attr">On Wed, Feb 4, 2026, 15:53 Stefan Monnier <<a href=3D"= mailto:monnier@HIDDEN" target=3D"_blank" rel=3D"noreferrer">monni= er@HIDDEN</a>> wrote:<br></div><blockquote class=3D"gmail_quot= e" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204)= ;padding-left:1ex">> Seems like my patch is too naive regarding wide cha= rs. Gotta fix that.<br> > What's the recommended way to iterate such strings in C code?<br> <br> I'm missing something: why does the width of characters matter?<br> <br> <br> =3D=3D=3D Stefan<br> <br> </blockquote></div></div><div data-smartmail=3D"gmail_signature">Jo=C3=A3o = T=C3=A1vora</div></div> --000000000000de089f064a01a09b--
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.
Received: (at 80323) by debbugs.gnu.org; 4 Feb 2026 13:31:48 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Wed Feb 04 08:31:48 2026
Received: from localhost ([127.0.0.1]:59835 helo=debbugs.gnu.org)
by debbugs.gnu.org with esmtp (Exim 4.84_2)
(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
id 1vncyv-0004iS-Gy
for submit <at> debbugs.gnu.org; Wed, 04 Feb 2026 08:31:48 -0500
Received: from mail-oa1-x2d.google.com ([2001:4860:4864:20::2d]:50343)
by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)
(Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>)
id 1vncyp-0004iD-ND
for 80323 <at> debbugs.gnu.org; Wed, 04 Feb 2026 08:31:43 -0500
Received: by mail-oa1-x2d.google.com with SMTP id
586e51a60fabf-409470ad5bbso2563955fac.0
for <80323 <at> debbugs.gnu.org>; Wed, 04 Feb 2026 05:31:39 -0800 (PST)
ARC-Seal: i=1; a=rsa-sha256; t=1770211898; cv=none;
d=google.com; s=arc-20240605;
b=YGPr+e8F2A+OJBKyjX9+Jnlt0Ys1F9arVqltAUQA+K+inS0aTtUnZATIQVDp1XBY6r
tV0UFcoklArg44+D6p43Jg1R8GfwT7LWlHlCcueRu6Qf8KO+0/Ekz0l645Ts5VQmbZ+v
fvN7hZrRZLbdZGL4oY8L9P/0WemJBNGl0+Kt3EIY2pyfE8E+dO4/sdcXG5O6ZMqecnTQ
TQQBtOzQigoxD0fQxDunqmKp/+3DtRchO/U0p8/V5ZS783Ia23ocqtosA1ZUSOgImTcK
e+/k2OIV5YMPdTBIEVr18bm/+EFS9OL4A8TWi1b/U6NwM4Z8cUs7jNdcdWtJ/Ij5sqDC
GbXw==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com;
s=arc-20240605;
h=to:subject:message-id:date:from:in-reply-to:references:mime-version
:dkim-signature;
bh=vVNCc2yncqJoDmPerpFO7zlV+NWL2PH8LCjj/GTMxDQ=;
fh=vn0RqOen5tsrdBRE0q4SRfweiUNyML0qzMfGNW7lHs8=;
b=hnd5H53ps8kh89yL9i4VTL+jL7IUWH9EawS3Q9EeVYeevE7O5RP1/Cd5LTlrVjrxij
BYtA4sz2+WAC8T0IwhbMBjuNNcQqhv9E6KTlGCZagGWt9TKjIzkIAykudXaPk7gx1CX0
RLMBbyr9R3I17BsLuOw/xwhOeAPqbWA04UskOYs0hdmsKwPnT+fS4hNm1+0hMJseZou8
374XnMdwqQPbh9N6Ctw3R3XlZxZ1gaDX4G9ddofigE4W9nH/UL6mYNyOCv2SUAQmA0c6
XP5kAKk28FWHH1o9TqohW9xlc9X3IcxX+Tmh+8PJoYEtHgKp5DoljD4G6USNP3wLj86L
+GzQ==; darn=debbugs.gnu.org
ARC-Authentication-Results: i=1; mx.google.com; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20230601; t=1770211898; x=1770816698; darn=debbugs.gnu.org;
h=to:subject:message-id:date:from:in-reply-to:references:mime-version
:from:to:cc:subject:date:message-id:reply-to;
bh=vVNCc2yncqJoDmPerpFO7zlV+NWL2PH8LCjj/GTMxDQ=;
b=PnwsJz80k39PpGeafisRXYjKegqn0cKEWpvWhknJ5Mi526TbFWs/1Cl/sY+4h6ZS/y
FQ0n+KXfzT6hWjqrVkPa9znVRTzjqx1mI0EzU/NGd7yhNoyidLFoVoS6XV/YaHeGGsG9
CsatY17DyiZ+Y3ibH32xcu0snT6t/pJmm7pRDCilIeC3JouQDEKh53cNmZh8q7+YUuVw
TJkpG8dTiwpZ3JiWy719+g+DEECNlJqg7+IC+et+UZDgI08d0YapdRFrBIKzT+h4pvZ8
jJW8hh4KQ4/3dM79y3Ut4YI9q3ZPDflLZlv3rRx32YuQlxzPkpiWLspDTlHkzbx04Eli
ghjw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20230601; t=1770211898; x=1770816698;
h=to:subject:message-id:date:from:in-reply-to:references:mime-version
:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id
:reply-to;
bh=vVNCc2yncqJoDmPerpFO7zlV+NWL2PH8LCjj/GTMxDQ=;
b=wb0W/6bko+h0vyo928gngp6MGWvbvmPwOQG9btTFuGHRNkB/c/Nk7TVqkvdRPMbUN9
8bmeTmuUWheRhXo3BJrdaMBj0I1rACSecqnrSExENJw653lHVoiCHaDR58RcLnN1Ti5P
NKdlqvu1Fp1OvKqKR64xLW8BKxcDq980L/JLZBZJkGVhSVEg5m9CqXdUCpRa0lU7v3gE
pRM8ptu8JcISeY0n/QMvTLDd46JwPTuKqX3b3Oqh3Mi8JJr9qoVC0oaNzj2U5xng7P8L
7BtA53WpFSyc7ZeACgR6dMfnz6etInj/zYpbDPD87x4hwnXjQ2k7XmN8V51yB2w5SrJH
7Oiw==
X-Gm-Message-State: AOJu0YyXQh3pseAmpmrk9Say3B5oEbWlHBemUIPr8sGrzorNa0XTuziw
oeInLXEa7Ek3QGOdJVs4iqFpk1dt4JgDTKyK4ngWsQ5sYIDw7gTNBjWuQ8bZ4baZAVW12Wcg4uR
I0nvKDJpoCObpkmo7e0nn86bgBalKP/F+9A==
X-Gm-Gg: AZuq6aJ1zUPTdT+Y80FmsYULkP/dmifNB6kRJUHVHMD28Hg8EQMgWtxT+TdHqH7TFCH
fLIkI0Z8tTncMT1ThH/Rr0SUnfi9jlLdcr7SCxZkfNIg3BEPw1F3zQDYc0ZOc69Ww6xQE8TsmU0
gm6e5D6Q785SWYkZoBPbANvVdX1Ug0pBgO3ThUbF0krg8HeumwH6l2fipxZhgsvt8ClzfuYhUNo
ePTkB4VRMfh6El/WYhJ3owXD7XphON3K/fNE/npATNy5/b5zrhb+SgKou46S1zCnhdP9fc=
X-Received: by 2002:a05:6820:2295:b0:66a:1886:e4c2 with SMTP id
006d021491bc7-66a207899d7mr1311296eaf.20.1770211898392; Wed, 04 Feb 2026
05:31:38 -0800 (PST)
MIME-Version: 1.0
References: <87y0la2egy.fsf@HIDDEN> <87ms1q9bpq.fsf@HIDDEN>
<CAN+1HbrAG_1YF4UzOyY_ARWzhKHsWCMaxgWb1qp8Rg1sq4SjVg@HIDDEN>
<87zf5p7362.fsf@HIDDEN>
In-Reply-To: <87zf5p7362.fsf@HIDDEN>
From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN>
Date: Wed, 4 Feb 2026 13:31:27 +0000
X-Gm-Features: AZwV_Qh64J4jrJ7_OLikFa-tAe2uaBe-CP0PQJveTgAFIxhDrgjHRFyflhUr5QE
Message-ID: <CALDnm51X1FZXk3JVRfxL3yPWsFSYmB9YVOe0u+0SDO-cpLM9SA@HIDDEN>
Subject: Fwd: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh
algorithm
To: 80323 <at> debbugs.gnu.org
Content-Type: multipart/alternative; boundary="00000000000061872d0649ff9353"
X-Spam-Score: 1.0 (+)
X-Debbugs-Envelope-To: 80323
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.0 (/)
--00000000000061872d0649ff9353
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Seems like I didn't send the latest patch to the bug tracker...
Jo=C3=A3o T=C3=A1vora
---------- Forwarded message ---------
From: Jo=C3=A3o T=C3=A1vora <joaotavora@HIDDEN>
Date: Wed, Feb 4, 2026, 00:39
Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh
algorithm
To: St=C3=A9phane Marks <shipmints@HIDDEN>
Cc: Sean Whitton <spwhitton@HIDDEN>, <axel@HIDDEN>, <
monnier@HIDDEN>
St=C3=A9phane Marks <shipmints@HIDDEN> writes:
> - list
>
> In my past doing some computational biology work, I'd also done a little
dabbling. I found this guy's ideas useful
> especially with regard to using integer arithmetic vs. floats and that
might help the efficiency of this adaptation for
> Emacs https://florianerhard.github.io/2016/gotoh3
>
https://github.com/florianerhard/florianerhard.github.io/tree/master/assets=
/gotoh
>
> I have not read the code beyond eyeballing the double-precision float
matrices which is what prompted my ancient memory
> cells to reactivate.
I've rewritten the patch to be cost-based, which is much cleaner. I
also cleaned up some C silliness along the way (like the indiscrimate
use of ptrdiff_t for loop indexes)
I've tried also some optimizations, like simplifying the "gap origin"
memory, using just a two-row matrix for match and using ints instead of
doubles. Neither made any practical difference. In a final version we
could consider removing them if we find they obfuscate the code
needlessly.
So The code is just as fast as before and only slightly faster than
hotfuzz. But now since it's cost-based too maybe it will be easier to
compare the implementations. I think hotfuzz's uses a simpler
backtracking method for highlighting somehow.
Also, I read the article, perhaps that guy did his PHD a long time ago
when CPU architectures were very different?
Anyway, the latest patch to play around with is after my sig.
Jo=C3=A3o
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index fc193fe54f0..47652d2bda4 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -4450,18 +4450,12 @@ completion-pcm--all-completions
(when (string-match-p regex c) (push c poss)))
(nreverse poss))))))
-(defvar flex-score-match-tightness 3
- "Controls how the `flex' completion style scores its matches.
-
-Value is a positive number. A number smaller than 1 makes the
-scoring formula reward matches scattered along the string, while
-a number greater than one make the formula reward matches that
-are clumped together. I.e \"foo\" matches both strings
-\"fbarbazoo\" and \"fabrobazo\", which are of equal length, but
-only a value greater than one will score the former (which has
-one large \"hole\" and a clumped-together \"oo\" match) higher
-than the latter (which has two \"holes\" and three
-one-letter-long matches).")
+(defvar flex-score-match-tightness nil)
+
+(make-obsolete-variable
+ 'flex-score-match-tightness
+ "It never did anything very useful anyway."
+ "31.0")
(defvar completion-lazy-hilit nil
"If non-nil, request lazy highlighting of completion candidates.
@@ -4502,133 +4496,46 @@ completion-lazy-hilit
(funcall completion-lazy-hilit-fn (copy-sequence str))
str))
-(defun completion--hilit-from-re (string regexp &optional point-idx)
- "Fontify STRING using REGEXP POINT-IDX.
-Uses `completions-common-part' and `completions-first-difference'
-faces to fontify STRING.
-POINT-IDX is the position of point in the presumed \"PCM\" pattern
-from which REGEXP was generated."
- (let* ((md (and regexp (string-match regexp string) (cddr (match-data
t))))
- (pos (if point-idx (match-beginning point-idx) (match-end 0)))
- (me (and md (match-end 0)))
- (from 0))
- (while md
- (add-face-text-property from (pop md)
- 'completions-common-part nil string)
- (setq from (pop md)))
- (if (and (numberp pos) (> (length string) pos))
- (add-face-text-property
- pos (1+ pos)
- 'completions-first-difference
- nil string))
- (unless (or (not me) (=3D from me))
- (add-face-text-property from me 'completions-common-part nil string)=
)
- string))
-
-(defun completion--flex-score-1 (md-groups match-end len)
- "Compute matching score of completion.
-The score lies in the range between 0 and 1, where 1 corresponds to
-the full match.
-MD-GROUPS is the \"group\" part of the match data.
-MATCH-END is the end of the match.
-LEN is the length of the completion string."
- (let* ((from 0)
- ;; To understand how this works, consider these simple
- ;; ascii diagrams showing how the pattern "foo"
- ;; flex-matches "fabrobazo", "fbarbazoo" and
- ;; "barfoobaz":
-
- ;; f abr o baz o
- ;; + --- + --- +
-
- ;; f barbaz oo
- ;; + ------ ++
-
- ;; bar foo baz
- ;; +++
-
- ;; "+" indicates parts where the pattern matched. A
- ;; "hole" in the middle of the string is indicated by
- ;; "-". Note that there are no "holes" near the edges
- ;; of the string. The completion score is a number
- ;; bound by (0..1] (i.e., larger than (but not equal
- ;; to) zero, and smaller or equal to one): the higher
- ;; the better and only a perfect match (pattern equals
- ;; string) will have score 1. The formula takes the
- ;; form of a quotient. For the numerator, we use the
- ;; number of +, i.e. the length of the pattern. For
- ;; the denominator, it first computes
- ;;
- ;; hole_i_contrib =3D 1 + (Li-1)^(1/tightness)
- ;;
- ;; , for each hole "i" of length "Li", where tightness
- ;; is given by `flex-score-match-tightness'. The
- ;; final value for the denominator is then given by:
- ;;
- ;; (SUM_across_i(hole_i_contrib) + 1) * len
- ;;
- ;; , where "len" is the string's length.
- (score-numerator 0)
- (score-denominator 0)
- (last-b 0))
- (while (and md-groups (car md-groups))
- (let ((a from)
- (b (pop md-groups)))
- (setq
- score-numerator (+ score-numerator (- b a)))
- (unless (or (=3D a last-b)
- (zerop last-b)
- (=3D a len))
- (setq
- score-denominator (+ score-denominator
- 1
- (expt (- a last-b 1)
- (/ 1.0
- flex-score-match-tightness)))))
- (setq
- last-b b))
- (setq from (pop md-groups)))
- ;; If `pattern' doesn't have an explicit trailing any, the
- ;; regex `re' won't produce match data representing the
- ;; region after the match. We need to account to account
- ;; for that extra bit of match (bug#42149).
- (unless (=3D from match-end)
- (let ((a from)
- (b match-end))
- (setq
- score-numerator (+ score-numerator (- b a)))
- (unless (or (=3D a last-b)
- (zerop last-b)
- (=3D a len))
- (setq
- score-denominator (+ score-denominator
- 1
- (expt (- a last-b 1)
- (/ 1.0
- flex-score-match-tightness)))))
- (setq
- last-b b)))
- (/ score-numerator (* len (1+ score-denominator)) 1.0)))
-
-(defvar completion--flex-score-last-md nil
- "Helper variable for `completion--flex-score'.")
-
-(defun completion--flex-score (str re &optional dont-error)
- "Compute flex score of completion STR based on RE.
-If DONT-ERROR, just return nil if RE doesn't match STR."
- (let ((case-fold-search completion-ignore-case))
- (cond ((string-match re str)
- (let* ((match-end (match-end 0))
- (md (cddr
- (setq
- completion--flex-score-last-md
- (match-data t completion--flex-score-last-md)))))
- (completion--flex-score-1 md match-end (length str))))
- ((not dont-error)
- (error "Internal error: %s does not match %s" re str)))))
-
-(defvar completion-pcm--regexp nil
- "Regexp from PCM pattern in `completion-pcm--hilit-commonality'.")
+(cl-defun completion--flex-score (pat str &optional dont-error)
+ "Compute flex score of STR matching PAT using Gotoh algorithm.
+If DONT-ERROR, return nil if PAT cannot match STR.
+Returns (COST . MATCHES) where COST is a float (lower is better) and
+MATCHES is a list of match positions in STR."
+ (or (completion--flex-score-gotoh pat str)
+ (unless dont-error
+ (error "Pattern %s does not match %s" pat str))))
+
+(defun completion--flex-propertize (str matches point-idx segments)
+ "Add completion faces to STR based on MATCHES and POINT-IDX.
+MATCHES is a list of match positions. POINT-IDX is a match group index
+from the PCM pattern. SEGMENTS are extracted from the full PCM pattern.
+Adds `completions-common-part' for matched positions and
+`completions-first-difference' for the position corresponding to point."
+ (when point-idx
+ ;; Compute character position from segments
+ (let* ((pos (cl-loop for seg in segments
+ for i from 1
+ while (<=3D i point-idx)
+ sum (length (car seg)))))
+ ;; Add first-difference after pos-th match, if in range
+ (let ((point-match (and (> pos 0)
+ (<=3D pos (length matches))
+ (nth (1- pos) matches))))
+ (when (and point-match (< (1+ point-match) (length str)))
+ (add-face-text-property
+ (1+ point-match) (+ 2 point-match)
+ 'completions-first-difference nil str)))))
+ ;; Highlight matched positions
+ (dolist (pos matches)
+ (add-face-text-property pos (1+ pos)
+ 'completions-common-part
+ nil str))
+ str)
+
+(defvar completion-flex--pattern-str nil
+ "Pattern string for flex completion scoring.
+This is the concatenated string parts from the PCM pattern,
+used by `completion--flex-score' for Gotoh algorithm matching.")
(defun completion-pcm--hilit-commonality (pattern completions)
"Show where and how well PATTERN matches COMPLETIONS.
@@ -4645,22 +4552,37 @@ completion-pcm--hilit-commonality
Else, if `completion-lazy-hilit' is t, return COMPLETIONS
unchanged, but setup a suitable `completion-lazy-hilit-fn' (which
see) for later lazy highlighting."
- (setq completion-pcm--regexp nil
- completion-lazy-hilit-fn nil)
+ (setq completion-lazy-hilit-fn nil
+ completion-flex--pattern-str nil)
(cond
((and completions (cl-loop for e in pattern thereis (stringp e)))
(let* ((segments (completion-pcm--pattern->segments pattern))
- (re (completion-pcm--segments->regex segments 'group))
- (point-idx (completion-pcm--segments-point-idx segments)))
- (setq completion-pcm--regexp re)
+ (point-idx (completion-pcm--segments-point-idx segments))
+ ;; Extract pattern string (concatenate string elements)
+ (pat (mapconcat #'identity
+ (delq nil (mapcar (lambda (x)
+ (if (stringp x) x nil))
+ pattern))
+ "")))
+ (setq completion-flex--pattern-str pat)
(cond (completion-lazy-hilit
(setq completion-lazy-hilit-fn
- (lambda (str) (completion--hilit-from-re str re
point-idx)))
+ (lambda (str)
+ (let ((result (completion--flex-score pat str t)))
+ (when result
+ (completion--flex-propertize
+ str (cdr result) point-idx segments)))
+ str))
completions)
(t
(mapcar
(lambda (str)
- (completion--hilit-from-re (copy-sequence str) re
point-idx))
+ (setq str (copy-sequence str))
+ (let ((result (completion--flex-score pat str t)))
+ (when result
+ (completion--flex-propertize
+ str (cdr result) point-idx segments)))
+ str)
completions)))))
(t completions)))
@@ -5009,7 +4931,7 @@ completion-flex-nospace
(defun completion--flex-adjust-metadata (metadata)
"If `flex' is actually doing filtering, adjust sorting."
- (let ((flex-is-filtering-p completion-pcm--regexp)
+ (let ((flex-is-filtering-p completion-flex--pattern-str)
(existing-dsf
(completion-metadata-get metadata 'display-sort-function))
(existing-csf
@@ -5021,11 +4943,11 @@ completion--flex-adjust-metadata
(mapcar
(lambda (str)
(cons
- (- (completion--flex-score
- (or (get-text-property
- 0 'completion--unquoted str)
- str)
- completion-pcm--regexp))
+ (car (completion--flex-score
+ completion-flex--pattern-str
+ (or (get-text-property
+ 0 'completion--unquoted str)
+ str)))
str))
(if existing-sort-fn
(funcall existing-sort-fn completions)
diff --git a/src/minibuf.c b/src/minibuf.c
index 5dc2b230883..a3a93454383 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -20,6 +20,7 @@ Copyright (C) 1985-1986, 1993-2026 Free Software
Foundation, Inc.
#include <config.h>
#include <errno.h>
+#include <math.h>
#include <binary-io.h>
@@ -2279,6 +2280,147 @@ init_minibuf_once_for_pdumper (void)
last_minibuf_string =3D Qnil;
}
+DEFUN ("completion--flex-score-gotoh", Fcompletion__flex_score_gotoh,
+ Scompletion__flex_score_gotoh, 2, 2, 0,
+ doc: /* Compute flex score of STR matching PAT using Gotoh
algorithm.
+Returns (COST . MATCHES) where COST is a float (lower is better) and
+MATCHES is a list of match positions in STR, or nil if no match found. */=
)
+ (Lisp_Object pat, Lisp_Object str)
+{
+ /* Pre-allocated matrices for flex completion scoring. */
+#define FLEX_MAX_STR_SIZE 512
+#define FLEX_MAX_PAT_SIZE 128
+
+ /* Only two rows actually needed for M and D */
+ static int M[2 * FLEX_MAX_STR_SIZE];
+ static int D[2 * FLEX_MAX_STR_SIZE];
+ static size_t P[FLEX_MAX_STR_SIZE * FLEX_MAX_PAT_SIZE];
+ /* Macro for 2D indexing. MAT uses only 2 rows for M and D,
+ alternating via bitmask. MAT uses full indexing for P. */
+#define MAT2(matrix, i, j) ((matrix)[(((i) + 1) & 1) * width + ((j) + 1)])
+#define MAT(matrix, i, j) ((matrix)[((i) + 1) * width + ((j) + 1)])
+
+ CHECK_STRING (pat);
+ CHECK_STRING (str);
+
+ size_t m =3D SCHARS (pat);
+ size_t n =3D SCHARS (str);
+ size_t width =3D n + 1;
+ size_t size =3D (m + 1) * width;
+
+ /* Bail if strings are empty or matrix too large. */
+ if (m =3D=3D 0 || n =3D=3D 0)
+ return Qnil;
+
+ if (size > sizeof(P))
+ return Qnil;
+
+ /* Extract string data. */
+ unsigned char *pat_data =3D SDATA (pat);
+ unsigned char *str_data =3D SDATA (str);
+
+ /* Cost constants (lower is better). */
+ const int gap_open_cost =3D 100;
+ const int gap_extend_cost =3D 10;
+ const int pos_inf =3D INT_MAX / 2;
+
+ /* Base case: can start matching at any position in str. Its a free
+ leading gap. So set the first row of D (row -1) to 0. */
+ for (int j =3D 0; j < width; j++)
+ D[j] =3D 0;
+
+ int prev_gap_origin =3D -1;
+
+ /* Forward pass - compute M and D matrices (minimize cost). */
+ for (int i =3D 0; i < m; i++)
+ {
+ unsigned char pat_char =3D pat_data[i];
+ int gap_origin =3D -1; /* Index of last match before a gap started *=
/
+
+ MAT2 (M, i, -1) =3D pos_inf;
+ MAT2 (D, i, -1) =3D pos_inf;
+
+ for (int j =3D 0; j < n; j++)
+ {
+ unsigned char str_char =3D str_data[j];
+
+ /* Compute gap cost D[i][j]. */
+ int from_match =3D MAT2 (M, i, j - 1) + gap_open_cost;
+ int from_gap =3D MAT2 (D, i, j - 1) + gap_extend_cost;
+
+ if (from_match < from_gap)
+ {
+ MAT2 (D, i, j) =3D from_match;
+ gap_origin =3D j - 1; /* New gap. */
+ }
+ else
+ MAT2 (D, i, j) =3D from_gap; /* Extend gap. */
+
+ /* Check if characters match (case-insensitive if needed). */
+ bool chars_match;
+ if (completion_ignore_case)
+ chars_match =3D (downcase (pat_char) =3D=3D downcase (str_char=
));
+ else
+ chars_match =3D (pat_char =3D=3D str_char);
+
+ /* Compute match cost M[i][j] (no cost for matching). */
+ MAT2 (M, i, j) =3D pos_inf;
+ if (chars_match)
+ {
+ int prev_match =3D MAT2 (M, i - 1, j - 1);
+ int prev_gap =3D MAT2 (D, i - 1, j - 1);
+
+ if (prev_match <=3D prev_gap)
+ {
+ MAT2 (M, i, j) =3D prev_match;
+ MAT (P, i, j) =3D j - 1;
+ }
+ else
+ {
+ MAT2 (M, i, j) =3D prev_gap;
+ MAT (P, i, j) =3D prev_gap_origin;
+ }
+ }
+ }
+ prev_gap_origin =3D gap_origin;
+ }
+
+ /* Find best (lowest) cost in last row. */
+ int best_cost =3D pos_inf;
+ int lastcol =3D -1;
+
+ for (int j =3D 0; j < n; j++)
+ {
+ int cost =3D MAT2 (M, m - 1, j);
+ if (cost < best_cost)
+ {
+ best_cost =3D cost;
+ lastcol =3D j;
+ }
+ }
+
+ if (lastcol < 0 || best_cost >=3D pos_inf)
+ return Qnil;
+
+ /* Normalize cost to penalize longer strings. Lower is better. */
+ double normalized_cost =3D best_cost + (double) (n - m) / (double) m;
+
+ /* Build match positions list by tracing back through P matrix. */
+ Lisp_Object matches =3D Qnil;
+ int k =3D lastcol;
+
+ for (int i =3D m - 1; i >=3D 0 && k >=3D 0; i--)
+ {
+ matches =3D Fcons (make_fixnum (k), matches);
+ k =3D MAT (P, i, k);
+ }
+
+#undef MAT2
+#undef MAT
+
+ return Fcons (make_float (normalized_cost), matches);
+}
+
void
syms_of_minibuf (void)
{
@@ -2541,6 +2683,7 @@ syms_of_minibuf (void)
defsubr (&Stest_completion);
defsubr (&Sassoc_string);
defsubr (&Scompleting_read);
+ defsubr (&Scompletion__flex_score_gotoh);
DEFSYM (Qminibuffer_quit_recursive_edit,
"minibuffer-quit-recursive-edit");
DEFSYM (Qinternal_complete_buffer, "internal-complete-buffer");
DEFSYM (Qcompleting_read_function, "completing-read-function");
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 79ffb1d3fc7..005d7c500d4 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -205,11 +205,6 @@ completion-all-sorted-completions
'("some/alpha" "base/epsilon" "base/delta"))
`("epsilon" "delta" "beta" "alpha" "gamma" . 5))))
-(defun completion--pcm-score (comp)
- "Get `completion-score' from COMP."
- ;; FIXME, uses minibuffer.el implementation details
- (completion--flex-score comp completion-pcm--regexp))
-
(defun completion--pcm-first-difference-pos (comp)
"Get `completions-first-difference' from COMP."
(cl-loop for pos =3D (next-single-property-change 0 'face comp)
@@ -244,20 +239,11 @@ completion-pcm-test-2
"barfoobar")))
(ert-deftest completion-pcm-test-3 ()
- ;; Full match!
- (should (eql
- (completion--pcm-score
- (car (completion-pcm-all-completions
- "R" '("R" "hello") nil 1)))
- 1.0)))
+ (should (car (completion-pcm-all-completions
+ "R" '("R" "hello") nil 1))))
(ert-deftest completion-pcm-test-4 ()
- ;; One fourth of a match and no match due to point being at the end
- (should (eql
- (completion--pcm-score
- (car (completion-pcm-all-completions
- "RO" '("RaOb") nil 1)))
- (/ 1.0 4.0)))
+ ;; No match due to point being at the end
(should (null
(completion-pcm-all-completions
"RO" '("RaOb") nil 2))))
@@ -420,24 +406,14 @@ completion-pcm-bug4219
"a")))
(ert-deftest completion-substring-test-1 ()
- ;; One third of a match!
(should (equal
(car (completion-substring-all-completions
"foo" '("hello" "world" "barfoobar") nil 3))
- "barfoobar"))
- (should (eql
- (completion--pcm-score
- (car (completion-substring-all-completions
- "foo" '("hello" "world" "barfoobar") nil 3)))
- (/ 1.0 3.0))))
+ "barfoobar")))
(ert-deftest completion-substring-test-2 ()
- ;; Full match!
- (should (eql
- (completion--pcm-score
- (car (completion-substring-all-completions
- "R" '("R" "hello") nil 1)))
- 1.0)))
+ (should (car (completion-substring-all-completions
+ "R" '("R" "hello") nil 1))))
(ert-deftest completion-substring-test-3 ()
;; Substring match
@@ -504,11 +480,8 @@ completion-flex-test-1
(ert-deftest completion-flex-test-2 ()
;; Full match!
- (should (eql
- (completion--pcm-score
- (car (completion-flex-all-completions
- "R" '("R" "hello") nil 1)))
- 1.0)))
+ (should (car (completion-flex-all-completions
+ "R" '("R" "hello") nil 1))))
(ert-deftest completion-flex-test-3 ()
;; Another fuzzy match, but more of a "substring" one
--00000000000061872d0649ff9353
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div>Seems like I didn't send the latest patch to the=
bug tracker...</div><div><br></div><div data-smartmail=3D"gmail_signature"=
>Jo=C3=A3o T=C3=A1vora</div></div><br><div class=3D"gmail_quote gmail_quote=
_container"><div dir=3D"ltr" class=3D"gmail_attr">---------- Forwarded mess=
age ---------<br>From: <strong class=3D"gmail_sendername" dir=3D"auto">Jo=
=C3=A3o T=C3=A1vora</strong> <span dir=3D"auto"><<a href=3D"mailto:joaot=
avora@HIDDEN">joaotavora@HIDDEN</a>></span><br>Date: Wed, Feb 4, 2=
026, 00:39<br>Subject: Re: bug#80323: [PATCH] Rewrite flex completion scori=
ng with Gotoh algorithm<br>To: St=C3=A9phane Marks <<a href=3D"mailto:sh=
ipmints@HIDDEN">shipmints@HIDDEN</a>><br>Cc: Sean Whitton <<a h=
ref=3D"mailto:spwhitton@HIDDEN">spwhitton@HIDDEN</a>>, =
<<a href=3D"mailto:axel@HIDDEN">axel@HIDDEN</a>>, <<a href=3D=
"mailto:monnier@HIDDEN">monnier@HIDDEN</a>><br></div=
><br><br>St=C3=A9phane Marks <<a href=3D"mailto:shipmints@HIDDEN" tar=
get=3D"_blank" rel=3D"noreferrer">shipmints@HIDDEN</a>> writes:<br>
<br>
> - list<br>
><br>
> In my past doing some computational biology work, I'd also done a =
little dabbling.=C2=A0 I found this guy's ideas useful<br>
> especially with regard to using integer arithmetic vs. floats and that=
might help the efficiency of this adaptation for<br>
> Emacs <a href=3D"https://florianerhard.github.io/2016/gotoh3" rel=3D"n=
oreferrer noreferrer" target=3D"_blank">https://florianerhard.github.io/201=
6/gotoh3</a><br>
> <a href=3D"https://github.com/florianerhard/florianerhard.github.io/tr=
ee/master/assets/gotoh" rel=3D"noreferrer noreferrer" target=3D"_blank">htt=
ps://github.com/florianerhard/florianerhard.github.io/tree/master/assets/go=
toh</a><br>
><br>
> I have not read the code beyond eyeballing the double-precision float =
matrices which is what prompted my ancient memory<br>
> cells to reactivate.<br>
<br>
I've rewritten the patch to be cost-based, which is much cleaner.=C2=A0=
I<br>
also cleaned up some C silliness along the way (like the indiscrimate<br>
use of ptrdiff_t for loop indexes)<br>
<br>
I've tried also some optimizations, like simplifying the "gap orig=
in"<br>
memory, using just a two-row matrix for match and using ints instead of<br>
doubles.=C2=A0 Neither made any practical difference.=C2=A0 In a final vers=
ion we<br>
could consider removing them if we find they obfuscate the code<br>
needlessly.<br>
<br>
So The code is just as fast as before and only slightly faster than<br>
hotfuzz.=C2=A0 But now since it's cost-based too maybe it will be easie=
r to<br>
compare the implementations.=C2=A0 I think hotfuzz's uses a simpler<br>
backtracking method for highlighting somehow.<br>
<br>
Also, I read the article, perhaps that guy did his PHD a long time ago<br>
when CPU architectures were very different?<br>
<br>
Anyway, the latest patch to play around with is after my sig.<br>
<br>
Jo=C3=A3o<br>
<br>
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el<br>
index fc193fe54f0..47652d2bda4 100644<br>
--- a/lisp/minibuffer.el<br>
+++ b/lisp/minibuffer.el<br>
@@ -4450,18 +4450,12 @@ completion-pcm--all-completions<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (when (string-match-p regex c) (p=
ush c poss)))<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (nreverse poss))))))<br>
<br>
-(defvar flex-score-match-tightness 3<br>
-=C2=A0 "Controls how the `flex' completion style scores its match=
es.<br>
-<br>
-Value is a positive number.=C2=A0 A number smaller than 1 makes the<br>
-scoring formula reward matches scattered along the string, while<br>
-a number greater than one make the formula reward matches that<br>
-are clumped together.=C2=A0 I.e \"foo\" matches both strings<br>
-\"fbarbazoo\" and \"fabrobazo\", which are of equal le=
ngth, but<br>
-only a value greater than one will score the former (which has<br>
-one large \"hole\" and a clumped-together \"oo\" match=
) higher<br>
-than the latter (which has two \"holes\" and three<br>
-one-letter-long matches).")<br>
+(defvar flex-score-match-tightness nil)<br>
+<br>
+(make-obsolete-variable<br>
+ 'flex-score-match-tightness<br>
+ "It never did anything very useful anyway."<br>
+ "31.0")<br>
<br>
=C2=A0(defvar completion-lazy-hilit nil<br>
=C2=A0 =C2=A0"If non-nil, request lazy highlighting of completion cand=
idates.<br>
@@ -4502,133 +4496,46 @@ completion-lazy-hilit<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0(funcall completion-lazy-hilit-fn (copy-sequence=
str))<br>
=C2=A0 =C2=A0 =C2=A0str))<br>
<br>
-(defun completion--hilit-from-re (string regexp &optional point-idx)<b=
r>
-=C2=A0 "Fontify STRING using REGEXP POINT-IDX.<br>
-Uses `completions-common-part' and `completions-first-difference'<=
br>
-faces to fontify STRING.<br>
-POINT-IDX is the position of point in the presumed \"PCM\" patte=
rn<br>
-from which REGEXP was generated."<br>
-=C2=A0 (let* ((md (and regexp (string-match regexp string) (cddr (match-da=
ta t))))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(pos (if point-idx (match-beginning poin=
t-idx) (match-end 0)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(me (and md (match-end 0)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(from 0))<br>
-=C2=A0 =C2=A0 (while md<br>
-=C2=A0 =C2=A0 =C2=A0 (add-face-text-property from (pop md)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 'completions-common-part nil string)<br=
>
-=C2=A0 =C2=A0 =C2=A0 (setq from (pop md)))<br>
-=C2=A0 =C2=A0 (if (and (numberp pos) (> (length string) pos))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 (add-face-text-property<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pos (1+ pos)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0'completions-first-difference<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nil string))<br>
-=C2=A0 =C2=A0 (unless (or (not me) (=3D from me))<br>
-=C2=A0 =C2=A0 =C2=A0 (add-face-text-property from me 'completions-comm=
on-part nil string))<br>
-=C2=A0 =C2=A0 string))<br>
-<br>
-(defun completion--flex-score-1 (md-groups match-end len)<br>
-=C2=A0 "Compute matching score of completion.<br>
-The score lies in the range between 0 and 1, where 1 corresponds to<br>
-the full match.<br>
-MD-GROUPS is the \"group\"=C2=A0 part of the match data.<br>
-MATCH-END is the end of the match.<br>
-LEN is the length of the completion string."<br>
-=C2=A0 (let* ((from 0)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; To understand how this works, conside=
r these simple<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; ascii diagrams showing how the patter=
n "foo"<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; flex-matches "fabrobazo", &=
quot;fbarbazoo" and<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; "barfoobaz":<br>
-<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;=C2=A0 =C2=A0 =C2=A0 f abr o baz o<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;=C2=A0 =C2=A0 =C2=A0 + --- + --- +<br>
-<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;=C2=A0 =C2=A0 =C2=A0 f barbaz oo<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;=C2=A0 =C2=A0 =C2=A0 + ------ ++<br>
-<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;=C2=A0 =C2=A0 =C2=A0 bar foo baz<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 +++=
<br>
-<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; "+" indicates parts where t=
he pattern matched.=C2=A0 A<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; "hole" in the middle of the=
string is indicated by<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; "-".=C2=A0 Note that there =
are no "holes" near the edges<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; of the string.=C2=A0 The completion s=
core is a number<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; bound by (0..1] (i.e., larger than (b=
ut not equal<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; to) zero, and smaller or equal to one=
): the higher<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; the better and only a perfect match (=
pattern equals<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; string) will have score 1.=C2=A0 The =
formula takes the<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; form of a quotient.=C2=A0 For the num=
erator, we use the<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; number of +, i.e. the length of the p=
attern.=C2=A0 For<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; the denominator, it first computes<br=
>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;=C2=A0 =C2=A0 =C2=A0hole_i_contrib =3D=
1 + (Li-1)^(1/tightness)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; , for each hole "i" of leng=
th "Li", where tightness<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; is given by `flex-score-match-tightne=
ss'.=C2=A0 The<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; final value for the denominator is th=
en given by:<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;=C2=A0 =C2=A0 (SUM_across_i(hole_i_con=
trib) + 1) * len<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;;<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; , where "len" is the string=
's length.<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(score-numerator 0)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(score-denominator 0)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(last-b 0))<br>
-=C2=A0 =C2=A0 (while (and md-groups (car md-groups))<br>
-=C2=A0 =C2=A0 =C2=A0 (let ((a from)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (b (pop md-groups)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0score-numerator=C2=A0 =C2=A0(+ score-num=
erator (- b a)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 (unless (or (=3D a last-b)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (zer=
op last-b)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (=3D=
a len))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0score-denominator (+ score-denomi=
nator<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 1<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (expt (- a last-b 1)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (/ 1.0<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fl=
ex-score-match-tightness)))))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0last-b=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 b))<br>
-=C2=A0 =C2=A0 =C2=A0 (setq from (pop md-groups)))<br>
-=C2=A0 =C2=A0 ;; If `pattern' doesn't have an explicit trailing an=
y, the<br>
-=C2=A0 =C2=A0 ;; regex `re' won't produce match data representing =
the<br>
-=C2=A0 =C2=A0 ;; region after the match.=C2=A0 We need to account to accou=
nt<br>
-=C2=A0 =C2=A0 ;; for that extra bit of match (bug#42149).<br>
-=C2=A0 =C2=A0 (unless (=3D from match-end)<br>
-=C2=A0 =C2=A0 =C2=A0 (let ((a from)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (b match-end))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0score-numerator=C2=A0 =C2=A0(+ score-num=
erator (- b a)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 (unless (or (=3D a last-b)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (zer=
op last-b)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (=3D=
a len))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0score-denominator (+ score-denomi=
nator<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 1<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (expt (- a last-b 1)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (/ 1.0<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fl=
ex-score-match-tightness)))))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0last-b=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 b)))<br>
-=C2=A0 =C2=A0 (/ score-numerator (* len (1+ score-denominator)) 1.0)))<br>
-<br>
-(defvar completion--flex-score-last-md nil<br>
-=C2=A0 "Helper variable for `completion--flex-score'.")<br>
-<br>
-(defun completion--flex-score (str re &optional dont-error)<br>
-=C2=A0 "Compute flex score of completion STR based on RE.<br>
-If DONT-ERROR, just return nil if RE doesn't match STR."<br>
-=C2=A0 (let ((case-fold-search completion-ignore-case))<br>
-=C2=A0 =C2=A0 (cond ((string-match re str)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(let* ((match-end (match-end 0))<=
br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (md (cddr<b=
r>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0(setq<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 completion--flex-score-last-md<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 (match-data t completion--flex-score-last-md)))))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(completion--flex-score-1 =
md match-end (length str))))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((not dont-error)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(error "Internal error: %s d=
oes not match %s" re str)))))<br>
-<br>
-(defvar completion-pcm--regexp nil<br>
-=C2=A0 "Regexp from PCM pattern in `completion-pcm--hilit-commonality=
'.")<br>
+(cl-defun completion--flex-score (pat str &optional dont-error)<br>
+=C2=A0 "Compute flex score of STR matching PAT using Gotoh algorithm.=
<br>
+If DONT-ERROR, return nil if PAT cannot match STR.<br>
+Returns (COST . MATCHES) where COST is a float (lower is better) and<br>
+MATCHES is a list of match positions in STR."<br>
+=C2=A0 (or (completion--flex-score-gotoh pat str)<br>
+=C2=A0 =C2=A0 =C2=A0 (unless dont-error<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (error "Pattern %s does not match %s"=
; pat str))))<br>
+<br>
+(defun completion--flex-propertize (str matches point-idx segments)<br>
+=C2=A0 "Add completion faces to STR based on MATCHES and POINT-IDX.<b=
r>
+MATCHES is a list of match positions.=C2=A0 POINT-IDX is a match group ind=
ex<br>
+from the PCM pattern.=C2=A0 SEGMENTS are extracted from the full PCM patte=
rn.<br>
+Adds `completions-common-part' for matched positions and<br>
+`completions-first-difference' for the position corresponding to point=
."<br>
+=C2=A0 (when point-idx<br>
+=C2=A0 =C2=A0 ;; Compute character position from segments<br>
+=C2=A0 =C2=A0 (let* ((pos (cl-loop for seg in segments<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0for i from 1<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0while (<=3D i point-idx)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0sum (length (car seg)))))<br>
+=C2=A0 =C2=A0 =C2=A0 ;; Add first-difference after pos-th match, if in ran=
ge<br>
+=C2=A0 =C2=A0 =C2=A0 (let ((point-match (and (> pos 0)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (<=3D pos (length matches))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (nth (1- pos) matches))))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (when (and point-match (< (1+ point-match) =
(length str)))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (add-face-text-property<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(1+ point-match) (+ 2 point-match=
)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0'completions-first-difference=
nil str)))))<br>
+=C2=A0 ;; Highlight matched positions<br>
+=C2=A0 (dolist (pos matches)<br>
+=C2=A0 =C2=A0 (add-face-text-property pos (1+ pos)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0'completions-common-part<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0nil str))<br>
+=C2=A0 str)<br>
+<br>
+(defvar completion-flex--pattern-str nil<br>
+=C2=A0 "Pattern string for flex completion scoring.<br>
+This is the concatenated string parts from the PCM pattern,<br>
+used by `completion--flex-score' for Gotoh algorithm matching.")<=
br>
<br>
=C2=A0(defun completion-pcm--hilit-commonality (pattern completions)<br>
=C2=A0 =C2=A0"Show where and how well PATTERN matches COMPLETIONS.<br>
@@ -4645,22 +4552,37 @@ completion-pcm--hilit-commonality<br>
=C2=A0Else, if `completion-lazy-hilit' is t, return COMPLETIONS<br>
=C2=A0unchanged, but setup a suitable `completion-lazy-hilit-fn' (which=
<br>
=C2=A0see) for later lazy highlighting."<br>
-=C2=A0 (setq completion-pcm--regexp nil<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 completion-lazy-hilit-fn nil)<br>
+=C2=A0 (setq completion-lazy-hilit-fn nil<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 completion-flex--pattern-str nil)<br>
=C2=A0 =C2=A0(cond<br>
=C2=A0 =C2=A0 ((and completions (cl-loop for e in pattern thereis (stringp =
e)))<br>
=C2=A0 =C2=A0 =C2=A0(let* ((segments (completion-pcm--pattern->segments =
pattern))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(re (completion-pcm--segments->=
;regex segments 'group))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(point-idx (completion-pcm--segme=
nts-point-idx segments)))<br>
-=C2=A0 =C2=A0 =C2=A0 (setq completion-pcm--regexp re)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(point-idx (completion-pcm--segme=
nts-point-idx segments))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; Extract pattern string (concat=
enate string elements)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(pat (mapconcat #'identity<br=
>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0(delq nil (mapcar (lambda (x)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0(if (stringp x) x nil))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0pattern))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0"")))<br>
+=C2=A0 =C2=A0 =C2=A0 (setq completion-flex--pattern-str pat)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0(cond (completion-lazy-hilit<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq completion-lazy-hili=
t-fn<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(lamb=
da (str) (completion--hilit-from-re str re point-idx)))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(lamb=
da (str)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0(let ((result (completion--flex-score pat str t)))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0(when result<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0(completion--flex-propertize<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 str (cdr result) point-idx segments)))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0str))<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 completions)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(t<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (mapcar<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(lambda (str)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (completion--hilit=
-from-re (copy-sequence str) re point-idx))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq str (copy-se=
quence str))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (let ((result (com=
pletion--flex-score pat str t)))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (when resul=
t<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (com=
pletion--flex-propertize<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0str (cdr result) point-idx segments)))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 str)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0completions)))))<br>
=C2=A0 =C2=A0 (t completions)))<br>
<br>
@@ -5009,7 +4931,7 @@ completion-flex-nospace<br>
<br>
=C2=A0(defun completion--flex-adjust-metadata (metadata)<br>
=C2=A0 =C2=A0"If `flex' is actually doing filtering, adjust sortin=
g."<br>
-=C2=A0 (let ((flex-is-filtering-p completion-pcm--regexp)<br>
+=C2=A0 (let ((flex-is-filtering-p completion-flex--pattern-str)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(existing-dsf<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (completion-metadata-get metadata 'd=
isplay-sort-function))<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(existing-csf<br>
@@ -5021,11 +4943,11 @@ completion--flex-adjust-metadata<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (mapcar<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(lambda (str)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(cons<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(- (completion--flex-score<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(or (get-text-pr=
operty<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0=
'completion--unquoted str)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0st=
r)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0completion-pcm--=
regexp))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(car (completion--flex-score<b=
r>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0completio=
n-flex--pattern-str<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(or (get-=
text-property<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 0 'completion--unquoted str)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0str)))<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 str))<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if existing-sort-fn<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(funcall existing-sort-=
fn completions)<br>
diff --git a/src/minibuf.c b/src/minibuf.c<br>
index 5dc2b230883..a3a93454383 100644<br>
--- a/src/minibuf.c<br>
+++ b/src/minibuf.c<br>
@@ -20,6 +20,7 @@ Copyright (C) 1985-1986, 1993-2026 Free Software Foundati=
on, Inc.<br>
<br>
=C2=A0#include <config.h><br>
=C2=A0#include <errno.h><br>
+#include <math.h><br>
<br>
=C2=A0#include <binary-io.h><br>
<br>
@@ -2279,6 +2280,147 @@ init_minibuf_once_for_pdumper (void)<br>
=C2=A0 =C2=A0last_minibuf_string =3D Qnil;<br>
=C2=A0}<br>
<br>
+DEFUN ("completion--flex-score-gotoh", Fcompletion__flex_score_g=
otoh,<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0Scompletion__flex_score_gotoh, 2, 2, 0,<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0doc: /* Compute flex score of STR matching PAT =
using Gotoh algorithm.<br>
+Returns (COST . MATCHES) where COST is a float (lower is better) and<br>
+MATCHES is a list of match positions in STR, or nil if no match found.=C2=
=A0 */)<br>
+=C2=A0 (Lisp_Object pat, Lisp_Object str)<br>
+{<br>
+=C2=A0 /* Pre-allocated matrices for flex completion scoring.=C2=A0 */<br>
+#define FLEX_MAX_STR_SIZE 512<br>
+#define FLEX_MAX_PAT_SIZE 128<br>
+<br>
+=C2=A0 /* Only two rows actually needed for M and D */<br>
+=C2=A0 static int M[2 * FLEX_MAX_STR_SIZE];<br>
+=C2=A0 static int D[2 * FLEX_MAX_STR_SIZE];<br>
+=C2=A0 static size_t P[FLEX_MAX_STR_SIZE * FLEX_MAX_PAT_SIZE];<br>
+=C2=A0 /* Macro for 2D indexing.=C2=A0 MAT uses only 2 rows for M and D,<b=
r>
+=C2=A0 =C2=A0 =C2=A0alternating via bitmask.=C2=A0 MAT uses full indexing =
for P.=C2=A0 */<br>
+#define MAT2(matrix, i, j) ((matrix)[(((i) + 1) & 1) * width + ((j) + =
1)])<br>
+#define MAT(matrix, i, j) ((matrix)[((i) + 1) * width + ((j) + 1)])<br>
+<br>
+=C2=A0 CHECK_STRING (pat);<br>
+=C2=A0 CHECK_STRING (str);<br>
+<br>
+=C2=A0 size_t m =3D SCHARS (pat);<br>
+=C2=A0 size_t n =3D SCHARS (str);<br>
+=C2=A0 size_t width =3D n + 1;<br>
+=C2=A0 size_t size =3D (m + 1) * width;<br>
+<br>
+=C2=A0 /* Bail if strings are empty or matrix too large.=C2=A0 */<br>
+=C2=A0 if (m =3D=3D 0 || n =3D=3D 0)<br>
+=C2=A0 =C2=A0 return Qnil;<br>
+<br>
+=C2=A0 if (size > sizeof(P))<br>
+=C2=A0 =C2=A0 return Qnil;<br>
+<br>
+=C2=A0 /* Extract string data.=C2=A0 */<br>
+=C2=A0 unsigned char *pat_data =3D SDATA (pat);<br>
+=C2=A0 unsigned char *str_data =3D SDATA (str);<br>
+<br>
+=C2=A0 /* Cost constants (lower is better).=C2=A0 */<br>
+=C2=A0 const int gap_open_cost =3D 100;<br>
+=C2=A0 const int gap_extend_cost =3D 10;<br>
+=C2=A0 const int pos_inf =3D INT_MAX / 2;<br>
+<br>
+=C2=A0 /* Base case: can start matching at any position in str. Its a free=
<br>
+=C2=A0 =C2=A0 =C2=A0leading gap.=C2=A0 So set the first row of D (row -1) =
to 0.=C2=A0 */<br>
+=C2=A0 for (int j =3D 0; j < width; j++)<br>
+=C2=A0 =C2=A0 D[j] =3D 0;<br>
+<br>
+=C2=A0 int prev_gap_origin =3D -1;<br>
+<br>
+=C2=A0 /* Forward pass - compute M and D matrices (minimize cost).=C2=A0 *=
/<br>
+=C2=A0 for (int i =3D 0; i < m; i++)<br>
+=C2=A0 =C2=A0 {<br>
+=C2=A0 =C2=A0 =C2=A0 unsigned char pat_char =3D pat_data[i];<br>
+=C2=A0 =C2=A0 =C2=A0 int gap_origin =3D -1; /* Index of last match before =
a gap started */<br>
+<br>
+=C2=A0 =C2=A0 =C2=A0 MAT2 (M, i, -1) =3D pos_inf;<br>
+=C2=A0 =C2=A0 =C2=A0 MAT2 (D, i, -1) =3D pos_inf;<br>
+<br>
+=C2=A0 =C2=A0 =C2=A0 for (int j =3D 0; j < n; j++)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 {<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 unsigned char str_char =3D str_data[j];=
<br>
+<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Compute gap cost D[i][j].=C2=A0 */<b=
r>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 int from_match =3D MAT2 (M, i, j - 1) +=
gap_open_cost;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 int from_gap =3D MAT2 (D, i, j - 1) + g=
ap_extend_cost;<br>
+<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (from_match < from_gap)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0{<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0MAT2 (D, i, j) =3D from_ma=
tch;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gap_origin =3D j - 1;=C2=
=A0 /* New gap. */<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0MAT2 (D, i, j) =3D from_gap;=C2=
=A0 /* Extend gap.=C2=A0 */<br>
+<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Check if characters match (case-inse=
nsitive if needed).=C2=A0 */<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 bool chars_match;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (completion_ignore_case)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 chars_match =3D (downcase (pat_c=
har) =3D=3D downcase (str_char));<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 else<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 chars_match =3D (pat_char =3D=3D=
str_char);<br>
+<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Compute match cost M[i][j] (no cost =
for matching).=C2=A0 */<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 MAT2 (M, i, j) =3D pos_inf;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (chars_match)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 int prev_match =3D MAT2 (=
M, i - 1, j - 1);<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 int prev_gap =3D MAT2 (D,=
i - 1, j - 1);<br>
+<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (prev_match <=3D pr=
ev_gap)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 MAT2 (M, i,=
j) =3D prev_match;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 MAT (P, i, =
j) =3D j - 1;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 else<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 MAT2 (M, i,=
j) =3D prev_gap;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 MAT (P, i, =
j) =3D prev_gap_origin;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
+=C2=A0 =C2=A0 =C2=A0 prev_gap_origin =3D gap_origin;<br>
+=C2=A0 =C2=A0 }<br>
+<br>
+=C2=A0 /* Find best (lowest) cost in last row.=C2=A0 */<br>
+=C2=A0 int best_cost =3D pos_inf;<br>
+=C2=A0 int lastcol =3D -1;<br>
+<br>
+=C2=A0 for (int j =3D 0; j < n; j++)<br>
+=C2=A0 =C2=A0 {<br>
+=C2=A0 =C2=A0 =C2=A0 int cost =3D MAT2 (M, m - 1, j);<br>
+=C2=A0 =C2=A0 =C2=A0 if (cost < best_cost)<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 {<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 best_cost =3D cost;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 lastcol =3D j;<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
+=C2=A0 =C2=A0 }<br>
+<br>
+=C2=A0 if (lastcol < 0 || best_cost >=3D pos_inf)<br>
+=C2=A0 =C2=A0 return Qnil;<br>
+<br>
+=C2=A0 /* Normalize cost to penalize longer strings.=C2=A0 Lower is better=
.=C2=A0 */<br>
+=C2=A0 double normalized_cost =3D best_cost + (double) (n - m) / (double) =
m;<br>
+<br>
+=C2=A0 /* Build match positions list by tracing back through P matrix.=C2=
=A0 */<br>
+=C2=A0 Lisp_Object matches =3D Qnil;<br>
+=C2=A0 int k =3D lastcol;<br>
+<br>
+=C2=A0 for (int i =3D m - 1; i >=3D 0 && k >=3D 0; i--)<br>
+=C2=A0 =C2=A0 {<br>
+=C2=A0 =C2=A0 =C2=A0 matches =3D Fcons (make_fixnum (k), matches);<br>
+=C2=A0 =C2=A0 =C2=A0 k =3D MAT (P, i, k);<br>
+=C2=A0 =C2=A0 }<br>
+<br>
+#undef MAT2<br>
+#undef MAT<br>
+<br>
+=C2=A0 return Fcons (make_float (normalized_cost), matches);<br>
+}<br>
+<br>
=C2=A0void<br>
=C2=A0syms_of_minibuf (void)<br>
=C2=A0{<br>
@@ -2541,6 +2683,7 @@ syms_of_minibuf (void)<br>
=C2=A0 =C2=A0defsubr (&Stest_completion);<br>
=C2=A0 =C2=A0defsubr (&Sassoc_string);<br>
=C2=A0 =C2=A0defsubr (&Scompleting_read);<br>
+=C2=A0 defsubr (&Scompletion__flex_score_gotoh);<br>
=C2=A0 =C2=A0DEFSYM (Qminibuffer_quit_recursive_edit, "minibuffer-quit=
-recursive-edit");<br>
=C2=A0 =C2=A0DEFSYM (Qinternal_complete_buffer, "internal-complete-buf=
fer");<br>
=C2=A0 =C2=A0DEFSYM (Qcompleting_read_function, "completing-read-funct=
ion");<br>
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el<=
br>
index 79ffb1d3fc7..005d7c500d4 100644<br>
--- a/test/lisp/minibuffer-tests.el<br>
+++ b/test/lisp/minibuffer-tests.el<br>
@@ -205,11 +205,6 @@ completion-all-sorted-completions<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0'(=
"some/alpha" "base/epsilon" "base/delta"))<br=
>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 `("epsi=
lon" "delta" "beta" "alpha" "gamma&=
quot;=C2=A0 . 5))))<br>
<br>
-(defun completion--pcm-score (comp)<br>
-=C2=A0 "Get `completion-score' from COMP."<br>
-=C2=A0 ;; FIXME, uses minibuffer.el implementation details<br>
-=C2=A0 (completion--flex-score comp completion-pcm--regexp))<br>
-<br>
=C2=A0(defun completion--pcm-first-difference-pos (comp)<br>
=C2=A0 =C2=A0"Get `completions-first-difference' from COMP."<=
br>
=C2=A0 =C2=A0(cl-loop for pos =3D (next-single-property-change 0 'face =
comp)<br>
@@ -244,20 +239,11 @@ completion-pcm-test-2<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "barfoobar")))<br>
<br>
=C2=A0(ert-deftest completion-pcm-test-3 ()<br>
-=C2=A0 ;; Full match!<br>
-=C2=A0 (should (eql<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(completion--pcm-score<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (car (completion-pcm-all-complet=
ions<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "R&quo=
t; '("R" "hello") nil 1)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01.0)))<br>
+=C2=A0 (should (car (completion-pcm-all-completions<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "R" '=
;("R" "hello") nil 1))))<br>
<br>
=C2=A0(ert-deftest completion-pcm-test-4 ()<br>
-=C2=A0 ;; One fourth of a match and no match due to point being at the end=
<br>
-=C2=A0 (should (eql<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(completion--pcm-score<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (car (completion-pcm-all-complet=
ions<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "RO&qu=
ot; '("RaOb") nil 1)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(/ 1.0 4.0)))<br>
+=C2=A0 ;; No match due to point being at the end<br>
=C2=A0 =C2=A0(should (null<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (completion-pcm-all-completions<b=
r>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"RO" '("=
RaOb") nil 2))))<br>
@@ -420,24 +406,14 @@ completion-pcm-bug4219<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "a")))<br>
<br>
=C2=A0(ert-deftest completion-substring-test-1 ()<br>
-=C2=A0 ;; One third of a match!<br>
=C2=A0 =C2=A0(should (equal<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (car (completion-substring-all-co=
mpletions<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "foo&qu=
ot; '("hello" "world" "barfoobar") nil 3)=
)<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"barfoobar"))<br>
-=C2=A0 (should (eql<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(completion--pcm-score<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (car (completion-substring-all-c=
ompletions<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "foo&q=
uot; '("hello" "world" "barfoobar") nil 3=
)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(/ 1.0 3.0))))<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"barfoobar")))<br>
<br>
=C2=A0(ert-deftest completion-substring-test-2 ()<br>
-=C2=A0 ;; Full match!<br>
-=C2=A0 (should (eql<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(completion--pcm-score<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (car (completion-substring-all-c=
ompletions<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "R&quo=
t; '("R" "hello") nil 1)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01.0)))<br>
+=C2=A0 (should (car (completion-substring-all-completions<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "R" '=
;("R" "hello") nil 1))))<br>
<br>
=C2=A0(ert-deftest completion-substring-test-3 ()<br>
=C2=A0 =C2=A0;; Substring match<br>
@@ -504,11 +480,8 @@ completion-flex-test-1<br>
<br>
=C2=A0(ert-deftest completion-flex-test-2 ()<br>
=C2=A0 =C2=A0;; Full match!<br>
-=C2=A0 (should (eql<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(completion--pcm-score<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (car (completion-flex-all-comple=
tions<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "R&quo=
t; '("R" "hello") nil 1)))<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01.0)))<br>
+=C2=A0 (should (car (completion-flex-all-completions<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "R" '=
;("R" "hello") nil 1))))<br>
<br>
=C2=A0(ert-deftest completion-flex-test-3 ()<br>
=C2=A0 =C2=A0;; Another fuzzy match, but more of a "substring" on=
e<br>
</div>
--00000000000061872d0649ff9353--
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 4 Feb 2026 13:24:23 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Feb 04 08:24:23 2026 Received: from localhost ([127.0.0.1]:59762 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1vncrn-0004HD-Cx for submit <at> debbugs.gnu.org; Wed, 04 Feb 2026 08:24:23 -0500 Received: from mail-vs1-xe2d.google.com ([2607:f8b0:4864:20::e2d]:52615) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <shipmints@HIDDEN>) id 1vncrk-0004H3-CV for 80323 <at> debbugs.gnu.org; Wed, 04 Feb 2026 08:24:21 -0500 Received: by mail-vs1-xe2d.google.com with SMTP id ada2fe7eead31-5f53ba9c548so2064583137.1 for <80323 <at> debbugs.gnu.org>; Wed, 04 Feb 2026 05:24:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770211459; cv=none; d=google.com; s=arc-20240605; b=PgbGuB0SkykLSnfhGE8UJM48JCuio58xn6UB5xKqMO+EoO4ZVlmncwB0r5Lnc18Ahk BUfGgQT6z2RBQFn7lj/uekeGiq+HTw+YU8xVymRbXdgVE+vZngOLZo9hJ1ahYRPr2kUd ZEqRSGC4ir1CAaI1yVVTK4YRu2AFobhgJno47n0NDJoUT/AUy49vlRMzpBGK04uIrO9v 0bf96qEtMEgmpS8wHwczARcvlcjxUQfc1+VsZGfDIiXaJnB3+PgBdEdoax8f3Lg2wZ+5 lK7Iw5mzQY6yBHoZIVlxVV2uJGc0xBC4EqFtkbstjh48tsE+BQL6CCttfKa2McqyrOpb xUMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=qLPc1Wbrm/D9IyBDyctlZpnSaz7heNVzIujDvGSVKlc=; fh=pk5mIRRl0g3d9nnxiaarSEKfjkGUGJG8rEbe455p4NM=; b=I/Ks0WKvBY9WM353N9jHZi78FCWX2N6zLGU4v3f3ib6o5Pe+QIPE/Og+5hitXyew15 xUCBN4Iewzjnrrdt08Sm1lPRnBlI+gwkmm20W3jATKVQT5r2qxMCyEy3y54bErs7v7uV jzKzOS/kxicBA70T4hp89wMFzUFCevPxOCat1ed500p+2oqZtg73TnEypoOEwQh6qJO4 csHbk7YpQiNwVfka+1sN9ubv51ifKzArKke5arlogs6eRQ7uGAv2Mp8HKpOMOK92NEk4 OF3vSupVUTXS3KGwc5mwkraODpmZ4tNSgAxIR7ZK0mwtbuVFIv0NLtqtDsJO4JdUm13Q nDzA==; darn=debbugs.gnu.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770211459; x=1770816259; darn=debbugs.gnu.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=qLPc1Wbrm/D9IyBDyctlZpnSaz7heNVzIujDvGSVKlc=; b=XC4r6+dFi4/TrNoWReY69S8qAWIhonyWdR7wAINBAJ/vgjvj9z06A0IlorpAI5KLuU oNHh1SzP0g4mFFTRQ+ynos4uliuc23/KR4Nd3c0nwCc3UvHIfBNiE7ph6IRc491ZKFqR Zh3qu81b5Z4lU6iDBiVoSOhDkoxqZ97maEAEOwn6kAC6fJ7BAdQJGQDo7VkFa97Ugbdp A8iXGwIighT+PImDqTDm3si/ZTmd3JDnKwSiIDdTu3tQcFSdLOW12XZIYgtO1CHb9L0N FB1a1jrepyxostEgF9FORfgnuGdUpCZJ3JuRSJQaSDBCd+iofvMjHgnFV8If6AaEz3YC yYmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770211459; x=1770816259; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=qLPc1Wbrm/D9IyBDyctlZpnSaz7heNVzIujDvGSVKlc=; b=LTryNUx+lHNSGXP+Pyah1lIpFWPz4eZKjVuD3KqXU+hJQ9p/ITR2hPbJ4zYySBxaeF y5+h3Hnu/5qrQ/6UPc4x9Z0odI+NqBEfhE9eV/gGkmc4grhGGANiAnnltQTGTwUA5tIp PBew1mvTfsUqC9szEPzPGKhD+ME1s73pSykLpvCUmpw/NJewBiOYk8Ltm8UKs7p6coUT +1zpINYhsB5Ebo2siL4R7NzJwG1W2YuuTr7YnCJYfXXXvln/8ZOgZl+ZGRri7zQIka0h Pea1hfiG7Rd3r5m2K9e+MxqGHxc6C2F0iSCmNGTBErKoCfFaJttwQ3Bic9XVh5xhQ0ZA 1Y0g== X-Forwarded-Encrypted: i=1; AJvYcCVD4Xf/EhotnbH21l6mZZNHNUSitMende5K5A84iICQcC4NVO2ApUySeeeBKGjkRueJTGGIXA==@debbugs.gnu.org X-Gm-Message-State: AOJu0YwRdZke+U+z59HaZKrn2n2vEUT5NOPO4mIizw5PCp/AFysdYAFL T2OMyBqIRZwPkcGxe7ESSkiFrau2+P1+jqjGT9CiQPQGYi2EHqrB7KcikFaPuiPBub5Q7Vy9cz1 t4QTdopIXoJMWdQs2sacWiCy1jFqwkgw= X-Gm-Gg: AZuq6aIqgV7v4RAjT7hQsEvfBvpj7XhrZHEorJHDO7J8hl+p/QTRg1svqJUvr12Xegj 48RGxOdC0gh1vheQOGl6yJmPOZw+mp9AbpDceLfW2LTHofjKOhllgAuY/77rblw1yWI2zmjHyGj JchHjo2zEUn98BjuZCmd+ii74ExYLQmJB8cERwdLVhwBcp45W2GD9xTDHU+Zh/GGVUWGc0MFcly TCDQvXjjsU/Td8A4OaVuaIKk9BKKH5nU/S6YDUEdL2IwbaUXNWVAcSpCKIaogOeEPWFxMun79+N NrbU5wBAxPW3Nz7E6yqxWorKlxnN2l0P48qbgopyVCdcM6nBlBS0BuZU8Nk7ow== X-Received: by 2002:a05:6102:3584:b0:5f5:2539:9b05 with SMTP id ada2fe7eead31-5f93961dbe9mr821437137.41.1770211459557; Wed, 04 Feb 2026 05:24:19 -0800 (PST) MIME-Version: 1.0 References: <87y0la2egy.fsf@HIDDEN> <87ms1q9bpq.fsf@HIDDEN> <CAN+1HbrAG_1YF4UzOyY_ARWzhKHsWCMaxgWb1qp8Rg1sq4SjVg@HIDDEN> <87zf5p7362.fsf@HIDDEN> <87qzr08yni.fsf@HIDDEN> <CALDnm50pn2rgD+K=gyr9Cj-iZy_rMFDmBRmHkT5P84hiVxaQnw@HIDDEN> In-Reply-To: <CALDnm50pn2rgD+K=gyr9Cj-iZy_rMFDmBRmHkT5P84hiVxaQnw@HIDDEN> From: =?UTF-8?Q?St=C3=A9phane_Marks?= <shipmints@HIDDEN> Date: Wed, 4 Feb 2026 08:24:08 -0500 X-Gm-Features: AZwV_Qi7o-OWxtvz3hNq9BjlNy7HvrmvJefkBQhJ8h_kIUoEHrH_zWdp2OR0vyc Message-ID: <CAN+1Hbo7ce95DpN0BVjFxZ-69d7CTEUW7mY-JjD8OYv4amivZw@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm To: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> Content-Type: multipart/alternative; boundary="000000000000396f330649ff79df" X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 80323 Cc: 80323 <at> debbugs.gnu.org, Stefan Monnier <monnier@HIDDEN>, Sean Whitton <spwhitton@HIDDEN> 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.0 (/) --000000000000396f330649ff79df Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Wed, Feb 4, 2026 at 8:09=E2=80=AFAM Jo=C3=A3o T=C3=A1vora <joaotavora@gm= ail.com> wrote: > Seems like my patch is too naive regarding wide chars. Gotta fix that. > What's the recommended way to iterate such strings in C code? > IIRC, you can model something like in search.c look for references to string_char_and_length. I'm sure I'll be corrected if wrong. --000000000000396f330649ff79df Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div dir=3D"ltr"><div class=3D"gmail_default" style=3D"fon= t-family:monospace"><span style=3D"font-family:Arial,Helvetica,sans-serif">= On Wed, Feb 4, 2026 at 8:09=E2=80=AFAM Jo=C3=A3o T=C3=A1vora <<a href=3D= "mailto:joaotavora@HIDDEN">joaotavora@HIDDEN</a>> wrote:</span></d= iv></div><div class=3D"gmail_quote gmail_quote_container"><blockquote class= =3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rg= b(204,204,204);padding-left:1ex"><div dir=3D"auto"><div>Seems like my patch= is too naive regarding wide chars. Gotta fix that. What's the recommen= ded way to iterate such strings in C code?</div></div></blockquote><div><br= ></div><div class=3D"gmail_default" style=3D"font-family:monospace">IIRC, y= ou can model something like in search.c look for references to string_char_= and_length.=C2=A0 I'm sure I'll be corrected if wrong.</div></div><= /div> --000000000000396f330649ff79df--
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 4 Feb 2026 13:08:25 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Feb 04 08:08:25 2026 Received: from localhost ([127.0.0.1]:59623 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1vnccK-0003W9-H9 for submit <at> debbugs.gnu.org; Wed, 04 Feb 2026 08:08:24 -0500 Received: from mail-oa1-x2e.google.com ([2001:4860:4864:20::2e]:58585) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>) id 1vnccF-0003Vt-HW for 80323 <at> debbugs.gnu.org; Wed, 04 Feb 2026 08:08:22 -0500 Received: by mail-oa1-x2e.google.com with SMTP id 586e51a60fabf-408778a8ec4so4433474fac.0 for <80323 <at> debbugs.gnu.org>; Wed, 04 Feb 2026 05:08:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770210498; cv=none; d=google.com; s=arc-20240605; b=XMsTpf1taFQubseR92GGDjq3QrNO5WidlGBQcDU+SXGOfx38yFmgNiE20Wx80y54V7 4j0rNwFaRgjZ9NIfoXLRWv7xR2F9QAylqlXFF8vsT8cy1av9vwnELisCPHe2al164Mp2 FszhWQqPjXYheYKvi2c1oDizZE9LWZI3WMyKzyXr9HB853cmYzqh2JYvNQ/C6ukYA7IV IWDWkAzwy2+98bAzFG58sF8zYczdvI4YgJRRAJwtObQM4fj7jJ8Pd8U2HiA2jWZbw4sT /IJ+20FqosV7h2Rp/r0cu2HBsSthU7bCH9hCJJrK5oDbmqWuZth98cjy3JZ7JLWRog3L WEDA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=eMEqcg0B0McpApmnmN+dMLY6U6+XczPWgFVFnxQoUws=; fh=b0B+DO3GdeQedSoRkdb4/yKupAjiRatcjSUdrQuQllM=; b=ZHvA8Hdf3LrQxqvFju3MFZmS2B8Gj7kMCe35w4hGdG6RfeVeLz5RAAHkU2Z7B1OqwF otq0tV89xTpImeaZMZ7ObvtgV814HQ1OK59AkrCEMCzldCMm6eX5VZ7qumevTIq3tfX1 5O8wVnW4xaKVE3MP6FyJrtEsOqueNRo0mZka6hn6PMRYCkCQS4LPR5PwzOyulIrB8Ida 4oUnIxXBwVbtpjIZ/UITI+h01QPM6u9lknAQf0ewCMxHGF5QvLkkwB0JX7jwRlgEqm3j TVaz/YPgzFO5r92k99V7e2AIIgH0qXyRgoH3CNUWA7+haiUrifuTege8qdJT+d0lWrin gIZg==; darn=debbugs.gnu.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770210498; x=1770815298; darn=debbugs.gnu.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=eMEqcg0B0McpApmnmN+dMLY6U6+XczPWgFVFnxQoUws=; b=gbvDwqxlh+f8eeaZf1oXcMmHymVuC1tRtSSz2NBJ26koH78XZWESFQrzUNJpIDBBta K4jxWBUTBza32AYy8bsQWEiZSYV8mItyo0Hc5wWOfHDst/sFezEwiJsZ+xR+jon+zMjv TpXce6yz3UipqvxqQ5th4Ijok5e7vYdjWjCdbiC+lmJsOuuzecxqj0VuO23vo4bnb3lw 2sbYNmCD0kPrrnMHtiAdP4Yyqjkw12kSMgMVqELQW+XcxTVwpHE0cMiB2G5zXmPJeATs IOgFbw3sO91756llhT8SgjPZ7Lt/HwzG6oM8Av99z7s5cT28lcJ97310cHYKwXAvhho8 iN5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770210498; x=1770815298; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=eMEqcg0B0McpApmnmN+dMLY6U6+XczPWgFVFnxQoUws=; b=JRvyBvTy+yZnjebzjI8DKiRvhWz0ZWwbbQlwN3w8JoKl5y54DrfzZh3lCeoASve2U5 S6jASKBjLaV1c9SQ7e0buUnqi3cESUuyfSGsjg9VslRuQbzbQFB4LVCKP4zq/k30r8CD wNudkRAdl5GWK67wPEqoDwq7Ms38H3CojwD2tO57iHUQJy3GTJotF+W3or7aKdxsQ5FK 3SKbyFKQMGRN9X5D97oC9ezF3UNJ1w43kbivTd50tZ17CiMfZ+0Hf1qc8OjBs+soOuPn x98MP3WveGRMwOaFXLH3OWnfGXz4Zw7Kwr1QeTN174a+9cTELesJWxxmPeW3FEU/zsrJ 76+Q== X-Forwarded-Encrypted: i=1; AJvYcCWy+aadoejBJTpRNCep+OVyOfxWwJO8IfIbCw85TqMpRo/HaXNdV/5hMA/19sp6UJvbNYDfqA==@debbugs.gnu.org X-Gm-Message-State: AOJu0YwD+6qROa4RFRHE1TS9w05rLKeEUHTEGF6/D9pcDt998vmlzwn3 5ypUZ1seUFuFV4ZudCBqvgcyqf2t5XiGeQYqSvek34tuLbUe+cA0dzTN7ptzf0XELaB1I8snXNW LrgRdxWoUh3IY7Ak7p7WXwOTeUa4QXEk= X-Gm-Gg: AZuq6aIrXAIZRRx7/suBQhIv+b46WWBDK9Ij3WyRU1B12hwMtb227Fp4XVapG62vXv6 6DFY37EpF6SoWVR9Ko9DCgoqsOC14HGWGLyN/HhoXCjug7/Yueuht9xCvdHKQ98ZBPqBQbbVaLH FYtbIXWN8ewDbzCUBbw+Qrd/zvUMm0OKVGRhEJ3bcWJJ+rVakkfBEZDtAeedjEYzDvVXZgaF8hX PM5Ul+9gpHkHS+gkxGxnmcFODY7oaToYG3isQTaINC+Vn1ecL3dujXN5cO5qPkbdwlduuA= X-Received: by 2002:a05:6820:80e:b0:663:117c:fe05 with SMTP id 006d021491bc7-66a2342dc7bmr1355398eaf.57.1770210498224; Wed, 04 Feb 2026 05:08:18 -0800 (PST) MIME-Version: 1.0 References: <87y0la2egy.fsf@HIDDEN> <87ms1q9bpq.fsf@HIDDEN> <CAN+1HbrAG_1YF4UzOyY_ARWzhKHsWCMaxgWb1qp8Rg1sq4SjVg@HIDDEN> <87zf5p7362.fsf@HIDDEN> <87qzr08yni.fsf@HIDDEN> In-Reply-To: <87qzr08yni.fsf@HIDDEN> From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> Date: Wed, 4 Feb 2026 13:07:44 +0000 X-Gm-Features: AZwV_QhJvNMm9XY6yn2ryjVCXVkngD6m5Yio-DcdW5je8tjjaclvY6KMUsIjGlk Message-ID: <CALDnm50pn2rgD+K=gyr9Cj-iZy_rMFDmBRmHkT5P84hiVxaQnw@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm To: Sean Whitton <spwhitton@HIDDEN> Content-Type: multipart/alternative; boundary="000000000000eca7890649ff3f4e" X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 80323 Cc: Stefan Monnier <monnier@HIDDEN>, 80323 <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: 0.0 (/) --000000000000eca7890649ff3f4e Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Seems like my patch is too naive regarding wide chars. Gotta fix that. What's the recommended way to iterate such strings in C code? Jo=C3=A3o T=C3=A1vora On Wed, Feb 4, 2026, 12:46 Sean Whitton <spwhitton@HIDDEN> wrote: > Hello, > > I've identified a regression. > When I use org-refile the candidates list can get stuck and > icomplete-forward-completions and icomplete-backward-completions stop > working. > > I try to type "Debiandevel" seeking to match "Debian.org/Development". > I get an error in *Messages*. I've pared down the CC list because it > contains personal information; please take care when replying: > > Error in post-command-hook (icomplete-post-command-hook): (error "Pattern > Deb does not match japanese.org/Development/Returning to Japanese/Ask > =E7=9F=B3=E5=B7=9D=E5=85=88=E7=94=9F to send out advert a second time as = semester begins/") > completion--flex-score: Pattern Debian does not match > RepeatedTasks.org/=E6=AF=8E=E6=97=A5=E3=81=AE=E3=82=A2=E3=82=B8=E3=82=A2= =E8=AA=9E/Anki reviews (after back on basic kanji, I > think)/ [12 times] > > -- > Sean Whitton > --000000000000eca7890649ff3f4e Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"auto"><div>Seems like my patch is too naive regarding wide char= s. Gotta fix that. What's the recommended way to iterate such strings i= n C code?</div><div><br></div><div data-smartmail=3D"gmail_signature">Jo=C3= =A3o T=C3=A1vora</div></div><br><div class=3D"gmail_quote gmail_quote_conta= iner"><div dir=3D"ltr" class=3D"gmail_attr">On Wed, Feb 4, 2026, 12:46 Sean= Whitton <<a href=3D"mailto:spwhitton@HIDDEN">spwhitton@spwhitto= n.name</a>> wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"m= argin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left= :1ex">Hello,<br> <br> I've identified a regression.<br> When I use org-refile the candidates list can get stuck and<br> icomplete-forward-completions and icomplete-backward-completions stop<br> working.<br> <br> I try to type "Debiandevel" seeking to match "Debian.org/Dev= elopment".<br> I get an error in *Messages*.=C2=A0 I've pared down the CC list because= it<br> contains personal information; please take care when replying:<br> <br> Error in post-command-hook (icomplete-post-command-hook): (error "Patt= ern Deb does not match <a href=3D"http://japanese.org/Development/Returning= " rel=3D"noreferrer noreferrer" target=3D"_blank">japanese.org/Development/= Returning</a> to Japanese/Ask =E7=9F=B3=E5=B7=9D=E5=85=88=E7=94=9F to send = out advert a second time as semester begins/")<br> completion--flex-score: Pattern Debian does not match RepeatedTasks.org/=E6= =AF=8E=E6=97=A5=E3=81=AE=E3=82=A2=E3=82=B8=E3=82=A2=E8=AA=9E/Anki reviews (= after back on basic kanji, I think)/ [12 times]<br> <br> -- <br> Sean Whitton<br> </blockquote></div> --000000000000eca7890649ff3f4e--
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.Received: (at 80323) by debbugs.gnu.org; 3 Feb 2026 13:51:57 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Feb 03 08:51:57 2026 Received: from localhost ([127.0.0.1]:45114 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1vnGov-0008Fs-8K for submit <at> debbugs.gnu.org; Tue, 03 Feb 2026 08:51:57 -0500 Received: from sendmail.purelymail.com ([34.202.193.197]:48284) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <spwhitton@HIDDEN>) id 1vnGot-0008FE-4s for 80323 <at> debbugs.gnu.org; Tue, 03 Feb 2026 08:51:56 -0500 DKIM-Signature: a=rsa-sha256; b=N00y2v7YqBCUmuJX+FgB1ZurQI25aYJLqaAfS2slTifGxYwPgVBbL/ecIIxf0nggddYL5qEf6Fm4ZfmUulaGsHbbQmDejO+PZOyts/ubH9ZY9MIu0NnSsN4z+R37/E8tqOgjMg3uS15RU5Y5WxJ50T8tgpTXA6F9wuD2QjNpwsh0P7oYD41sax4dxI/zEFAk1bBtP3qj1yn4OGRzq89yEABGeMTnaNVX7QutbQRA7GA0L8JICWyiEo+1pM2WjlbI80T4oiKSWplWXrw5oSdf0oDh/2Y2gKJ024PAcM7o5RC4Fb+Iam97MoQZsAZRPLVUrn07QpW7uVxei76+Wb3qnQ==; s=purelymail2; d=spwhitton.name; v=1; bh=17csVbrBLSxFgQf3CfqNcrOIk2n9M7Ec02yOVVflPm8=; h=Received:Received:From:To:Subject:Date; DKIM-Signature: a=rsa-sha256; b=qGVdCZtbGMJOUKFH6XsQTgji5SPPgqK5bFWgE2lB9c5xT2eNMXtSgnKaj8J9034eVhKMlj6ybzp6HUUpLcBqkJlUOicstA/GVC+UV7eUkmdDFgGwvqyI1G5iZgh2nLfePSEmgXuilxv44AWHLG5aOcxm9mpSqsOJiNPLbwSy5b5LQa8Ny7HZGMb3UB1Rl4x2YOdLSCzMqexShyGyDX8hsTWsn8OMcS60PiX6m4Jj5ytsG496B/duwnJUoGyyncu+TEw0slzN8/q5BHYGxmLXXg0OudAoTQJKB3Ow3Co5q79MWjROCeklyLrgu/08Sa7CT0C7dXQYQbgDV90Q3JVzBA==; s=purelymail2; d=purelymail.com; v=1; bh=17csVbrBLSxFgQf3CfqNcrOIk2n9M7Ec02yOVVflPm8=; h=Feedback-ID:Received:Received:From:To:Subject:Date; Feedback-ID: 20115:3760:null:purelymail X-Pm-Original-To: 80323 <at> debbugs.gnu.org Received: by smtp.purelymail.com (Purelymail SMTP) with ESMTPSA id 600957282; (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384); Tue, 03 Feb 2026 13:51:46 +0000 (UTC) Received: by melete.silentflame.com (Postfix, from userid 1000) id 7A80C7E018C; Tue, 03 Feb 2026 13:51:45 +0000 (GMT) From: Sean Whitton <spwhitton@HIDDEN> To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN> Subject: Re: bug#80323: [PATCH] Rewrite flex completion scoring with Gotoh algorithm In-Reply-To: <87y0la2egy.fsf@HIDDEN> References: <87y0la2egy.fsf@HIDDEN> Date: Tue, 03 Feb 2026 13:51:45 +0000 Message-ID: <87ms1q9bpq.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 80323 Cc: axel@HIDDEN, 80323 <at> debbugs.gnu.org, monnier@HIDDEN 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, Jo=C3=A3o T=C3=A1vora [03/Feb 12:34pm GMT] wrote: > The greedy regexp matching, broken scoring and broken highlight were > sources of frequent complaints about the 'flex' completion style. The > origin flex, created by me, was a naive half-decent algorithm to score > so-called PCM pattern matches on completion candidates, to emulate the > fuzzy searches found ubiqutously in the wild. It served me and maybe > others well for a number of years, but the annoyances are very real. > > The patch I'm attaching fixes them for good. Thanks. I use flex, so I'll install this locally right away, and see if I notice any anomalies over the next few weeks. Other people would be better qualified to comment on the implementation. --=20 Sean Whitton
bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.
Received: (at submit) by debbugs.gnu.org; 3 Feb 2026 12:34:29 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Tue Feb 03 07:34:29 2026
Received: from localhost ([127.0.0.1]:44122 helo=debbugs.gnu.org)
by debbugs.gnu.org with esmtp (Exim 4.84_2)
(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
id 1vnFbw-0001Uy-1f
for submit <at> debbugs.gnu.org; Tue, 03 Feb 2026 07:34:29 -0500
Received: from lists.gnu.org ([2001:470:142::17]:38226)
by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
(Exim 4.84_2) (envelope-from <joaotavora@HIDDEN>)
id 1vnFbt-0001Ui-BQ
for submit <at> debbugs.gnu.org; Tue, 03 Feb 2026 07:34:26 -0500
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 <joaotavora@HIDDEN>)
id 1vnFbm-0007QE-NU
for bug-gnu-emacs@HIDDEN; Tue, 03 Feb 2026 07:34:18 -0500
Received: from mail-wm1-x32a.google.com ([2a00:1450:4864:20::32a])
by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)
(Exim 4.90_1) (envelope-from <joaotavora@HIDDEN>)
id 1vnFbj-0001if-VM
for bug-gnu-emacs@HIDDEN; Tue, 03 Feb 2026 07:34:18 -0500
Received: by mail-wm1-x32a.google.com with SMTP id
5b1f17b1804b1-47ee07570deso46765355e9.1
for <bug-gnu-emacs@HIDDEN>; Tue, 03 Feb 2026 04:34:15 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20230601; t=1770122054; x=1770726854; darn=gnu.org;
h=content-transfer-encoding:mime-version:message-id:date:subject:to
:from:from:to:cc:subject:date:message-id:reply-to;
bh=w6WT4OyJPCnljCKH1DlR7raevSQZRr7h99rfQ1Kw4lM=;
b=dP4ZQgF6Jrp2fcUCo1KpQycI8h7ej+kHsI9Odqvll2tmjpYmElV2OixhZi0j1cp+6u
URqj9saGCTX8CpKlHBnEjWkmPBFMIwbWDLS8DS8S7UkJI+rKW7368svx91rVnLVb/C0N
+jzP8qzfTwvHwvJrbDDU+clDe34zGa7rpOIikyS3UfTk8zFDGC05yF4U+vh2Si+zJIZs
qvm61Q8HKPNzu8L2rvW494J89sXxBd5qiEL+Mzd1WNm6+5ojRUTp9fBtzqRjFnJGgS5D
x3JcHazzHjvjITougG7XhyqDvumdfUayWlJdyXAl4xdUqhX5mgunHv1YaJXCwZ27afX8
3g5w==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20230601; t=1770122054; x=1770726854;
h=content-transfer-encoding:mime-version:message-id:date:subject:to
:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id
:reply-to;
bh=w6WT4OyJPCnljCKH1DlR7raevSQZRr7h99rfQ1Kw4lM=;
b=BL7jMiFkRwwSr9p04XkFHoxX7SCqyUxfn20/KpQWJFDt88qBmkENoXIy5bUJipbWfh
tUX8tbd6ZfPef5DYslVLs+RZBbg5Ml7FTRjYcUCTwnUYB1hiRysFp6nC4KEecgXVDVs/
dV1E6ldoZICmmfK6V5pNZnOTW9rmTT1ber/cVcxCXyULAJYpGUr7yDtajf/wgOrCPQGX
QnrT5SAeSpBER4IMle9vbuNvUsf0+NmUSJPIM+MoaxOoBhvbJbgLv7drqPyuaWqUrXvf
OWK1+XxX8CpJGJo57gUzV3FNUBcSSbo2pbXEgCkbXHKNn2bvIon68WwIC9Y6SMgegTMD
xLHA==
X-Gm-Message-State: AOJu0YzA/0UXT8llC16tTUKZXVTmuRrHmX9DvjTmfIAfBKFzVgNZLYSA
JUulVqUjNncCBkDdHKAWAP3HWO7JBt729qC/lc2fEG6EU8vxnI4QehXu
X-Gm-Gg: AZuq6aKR+997W+GpJH79PDpwLmq0O6jtku5IvZGZqC6mwI7r2iLx4bnXpTQcJTYhIao
JP4FsCx0ou0mi8I4DIudzFffqfOvM4jVM8fzyuhIGdBt3zXhMHRTImqyHtmn9SiR93YHHpORvp9
DfDB2JvNh6AdV+Fvt4cY32m3X1/w2C/B2P3S6TWSzPsDOeiusGOu0pepSZtUDrSNVZ916Kfsnli
Dkn190gafrDyfOJSD8hT8EiemR8KkTdoF4fHClMsDYptPiIeh7YB4DvVA1sQBkXolktRRtrRxQv
xR+556GzCCUpZHYLuqQzUF+hUD2Il4Pu6agtDtUo5WtMizte6pRs0GbJ40wKrn5UlDFzPyZO2T2
iLe3XQwjteL9bxYWRvjPfXOOMmAQfv5CdxEAl7EZT3+9AY4CAdhDct998ES0ZlhCdEtYYUE7JJj
+z9pydDxl0I1qzCEdmKZlQkp48wA==
X-Received: by 2002:a05:600c:3155:b0:47e:e9bf:dd8a with SMTP id
5b1f17b1804b1-482db4b5a1dmr186768915e9.37.1770122053393;
Tue, 03 Feb 2026 04:34:13 -0800 (PST)
Received: from krug (87-196-74-61.net.novis.pt. [87.196.74.61])
by smtp.gmail.com with ESMTPSA id
ffacd0b85a97d-436143d81desm3657235f8f.42.2026.02.03.04.34.11
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Tue, 03 Feb 2026 04:34:12 -0800 (PST)
From: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= <joaotavora@HIDDEN>
To: bug-gnu-emacs@HIDDEN, monnier@HIDDEN, axel@HIDDEN
Subject: [PATCH] Rewrite flex completion scoring with Gotoh algorithm
Date: Tue, 03 Feb 2026 12:34:05 +0000
Message-ID: <87y0la2egy.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Received-SPF: pass client-ip=2a00:1450:4864:20::32a;
envelope-from=joaotavora@HIDDEN; helo=mail-wm1-x32a.google.com
X-Spam_score_int: -20
X-Spam_score: -2.1
X-Spam_bar: --
X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,
DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001,
RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,
SPF_PASS=-0.001 autolearn=ham autolearn_force=no
X-Spam_action: no action
X-Spam-Score: 2.0 (++)
X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org",
has NOT identified this incoming email as spam. The original
message has been attached to this so you can view it or label
similar future email. If you have any questions, see
the administrator of that system for details.
Content preview: Hi, The greedy regexp matching, broken scoring and broken
highlight were sources of frequent complaints about the 'flex' completion
style. The origin flex, created by me, was a naive half-decent algorithm [...]
Content analysis details: (2.0 points, 10.0 required)
pts rule name description
---- ---------------------- --------------------------------------------------
-0.0 SPF_HELO_PASS SPF: HELO matches SPF record
-0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/,
no trust [2001:470:142:0:0:0:0:17 listed in] [list.dnswl.org]
0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail
provider (joaotavora[at]gmail.com)
1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail)
1.0 FORGED_GMAIL_RCVD 'From' gmail.com does not match 'Received'
headers
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: 1.0 (+)
Hi,
The greedy regexp matching, broken scoring and broken highlight were
sources of frequent complaints about the 'flex' completion style. The
origin flex, created by me, was a naive half-decent algorithm to score
so-called PCM pattern matches on completion candidates, to emulate the
fuzzy searches found ubiqutously in the wild. It served me and maybe
others well for a number of years, but the annoyances are very real.
The patch I'm attaching fixes them for good.
It was inspired by the 'hotfuzz' style available at
https://github.com/axelf4/hotfuzz which a modified version of Gotoh's
1982 dynamic programming algorithm (see: GOTOH, Osamu. An improved
algorithm for matching biological sequences. Journal of molecular
biology, 1982, 162.3: 705-708.). That style is more sophisticated than
'flex' (has special rules for matching things at word boundaries, a C
module with multhreading support). It's _almost_ void of hacks or
problems (see [1]) so its code would make a good candidate to replace
'flex' entirely, but no progress has been made in getting it into
Emacs's core in over 2 years...
The new 'flex' implementation also uses the Gotoh algorithm (apparently
a common choice for these kinds of task) and happens mostly in a new C
function. The algorithm isn't easy to understand, and I'm not a
mathematician, so at a certain point I was coding it a bit on a
trial-and-error basis. But it can be understood with some effort, and
at age 44 it's not exactly a revolutionary approach. I can add source
code comments to clear up any doubts about how it works.
This is strictly better than the "old" flex in correctness. For
example, when matching the pattern "goto" to, say, "eglot--goto" and
"eglot--bol", no longer is the latter returned first, which was a
substantial annoyance. And of course the highlighting is also correctly
placed on the "goto" not scattered in the main string.
Regarding performance, it seems to be slightly slower than the naive
Elisp 'flex'. It seems to be on-par with 'hotfuzz', if not slightly
faster. The reason I write "seems" is that it isn't easy at all to
benchmark styles. There's no single function to call that will show how
fast a given style matches, sorts and highlights when used via a
real-world frontend. A possible way is to place a 'benchmark-progn'
inside a completion frontend, like in icomplete.el's call to
'completion-all-sorted-completions'. But I can provide some naive
benchmark code too.
There may still be some speed improvements that can be made, like not
backtracking to understand the matching path when it isn't needed. And
perhaps other clever ones. In regards to memory usage it could also use
slightly smaller tables (currently three 64K float matrixes are used).
Although this uses statically allocated arrays already, so I thought
it's best to keep it relatively simple.
[1]: https://github.com/axelf4/hotfuzz/issues/16#issuecomment-2091181666
Jo=C3=A3o
And now the patch
* src/minibuf.c (completion--flex-score-gotoh): New function.
Implement Gotoh algorithm with dynamic programming to compute
optimal alignment score and match positions.
(syms_of_minibuf): Tweak.
(math.h): Include.
* lisp/minibuffer.el (completion--flex-score): Rework extensively.
Return (score . matches) without side effects.
(completion--flex-propertize): New function. Handle face
propertization with proper segment-based position calculation.
(completion--highlight-from-re): Delete.
(flex-score-match-tightness): Obsolete.
(completion-pcm--hilit-commonality): Rework. No longer use regular
expressions at all.
(completion-flex--make-flex-pattern): Extract score from cons before
negating for sort.
* test/lisp/minibuffer-tests.el (completion--pcm-score): Update to
extract score from cons return value. (completion-pcm-test-4): Remove
unreasonable scoring expectation from old flex
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index fc193fe54f0..088297b3f45 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -4450,18 +4450,12 @@ completion-pcm--all-completions
(when (string-match-p regex c) (push c poss)))
(nreverse poss))))))
=20
-(defvar flex-score-match-tightness 3
- "Controls how the `flex' completion style scores its matches.
-
-Value is a positive number. A number smaller than 1 makes the
-scoring formula reward matches scattered along the string, while
-a number greater than one make the formula reward matches that
-are clumped together. I.e \"foo\" matches both strings
-\"fbarbazoo\" and \"fabrobazo\", which are of equal length, but
-only a value greater than one will score the former (which has
-one large \"hole\" and a clumped-together \"oo\" match) higher
-than the latter (which has two \"holes\" and three
-one-letter-long matches).")
+(defvar flex-score-match-tightness nil)
+
+(make-obsolete-variable
+ 'flex-score-match-tightness
+ "It never did anything very useful anyway."
+ "31.0")
=20
(defvar completion-lazy-hilit nil
"If non-nil, request lazy highlighting of completion candidates.
@@ -4502,133 +4496,45 @@ completion-lazy-hilit
(funcall completion-lazy-hilit-fn (copy-sequence str))
str))
=20
-(defun completion--hilit-from-re (string regexp &optional point-idx)
- "Fontify STRING using REGEXP POINT-IDX.
-Uses `completions-common-part' and `completions-first-difference'
-faces to fontify STRING.
-POINT-IDX is the position of point in the presumed \"PCM\" pattern
-from which REGEXP was generated."
- (let* ((md (and regexp (string-match regexp string) (cddr (match-data t)=
)))
- (pos (if point-idx (match-beginning point-idx) (match-end 0)))
- (me (and md (match-end 0)))
- (from 0))
- (while md
- (add-face-text-property from (pop md)
- 'completions-common-part nil string)
- (setq from (pop md)))
- (if (and (numberp pos) (> (length string) pos))
- (add-face-text-property
- pos (1+ pos)
- 'completions-first-difference
- nil string))
- (unless (or (not me) (=3D from me))
- (add-face-text-property from me 'completions-common-part nil string))
- string))
-
-(defun completion--flex-score-1 (md-groups match-end len)
- "Compute matching score of completion.
-The score lies in the range between 0 and 1, where 1 corresponds to
-the full match.
-MD-GROUPS is the \"group\" part of the match data.
-MATCH-END is the end of the match.
-LEN is the length of the completion string."
- (let* ((from 0)
- ;; To understand how this works, consider these simple
- ;; ascii diagrams showing how the pattern "foo"
- ;; flex-matches "fabrobazo", "fbarbazoo" and
- ;; "barfoobaz":
-
- ;; f abr o baz o
- ;; + --- + --- +
-
- ;; f barbaz oo
- ;; + ------ ++
-
- ;; bar foo baz
- ;; +++
-
- ;; "+" indicates parts where the pattern matched. A
- ;; "hole" in the middle of the string is indicated by
- ;; "-". Note that there are no "holes" near the edges
- ;; of the string. The completion score is a number
- ;; bound by (0..1] (i.e., larger than (but not equal
- ;; to) zero, and smaller or equal to one): the higher
- ;; the better and only a perfect match (pattern equals
- ;; string) will have score 1. The formula takes the
- ;; form of a quotient. For the numerator, we use the
- ;; number of +, i.e. the length of the pattern. For
- ;; the denominator, it first computes
- ;;
- ;; hole_i_contrib =3D 1 + (Li-1)^(1/tightness)
- ;;
- ;; , for each hole "i" of length "Li", where tightness
- ;; is given by `flex-score-match-tightness'. The
- ;; final value for the denominator is then given by:
- ;;
- ;; (SUM_across_i(hole_i_contrib) + 1) * len
- ;;
- ;; , where "len" is the string's length.
- (score-numerator 0)
- (score-denominator 0)
- (last-b 0))
- (while (and md-groups (car md-groups))
- (let ((a from)
- (b (pop md-groups)))
- (setq
- score-numerator (+ score-numerator (- b a)))
- (unless (or (=3D a last-b)
- (zerop last-b)
- (=3D a len))
- (setq
- score-denominator (+ score-denominator
- 1
- (expt (- a last-b 1)
- (/ 1.0
- flex-score-match-tightness)))))
- (setq
- last-b b))
- (setq from (pop md-groups)))
- ;; If `pattern' doesn't have an explicit trailing any, the
- ;; regex `re' won't produce match data representing the
- ;; region after the match. We need to account to account
- ;; for that extra bit of match (bug#42149).
- (unless (=3D from match-end)
- (let ((a from)
- (b match-end))
- (setq
- score-numerator (+ score-numerator (- b a)))
- (unless (or (=3D a last-b)
- (zerop last-b)
- (=3D a len))
- (setq
- score-denominator (+ score-denominator
- 1
- (expt (- a last-b 1)
- (/ 1.0
- flex-score-match-tightness)))))
- (setq
- last-b b)))
- (/ score-numerator (* len (1+ score-denominator)) 1.0)))
-
-(defvar completion--flex-score-last-md nil
- "Helper variable for `completion--flex-score'.")
-
-(defun completion--flex-score (str re &optional dont-error)
- "Compute flex score of completion STR based on RE.
-If DONT-ERROR, just return nil if RE doesn't match STR."
- (let ((case-fold-search completion-ignore-case))
- (cond ((string-match re str)
- (let* ((match-end (match-end 0))
- (md (cddr
- (setq
- completion--flex-score-last-md
- (match-data t completion--flex-score-last-md)))))
- (completion--flex-score-1 md match-end (length str))))
- ((not dont-error)
- (error "Internal error: %s does not match %s" re str)))))
-
-(defvar completion-pcm--regexp nil
- "Regexp from PCM pattern in `completion-pcm--hilit-commonality'.")
+(cl-defun completion--flex-score (pat str &optional dont-error)
+ "Compute flex score of STR matching PAT. If DONT-ERROR,
+return nil if PAT cannot match STR. Returns (SCORE . MATCHES) where
+SCORE is a float and MATCHES is a list of match positions in STR."
+ (or (completion--flex-score-gotoh pat str)
+ (unless dont-error
+ (error "Pattern %s does not match %s" pat str))))
+
+(defun completion--flex-propertize (str matches point-idx segments)
+ "Add completion faces to STR based on MATCHES and POINT-IDX.
+MATCHES is a list of match positions. POINT-IDX is a match group index
+from the PCM pattern. SEGMENTS are extracted from the full PCM pattern.
+Adds `completions-common-part' for matched positions and
+`completions-first-difference' for the position corresponding to point."
+ (when point-idx
+ ;; Compute character position from segments
+ (let* ((pos (cl-loop for seg in segments
+ for i from 1
+ while (<=3D i point-idx)
+ sum (length (car seg)))))
+ ;; Add first-difference after pos-th match, if in range
+ (let ((point-match (and (> pos 0)
+ (<=3D pos (length matches))
+ (nth (1- pos) matches))))
+ (when (and point-match (< (1+ point-match) (length str)))
+ (add-face-text-property
+ (1+ point-match) (+ 2 point-match)
+ 'completions-first-difference nil str)))))
+ ;; Highlight matched positions
+ (dolist (pos matches)
+ (add-face-text-property pos (1+ pos)
+ 'completions-common-part
+ nil str))
+ str)
+
+(defvar completion-flex--pattern-str nil
+ "Pattern string for flex completion scoring.
+This is the concatenated string parts from the PCM pattern,
+used by `completion--flex-score' for Gotoh algorithm matching.")
=20
(defun completion-pcm--hilit-commonality (pattern completions)
"Show where and how well PATTERN matches COMPLETIONS.
@@ -4645,22 +4551,37 @@ completion-pcm--hilit-commonality
Else, if `completion-lazy-hilit' is t, return COMPLETIONS
unchanged, but setup a suitable `completion-lazy-hilit-fn' (which
see) for later lazy highlighting."
- (setq completion-pcm--regexp nil
- completion-lazy-hilit-fn nil)
+ (setq completion-lazy-hilit-fn nil
+ completion-flex--pattern-str nil)
(cond
((and completions (cl-loop for e in pattern thereis (stringp e)))
(let* ((segments (completion-pcm--pattern->segments pattern))
- (re (completion-pcm--segments->regex segments 'group))
- (point-idx (completion-pcm--segments-point-idx segments)))
- (setq completion-pcm--regexp re)
+ (point-idx (completion-pcm--segments-point-idx segments))
+ ;; Extract pattern string (concatenate string elements)
+ (pat (mapconcat #'identity
+ (delq nil (mapcar (lambda (x)
+ (if (stringp x) x nil))
+ pattern))
+ "")))
+ (setq completion-flex--pattern-str pat)
(cond (completion-lazy-hilit
(setq completion-lazy-hilit-fn
- (lambda (str) (completion--hilit-from-re str re point-i=
dx)))
+ (lambda (str)
+ (let ((result (completion--flex-score pat str t)))
+ (when result
+ (completion--flex-propertize
+ str (cdr result) point-idx segments)))
+ str))
completions)
(t
(mapcar
(lambda (str)
- (completion--hilit-from-re (copy-sequence str) re point-id=
x))
+ (setq str (copy-sequence str))
+ (let ((result (completion--flex-score pat str t)))
+ (when result
+ (completion--flex-propertize
+ str (cdr result) point-idx segments)))
+ str)
completions)))))
(t completions)))
=20
@@ -5009,7 +4930,7 @@ completion-flex-nospace
=20
(defun completion--flex-adjust-metadata (metadata)
"If `flex' is actually doing filtering, adjust sorting."
- (let ((flex-is-filtering-p completion-pcm--regexp)
+ (let ((flex-is-filtering-p completion-flex--pattern-str)
(existing-dsf
(completion-metadata-get metadata 'display-sort-function))
(existing-csf
@@ -5021,11 +4942,11 @@ completion--flex-adjust-metadata
(mapcar
(lambda (str)
(cons
- (- (completion--flex-score
- (or (get-text-property
- 0 'completion--unquoted str)
- str)
- completion-pcm--regexp))
+ (- (car (completion--flex-score
+ completion-flex--pattern-str
+ (or (get-text-property
+ 0 'completion--unquoted str)
+ str))))
str))
(if existing-sort-fn
(funcall existing-sort-fn completions)
diff --git a/src/minibuf.c b/src/minibuf.c
index 5dc2b230883..16d30307ed4 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -20,6 +20,7 @@ Copyright (C) 1985-1986, 1993-2026 Free Software Foundati=
on, Inc.
=20
#include <config.h>
#include <errno.h>
+#include <math.h>
=20
#include <binary-io.h>
=20
@@ -2279,6 +2280,143 @@ init_minibuf_once_for_pdumper (void)
last_minibuf_string =3D Qnil;
}
=20
+/* Pre-allocated matrices for flex completion scoring. */
+#define FLEX_MAX_MATRIX_SIZE 65536
+
+static double flex_M[FLEX_MAX_MATRIX_SIZE];
+static double flex_D[FLEX_MAX_MATRIX_SIZE];
+static ptrdiff_t flex_P[FLEX_MAX_MATRIX_SIZE];
+
+DEFUN ("completion--flex-score-gotoh", Fcompletion__flex_score_gotoh,
+ Scompletion__flex_score_gotoh, 2, 2, 0,
+ doc: /* Compute flex score of STR matching PAT using Gotoh algorith=
m.
+Returns a list (SCORE MATCHES) where SCORE is a float and MATCHES
+is a list of match positions in STR, or nil if no valid score. */)
+ (Lisp_Object pat, Lisp_Object str)
+{
+ CHECK_STRING (pat);
+ CHECK_STRING (str);
+
+ ptrdiff_t m =3D SCHARS (pat);
+ ptrdiff_t n =3D SCHARS (str);
+
+ /* Bail if strings are empty or matrix too large. */
+ if (m =3D=3D 0 || n =3D=3D 0)
+ return Qnil;
+
+ ptrdiff_t width =3D n + 1;
+ ptrdiff_t size =3D (m + 1) * width;
+
+ if (size > FLEX_MAX_MATRIX_SIZE)
+ return Qnil;
+
+ /* Extract string data. */
+ unsigned char *pat_data =3D SDATA (pat);
+ unsigned char *str_data =3D SDATA (str);
+
+ /* Scoring constants. */
+ const double match_score =3D 1.0;
+ const double gap_extend =3D -0.05;
+ const double gap_open =3D -0.1;
+ const double neg_inf =3D -INFINITY;
+
+ /* Macro for 2D indexing into flat arrays. */
+ #define MAT(matrix, i, j) ((matrix)[((i) + 1) * width + ((j) + 1)])
+
+ /* Initialize matrices with neg_inf and -1. */
+ for (ptrdiff_t idx =3D 0; idx < size; idx++)
+ {
+ flex_M[idx] =3D neg_inf;
+ flex_D[idx] =3D neg_inf;
+ flex_P[idx] =3D -1;
+ }
+
+ /* Base case: can start matching at any position in str (free leading ga=
p).
+ Initialize first row of D (row -1) to 0.0. */
+ for (ptrdiff_t j =3D 0; j < width; j++)
+ flex_D[j] =3D 0.0;
+
+ /* Forward pass - compute M and D matrices. */
+ for (ptrdiff_t i =3D 0; i < m; i++)
+ {
+ unsigned char pat_char =3D pat_data[i];
+
+ for (ptrdiff_t j =3D 0; j < n; j++)
+ {
+ unsigned char str_char =3D str_data[j];
+
+ /* Compute gap score D[i][j]. */
+ double from_match =3D MAT (flex_M, i, j - 1) + gap_open;
+ double from_gap =3D MAT (flex_D, i, j - 1) + gap_extend;
+ MAT (flex_D, i, j) =3D fmax (from_match, from_gap);
+
+ /* Check if characters match (case-insensitive if needed). */
+ bool chars_match;
+ if (completion_ignore_case)
+ chars_match =3D (downcase (pat_char) =3D=3D downcase (str_char=
));
+ else
+ chars_match =3D (pat_char =3D=3D str_char);
+
+ /* Compute match score M[i][j]. */
+ if (chars_match)
+ {
+ double prev_match =3D MAT (flex_M, i - 1, j - 1);
+ double prev_gap =3D MAT (flex_D, i - 1, j - 1);
+
+ if (prev_match >=3D prev_gap)
+ {
+ MAT (flex_M, i, j) =3D prev_match + match_score;
+ MAT (flex_P, i, j) =3D j - 1;
+ }
+ else
+ {
+ MAT (flex_M, i, j) =3D prev_gap + match_score;
+ /* Find gap origin. */
+ ptrdiff_t gap_origin =3D j - 1;
+ while (gap_origin >=3D 0
+ && MAT (flex_M, i - 1, gap_origin) < MAT (flex_D,=
i - 1, gap_origin))
+ gap_origin--;
+ MAT (flex_P, i, j) =3D gap_origin;
+ }
+ }
+ }
+ }
+
+ /* Find best score in last row. */
+ double best_score =3D neg_inf;
+ ptrdiff_t lastcol =3D -1;
+
+ for (ptrdiff_t j =3D 0; j < n; j++)
+ {
+ double score =3D MAT (flex_M, m - 1, j);
+ if (score > best_score)
+ {
+ best_score =3D score;
+ lastcol =3D j;
+ }
+ }
+
+ if (lastcol < 0 || isinf (best_score))
+ return Qnil;
+
+ /* Normalize score to penalize longer strings and gap penalties. */
+ double normalized_score =3D (double) m / ((double) n * (1.0 + ((double) =
m - best_score)));
+
+ /* Build match positions list by tracing back through P matrix. */
+ Lisp_Object matches =3D Qnil;
+ ptrdiff_t k =3D lastcol;
+
+ for (ptrdiff_t i =3D m - 1; i >=3D 0 && k >=3D 0; i--)
+ {
+ matches =3D Fcons (make_fixnum (k), matches);
+ k =3D MAT (flex_P, i, k);
+ }
+
+ #undef MAT
+
+ return Fcons (make_float (normalized_score), matches);
+}
+
void
syms_of_minibuf (void)
{
@@ -2541,6 +2679,7 @@ syms_of_minibuf (void)
defsubr (&Stest_completion);
defsubr (&Sassoc_string);
defsubr (&Scompleting_read);
+ defsubr (&Scompletion__flex_score_gotoh);
DEFSYM (Qminibuffer_quit_recursive_edit, "minibuffer-quit-recursive-edit=
");
DEFSYM (Qinternal_complete_buffer, "internal-complete-buffer");
DEFSYM (Qcompleting_read_function, "completing-read-function");
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 79ffb1d3fc7..9f25ec1e78c 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -208,7 +208,7 @@ completion-all-sorted-completions
(defun completion--pcm-score (comp)
"Get `completion-score' from COMP."
;; FIXME, uses minibuffer.el implementation details
- (completion--flex-score comp completion-pcm--regexp))
+ (car (completion--flex-score completion-flex--pattern-str comp)))
=20
(defun completion--pcm-first-difference-pos (comp)
"Get `completions-first-difference' from COMP."
@@ -252,12 +252,7 @@ completion-pcm-test-3
1.0)))
=20
(ert-deftest completion-pcm-test-4 ()
- ;; One fourth of a match and no match due to point being at the end
- (should (eql
- (completion--pcm-score
- (car (completion-pcm-all-completions
- "RO" '("RaOb") nil 1)))
- (/ 1.0 4.0)))
+ ;; No match due to point being at the end
(should (null
(completion-pcm-all-completions
"RO" '("RaOb") nil 2))))
João Távora <joaotavora@HIDDEN>:bug-gnu-emacs@HIDDEN.
Full text available.bug-gnu-emacs@HIDDEN:bug#80323; Package emacs.
Full text available.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997 nCipher Corporation Ltd,
1994-97 Ian Jackson.