* bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks @ 2024-11-18 17:33 Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-18 17:36 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 7+ messages in thread From: Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-18 17:33 UTC (permalink / raw) To: 74420; +Cc: monnier Assuming one has an Emacs repo at ~/src/emacs/trunk, 1. emacs -Q 2. C-x C-f C-a C-k ~/src/emacs/trunk/*/minibuf TAB 3. The minibuffer contents change to ~/src/emacs/trunk//minibuf 4. Since there's a //, subsequent file name completion tries to complete on the root directory, which is not what should happen. A more concise reproduction: (completion-pcm-try-completion "*/minibuf" '("lisp/minibufA" "src/minibufB") nil (length "*/minibuf")) evalutes to ("/minibuf" . 8) We should be preserving the *. A patch to fix this will follow. In GNU Emacs 31.0.50 (build 18, x86_64-pc-linux-gnu, X toolkit, cairo version 1.15.12, Xaw scroll bars) of 2024-11-18 built on igm-qws-u22796a Repository revision: 6610135a50ac2fd0683a5e467fe33faa81df21b8 Repository branch: master Windowing system distributor 'The X.Org Foundation', version 11.0.12011000 System Description: Rocky Linux 8.10 (Green Obsidian) Configured using: 'configure -C --with-gif=no --with-x-toolkit=lucid --with-native-compilation=yes --prefix=/home/sbaugh/prefix-jane-emacs' Configured features: CAIRO DBUS FREETYPE GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG LIBSELINUX LIBSYSTEMD LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS X11 XDBE XIM XINPUT2 XPM LUCID ZLIB Important settings: value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix Major mode: Lisp Interaction Minor modes in effect: tooltip-mode: t global-eldoc-mode: t eldoc-mode: t show-paren-mode: t electric-indent-mode: t mouse-wheel-mode: t tool-bar-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t minibuffer-regexp-mode: t line-number-mode: t indent-tabs-mode: t transient-mark-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t Load-path shadows: None found. Features: (shadow sort mail-extr compile comint ansi-osc ansi-color ring comp-run bytecomp byte-compile comp-common rx emacsbug message mailcap yank-media puny dired dired-loaddefs rfc822 mml mml-sec password-cache epa derived epg rfc6068 epg-config gnus-util text-property-search time-date subr-x mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader cl-loaddefs cl-lib sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils rmc iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win term/common-win x-dnd touch-screen tool-bar dnd fontset image regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors frame minibuffer nadvice seq simple cl-generic indonesian philippine cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese composite emoji-zwj charscript charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp files window text-properties overlay sha1 md5 base64 format env code-pages mule custom widget keymap hashtable-print-readable backquote threads dbusbind inotify dynamic-setting system-font-setting font-render-setting cairo x-toolkit xinput2 x multi-tty move-toolbar make-network-process native-compile emacs) Memory information: ((conses 16 107684 9391) (symbols 48 11073 0) (strings 32 32202 1340) (string-bytes 1 982590) (vectors 16 14035) (vector-slots 8 173934 7491) (floats 8 29 1) (intervals 56 284 0) (buffers 984 11)) ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks 2024-11-18 17:33 bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-18 17:36 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-18 20:39 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 7+ messages in thread From: Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-18 17:36 UTC (permalink / raw) To: 74420; +Cc: monnier [-- Attachment #1: Type: text/plain, Size: 20 bytes --] Patch to fix this: [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-Preserve-an-explicit-in-pcm-try-completion.patch --] [-- Type: text/x-patch, Size: 5345 bytes --] From d7377eb6abfc57552f43687aec358934b33707e6 Mon Sep 17 00:00:00 2001 From: Spencer Baugh <sbaugh@janestreet.com> Date: Mon, 18 Nov 2024 12:26:55 -0500 Subject: [PATCH] Preserve an explicit * in pcm-try-completion An explicitly typed * has different semantics from automatically inserted PCM wildcards, so it should be preserved on try-completion. We already do this in some cases, but now we do it more. Concretely, we do it by optimizing the PCM pattern more aggressively to avoid having multiple wildcards in a row: after those are removed, the existing code in completion-pcm--merge-completions is able to preserve * in more cases. The additional optimization should also improve performance. This is especially significant for filename completion: removing an explicit * can take us from ~/src/emacs/trunk/*/minibuf to ~/src/emacs/trunk//minibuf The explicit double slash is interpreted by the file name completion table to mean "start completing from the root directory", so deleting the * here substantially changes semantics. * lisp/minibuffer.el (completion-pcm--optimize-pattern): Add more optimizations. (bug#74420) (completion-pcm--find-all-completions): Optimize the pattern after concatenating two subpatterns. * test/lisp/minibuffer-tests.el (completion-pcm--optimize-pattern) (completion-pcm-test-7): Add tests. --- lisp/minibuffer.el | 20 ++++++++++++++++---- test/lisp/minibuffer-tests.el | 30 +++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 5f3f5d3ead1..e48d85b777d 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -4073,8 +4073,18 @@ completion-pcm--optimize-pattern (let ((n '())) (while p (pcase p - (`(,(or 'any 'any-delim) ,(or 'any 'point) . ,_) - (setq p (cdr p))) + ;; Remove duplicate `any' and `prefix' + (`(any any . ,rest) + (setq p (cons 'any rest))) + (`(prefix prefix . ,rest) + (setq p (cons 'prefix rest))) + ;; `any' matches anything `any-delim' does, and grows the same way. + (`(any-delim any . ,rest) + (setq p (cons 'any rest))) + ;; Remove other wildcards found around `star' or `point'. + ((or `(,(and keep (or 'star 'point)) ,(or 'any 'any-delim 'prefix) . ,rest) + `(,(or 'any 'any-delim 'prefix) ,(and keep (or 'star 'point)) . ,rest)) + (setq p (cons keep rest))) ;; This is not just a performance improvement: it turns a ;; terminating `point' into an implicit `any', which affects ;; the final position of point (because `point' gets turned @@ -4445,8 +4455,10 @@ completion-pcm--find-all-completions ;; (dolist (submatch suball) ;; (push (concat submatch between newsubstring) all))) )) - (setq pattern (append subpat (list 'any (string sep)) - (if between (list between)) pattern)) + (setq pattern + (completion-pcm--optimize-pattern + (append subpat (list 'any (string sep)) + (if between (list between)) pattern))) (setq prefix subprefix))) (if (and (null all) firsterror) (signal (car firsterror) (cdr firsterror)) diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el index 38c2b8c4552..d988a2007cb 100644 --- a/test/lisp/minibuffer-tests.el +++ b/test/lisp/minibuffer-tests.el @@ -133,7 +133,19 @@ completion-pcm--optimize-pattern (should (equal (completion-pcm--optimize-pattern '("buf" point "f")) '("buf" point "f"))) (should (equal (completion-pcm--optimize-pattern '(any "" any)) - '(any)))) + '(any))) + (should (equal (completion-pcm--optimize-pattern '(any-delim "" any)) + '(any))) + (should (equal (completion-pcm--optimize-pattern '(prefix "" prefix)) + '(prefix))) + (should (equal (completion-pcm--optimize-pattern '(prefix star any)) + '(star))) + (should (equal (completion-pcm--optimize-pattern '(any point prefix "foo")) + '(point "foo"))) + ;; The `any' and `prefix' are erased because they're next to `point', + ;; then `point' is erased because it's at the end. + (should (equal (completion-pcm--optimize-pattern '(any point prefix)) + '()))) (defun test-completion-all-sorted-completions (base def history-var history-list) (with-temp-buffer @@ -258,6 +270,22 @@ completion-pcm-test-6 (car (completion-pcm-all-completions "li-pac*" '("do-not-list-packages") nil 7))))) +(ert-deftest completion-pcm-test-7 () + ;; Wildcards are preserved even when right before a delimiter. + (should (equal + (completion-pcm-try-completion + "x*/" + '("x1/y1" "x2/y2") + nil 3) + '("x*/y" . 4))) + ;; This is important if the wildcard is at the start of a component. + (should (equal + (completion-pcm-try-completion + "*/minibuf" + '("lisp/minibuffer.el" "src/minibuf.c") + nil 9) + ("*/minibuf" . 9)))) + (ert-deftest completion-substring-test-1 () ;; One third of a match! (should (equal -- 2.39.3 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks 2024-11-18 17:36 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-18 20:39 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-18 22:17 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 7+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-18 20:39 UTC (permalink / raw) To: Spencer Baugh; +Cc: 74420 > An explicitly typed * has different semantics from automatically > inserted PCM wildcards, so it should be preserved on > try-completion. We already do this in some cases, but now we do > it more. Concretely, we do it by optimizing the PCM pattern > more aggressively to avoid having multiple wildcards in a row: > after those are removed, the existing code in > completion-pcm--merge-completions is able to preserve * in more > cases. Oh, indeed, thank you. The patch looks good to me, so if there are no objection, I'll install it in a few days (feel free to ping me if I forget). Banter follows. > * lisp/minibuffer.el (completion-pcm--optimize-pattern): Add > more optimizations. (bug#74420) Aha, so that's why you didn't submit the patch together with the initial bug report! > - (`(,(or 'any 'any-delim) ,(or 'any 'point) . ,_) > - (setq p (cdr p))) > + ;; Remove duplicate `any' and `prefix' > + (`(any any . ,rest) > + (setq p (cons 'any rest))) > + (`(prefix prefix . ,rest) > + (setq p (cons 'prefix rest))) > + ;; `any' matches anything `any-delim' does, and grows the same way. > + (`(any-delim any . ,rest) > + (setq p (cons 'any rest))) AFAICT you can still merge the `any-delim any` and `any any` cases. > + ;; Remove other wildcards found around `star' or `point'. > + ((or `(,(and keep (or 'star 'point)) ,(or 'any 'any-delim 'prefix) . ,rest) > + `(,(or 'any 'any-delim 'prefix) ,(and keep (or 'star 'point)) . ,rest)) > + (setq p (cons keep rest))) BTW, maybe we should go with something like (`(,(and (pred symbolp) s1) ,(and (pred symbolp) s2) . ,rest) (cond ((completion-pcm--<something>-p s1 s2) (setq p (cons s1 rest))) ((completion-pcm--<something>-p s2 s1) (setq p (cons s2 rest))) (t (push (pop p) n)))) Where `completion-pcm--<something>-p` is some kind of partial ordering? Stefan ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks 2024-11-18 20:39 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-18 22:17 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-18 23:58 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 7+ messages in thread From: Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-18 22:17 UTC (permalink / raw) To: Stefan Monnier; +Cc: 74420 [-- Attachment #1: Type: text/plain, Size: 3430 bytes --] Stefan Monnier <monnier@iro.umontreal.ca> writes: >> An explicitly typed * has different semantics from automatically >> inserted PCM wildcards, so it should be preserved on >> try-completion. We already do this in some cases, but now we do >> it more. Concretely, we do it by optimizing the PCM pattern >> more aggressively to avoid having multiple wildcards in a row: >> after those are removed, the existing code in >> completion-pcm--merge-completions is able to preserve * in more >> cases. > > Oh, indeed, thank you. > > The patch looks good to me, so if there are no objection, I'll install > it in a few days (feel free to ping me if I forget). Actually... I just realized this misses some cases, namely when we have "star point" or "point star". Attached at the end is a different patch which takes a different approach (and which includes new tests for the problematic cases). The changes to optimize still seem reasonable to me, since they might improve performance, so feel free to install it if you think it's good. Although maybe we want to revise it with the below discussion. > Banter follows. > >> * lisp/minibuffer.el (completion-pcm--optimize-pattern): Add >> more optimizations. (bug#74420) > > Aha, so that's why you didn't submit the patch together with the initial > bug report! > >> - (`(,(or 'any 'any-delim) ,(or 'any 'point) . ,_) >> - (setq p (cdr p))) >> + ;; Remove duplicate `any' and `prefix' >> + (`(any any . ,rest) >> + (setq p (cons 'any rest))) >> + (`(prefix prefix . ,rest) >> + (setq p (cons 'prefix rest))) >> + ;; `any' matches anything `any-delim' does, and grows the same way. >> + (`(any-delim any . ,rest) >> + (setq p (cons 'any rest))) > > AFAICT you can still merge the `any-delim any` and `any any` cases. True, I just thought this was a bit easier to read, since the cases are justified as an optimization in slightly different ways. >> + ;; Remove other wildcards found around `star' or `point'. >> + ((or `(,(and keep (or 'star 'point)) ,(or 'any 'any-delim 'prefix) . ,rest) >> + `(,(or 'any 'any-delim 'prefix) ,(and keep (or 'star 'point)) . ,rest)) >> + (setq p (cons keep rest))) > > BTW, maybe we should go with something like > > (`(,(and (pred symbolp) s1) ,(and (pred symbolp) s2) . ,rest) > (cond ((completion-pcm--<something>-p s1 s2) (setq p (cons s1 rest))) > ((completion-pcm--<something>-p s2 s1) (setq p (cons s2 rest))) > (t (push (pop p) n)))) > > Where `completion-pcm--<something>-p` is some kind of partial ordering? Interesting thought. Maybe it would make sense to have something like - completion-pcm--wildcard-grows-on-left-p (non-nil for star, point, any, any-delim) - completion-pcm--wildcard-grows-on-right-p (non-nil for star, point, prefix) - completion-pcm--wildcard-in-text-p (non-nil for star and point) Then this case would be something like "if grows-left/right-p is the same, and at most one of the symbols is in-text-p, delete the non-in-text-p one". Also, then the first two helpers could be used in completion-pcm--merge-completions as well, which could make the wildcard behavior easier to understand. (I want to do a bit of refactoring in completion-pcm--merge-completions, especially after my attached change; I think it could all be a bit easier to understand.) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-Preserve-an-explicit-in-pcm-try-completion.patch --] [-- Type: text/x-patch, Size: 5158 bytes --] From 8c2ff1152800ede05cb9a9fd80deac45646ce52f Mon Sep 17 00:00:00 2001 From: Spencer Baugh <sbaugh@janestreet.com> Date: Mon, 18 Nov 2024 12:26:55 -0500 Subject: [PATCH] Preserve an explicit * in pcm-try-completion An explicitly typed * has different semantics from automatically inserted PCM wildcards, so it should be preserved on try-completion. We already do this in some cases, but now we do it more. This is especially significant for filename completion: removing an explicit * can take us from ~/src/emacs/trunk/*/minibuf to ~/src/emacs/trunk//minibuf The explicit double slash is interpreted by the file name completion table to mean "start completing from the root directory", so deleting the * here substantially changes semantics. * lisp/minibuffer.el (completion-pcm--merge-completions): Don't drop important wildcards. (bug#74420) * test/lisp/minibuffer-tests.el (completion-pcm-test-7): Add tests. --- lisp/minibuffer.el | 21 +++++++++++++++------ test/lisp/minibuffer-tests.el | 25 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 5f3f5d3ead1..2d27fef44ab 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -4513,12 +4513,17 @@ completion-pcm--merge-completions ;; Then for each of those non-constant elements, extract the ;; commonality between them. (let ((res ()) - (fixed "")) + (fixed "") + ;; Accumulate each stretch of wildcards, and process them as a unit. + (wildcards ())) ;; Make the implicit trailing `any' explicit. (dolist (elem (append pattern '(any))) (if (stringp elem) - (setq fixed (concat fixed elem)) + (progn + (setq fixed (concat fixed elem)) + (setq wildcards nil)) (let ((comps ())) + (push elem wildcards) (dolist (cc (prog1 ccs (setq ccs nil))) (push (car cc) comps) (push (cdr cc) ccs)) @@ -4542,14 +4547,16 @@ completion-pcm--merge-completions (push prefix res) ;; `prefix' only wants to include the fixed part before the ;; wildcard, not the result of growing that fixed part. - (when (eq elem 'prefix) + (when (seq-some (lambda (elem) (eq elem 'prefix)) wildcards) (setq prefix fixed)) (push prefix res) - (push elem res) + ;; Push all the wildcards in this stretch, to preserve `point' and + ;; `star' wildcards before ELEM. + (setq res (nconc wildcards res)) ;; Extract common suffix additionally to common prefix. ;; Don't do it for `any' since it could lead to a merged ;; completion that doesn't itself match the candidates. - (when (and (memq elem '(star point prefix)) + (when (and (seq-some (lambda (elem) (memq elem '(star point prefix))) wildcards) ;; If prefix is one of the completions, there's no ;; suffix left to find. (not (assoc-string prefix comps t))) @@ -4563,7 +4570,9 @@ completion-pcm--merge-completions comps)))))) (cl-assert (stringp suffix)) (unless (equal suffix "") - (push suffix res))))) + (push suffix res)))) + ;; We pushed these wildcards on RES, so we're done with them. + (setq wildcards nil)) (setq fixed ""))))) ;; We return it in reverse order. res))))) diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el index 38c2b8c4552..c166450d87a 100644 --- a/test/lisp/minibuffer-tests.el +++ b/test/lisp/minibuffer-tests.el @@ -258,6 +258,31 @@ completion-pcm-test-6 (car (completion-pcm-all-completions "li-pac*" '("do-not-list-packages") nil 7))))) +(ert-deftest completion-pcm-test-7 () + ;; Wildcards are preserved even when right before a delimiter. + (should (equal + (completion-pcm-try-completion + "x*/" + '("x1/y1" "x2/y2") + nil 3) + '("x*/y" . 4))) + ;; Or around point. + (should (equal + (completion-pcm--merge-try + '(point star "foo") '("xxfoo" "xyfoo") "" "") + '("x*foo" . 1))) + (should (equal + (completion-pcm--merge-try + '(star point "foo") '("xxfoo" "xyfoo") "" "") + '("x*foo" . 2))) + ;; This is important if the wildcard is at the start of a component. + (should (equal + (completion-pcm-try-completion + "*/minibuf" + '("lisp/minibuffer.el" "src/minibuf.c") + nil 9) + '("*/minibuf" . 9)))) + (ert-deftest completion-substring-test-1 () ;; One third of a match! (should (equal -- 2.39.3 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks 2024-11-18 22:17 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-18 23:58 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-19 13:18 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 7+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-18 23:58 UTC (permalink / raw) To: Spencer Baugh; +Cc: 74420 > Actually... I just realized this misses some cases, namely when we have > "star point" or "point star". FWIW, my local patches have included for years optimizations like the ones you suggested *and* they replaced `star point` and `point star` with just `star`. Do you think it's important to preserve `point` in those cases? >> BTW, maybe we should go with something like >> >> (`(,(and (pred symbolp) s1) ,(and (pred symbolp) s2) . ,rest) >> (cond ((completion-pcm--<something>-p s1 s2) (setq p (cons s1 rest))) >> ((completion-pcm--<something>-p s2 s1) (setq p (cons s2 rest))) >> (t (push (pop p) n)))) >> >> Where `completion-pcm--<something>-p` is some kind of partial ordering? > > Interesting thought. Maybe it would make sense to have something like > - completion-pcm--wildcard-grows-on-left-p > (non-nil for star, point, any, any-delim) > - completion-pcm--wildcard-grows-on-right-p > (non-nil for star, point, prefix) > - completion-pcm--wildcard-in-text-p > (non-nil for star and point) > Then this case would be something like "if grows-left/right-p is the > same, and at most one of the symbols is in-text-p, delete the > non-in-text-p one". But I guess your `completion-pcm--merge-completions` is still needed as long as we can't optimize all sequences of symbols to a single symbol. 🙁 Stefan ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks 2024-11-18 23:58 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-19 13:18 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-27 19:30 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 7+ messages in thread From: Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-19 13:18 UTC (permalink / raw) To: Stefan Monnier; +Cc: 74420 Stefan Monnier <monnier@iro.umontreal.ca> writes: >> Actually... I just realized this misses some cases, namely when we have >> "star point" or "point star". > > FWIW, my local patches have included for years optimizations like the > ones you suggested *and* they replaced `star point` and `point star` > with just `star`. > > Do you think it's important to preserve `point` in those cases? Hm, I'm not sure. I've been playing around with alternative ways to move point in pcm-try-completion but haven't yet got something I'm satisfied with. So let me defer this question until I've hacked on that some more :) >>> BTW, maybe we should go with something like >>> >>> (`(,(and (pred symbolp) s1) ,(and (pred symbolp) s2) . ,rest) >>> (cond ((completion-pcm--<something>-p s1 s2) (setq p (cons s1 rest))) >>> ((completion-pcm--<something>-p s2 s1) (setq p (cons s2 rest))) >>> (t (push (pop p) n)))) >>> >>> Where `completion-pcm--<something>-p` is some kind of partial ordering? >> >> Interesting thought. Maybe it would make sense to have something like >> - completion-pcm--wildcard-grows-on-left-p >> (non-nil for star, point, any, any-delim) >> - completion-pcm--wildcard-grows-on-right-p >> (non-nil for star, point, prefix) >> - completion-pcm--wildcard-in-text-p >> (non-nil for star and point) >> Then this case would be something like "if grows-left/right-p is the >> same, and at most one of the symbols is in-text-p, delete the >> non-in-text-p one". > > But I guess your `completion-pcm--merge-completions` is still needed as > long as we can't optimize all sequences of symbols to a single symbol. > 🙁 Yep. And here's one case that I think makes optimizing all sequences down to a single symbol impossible: (star star star) is reified as ***, not shrunk down to a single *. I think that behavior is probably reasonable (or at least I'm not in any rush to get rid of it), but to preserve it we have to preserve sequences of multiple symbols. ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks 2024-11-19 13:18 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-27 19:30 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 0 replies; 7+ messages in thread From: Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-27 19:30 UTC (permalink / raw) To: Stefan Monnier; +Cc: 74420 Spencer Baugh <sbaugh@janestreet.com> writes: > Stefan Monnier <monnier@iro.umontreal.ca> writes: >>> Actually... I just realized this misses some cases, namely when we have >>> "star point" or "point star". >> >> FWIW, my local patches have included for years optimizations like the >> ones you suggested *and* they replaced `star point` and `point star` >> with just `star`. >> >> Do you think it's important to preserve `point` in those cases? > > Hm, I'm not sure. I've been playing around with alternative ways to > move point in pcm-try-completion but haven't yet got something I'm > satisfied with. So let me defer this question until I've hacked on that > some more :) Okay, so I ended up not wanting to move point. What I have instead now is something which explicitly inserts a * in the minibuffer, specifically with completion-pcm-leading-wildcard: diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 01502235403..db13c659004 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -3925,7 +3925,7 @@ completion-pcm--string->pattern (setq p0 p) (push (substring string p (match-end 0)) pattern) ;; `any-delim' is used so that "a-b" also finds "array->beginning". - (setq pending 'any-delim) + (setq pending (if completion-pcm-leading-wildcard 'star 'any-delim)) (setq p0 (match-end 0)))) (setq p p0)) @@ -3935,7 +3935,7 @@ completion-pcm--string->pattern (setq pattern (nreverse pattern)) (when completion-pcm-leading-wildcard (when (stringp (car pattern)) - (push 'prefix pattern))) + (push 'star pattern))) pattern))) (defun completion-pcm--optimize-pattern (p) -- 2.39.3 This does two things: - completion-pcm-leading-wildcard previously had inconsistent behavior: if completion-pcm--find-all-completions makes a recursive call, completion-pcm-leading-wildcard would effectively add a leading wildcard to each component. But that wouldn't happen if the original pattern happens to match, in the first completion-pcm--all-completions call. To make them behave identically, now completion-pcm-leading-wildcard changes the 'any-delim inserted at the start of each component into a proper wildcard. This is just a bugfix. - More radically, actually insert a * in the minibuffer text if we run completion-pcm-try-completion with completion-pcm-leading-wildcard=t. Inserting a * is pretty nice for multiple reasons. Paradoxically, inserting a * makes things more efficient for the configuration I intend people to use, where completion-styles contains: ... partial-completion (partial-completion ((completion-pcm-leading-wildcard t))) ... With this configuration, if partial-completion fails, we make one call to the expensive completion-pcm-leading-wildcard=t mode, and then afterwards the explicit *s cause us to stay in regular partial-completion, with only the exact amount of leading wildcards that we actually need, rather than having an extra 'prefix wildcard at the start of every single component. And, inserting the * ensures that we stay in this "leading wildcard" mode. I've found that tab-completing with completion-pcm-leading-wildcard tends to sometimes change the minibuffer contents such that subsequent tab-completions get handled by another completion style. With leading wildcards, that's pretty undesirable, because it can make the set of completions much narrower. But explicitly inserting the * forces the leading-wildcard behavior to stay around. And it just looks pretty good: because the 'star wildcards are removed if they can't expand to anything, when you hit TAB the * are basically inserted everywhere that you might add new text. This is pretty neat. I usually use completion-pcm-leading-wildcard with project-find-file, so e.g. this is a decent way to test: (setf (alist-get 'project-file completion-category-overrides) '((styles basic partial-completion (partial-completion ((completion-pcm-leading-wildcard t)))))) Then C-x p f in the Emacs repo What do you think? ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-11-27 19:30 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-11-18 17:33 bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-18 17:36 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-18 20:39 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-18 22:17 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-18 23:58 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-19 13:18 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-11-27 19:30 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.