The greedy regexp matching, broken scoring and broken highlight were
sources of frequent complaints about the 'flex' matching style. This
commit fixes that.
It was inspired by the 'hotfuzz' style available at
https://github.com/axelf4/hotfuzz which is 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 slightly more
sophisticated than 'flex' (has special rules for matching things at word
boundaries, a C module with multithreading support). It's almost (but
not entirely) void of hacks so it'd 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, so I thought I'd try my hand at it.
The new 'flex' implementation also uses Gotoh algorithm (apparently
a common choice for these kinds of task) and happens mostly in a new C
function. It is strictly more correct than the "old" flex. 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 across the candidate.
Regarding performance, it is faster than the naive 'flex', but that's
mainly because this commit also includes changes to the Elisp code which
make faster regexp's for the filtering step. It is slower than
'hotfuzz' when that style's C-module extension is leveraged. 'hotfuzz'
does the filtering and sorting steps together in C code and has
multithreaded workers there. The matching and scoring algorithm itself
is not the bottleneck.
The flex style was completely decoupled from the pcm/substring styles in
lisp/minibuffer.el. Test code were refactored and more tests were
added.
* src/minibuf.c (completion--flex-cost-gotoh): New function.
* lisp/minibuffer.el (completion-flex--pattern-str): New variable.
(flex-score-match-tightness): Make obsolete.
(completion--flex-all-completions-1): New helper function.
(completion-flex-try-completion, completion-flex-all-completions): Rewrite.
(completion-substring--all-completions): No longer take transform-pattern-fn.
(completion--flex-adjust-metadata): Tweak.
(completion--flex-score, completion--flex-score-1)
(completion--flex-score-last-md, completion-flex--make-flex-pattern): Delete.
* test/lisp/minibuffer-tests.el (completion--sorted-flex-completions):
New helper function.
(completion-flex-test-non-ascii): New test.
(completion--pcm-score): Delete.
(completion-pcm-test-3, completion-pcm-test-4)
(completion-substring-test-1, completion-substring-test-2)
(completion-flex-test-2, completion-flex-test-3): Tweak.
Just because a specific request of a specific "hint" is
cancelled doesn't mean we can cancel the other's too. Also
eglot-advertise-cancellation = nil was subtly broken.
This manifested itself mostly in Eglot semantic tokens.
* lisp/progmodes/eglot.el (eglot--async-request): Fix thinkos.
* lisp/align.el (align-region): Use markers to ensure the regions
stay accurate after overlapping aligning modifications. (Bug#80316)
* test/lisp/align-tests.el (align-c-multi-section): New test.
It is both simpler to code and marginally more general (allows
spaces in arguments).
* lisp/textmodes/yaml-ts-mode.el (yaml-ts-mode-yamllint-options): Use
a list.
(yaml-ts-mode-flymake): Adjust accordingly.
* test/lisp/vc/vc-git-tests.el (vc-git-test-branch-remotes):
The 'unset' subcommand to 'git config' was introduced in git 2.46; use
the '--unset' option instead.
* src/xdisp.c (move_it_vertically_backward): Zero out cached value
of line height, to avoid using stale and incorrect values.
(try_window_reusing_current_matrix): Fix conditions for changes in
tab-line height.
Reported by Michael Heerdegen <michael_heerdegen@mailbox.org> in
https://lists.gnu.org/archive/html/help-gnu-emacs/2026-01/msg00163.html
This improves the scrolling a little bit, but doesn't solve the
problem entirely.
* lisp/progmodes/elisp-mode.el (elisp-byte-code-syntax-propertize):
Reset point to just after the start of the previous match so that we
don't skip past the end of the lazy string, which can happen if it's
zero-length; that could lead to an infinite loop.
macOS 26 introduced new event processing behavior that causes scrolling
lag and input handling problems in Emacs. This patch disables two
features via NSUserDefaults when built against the macOS 26 SDK:
- NSEventConcurrentProcessingEnabled
- NSApplicationUpdateCycleEnabled
This fix is based on the equivalent patch in emacs-mac by Mitsuharu
Yamamoto. See: https://bitbucket.org/mituharu/emacs-mac/commits/e52ebfd
* src/nsterm.m (ns_term_init): Disable problematic event processing
when built for macOS 26+. (Bug#80268)
This option controls the format of the help-echo when hovering
over the time display in mode line. (Bug#80143)
* lisp/time.el (display-time-help-echo-format): Add option.
(display-time-string-forms): Use it.
* etc/NEWS (Time): Announce the new option.
This function will truncate a string on a pixelwise basis in a
work buffer and using a binary search rather than brute force.
* lisp/emacs-lisp/subr-x.el (work-buffer--prepare-pixelwise):
New defun helper function.
(string-pixel-width): Use the helper function.
(truncate-string-pixelwise): New defun.
* test/lisp/misc-tests.el (misc-test-truncate-string-pixelwise):
(misc-test-truncate-string-pixelwise-unicode): New test.
* doc/lispref/display.texi (Size of Displayed Text): Document
the function.
* etc/NEWS: Announce the function.